vite ⚡
No-bundle Dev Server for Vue 3 Single-File Components.
Getting Started
$ npx create-vite-app <project-name>
$ cd <project-name>
$ npm install
$ npm run dev
If using Yarn:
$ yarn create vite-app <project-name>
$ cd <project-name>
$ yarn
$ yarn dev
How is This Different from a Bundler-based Setup?
The primary difference is that for vite
there is no bundling during development. The ES Import syntax in your source code is served directly to the browser, and the browser parses them via native <script module>
support, making HTTP requests for each import. The dev server intercepts the requests and performs code transforms if necessary. For example, an import to a *.vue
file is compiled on the fly right before it's sent back to the browser.
There are a few advantages of this approach:
-
Since there is no bundling work to be done, the server cold start is extremely fast.
-
Code is compiled on demand, so only code actually imported on the current screen is compiled. You don't have to wait until your entire app to be bundled to start developing. This can be a huge difference in apps with dozens of screens.
-
Hot module replacement (HMR) performance is decoupled from the total number of modules. This makes HMR consistently fast no matter how big your app is.
Full page reload could be slightly slower than a bundler-based setup, since native ES imports result in network waterfalls with deep import chains. However since this is local development, the difference should be trivial compared to actual compilation time. (There is no compile cost on page reload since already compiled files are cached in memory.)
Finally, because compilation is still done in Node, it can technically support any code transforms a bundler can, and nothing prevents you from eventually bundling the code for production. In fact, vite
provides a vite build
command to do exactly that so the app doesn't suffer from network waterfall in production.
vite
is highly experimental at this stage and is not suitable for production use, but we hope to one day make it so.
Features
Bare Module Resolving
Native ES imports doesn't support bare module imports like
import { createApp } from 'vue'
The above will throw an error by default. vite
detects such bare module imports in all served .js
files and rewrite them with special paths like /@modules/vue
. Under these special paths, vite
performs module resolution to locate the correct files on disk:
-
vue
has special handling: you don't need to install it sincevite
will serve it by default. But if you want to use a specific version ofvue
(only supports Vue 3.x), you can installvue
locally intonode_modules
and it will be preferred (@vue/compiler-sfc
of the same version will also need to be installed). -
If a
web_modules
directory (generated by Snowpack)is present, we will try to locate the module it. -
Finally we will try resolving the module from
node_modules
, using the package'smodule
entry if available.
Hot Module Replacement
-
*.vue
files come with HMR out of the box. -
For
*.js
files, a simple HMR API is provided:import { foo } from './foo.js' import { hot } from '@hmr' foo() hot.accept('./foo.js', ({ foo }) => { // the callback receives the updated './foo.js' module foo() })
Note it's simplified and not fully compatible with webpack's HMR API, for example there is no self-accepting modules, and if you re-export
foo
from this file, it won't reflect changes in modules that import this file.
CSS Pre-Processors
Install the corresponding pre-processor and just use it!
yarn add -D sass
<style lang="scss">
/* use scss */
</style>
Note importing CSS / preprocessor files from .js
files, and HMR from imported pre-proccessor files are currently not supported, but can be in the future.
Building for Production
Starting with version ^0.5.0
, you can run vite build
to bundle the app and deploy it for production.
-
vite build --root dir
: build files in the target directory instead of current working directory. -
vite build --cdn
: importvue
from a CDN link in the built js. This will make the build faster, but overall the page payload will be larger because therer will be no tree-shaking for Vue APIs.
Internally, we use a highly opinionated Rollup config to generate the build. The build is configurable by passing on most options to Rollup - check out src/node/build.ts
for more details.
API
You can customize the server using the API. The server can accept plugins which have access to the internal Koa app instance. You can then add custom Koa middlewares to add pre-processor support:
const { createServer } = require('vite')
const myPlugin = ({
root, // project root directory, absolute path
app, // Koa app instance
server, // raw http server instance
watcher // chokidar file watcher instance
}) => {
app.use(async (ctx, next) => {
// You can do pre-processing here - this will be the raw incoming requests
// before vite touches it.
if (ctx.path.endsWith('.scss')) {
// Note vue <style lang="xxx"> are supported by
// default as long as the corresponding pre-processor is installed, so this
// only applies to <link ref="stylesheet" href="*.scss"> or js imports like
// `import '*.scss'`.
console.log('pre processing: ', ctx.url)
ctx.type = 'css'
ctx.body = 'body { border: 1px solid red }'
}
// ...wait for vite to do built-in transforms
await next()
// Post processing before the content is served. Note this includes parts
// compiled from `*.vue` files, where <template> and <script> are served as
// `application/javascript` and <style> are served as `text/css`.
if (ctx.response.is('js')) {
console.log('post processing: ', ctx.url)
console.log(ctx.body) // can be string or Readable stream
}
})
}
createServer({
plugins: [
myPlugin
]
}).listen(3000)
TODOs
- Source Map support
- Auto loading postcss config
Trivia
vite is the french word for "fast" and is pronounced /vit/
.
License
MIT