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.xand 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/base-cms-dependency-tool@v4.1.0
-
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_modulesfoldersfind . -name 'node_modules' -type d -prune -exec rm -rf '{}' +
-
References to
node:10images (specifically,node:10.24) should be changed tonode:14.21in all files nameddocker-compose.ymlDockerfile
-
If GitHub actions are used by the repo, the
node-versionvalue must be changed to14.21in the.github/workflows/node-ci.ymlfile. If TravisCI is still used, check the.travisfile in the root of the project and update the node version.
- Upgrade
lernato the latest major version in your rootpackage.jsonfile"lerna": "^6.5.1"
- Upgrade
newrelicto the latest major version whereever present in yourpackage.jsonfiles - usually in thepackages/globalpackage."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 installyet. We'll save that to the very end. :) -
Delete references to
@babel/*dependencies in theyarn.lockfile. 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
@importdeclarations in.scssfiles 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
.scssfiles 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-migratorand then runsass-migrator division **/*.scssfrom 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.markofile.
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-cleanIf 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.jsonfiles 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.jsonfiles 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.jsonfiles 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
Dockerfilewill 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
buildscript 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.ymlare usingyarn devas their entrypoint and command. Some sites run thebasecms-websitecommand directly. Replace thex-site-commandentry 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.jsfile 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.ymlfile 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.ymlfile 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.ymlfile: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.ymlfile: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/.stylelintignorefiles -- 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
stylelintinstalled as a dependency by searching the project for"stylelint". If it appears in any of your project'spackage.jsonfiles, 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-eslintwrapper package and the browserslist config in the monorepo root.- In the root
package.jsonadd 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-eslintpackages, since@babel/eslint-parseris 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
browserslistconfig to the rootpackage.jsonfile:"browserslist": [ "extends @parameter1/browserslist-config-base-cms" ]
-
Update the
.eslintrc.jsfound 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.jsfile 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.shand then runyarn lint:fixfrom 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:fixagain.
- Once all of the tasks above have been completed, run
./scripts/yarn.sh upgradeto ensure all semver versions get normalized. - Run
yarn compilefrom 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-guidetemplates 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 testfrom 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.