vue-dummy-mono-repo
This is a sample boilerplate monorepo for a collection of Vue components that you intend to publish to the NPM registry. To some extent, each individual component structure is based on the vue-dummy-published-component setup - and then adjusted to work in this monorepo setup with Lerna.
If you wish to only publish a single component, you are better off using vue-dummy-published-component.
Credits
Much of the baseline for this work comes from:
- The Packaging Vue Components for npm entry in the Vue Cookbook
- The associated vue-sfc-rollup GitHub repo
What's Included in this Boilerplate?
This adds a few new features that you mind useful when creating robust open-source Vue components (all of which you are welcome to change once your fork for your own purposes):
- Code linting via
eslint
- Leverages the AirBnb ESLint Config via the
eslint-config-airbnb-base
plugin - Adds the
eslint-plugin-vue
plugin with the "recommended" settings - Configured via
.eslintrc.js
- Leverages the AirBnb ESLint Config via the
- Unit testing via
jest
and@vue/test-utils
- Configured via
jest.config.js
- Tests located in the
test/unit
directories of components
- Configured via
- Storybook Generation
- Configured via the
.storybook
directories of components - Stories located in the
stories
directories of components
- Configured via the
- End-to-End tests with
cypress
that run on top of your generated Storybook- This is a pattern I haven't seen before that makes a lot of sense to me. Storybook is intended to show off the various usages of your components - so why not write integration tests to ensure those usages are working as expected?
- Configured in
cypress.json
- Tests located in the
tests/e2e
directories of components
- Precommit hook using
husky
to lint and test the component
MonoRepo Setup
This was my first time playing with Lerna, so there is always room for improvement, but I attempted to hoist as much to the root as possible to reduce duplication amongst leaf component packages.
- All
devDependencies
live at the rootpackage.json
- Component
devDependencies
that are directly used in component npm scripts are listed withfile:
specifiers pointing up to the root - For this reason, it should never be required to run
lerna bootstrap
or deal withpackage-lock.json
files in components- If your components have
dependencies
, then this may not work quite right for you. There's a good discussion in this lerna issue that might be useful.
- If your components have
- Linting and Unit testing is done solely from the root, since there's nothing inherently component-specific about those. There are no
npm run lint
ornpm run test:unit
commands in components. - Storybook building and Cypress E2E tests must still be implemented at the component level because they require component-specific setups. They are executed from the root using
lerna exec
- Cypress requires a local
cypress.json
file, so the file lives at the root and is symlinked into each sub-package - Storybook didn't seem to like using
--config
to point to../../.storybook
, nor did it seem to like the symlink approach, so each sub-package has it's own.storybook
directory
- Cypress requires a local
- A single
rollup.config.js
is used from the root for all components, which loads component-specific info from the componentpackage.json
file
Getting Started
To get started with your own publishable components via a monorepo, I would start by copying this to your own new repo and then there's a few changes to make as well as some things to add that have been intentionally left out.
Things to Change
- Update all relevant
package.json
fields (name
,author
,repository
, etc.) - Modify the exported component names in the
package.json
rollup
field - which is deep-merged onto the shared rollup config. - Write your components, unit tests, stories, and E2E Tests!
- Update the LICENSE.md with the proper license and attribution
Things to Add
- Add some docs for how users can file issues and contribute back to your open-source components. Check out the Mozilla Science Lab Post for ideas and examples
- Don't forget to host your Storybooks somewhere so users can access it. gitHub Pages is one potential solution.
Usage
# Build all components
npx lerna run build
# Run unit tests
npm run test:unit
# Build all storybooks
npm run storybook:build
# Run all E2E Tests against built Storybooks
npm run test:e2e
Publishing to NPM
Please refer to the NPM documentation and the Lerna Documentation