Petite is an opinionated GitHub template built for Vue component authors. It sets up the tooling required to develop, document, and test Universal SFC Components that are backwards-compatible with the Vue 2.7 runtime.
This is accomplished with some runtime helpers and a very opinionated monorepo structure.
Petite sets up Vite, Volar, Linting, Vitepress, TypeScript, and Testing so that you can choose to write Vue 3-style code while easily maintaining backwards compatibility for your Vue 2.x users. 👏👏
Build + Compile
- Vue 2.7 + Vue 3 w/ Script Setup
- Volar support for Vue 2.7 and Vue 3
- TypeScript
- Ship d.ts files for each source file
- Ship global types via
dist/components.d.ts
for your users (viaunplugin-vue-components
)
- pnpm workspaces + monorepo
- Vite
Lint
- Eslint and prettier
- Lint pre-commit and on save
Document
- Documentation Site via Vitepress
- netlify.toml
- Type-gen documentation (see Faker's Vitepress config)
Test and Run
- Component Testing via Cypress for headed components
- Fix HMR for Vue 2 (Cypress isn't watching symlinks?)
- Unit Testing via Vitest for headless components and logic
- Stories via Histoire
- netlify.toml
- Cypress End-to-end example
Tooling + README
- GitHub integration
- GitHub actions
- Issue templates
- Fancy README Badges
Style
- SCSS
- UnoCSS
- CSS-only Icons via Iconify
It is possible to write universal Vue SFC components that work for Vue 2 and Vue 3; however, setting up the tooling required to develop, lint, compile, test, and deploy these libraries can be painful and there are often conflicts between versions.
Most Vue library authors:
- Use vue-demi for headless components
- Only choose Vue 3 when writing renderable components
- Painstakingly backport Vue 3 features to Vue 2 user
Petite gives you a GitHub template that works out-of-the-box with all of the modern tooling you'd like to use, and asks you to make few concessions on how you write your code.
- Grab Petite, either via GitHub's "Use Template" button or
degit
.
npx degit JessicaSachs/petite your-project-name
- Install pnpm if you don't have it.
pnpm install
- Change all references to
@petite/lib-vue2
and@petite/lib-vue3
to your library's name. - Optionally rename the folders, as well.
pnpm dev:3
Vite suggests that library authors re-use their index.html
as a sort of playground and ship that as a website. This can be helpful for getting started, but it's sometimes not enough.
Petite has a couple of tools that it ships with that can help library authors develop quickly and deliver well-tested libraries.
- Component-driven development with Cypress.
- Docs-driven development with Vitepress.
- Vite's own
index.html
, which can then be End-to-end tested.
When writing Universal SFC Components, any reactivity caveats to objects and arrays will still apply. Please ensure that you abide by the rules in the Reactivity section of the Vue 2 docs.
Petite ships with Antfu's eslint config (no-semis, trailing commas) and prettier.
- Lints on save (VSCode)
- Lints markdown, tsx, vue, ts, and more.
- Lints before commit using
lint-staged
andsimple-git-hooks
Rather than break on a major version to support Vue 2 or Vue 3, you will ship two versions of your package on npm.
The downside of this is that your users will need to install a new version when they upgrade and change their imports. The upside is that it is much easier for you to write backwards compatible code and provide regular upgrades for your users. Additionally, you are able to split out your Vue 2-only and Vue 3-only dependencies.
If you use lodash
in your universal code, you'll want to
After you run pnpm build
in the workspace root, each package (lib-vue3
, lib-vue2
) should be deployed independently.
Petite supports both Atomic CSS frameworks such as UnoCSS, Tailwind, and WindiCSS. It comes with UnoCSS and a style reset.
Petite comes with sass
installed and will export your styles, minified, to dist/styles.css
for your users to manually install at the top of their main.ts
.
If you prefer an atomic style framework, such as UnoCSS or Tailwind... you're in luck!
Petite supports these as normal Vite plugins. Just add their relevant configurations to vite.config.shared.ts
at the root of the workspace using pnpm install unocss -D -w
(or the Tailwind equivalent) and then follow the setup instructions.
Petite provides no ability to extend the themes of your Atomic CSS libraries. This is out-of-scope for Petite, whose purpose is to give you a build configuration that will give you an environment to build + test + publish Vue 2 + Vue 3 compatible libraries.
If you would like to provide your users with the ability to extend your CSS either at runtime or build time, consider using vanilla CSS variables or other runtime solutions.
Petite ships with Unit Testing via Vitest and Component Testing via Cypress. Both of them re-use your Vite config and Vite dev server.
In any of the libraries, or the workspace root you are able to run a test command. Simply append --watch
if you'd like to re-run your tests on change.
pnpm test:unit
Unit testing support is provided by Vitest and, like Cypress, will re-use each application's build configuration. This means that if you do something that would break Vue 2 or Vue 3 only, your tests will catch it.
Petite's development ethos is centered around the belief that library code should be developed in the environment that users will consume it in. For components that render, Petite uses Cypress Component Testing.
Cypress is a thorough way to accomplish component testing and isolated component development in one tool.
TODO: Petite aspires to use Histoire which you could use as an isolated sandbox and then point an end-to-end testing tool at. Histoire is a Vite-based Storybook replacement and is developed by Vue Core Team Member, Akyrum.
This is not implemented. If your library requires a lot of app-level dependencies or setup before users can use your library, you may consider writing End-to-end tests that test the integration of your user's JS, any HTML, and any styles you expect them to write before loading and using your library code.
Cypress is already installed and has linting and types already set up, however you'll have to start and run an example playground app yourself.
Here are some approaches to end-to-end testing your library code.
- Run
pnpm build
- Use Vite's
index.html
and import the files directly using module syntax - Run Cypress to test the example usage
<!-- index.html -->
<html>
<body>
<div id="vue3" />
</body>
<script type="module">
// import [email protected], [email protected], or Vue@3 from jsdelivr or your own local dependencies
// Alias Vue 3, Vue 2.6, and Vue 2.7 in your root package.json
import { createApp } from "vue3";
import "./packages/lib-vue3/dist/style.css";
const Petite = await import("./packages/lib-vue3/dist/main.ts");
const { Counter } = Petite;
createApp(Counter).mount("#app");
</script>
</html>
A more complex integration testing architecture allows you to test that any integrated Vite changes are working as expected. E.g. if you're writing a Vite plugin with virtual modules, etc... this is a viable strategy.
Create the test applications
- Create test workspaces with their own Vite config files
- Create fully-formed applications within them
- Use pnpm's
workspace
notation to import the package's dist'd files.
Run your E2E tests At the workspace root...
- Run
pnpm build
at the workspace root - Start up each workspace's Vite server (
vite preview
orvite dev
) - Once the server is started, begin executing your End-to-end tests.
pnpm run docs
All good libraries have documentation. Petite uses Vitepress for its documentation.
Inspired by the following repositories:
Big thanks to Anthony Fu (@antfu) for the templates and resources and Thorsten Lünborg (@LinusBorg) for answering questions and walking me through Vue Bridge.