Skip to content

Commit 7867825

Browse files
rmunnmyieye
andauthored
Switch from NPM to PNPM for package management (#1818)
* Switch from NPM to PNPM as package tool Advantage of PNPM is speed and storage size on disk: if you have multiple projects using the same NPM package, NPM will store multiple copies, but PNPM will store only one copy and share it between projects. Most recent version of PNPM also requires Node version 18 or later, so we'll bump any Node 16 references to most recent Node (22.2.0). * Don't copy node_modules from dev, run pnpm i in Docker Also lets us remove the rebuild of node-sass, which was needed for devs running a different architecture on their dev machines than the architecture the Docker containers are built for (e.g. devs running Macs with ARM chips, when the Docker containers we build are for x64). * Add mention of PNPM to developer readme * Use build targets to reduce unneeded builds By specifying `target: development` in docekr-compose.yml, we get the same effect as specifying `docker build --target=development`: with buildx, unused build stages (e.g., prod stages) are skipped. * Add pnpm/action-setup * Replace most pnpx with pnpm exec and fix running sub-make cmds in Windows * Fix yaml syntax --------- Co-authored-by: Tim Haasdyk <[email protected]>
1 parent 93255b5 commit 7867825

21 files changed

+9037
-14631
lines changed

.github/workflows/e2e-tests.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ jobs:
1818
steps:
1919
-
2020
uses: actions/checkout@v3
21+
-
22+
uses: pnpm/action-setup@v4
2123
-
2224
name: Playwright E2E Tests
2325
run: make e2e-tests-ci browser=${{ matrix.browser }} shard="${{ matrix.shard }}/${{ matrix.shards }}"

.github/workflows/integrate-and-deploy.yml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,18 @@ jobs:
5454
TAG_LFMERGE=${TAG_LFMERGE:-latest}
5555
echo "TAG_LFMERGE=${TAG_LFMERGE}" >> $GITHUB_OUTPUT
5656
-
57-
uses: actions/setup-node@v3
57+
uses: pnpm/action-setup@v4
58+
-
59+
uses: actions/setup-node@v4
5860
with:
59-
node-version: '16.14.0'
60-
cache: 'npm'
61+
node-version: '22.2.0'
62+
cache: 'pnpm'
63+
-
64+
run: pnpm install
6165
-
62-
run: npm ci
66+
name: Prep for production build of legacy app
67+
# docker compose build doesn't allow passing a `--target` parameter, so we have to replace the target in docker-compose.yml
68+
run: "sed -i 's/target: development/target: production/g' docker-compose.yml"
6369
-
6470
name: Build legacy app
6571
run: docker compose build --build-arg ENVIRONMENT=production --build-arg BUILD_VERSION=${{ steps.image.outputs.TAG_APP }} app

.github/workflows/pull-request.yml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,14 @@ jobs:
6363
-
6464
uses: actions/checkout@v3
6565
-
66-
uses: actions/setup-node@v3
66+
uses: pnpm/action-setup@v4
67+
-
68+
uses: actions/setup-node@v4
6769
with:
68-
node-version: "16.14.0"
69-
cache: "npm"
70+
node-version: "22.2.0"
71+
cache: "pnpm"
7072
-
7173
name: Run prettier check
7274
run: |
73-
npx prettier -v
74-
npx prettier --check .
75+
pnpm dlx prettier -v
76+
pnpm dlx prettier --check .

.husky/pre-commit

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#!/usr/bin/env sh
22
. "$(dirname -- "$0")/_/husky.sh"
33

4-
npx lint-staged
4+
pnpm exec lint-staged

.vscode/tasks.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
"label": "npm install",
88
"type": "shell",
99
"windows": {
10-
"command": "bash -c 'npm install'"
10+
"command": "bash -c 'pnpm install'"
1111
},
12-
"command": "npm install",
12+
"command": "pnpm install",
1313
"presentation": {
1414
"reveal": "silent"
1515
},

Makefile

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
.PHONY: start
44
start: build
5-
# starts the entire runtime infrastructure
5+
# starts the entire runtime infrastructure
66
docker compose up -d ssl
77

88
.PHONY: dev
@@ -14,22 +14,22 @@ ui-builder:
1414

1515
.PHONY: e2e-tests-ci
1616
e2e-tests-ci:
17-
npm ci
18-
$(MAKE) e2e-app
19-
npx playwright install ${browser} --with-deps
20-
npx playwright test -c ./test/e2e/playwright.config.ts --project=${browser} --shard=${shard}
17+
pnpm install
18+
"$(MAKE)" e2e-app
19+
pnpm exec playwright install ${browser} --with-deps
20+
pnpm exec playwright test -c ./test/e2e/playwright.config.ts --project=${browser} --shard=${shard}
2121

2222
.PHONY: e2e-tests
2323
e2e-tests: ui-builder
24-
npm install
25-
$(MAKE) e2e-app
26-
npx playwright install chromium firefox
27-
npx playwright test -c ./test/e2e/playwright.config.ts $(params)
24+
pnpm install
25+
"$(MAKE)" e2e-app
26+
pnpm exec playwright install chromium firefox
27+
pnpm exec playwright test -c ./test/e2e/playwright.config.ts $(params)
2828

2929
.PHONY: e2e-app
3030
e2e-app:
31-
# delete any cached session storage state files if the service isn't running
32-
docker compose ps e2e-app > /dev/null 2>&1 || $(MAKE) clean-test
31+
# delete any cached session storage state files if the service isn't running
32+
docker compose ps e2e-app > /dev/null 2>&1 || "$(MAKE)" clean-test
3333
docker compose up -d e2e-app --build
3434

3535
.PHONY: unit-tests
@@ -45,9 +45,9 @@ unit-tests-ci:
4545

4646
.PHONY: build
4747
build:
48-
npm install
48+
pnpm install
4949

50-
# ensure we start with a clean ui-dist volume for every build
50+
# ensure we start with a clean ui-dist volume for every build
5151
-docker volume rm web-languageforge_lf-ui-dist 2>/dev/null
5252

5353
docker compose build mail app lfmerge ld-api next-proxy next-app
@@ -83,11 +83,11 @@ clean:
8383

8484
.PHONY: clean-test
8585
clean-test:
86-
cd test/e2e && npx rimraf test-storage-state
86+
cd test/e2e && pnpm dlx rimraf test-storage-state
8787

8888
.PHONY: clean-powerwash
8989
clean-powerwash: clean
90-
$(MAKE) clean-test
90+
"$(MAKE)" clean-test
9191
docker system prune -f --volumes
9292
- docker rmi -f `docker images -q "lf-*"` sillsdev/web-languageforge:base-php
9393
docker builder prune -f

docker-compose.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ services:
2323
- ./webpack-dev.config.js:/data/webpack-dev.config.js
2424
- ./webpack-prd.config.js:/data/webpack-prd.config.js
2525
- ./package.json:/data/package.json
26-
- ./package-lock.json:/data/package-lock.json
26+
- ./pnpm-lock.yaml:/data/pnpm-lock.yaml
2727

2828
# needed these volume maps so changes to typescript/scss would be reflected in running app, actually rebundled and output to dist which is then shared to the app container.
2929
- ./src/angular-app:/data/src/angular-app
@@ -34,6 +34,7 @@ services:
3434
build:
3535
context: .
3636
dockerfile: docker/app/Dockerfile
37+
target: development
3738
args:
3839
- ENVIRONMENT=development
3940
image: lf-app
@@ -178,7 +179,7 @@ services:
178179
container_name: lf-next-app-dev
179180
environment:
180181
- API_HOST=http://app
181-
command: npm run dev-w-host
182+
command: pnpm run dev-w-host
182183
volumes:
183184
# for developer convenience
184185
- ./next-app/src:/app/src
@@ -269,6 +270,7 @@ services:
269270
build:
270271
context: .
271272
dockerfile: docker/app/Dockerfile
273+
target: development
272274
args:
273275
- ENVIRONMENT=development
274276
image: lf-e2e-app

docker/app/Dockerfile

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,19 @@
22
ARG ENVIRONMENT=${ENVIRONMENT:-'production'}
33

44
# UI-BUILDER
5-
FROM node:22.0.0-alpine3.18 AS ui-builder-base
5+
FROM node:22.2.0-alpine3.18 AS ui-builder-base
66

77
RUN mkdir -p /data
88
WORKDIR /data
99

1010
# Copy in files needed for compilation, located in the repo root
11-
COPY typings ./typings/
12-
COPY package.json webpack.config.js webpack-dev.config.js webpack-prd.config.js tsconfig.json tslint.json ./
13-
14-
# Use built node_modules from host
15-
COPY node_modules ./node_modules/
11+
COPY package.json pnpm-lock.yaml ./
1612

17-
# node-sass is platform dependent and so must be rebuilt inside docker
18-
RUN npm rebuild node-sass
13+
RUN corepack enable
14+
RUN pnpm install
1915

16+
COPY typings ./typings/
17+
COPY webpack.config.js webpack-dev.config.js webpack-prd.config.js tsconfig.json tslint.json ./
2018
# copy in src local files
2119
# Note: *.html files in src/angular-app aren't necessary for webpack compilation, however changes to HTML files will invalidate this layer
2220
COPY src/angular-app ./src/angular-app
@@ -33,7 +31,7 @@ ENV NPM_BUILD_SUFFIX=dev
3331
FROM ${ENVIRONMENT}-ui-builder AS ui-builder
3432

3533
# artifacts built to /data/src/dist
36-
RUN npm run build:${NPM_BUILD_SUFFIX}
34+
RUN pnpm run build:${NPM_BUILD_SUFFIX}
3735

3836
# COMPOSER-BUILDER
3937
# download composer app dependencies
@@ -44,23 +42,24 @@ WORKDIR /composer
4442
COPY src/composer.json src/composer.lock /composer/
4543
RUN composer install
4644

47-
# PRODUCTION IMAGE
48-
FROM sillsdev/web-languageforge:base-php AS production-app
45+
# PRODUCTION BASE IMAGE
46+
FROM sillsdev/web-languageforge:base-php AS production-base
4947
RUN rm /usr/local/bin/install-php-extensions /usr/local/bin/composer
5048
RUN apt-get remove -y gnupg2 git
5149
RUN mv $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini
5250
# had to add /wait into prod image so the prod image could be run through E2E tests.
5351
COPY --from=sillsdev/web-languageforge:wait-latest /wait /wait
5452

55-
# DEVELOPMENT IMAGE
56-
FROM sillsdev/web-languageforge:base-php AS development-app
53+
# DEVELOPMENT BASE IMAGE
54+
FROM sillsdev/web-languageforge:base-php AS development-base
5755
RUN install-php-extensions xdebug-^3.1
5856
COPY docker/app/docker-php-ext-xdebug.ini /usr/local/etc/php/conf.d
5957
RUN mv $PHP_INI_DIR/php.ini-development $PHP_INI_DIR/php.ini
6058
COPY --from=sillsdev/web-languageforge:wait-latest /wait /wait
6159
COPY docker/app/run-with-wait.sh /run-with-wait.sh
6260

63-
FROM ${ENVIRONMENT}-app AS languageforge-app
61+
# COMMON BASE IMAGE
62+
FROM ${ENVIRONMENT}-base AS languageforge-base
6463
ARG BUILD_VERSION=${BUILD_VERSION:-'9.9.9'}
6564

6665
# copy app into image
@@ -84,5 +83,14 @@ COPY --from=composer-builder /composer/vendor /var/www/html/vendor
8483
RUN echo "${BUILD_VERSION}" > build-version.txt \
8584
&& sed -i "s/9.9.9/${BUILD_VERSION}/" version.php
8685

86+
# Final image, to be selected with docker build --target=development
87+
FROM languageforge-base AS development
88+
89+
ENTRYPOINT [ "tini", "-g", "--" ]
90+
CMD [ "apache2-foreground" ]
91+
92+
# Final image, to be selected with docker build --target=production
93+
FROM languageforge-base AS production
94+
8795
ENTRYPOINT [ "tini", "-g", "--" ]
8896
CMD [ "apache2-foreground" ]

docker/next-app/Dockerfile.next-app

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
# Build the app
2-
FROM node:alpine AS builder
2+
FROM node:22.2.0-alpine3.18 AS builder
33

44
WORKDIR /app
55

6-
COPY tsconfig.json package-lock.json package.json postcss.config.cjs svelte.config.js vite.config.js tailwind.config.cjs /app/
6+
COPY tsconfig.json pnpm-lock.yaml package.json postcss.config.cjs svelte.config.js vite.config.js tailwind.config.cjs /app/
77
COPY src /app/src
88
COPY static /app/static
99

10-
RUN npm install
11-
RUN npm run build
10+
RUN corepack enable
11+
RUN pnpm install
12+
RUN pnpm run build
1213

1314
# Run
14-
FROM node:alpine
15+
FROM node:22.2.0-alpine3.18
1516

1617
COPY --from=builder /app/build /app/
1718
COPY --from=builder /app/node_modules /app/node_modules

docker/next-app/dev/Dockerfile

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
FROM node:alpine
1+
FROM node:22.2.0-alpine3.18
22

33
WORKDIR /app
44

5-
COPY tsconfig.json package-lock.json package.json postcss.config.cjs svelte.config.js vite.config.js tailwind.config.cjs /app/
5+
COPY tsconfig.json pnpm-lock.yaml package.json postcss.config.cjs svelte.config.js vite.config.js tailwind.config.cjs /app/
66
COPY src /app/src
77
COPY static /app/static
88

9-
RUN npm install
9+
RUN corepack enable
10+
RUN pnpm install
1011

1112
EXPOSE 3000

docker/ui-builder/Dockerfile

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
FROM node:16.14.0-alpine3.15
1+
FROM node:22.2.0-alpine3.18
22

33
RUN mkdir -p /data
44
WORKDIR /data
55

6-
COPY package.json ./
7-
COPY node_modules ./node_modules/
6+
COPY package.json pnpm-lock.yaml ./
7+
8+
RUN corepack enable
9+
RUN pnpm install
810

911
# Copy in files needed for compilation, located in the repo root
1012
COPY typings ./typings/
@@ -18,4 +20,4 @@ COPY src/json ./src/json
1820
COPY src/sass ./src/sass
1921
COPY src/Site/views ./src/Site/views
2022

21-
CMD npm run build:dev:watch
23+
CMD pnpm run build:dev:watch

docs/DEVELOPER.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ While Docker is great way to encapsulate all of the dependencies, build tools an
3838

3939
- PHP 7.4
4040
- Composer
41-
- Node and npm
41+
- Node and pnpm
4242
- .Net SDK
4343

4444
### Project Setup
@@ -52,7 +52,8 @@ While Docker is great way to encapsulate all of the dependencies, build tools an
5252
2. Install [Make](https://www.gnu.org/software/make/): `sudo apt install make`.
5353
3. Install [Node 22](https://nodejs.org/en/download/). We recommend using [nvm](https://github.com/nvm-sh/nvm#installation-and-update) or [nvm on Windows](https://github.com/coreybutler/nvm-windows).
5454
4. Clone the repo: `git clone https://github.com/sillsdev/web-languageforge`.
55-
5. Run `npm install` (required for git pre-commit hook with Prettier)
55+
5. Run `corepack enable` to download and set up PNPM if it's not alraedy installed
56+
6. Run `pnpm install` (required for git pre-commit hook with Prettier)
5657

5758
### Running the App Locally
5859

@@ -99,8 +100,8 @@ ngrok will return two URLs, one http and one https, that contain what is being s
99100

100101
### Running Playwright E2E Tests
101102

102-
Before running Playwright tests for the first time use `npx playwright install --with-deps chromium` to install chromium with its dependencies. It will ask for root access.
103-
After Playwright updates, you'll likely need to run `npx playwright install` to update the browsers, but Playwright should provide fairly explicit failure logs if that's the case.
103+
Before running Playwright tests for the first time use `pnpm exec playwright install --with-deps chromium` to install chromium with its dependencies. It will ask for root access.
104+
After Playwright updates, you'll likely need to run `pnpm exec playwright install` to update the browsers, but Playwright should provide fairly explicit failure logs if that's the case.
104105

105106
1. `make e2e-tests`
106107
1. Test results will appear in your terminal

next-app/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ From the project root directory, `make next-dev` and access app via http://local
1010

1111
### Alternate local development (limited)
1212

13-
From within the `/next-app` directory, `npm run dev` will also start the next app and the root page can be used for simple testing, i.e., http://localhost:3000/. This approach is limited in that the backend will not be started so all development must be isolated to pages without a required backend call.
13+
From within the `/next-app` directory, `pnpm run dev` will also start the next app and the root page can be used for simple testing, i.e., http://localhost:3000/. This approach is limited in that the backend will not be started so all development must be isolated to pages without a required backend call.

0 commit comments

Comments
 (0)