Voie is a vite plugin which enables file system based routing for Vue 3 applications.
- File system based routing
- Code splitting and async components by default
Install Voie:
$ npm install vite-plugin-voie
Note: vue-router@4.0.0 is a peer dependency
Add to your vite.config.js
:
import voie from 'vite-plugin-voie';
export default {
plugins: [voie()],
};
When using Voie, a page is a Vue component exported from a .vue
or .js
file in the src/pages
directory.
The routes configuration will be exported from the voie-pages
module. Import this module and add it to your Vue Router configuration:
import { createRouter } from 'vue-router';
import routes from 'voie-pages';
const router = createRouter({
// ...
routes,
});
Note: TypeScript users can install type definitions for the generated routes via the voie-pages package:
$ npm install --save-dev voie-pages
Voie supports some configuration options in case your environment doesn't match the defaults.
interface UserOptions {
pagesDir?: string;
extensions?: string[];
importMode?: ImportMode | ImportModeResolveFn;
}
Relative path to the pages directory
Default: 'src/pages'
Array of valid extensions for pages
Default: ['vue', 'js']
A string or function that returns a string which represents whether routes should be loaded synchronously or asynchronously.
Default: 'async'
To get more fine-grained control over which routes are loaded sync/async, you can use a function to resolve the value based on the route path. For example:
// vite.config.js
export default {
// ...
plugins: [
voie({
importMode(path) {
// Load index synchronously, all other pages are async.
return path.includes('index') ? 'sync' : 'async';
},
}),
],
};
To use custom configuration, pass your options to Voie when creating the plugin:
// vite.config.js
import voie from 'vite-plugin-voie';
export default {
plugins: [
voie({
pagesDir: 'src/views',
extensions: ['vue', 'ts'],
}),
],
};
Voie's routing is inspired by NuxtJS, and so you can expect similar features with some small differences.
Voie will automatically map files named index
to the root of the directory:
src/pages/index.vue
->/
src/pages/users/index.vue
->/users
A nested folder structure will result in nested routes, making use of Vue Router's child routes:
src/pages/users/one.vue
->/users/one
src/pages/dashboard/settings/profile.vue
->/dashboard/settings/profile
You can effectively create layout pages by naming a page with the same name as the directory that contains its children pages:
This directory structure:
src/pages/
├── users/
│ ├── [id].vue
│ └── index.vue
└── users.vue
will result in this routes configuration:
[
{
path: '/users',
component: '/src/pages/users.vue',
children: [
{
path: '',
component: '/src/pages/users/index.vue',
name: 'users',
},
{
path: ':id',
component: '/src/pages/users/[id].vue',
name: 'users-id',
},
],
},
];
Dynamic routes are denoted using square brackets. Directories and pages can be dynamic:
src/pages/users/[id].vue
->/users/:id
(/users/one
)src/[user]/settings.vue
->/:user/settings
(/one/settings
)
Catch-all routes are denoted with square brackets containing an ellipsis:
src/pages/[...all].vue
->/*
(/non-existent-page
)
The text after the ellipsis will be used both to name the route, and as the name of the prop in which the route parameters are passed.
Many thanks go to @antfu for their support of this project.
voie is the french word for "way" and is pronounced /vwa/
.