Project template for Vue.js 2.7 component library
- 📦 PNPM for package management
- ⚡ Vite for library build
- 🧪 Vitest and Vue Testing Library for unit testing
- 📕 Storybook for component presentation
- 🔥 Rendering smoke tests for Storybook stories
- 👀 Visual regression tests for Storybook stories
- ♿ Accessibility tests for Storybook stories
- ✅ TypeScript for static type checking
- 🔬 ESLint for static code analysis
- 💅 Prettier for code formatting
- 🚢 Changesets for release management
As a prerequisite make sure you have installed the following software.
Follow these steps to preview components in Storybook.
-
Install dependencies for all workspaces. Run this command in project root:
pnpm install
-
Start development mode. Run this command in project root:
pnpm dev
This will build the component library first and then start Storybook in development mode.
It should open your browser automatically. Or you can visit http://localhost:6006 manually.
Run the following command in project root to create production builds for both the library and Storybook.
pnpm build
Each workspace will have its distribution output in dist
subdirectory.
Run the following command in project root to lint source code in all workspaces.
pnpm lint
Make sure either Storybook is running in development mode or a web server is hosting production build on http://localhost:6006. Then run the following command in project root to start automated tests.
pnpm test:run
Run unit tests of component library only by executing the command in components
subdirectory.
Run the following command to perform quality checks and production builds all at once.
pnpm ci
This will execute the following steps and bail if any of them does not succeed.
- Lint source code in all workspaces
- Type-check library source code
- Run library unit tests
- Perform library production build
- Perform Storybook production build
- Start web server hosting Storybook distribution
- Run smoke tests, visual regression tests und accessibility tests for Storybook in parallel
- Stop web server
For each new feature or bugfix developers should add changesets by running the following command in project root.
pnpm changeset
It will ask some questions which workspaces have been changed and generate a Markdown file for each change in .changeset
subdirectory.
To release a stable version perform the following steps.
-
Bump package versions and update changelog files by running the following command in project root.
pnpm prepare:release
-
Install dependencies and update lockfile (see details in PNPM docs).
pnpm install
-
Commit all updated files to Git.
-
Perform production build by running the following command in project root.
pnpm ci
-
If build succeeds publish release by running the following command in project root.
pnpm publish:release
-
Push Git tags created for release.
git push --follow-tags
Snapshot releases can be published the same way as described above but instead of pnpm prepare:release
and pnpm publish:release
run the following commands.
pnpm prepare:snapshot
pnpm publish:snapshot
This will include timestamps in bumped versions and publish packages with dist-tag next
instead of latest
.
Library build generates a main module with exports of all components and separate submodules for each individual component. This code splitting allows bundlers like Webpack and rollup.js to perform build optimizations in applications:
- Each component can be bundled in the JavaScript chunk where it makes sense depending on its usage (see diagram below).
- Unused components are eliminated from application code.
Applications can either use static imports from the main module...
// Only used exports will be included in application bundle.
import { ActionButton } from 'vue-library-template-components';
Or they can use dynamic imports from specific submodules as needed.
// Only requested component module will be included in application bundle.
import('vue-library-template-components/dist/components/VideoPlayer').then(
({ VideoPlayer }) => VideoPlayer
);
Note: Dynamic imports should always use specific component submodules because they cannot benefit from tree-shaking.
Components have different options to contribute styles.
<style>
block in the component file. This will be bundled instyle.css
.- Plain CSS file import in
<script>
block:import 'other-styles.css';
. This will be bundled instyle.css
. - Client-side style injection in
<script>
block (see below). This embeds CSS code in component module itself rather than bundling it instyle.css
.
Components requiring extensive CSS code should import non-critical stylesheets using ?inline
suffix and inject the code using style-inject
helper.
import styleInject from 'style-inject';
import videojsStylesheet from 'video.js/dist/video-js.min.css?inline';
styleInject(videojsStylesheet);
Note: Style injection is performed client-side once the component module is loaded. If the component is rendered server-side this can result in a flash of unstyled content (FOUC) on page load.
Library build generates TypeScript declaration files for components using vue-tsc
. This enables JSDoc and type checking for component props in applications.
The generic utility type StoryArgs
defined in storybook/stories/types.ts
can be used to derive a type for story args based on Vue component type declaration. It picks prop types automatically and allows definition of additional args properties. This enables at least basic type safety for story args. For example, it yields an error when attempting to set args which are not specified (or derived from component's props).
StoryShots addon with Puppeteer integration is installed to implement these additional tests.
It runs image snapshot tests for each story using jest-image-snapshot
.
It runs accessibility tests using Axe and jest-puppeteer-axe
.
Changesets are one solution for semantic version management in mono-repos. It works independent from Git by saving special Markdown files in .changeset
subdirectory. Configuration file in this project template is set up to keep version of library and Storybook packages in sync.
MIT