Before following the migration steps, make sure the following have been completed.
-
Select the target website or newsletter repo to upgrade and pull all latest changes from
master
/main
. -
Create a new branch called
4.x
and push it to your fork. This is where all changes will be pushed to. -
Ensure you're only loading one repo into VSCode at a time.
-
Ensure you have the latest depenency tool installed globally. To do so, run the following command:
yarn global add @parameter1/[email protected]
-
Down any running Docker containers in your project by running the following from the project root
docker-compose down
-
It's highly recommended that you recursively delete all
node_modules
foldersfind . -name 'node_modules' -type d -prune -exec rm -rf '{}' +
-
References to
node:10
images (specifically,node:10.24
) should be changed tonode:14.21
in all files nameddocker-compose.yml
Dockerfile
-
If GitHub actions are used by the repo, the
node-version
value must be changed to14.21
in the.github/workflows/node-ci.yml
file. If TravisCI is still used, check the.travis
file in the root of the project and update the node version.
- Upgrade
lerna
to the latest major version in your rootpackage.json
file"lerna": "^6.5.1"
- Upgrade
newrelic
to the latest major version whereever present in yourpackage.json
files - usually in thepackages/global
package."newrelic": "^9.10.1"
All core @parameter1/base-cms-*
dependencies will need to be upgraded to the latest versions. Additionally, because lower-level dependencies (such as @babel/*
and node-sass
) had significant version adjustments, references to these should be deleted from the yarn.lock
before running an install.
-
Upgrade all BaseCMS dependencies to v4.x by running the below in the project root
p1-basecms-dependencies upgrade --latest
-
Once completed, do not run a
yarn install
yet. We'll save that to the very end. :) -
Delete references to
@babel/*
dependencies in theyarn.lock
file. The easiest way to do this is to search in the file using regex^"@babel\/
and then delete all entries. There may be alot of these, and that's okay :) -
Now run
./scripts/yarn.sh
-- this should run in the new Node14 Docker container (which may need to be downloaded). MAKE SURE YOU RUN THE INSTALL USING THE SCRIPT This ensures the install runs in the proper version of Node.
The new build process will no longer resolve relative @import
statements to files located in node_modules
. The good news, however, is that it can import using standard package names.
- Update relative node_module
@import
declarations in.scss
files to their absolute counterparts. For example:@import "../../node_modules/bootstrap/scss/mixins"
would become@import "bootstrap/scss/mixins";
- the number of relative parent paths does not matter... so
../
and../../
and../../../
etc all need to be removed.
- The quickest way to change the import statements is to search all
.scss
files using regex@import ".*\/node_modules\/
and replacing the matched entries with@import "
(note the ending double-quote -- that should be there) - To avoid possible deprecation errors when building, run
yarn global add sass-migrator
and then runsass-migrator division **/*.scss
from the project root. This should replace instances where deprecated division (/
) operators are being used.
The marko-web-deferred-script-loader
is now loaded into core. As such, certain component calls can be removed.
- Remove any references to components
<marko-web-deferred-script-loader-init />
and<marko-web-deferred-script-loader-load />
. These normally occur in the site or globaldocument.marko
file.
The CLI was significantly improved for performance and build time speed. While the CLI commands are still named the same (except for dropping lint
-- see ESLint and Stylelint sections) their arguments need to be adjusted to ensure proper dev server operation, production build, and testing functions.
NOTE ON @PARAMETER1/BASE-CMS MARKO FILES: All .marko
files inside @parameter1/base-cms-*
packages (found in node_modules
) are now compiled when the package is built and published to NPM. Because of this, the compiled .marko.js
files will already exist in node_modules
when the packages are installed. These files are not automatically compiled by the new CLI. The drawback is that you can no longer modify .marko
files found in node_modules
without re-compiling manually. If you make changes to a .marko
file within node_modules
, you'll need to re-compile by running the below from the root of your project:
yarn basecms-marko-compile compile --cwd ./node_modules/@parameter1/base-cms-marko-web-[name-of-package] --no-clean
If the website's dev server is running, this will not automatically restart the server and you'll need to save a file within the site folder to trigger the restart.
-
Update the website scripts found in
./sites/*/package.json
files with the following:"scripts": { "dev": "basecms-website dev --compile-dir ../../packages --watch-dir ../../packages", "build": "basecms-website build", "compile": "basecms-marko-compile compile", "lint": "eslint --ext .js --ext .vue --max-warnings 5 --config ../../.eslintrc.js --ignore-path ../../.eslintignore ./", "lint:fix": "yarn lint --fix", "test": "yarn lint && yarn compile --no-clean" }
-
Update the package scripts found in
./packages/*/package.json
files with the following:"scripts": { "compile": "basecms-marko-compile compile", "build": "yarn compile", "lint": "eslint --ext .js --ext .vue --max-warnings 5 --config ../../.eslintrc.js --ignore-path ../../.eslintignore ./", "lint:fix": "yarn lint --fix", "test": "yarn lint && yarn compile --no-clean" },
-
Update the core/root scripts found in
./package.json
files with the following:"scripts": { "build": "lerna run build", "compile": "lerna run compile", "lint": "lerna run lint", "lint:fix": "lerna run lint:fix", "test": "lerna run test" }
-
The root
Dockerfile
will need updating to properly build the sites in production. Replace the contents of the file with the following:FROM node:14.21 as build WORKDIR /repo ARG SITE ADD package.json yarn.lock lerna.json /repo/ ADD packages /repo/packages ADD sites/$SITE /repo/sites/$SITE RUN --mount=type=cache,target=/repo/.yarn YARN_CACHE_FOLDER=/repo/.yarn yarn install --frozen-lockfile ENV NODE_ENV production RUN yarn build FROM node:14.21-alpine ENV NODE_ENV production ENV PORT 80 ARG SITE COPY --from=build /repo /repo WORKDIR /repo/sites/$SITE ENTRYPOINT [ "node", "index.js" ]
- This will run the
build
script found in each website (js/css/ssr/marko) and each package (compiles Marko files)
- This will run the
-
Verify that the sites in
docker-compose.yml
are usingyarn dev
as their entrypoint and command. Some sites run thebasecms-website
command directly. Replace thex-site-command
entry with the following:x-site-command: &site-cmd <<: *node entrypoint: ["yarn"] command: ["dev"]
Note: all of the below files are located in the .github/workflows
folder.
-
Create the
tests/integration.js
file in the root of the repository with the following contents// eslint-disable-next-line require('@parameter1/base-cms-marko-web/integration/test-website-boot');
-
Update the
node-ci.yml
file to the following:name: Node.js CI on: push: branches: ["*"] pull_request: branches: ["*"] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 14.21 - uses: actions/cache@v3 id: yarn-cache with: path: '**/node_modules' key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }} - name: Install dependencies if: steps.yarn-cache.outputs.cache-hit != 'true' run: yarn install --pure-lockfile - run: yarn test
-
Create the
integration-tests.yml
file with the contents below. NOTE you must update the site configs found within the comments to match the current reponame: Integration Tests on: push: branches: ["*"] pull_request: branches: ["*"] jobs: build-and-test-image: uses: parameter1/actions/.github/workflows/website-build-push-test.yml@main strategy: matrix: ############################################### #v# Make sure this matches the site matrix! #v# ############################################### tenant_key: [abmedia_all] image_prefix: [ab-media] site: - { id: 60f6ec0bd28860bc3384daa1, stack: virgon, host: athleticbusiness.com } - { id: 60f6ec3bd28860bc3384e784, stack: virgon, host: woodfloorbusiness.com } - { id: 60f6ec34d28860bc3384e447, stack: virgon, host: aquamagazine.com } ############################################### #^# Make sure this matches the site matrix! #^# ############################################### with: docker_image: website-${{ matrix.site.host }} site_id: ${{ matrix.site.id }} site_host: ${{ matrix.site.host }} infra_stack: ${{ matrix.site.stack }} tenant_key: ${{ matrix.tenant_key }} ecr_registry: ${{ vars.AWS_ECR_REGISTRY }}
-
Update the
deploy-staging.yml
file:name: Deploy sites (staging) on: push: tags: - '*' jobs: version: runs-on: ubuntu-latest steps: - id: tag_version run: | REF=$(echo $GITHUB_REF | cut -d / -f 3) [[ "$GITHUB_REF" =~ ^refs/tags.*$ ]] && VERSION="$REF" || VERSION="${REF}-${GITHUB_SHA::7}" echo "version=$VERSION" >> $GITHUB_OUTPUT outputs: version: ${{ steps.tag_version.outputs.version }} notify-start: needs: [version] uses: parameter1/actions/.github/workflows/notify-start.yml@main secrets: inherit with: version: ${{ needs.version.outputs.version }} post-deploy-failure: if: failure() needs: [notify-start, deploy-sites] uses: parameter1/actions/.github/workflows/notify-fail.yml@main secrets: inherit with: slack-thread: ${{ needs.notify-start.outputs.slack-thread }} post-deploy-complete: if: success() needs: [notify-start, deploy-sites] uses: parameter1/actions/.github/workflows/notify-complete.yml@main secrets: inherit with: slack-thread: ${{ needs.notify-start.outputs.slack-thread }} ###################### # Add websites here! # ###################### build-sites: needs: [version] uses: parameter1/actions/.github/workflows/website-build-push-test.yml@main strategy: matrix: ############################################### #v# Make sure this matches the site matrix! #v# ############################################### tenant_key: [abmedia_all] image_prefix: [ab-media] site: - { id: 60f6ec0bd28860bc3384daa1, stack: virgon, host: athleticbusiness.com } - { id: 60f6ec3bd28860bc3384e784, stack: virgon, host: woodfloorbusiness.com } - { id: 60f6ec34d28860bc3384e447, stack: virgon, host: aquamagazine.com } ############################################### #^# Make sure this matches the site matrix! #^# ############################################### with: ecr_registry: ${{ vars.AWS_ECR_REGISTRY }} docker_image: ${{ vars.AWS_ECR_REGISTRY }}/${{ matrix.image_prefix }}-${{ matrix.site.host }}:${{ needs.version.outputs.version }} site_id: ${{ matrix.site.id }} site_host: ${{ matrix.site.host }} infra_stack: ${{ matrix.site.stack }} tenant_key: ${{ matrix.tenant_key }} push: true secrets: inherit deploy-sites: needs: [version, build-sites] uses: parameter1/actions/.github/workflows/website-deploy-staging.yml@main strategy: matrix: ############################################### #v# Make sure this matches the site matrix! #v# ############################################### tenant_key: [abmedia_all] image_prefix: [ab-media] site: - { id: 60f6ec0bd28860bc3384daa1, stack: virgon, host: athleticbusiness.com } - { id: 60f6ec3bd28860bc3384e784, stack: virgon, host: woodfloorbusiness.com } - { id: 60f6ec34d28860bc3384e447, stack: virgon, host: aquamagazine.com } ############################################### #^# Make sure this matches the site matrix! #^# ############################################### with: docker_image: ${{ vars.AWS_ECR_REGISTRY }}/${{ matrix.image_prefix }}-${{ matrix.site.host }}:${{ needs.version.outputs.version }} infra_stack: ${{ matrix.site.stack }} rancher_label_key: basecms-website rancher_label_val: ${{ matrix.image_prefix }}-${{ matrix.site.host }} secrets: inherit
-
Update the
deploy-production.yml
file:name: Deploy sites (production) on: push: tags: - 'v[0-9]+.[0-9]+.[0-9]+' jobs: version: runs-on: ubuntu-latest steps: - id: tag_version run: | REF=$(echo $GITHUB_REF | cut -d / -f 3) [[ "$GITHUB_REF" =~ ^refs/tags.*$ ]] && VERSION="$REF" || VERSION="${REF}-${GITHUB_SHA::7}" echo "version=$VERSION" >> $GITHUB_OUTPUT outputs: version: ${{ steps.tag_version.outputs.version }} notify-start: needs: [version] uses: parameter1/actions/.github/workflows/notify-start.yml@main secrets: inherit with: version: ${{ needs.version.outputs.version }} post-deploy-failure: if: failure() needs: [notify-start, deploy-sites] uses: parameter1/actions/.github/workflows/notify-fail.yml@main secrets: inherit with: slack-thread: ${{ needs.notify-start.outputs.slack-thread }} post-deploy-complete: if: success() needs: [notify-start, deploy-sites] uses: parameter1/actions/.github/workflows/notify-complete.yml@main secrets: inherit with: slack-thread: ${{ needs.notify-start.outputs.slack-thread }} ###################### # Add websites here! # ###################### build-sites: needs: [version] uses: parameter1/actions/.github/workflows/website-build-push-test.yml@main strategy: matrix: ############################################### #v# Make sure this matches the site matrix! #v# ############################################### tenant_key: [abmedia_all] image_prefix: [ab-media] site: - { id: 60f6ec0bd28860bc3384daa1, stack: virgon, host: athleticbusiness.com } - { id: 60f6ec3bd28860bc3384e784, stack: virgon, host: woodfloorbusiness.com } - { id: 60f6ec34d28860bc3384e447, stack: virgon, host: aquamagazine.com } ############################################### #^# Make sure this matches the site matrix! #^# ############################################### with: ecr_registry: ${{ vars.AWS_ECR_REGISTRY }} docker_image: ${{ vars.AWS_ECR_REGISTRY }}/${{ matrix.image_prefix }}-${{ matrix.site.host }}:${{ needs.version.outputs.version }} site_id: ${{ matrix.site.id }} site_host: ${{ matrix.site.host }} infra_stack: ${{ matrix.site.stack }} tenant_key: ${{ matrix.tenant_key }} push: true secrets: inherit deploy-sites: needs: [version, build-sites] uses: parameter1/actions/.github/workflows/website-deploy-production.yml@main strategy: matrix: ############################################### #v# Make sure this matches the site matrix! #v# ############################################### tenant_key: [abmedia_all] image_prefix: [ab-media] site: - { id: 60f6ec0bd28860bc3384daa1, stack: virgon, host: athleticbusiness.com } - { id: 60f6ec3bd28860bc3384e784, stack: virgon, host: woodfloorbusiness.com } - { id: 60f6ec34d28860bc3384e447, stack: virgon, host: aquamagazine.com } ############################################### #^# Make sure this matches the site matrix! #^# ############################################### with: docker_image: ${{ vars.AWS_ECR_REGISTRY }}/${{ matrix.image_prefix }}-${{ matrix.site.host }}:${{ needs.version.outputs.version }} infra_stack: ${{ matrix.site.stack }} rancher_label_key: basecms-website rancher_label_val: ${{ matrix.image_prefix }}-${{ matrix.site.host }} secrets: inherit
Linting styles via stylelint
has been removed. The reasons are varied, but primarily version 10 is really old and the bootstrap config preset isn't well-supported anymore.
- Delete any
.stylelintrc.js
/.stylelintignore
files -- these are normally in the root of the repository, but ensure no other files exist in site or package folders. - Check to see if you have
stylelint
installed as a dependency by searching the project for"stylelint"
. If it appears in any of your project'spackage.json
files, please remove the dependency and re-run./scripts/yarn.sh
The internal eslint
version was upgrade from v5 to v8 -- quite a large jump -- and the supporting eslint-plugin-import
and eslint-config-airbnb-base
were also upgraded. As such, if you were relying on the eslint version provided by base-cms
(most likely), you'll need to update your code to fix any lint errors.
-
Install the
@parameter1/base-cms-eslint
wrapper package and the browserslist config in the monorepo root.- In the root
package.json
add or update the following devDependencies:
"@parameter1/base-cms-eslint": "^4.1.0", "@parameter1/browserslist-config-base-cms": "^4.1.0",
- You must remove all
babel-eslint
packages, since@babel/eslint-parser
is now used under the hood - Double-check your website and global package files and ensure there aren't any references to eslint or any of it's plugins - this way only the root version will be used.
- In the root
-
Add the shared
browserslist
config to the rootpackage.json
file:"browserslist": [ "extends @parameter1/browserslist-config-base-cms" ]
-
Update the
.eslintrc.js
found in the project root to use the common server config. Replace with:module.exports = require('@parameter1/base-cms-eslint/eslintrc.server');
-
Update the root
eslint.browser.js
file to use the common browser config. Replace with:// eslint-disable-next-line module.exports = require('@parameter1/base-cms-eslint/eslintrc.browser');
-
Because the new version of the vue plugin can support Vue3, we should also instruct any plugins as to our target Vue version. In the root of the repo create a
jsconfig.json
(if it doesn't exist) and add:{ "vueCompilerOptions": { "target": 2.7 } }
-
Once the new devDependencies are added, run
./scripts/yarn.sh
-
Restart VSCode (via
Cmd+Q
) so the new eslint library will load -
Open to Docker terminal via
./scripts/terminal.sh
and then runyarn lint:fix
from the root. This will attempt to fix lint errors automatically. If the lint fixer does encounter errors, you'll need to manually fix those, then runyarn lint:fix
again.
- Once all of the tasks above have been completed, run
./scripts/yarn.sh upgrade
to ensure all semver versions get normalized. - Run
yarn compile
from the project root to re-compile all marko templates- All marko files are compiled during testing. As such, if any components/templates contain references to missing components, you'll need to fix those errors before the tests will pass. For example, some sites had
spec-guide
templates pasted in from other repos that aren't actively used, etc.
- All marko files are compiled during testing. As such, if any components/templates contain references to missing components, you'll need to fix those errors before the tests will pass. For example, some sites had
- Run
yarn test
from the project root to ensure tests pass - Then start a website container and ensure it builds, boots, and serves.
Tested inside Docker container on Mac using example website.
- Initial boot
- Legacy: ~1 minute
- New: ~40 seconds
- Restart time after save of marko file
- Legacy: ~34 seconds
- New: ~9 seconds
- Restart time after save of browser JS file
- Legacy: ~32 seconds
- New: ~2 seconds
- Restart time after save of SSR file
- Legacy: ~30 seconds
- New: ~4 seconds
- Restart time after save of SCSS file
- Legacy: ~32 seconds
- New: ~3 seconds
- Legacy: ~34 seconds
- New: ~57 seconds
- this will be much faster in an actual website, since the example site needs to delete and re-compile all marko templates in the entire base-cms repo, which wouldn't happen in a site repo.