Frontend-base development with yalc

Frontend-base development with yalc

As an alternative to the npm pack => npm install *.tgz development flow, one can use the yalc command to automate the process. The end result is the same - dependency resolution that is as similar to production-use as possible - but with little cognitive load and optimized system resource consumption.

Start by installing this fork of yalc locally, as the original doesn’t have the --peer feature we need (plus, it hasn’t been maintained in a while):

npm i -g @arbrandes/yalc

The frontend-base repo

Publish the version of frontend-base you’re developing to the local “npm” repository:

cd frontend-base yalc publish

App repositories

In app repos, yalc-add the local version of frontend-base before running npm i. This is so any updated frontend-base dependencies are properly installed. We also use the --peer flag because @openedx/frontend-base is a peer dependency in app packages (remember, we want to keep this as close to production as possible):

cd ../frontend-app-authn yalc add --peer @openedx/frontend-base rm -fr package-lock.json node_modules npm i

If you’re just developing this app, go ahead and run it in dev mode:

npm run dev

Publishing apps you’re also developing

If instead of running the app in dev mode you want to develop it against a frontend-template-site fork, there’s more to consider:

Running yalc add is much like npm-installing a tarball: both package.json and package-lock.json are modified to point to a local directory. This is a good thing, as it’s what allows npm i to install the added package’s latest dependency requirements.

However, if you’re also publishing the app for downstream development, you don’t want to have a file: dependency in the app’s package.json, as this will break npm resolution (and deduplication) in consumers. Which is to say, after running npm i you’ll want to revert the package-*.json files to a pristine state. Luckily, you can do so while still benefitting from subsequent yalc publish --pushes by:

git checkout package-*.json yalc link @openedx/frontend-base

This way, running yalc update locally - or a yalc publish --push from frontend-base - will still update the app accordingly, including binary files. And, of course, you’re also free to publish the app itself at any time:

yalc publish

Site repository

To develop the site (presumably a fork of frontend-template-site) we can also yalc add the libraries. But since we're not concerned about changes to package.json files (we won’t be publishing the site as a library!), we don't bother yalc-linking them afterwards. We also don’t need to --peer them, as they’re straight dependencies:

cd ../frontend-template-site yalc add \ @openeds/frontend-base \ @openedx/frontend-app-authn \ @openedx/frontend-app-learner-dashboard #... rm -fr package-lock.json node_modules npm i npm run dev

Propagating changes

Whenever you make a change to one of the yalc-published libraries, run yalc publish --push from their corresponding repositories. This will automagically update all repos that npm-added that library, so that if they’re running npm run dev, Webpack will pick up the changes without a manual reload.

Having to do that manually is not very productive, though. Here's a oneliner that does the publishing automatically when source files are changed in frontend-base. It overrides the exec line from the existing nodemon.pack.json configuration. Run this from a terminal window inside the frontend-base directory:

npm run pack:watch -- --exec yalc publish --push

And one for apps. It’s longer because apps don’t yet ship a pack:watch script:

npx nodemon --delay 1 --watch src -e js,ts,jsx,tsx,scss --exec yalc publish --push

To paint a clear picture: if you’re developing frontend-base, two apps, and using a frontend site to view changes, you’re going to need four terminal windows. Three running nodemon watchers as described above, and the last one regular npm run dev:

  • frontend-base: npm run pack:watch …

  • frontend-app-authn: npx nodemon …

  • frontend-app-learner-dashboard: npx nodemon …

  • frontend-template-site: npm run dev