vite/docs/guide/build.md

231 lines
8.8 KiB
Markdown
Raw Normal View History

2021-01-01 21:40:16 +00:00
# Building for Production
2021-03-15 08:52:01 +00:00
When it is time to deploy your app for production, simply run the `vite build` command. By default, it uses `<root>/index.html` as the build entry point, and produces an application bundle that is suitable to be served over a static hosting service. Check out the [Deploying a Static Site](./static-deploy) for guides about popular services.
2021-01-01 21:40:16 +00:00
## Browser Compatibility
The production bundle assumes support for modern JavaScript. By default, Vite targets browsers which support the [native ES Modules](https://caniuse.com/es6-module) and [native ESM dynamic import](https://caniuse.com/es6-module-dynamic-import) and [`import.meta`](https://caniuse.com/mdn-javascript_statements_import_meta):
- Chrome >=87
- Firefox >=78
- Safari >=13
- Edge >=88
2022-06-19 09:12:59 +00:00
You can specify custom targets via the [`build.target` config option](/config/build-options.md#build-target), where the lowest target is `es2015`.
2021-01-09 02:54:22 +00:00
Note that by default, Vite only handles syntax transforms and **does not cover polyfills by default**. You can check out [Polyfill.io](https://polyfill.io/v3/) which is a service that automatically generates polyfill bundles based on the user's browser UserAgent string.
2021-01-01 21:40:16 +00:00
2021-01-09 02:54:22 +00:00
Legacy browsers can be supported via [@vitejs/plugin-legacy](https://github.com/vitejs/vite/tree/main/packages/plugin-legacy), which will automatically generate legacy chunks and corresponding ES language feature polyfills. The legacy chunks are conditionally loaded only in browsers that do not have native ESM support.
2021-01-01 21:40:16 +00:00
## Public Base Path
- Related: [Asset Handling](./assets)
2021-01-01 21:40:16 +00:00
2022-06-19 09:12:59 +00:00
If you are deploying your project under a nested public path, simply specify the [`base` config option](/config/shared-options.md#base) and all asset paths will be rewritten accordingly. This option can also be specified as a command line flag, e.g. `vite build --base=/my/public/path/`.
2021-01-01 21:40:16 +00:00
JS-imported asset URLs, CSS `url()` references, and asset references in your `.html` files are all automatically adjusted to respect this option during build.
The exception is when you need to dynamically concatenate URLs on the fly. In this case, you can use the globally injected `import.meta.env.BASE_URL` variable which will be the public base path. Note this variable is statically replaced during build so it must appear exactly as-is (i.e. `import.meta.env['BASE_URL']` won't work).
For advanced base path control, check out [Advanced Base Options](#advanced-base-options).
2021-01-01 21:40:16 +00:00
## Customizing the Build
2022-06-19 09:12:59 +00:00
The build can be customized via various [build config options](/config/build-options.md). Specifically, you can directly adjust the underlying [Rollup options](https://rollupjs.org/guide/en/#big-list-of-options) via `build.rollupOptions`:
2021-01-01 21:40:16 +00:00
```js
// vite.config.js
2022-07-08 09:05:58 +00:00
export default defineConfig({
2021-01-01 21:40:16 +00:00
build: {
rollupOptions: {
// https://rollupjs.org/guide/en/#big-list-of-options
}
}
2021-07-27 15:00:51 +00:00
})
2021-01-01 21:40:16 +00:00
```
For example, you can specify multiple Rollup outputs with plugins that are only applied during build.
2021-01-01 21:40:16 +00:00
## Chunking Strategy
You can configure how chunks are split using `build.rollupOptions.output.manualChunks` (see [Rollup docs](https://rollupjs.org/guide/en/#outputmanualchunks)). Until Vite 2.8, the default chunking strategy divided the chunks into `index` and `vendor`. It is a good strategy for some SPAs, but it is hard to provide a general solution for every Vite target use case. From Vite 2.9, `manualChunks` is no longer modified by default. You can continue to use the Split Vendor Chunk strategy by adding the `splitVendorChunkPlugin` in your config file:
```js
// vite.config.js
import { splitVendorChunkPlugin } from 'vite'
2022-07-08 09:05:58 +00:00
export default defineConfig({
plugins: [splitVendorChunkPlugin()]
})
```
This strategy is also provided as a `splitVendorChunk({ cache: SplitVendorChunkCache })` factory, in case composition with custom logic is needed. `cache.reset()` needs to be called at `buildStart` for build watch mode to work correctly in this case.
## Rebuild on files changes
You can enable rollup watcher with `vite build --watch`. Or, you can directly adjust the underlying [`WatcherOptions`](https://rollupjs.org/guide/en/#watch-options) via `build.watch`:
```js
// vite.config.js
2022-07-08 09:05:58 +00:00
export default defineConfig({
build: {
watch: {
// https://rollupjs.org/guide/en/#watch-options
}
}
2021-07-27 15:00:51 +00:00
})
```
With the `--watch` flag enabled, changes to the `vite.config.js`, as well as any files to be bundled, will trigger a rebuild.
2021-01-01 21:40:16 +00:00
## Multi-Page App
Suppose you have the following source code structure:
```
├── package.json
├── vite.config.js
├── index.html
├── main.js
└── nested
├── index.html
└── nested.js
2021-01-01 21:40:16 +00:00
```
During dev, simply navigate or link to `/nested/` - it works as expected, just like for a normal static file server.
During build, all you need to do is to specify multiple `.html` files as entry points:
```js
// vite.config.js
2022-07-08 09:05:58 +00:00
import { resolve } from 'path'
import { defineConfig } from 'vite'
2021-01-01 21:40:16 +00:00
2022-07-08 09:05:58 +00:00
export default defineConfig({
2021-01-01 21:40:16 +00:00
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
nested: resolve(__dirname, 'nested/index.html')
}
}
}
2021-07-27 15:00:51 +00:00
})
2021-01-01 21:40:16 +00:00
```
2021-06-01 08:45:38 +00:00
If you specify a different root, remember that `__dirname` will still be the folder of your vite.config.js file when resolving the input paths. Therefore, you will need to add your `root` entry to the arguments for `resolve`.
2021-01-01 21:40:16 +00:00
## Library Mode
When you are developing a browser-oriented library, you are likely spending most of the time on a test/demo page that imports your actual library. With Vite, you can use your `index.html` for that purpose to get the smooth development experience.
2022-06-19 09:12:59 +00:00
When it is time to bundle your library for distribution, use the [`build.lib` config option](/config/build-options.md#build-lib). Make sure to also externalize any dependencies that you do not want to bundle into your library, e.g. `vue` or `react`:
2021-01-01 21:40:16 +00:00
```js
// vite.config.js
2022-07-08 09:05:58 +00:00
import { resolve } from 'path'
import { defineConfig } from 'vite'
2021-01-01 21:40:16 +00:00
2022-07-08 09:05:58 +00:00
export default defineConfig({
2021-01-01 21:40:16 +00:00
build: {
lib: {
entry: resolve(__dirname, 'lib/main.js'),
name: 'MyLib',
2022-05-05 15:34:27 +00:00
// the proper extensions will be added
fileName: 'my-lib'
},
rollupOptions: {
// make sure to externalize deps that shouldn't be bundled
// into your library
external: ['vue'],
output: {
// Provide global variables to use in the UMD build
// for externalized deps
globals: {
vue: 'Vue'
}
}
2021-01-01 21:40:16 +00:00
}
}
2021-07-27 15:00:51 +00:00
})
2021-01-01 21:40:16 +00:00
```
The entry file would contain exports that can be imported by users of your package:
```js
// lib/main.js
import Foo from './Foo.vue'
import Bar from './Bar.vue'
export { Foo, Bar }
```
2021-01-01 21:40:16 +00:00
Running `vite build` with this config uses a Rollup preset that is oriented towards shipping libraries and produces two bundle formats: `es` and `umd` (configurable via `build.lib`):
```
$ vite build
building for production...
2022-05-22 18:42:51 +00:00
[write] my-lib.mjs 0.08kb, brotli: 0.07kb
2021-01-01 21:40:16 +00:00
[write] my-lib.umd.js 0.30kb, brotli: 0.16kb
```
Recommended `package.json` for your lib:
```json
{
"name": "my-lib",
"files": ["dist"],
"main": "./dist/my-lib.umd.js",
2022-05-22 18:42:51 +00:00
"module": "./dist/my-lib.mjs",
"exports": {
".": {
2022-05-22 18:42:51 +00:00
"import": "./dist/my-lib.mjs",
"require": "./dist/my-lib.umd.js"
}
}
2021-01-01 21:40:16 +00:00
}
```
## Advanced Base Options
::: warning
This feature is experimental, the API may change in a future minor without following semver. Please fix the minor version of Vite when using it.
:::
For advanced use cases, the deployed assets and public files may be in different paths, for example to use different cache strategies.
A user may choose to deploy in three different paths:
- The generated entry HTML files (which may be processed during SSR)
- The generated hashed assets (JS, CSS, and other file types like images)
- The copied [public files](assets.md#the-public-directory)
A single static [base](#public-base-path) isn't enough in these scenarios. Vite provides experimental support for advanced base options during build, using `experimental.renderBuiltUrl`.
```js
experimental: {
renderBuiltUrl: (filename: string, { hostType: 'js' | 'css' | 'html' }) => {
if (hostType === 'js') {
return { runtime: `window.__toCdnUrl(${JSON.stringify(filename)})` }
} else {
return { relative: true }
}
}
}
```
If the hashed assets and public files aren't deployed together, options for each group can be defined independently using asset `type` included in the third `context` param given to the function.
```js
2022-07-08 09:05:58 +00:00
experimental: {
renderBuiltUrl(filename: string, { hostType: 'js' | 'css' | 'html', type: 'public' | 'asset' }) {
if (type === 'public') {
return 'https://www.domain.com/' + filename
}
else if (path.extname(importer) === '.js') {
return { runtime: `window.__assetsPath(${JSON.stringify(filename)})` }
}
else {
return 'https://cdn.domain.com/assets/' + filename
}
}
2022-07-08 09:05:58 +00:00
}
```