构建生产版本
浏览器兼容性
- Vite 的目标浏览器是指能够 支持原生 ESM script 标签 和 支持原生 ESM 动态导入 的
- 注释:ESM script 标签
<script type="module">
- 注释:支持原生 ESM 动态导入
import()
- 注释:ECMAScript 6(简称ES6)是于2015年6月正式发布的JavaScript语言的标准,正式名为ECMAScript 2015(ES2015)一些情况下ES6也泛指ES2015及之后的新增特性,虽然之后的版本应当称为ES7、ES8等
- 默认情况下 Vite 只处理语法转译,且 默认不包含任何 polyfill
- 可以前往 Polyfill.io 查看,这是一个基于用户浏览器 User-Agent 字符串自动生成 polyfill 包的服务
- 传统浏览器可以通过插件 @vitejs/plugin-legacy 来支持,它将自动生成传统版本的 chunk 及与其相对应 ES 语言特性方面的 polyfill。
- 兼容版的 chunk 只会在不支持原生 ESM 的浏览器中进行按需加载。
公共基础路径
- 如果你需要在嵌套的公共路径下部署项目,只需指定 base 配置项
- 由 JS 引入的资源 URL,CSS 中的 url() 引用以及 .html 文件中引用的资源在构建过程中都会自动调整,以适配此选项
- 当访问过程中需要使用动态连接的 url 时,可以使用全局注入的 import.meta.env.BASE_URL 变量
- 注意,这个变量在构建时会被静态替换,因此,它必须按 import.meta.env.BASE_URL 的原样出现
产物分块策略
- 到 Vite 2.8 时,默认的策略是将 chunk 分割为 index 和 vendor
- Vite 2.9 起,build.rollupOptions.output.manualChunks 默认情况下不再被更改
- 你可以通过在配置文件中添加 splitVendorChunkPlugin 来继续使用 “分割 Vendor Chunk” 策略
// vite.config.js
import { splitVendorChunkPlugin } from 'vite'
module.exports = defineConfig({
plugins: [splitVendorChunkPlugin()]
})
- 疑问:也可以用一个工厂函数 splitVendorChunk({ cache: SplitVendorChunkCache }) 来提供该策略
- 疑问:在需要与自定义逻辑组合的情况下,cache.reset() 需要在 buildStart 阶段被调用,以便构建的 watch 模式在这种情况下正常工作
文件变化时重新构建
- 当启用 --watch 标志时,对 vite.config.js 的改动,以及任何要打包的文件,都将触发重新构建。
多页面应用模式
- 注释:在开发过程中,默认支持多页面应用(有多个 html 文件作为入口,可直接在 html 跳转)
- 在构建过程中,你只需指定多个 .html 文件作为入口点即可
// vite.config.js
const { resolve } = require('path')
const { defineConfig } = require('vite')
module.exports = defineConfig({
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
nested: resolve(__dirname, 'nested/index.html')
}
}
}
})
- 在解析输入路径时,__dirname 的值将仍然是 vite.config.js 文件所在的目录
库模式
- 当这个库要进行发布构建时,请使用 build.lib 配置项,以确保将那些你不想打包进库的依赖进行外部化处理
- 注释:name 则是暴露的全局变量,在 formats 包含 'umd' 或 'iife' 时是必须的。
- 注释:UMD模块,通用模块规范,可以同时满足 CommonJS, AMD, CMD 等
- 注释:iife 立即调用函数表达式
- 注释:默认 formats 是 ['es', 'umd']
- 注释:fileName 是输出的包文件名,默认 fileName 是 package.json 的 name 选项,同时,它还可以被定义为参数为 format 的函数
// vite.config.js
const path = require('path')
const { defineConfig } = require('vite')
module.exports = defineConfig({
build: {
lib: {
entry: path.resolve(__dirname, 'lib/main.js'),
name: 'MyLib',
// the proper extensions will be added
fileName: 'my-lib'
},
rollupOptions: {
// 确保外部化处理那些你不想打包进库的依赖
external: ['vue'],
output: {
// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
globals: {
vue: 'Vue'
}
}
}
}
})
- 推荐在你库的 package.json 中使用如下格式:
- 疑问:files安装依赖时应该包含的文件?其他文件不会通过 npm install 下载吗?
- 注释:main:umd 引入目标文件
- 注释:module:esm 引入目标文件
- 注释:.MJS 文件是一个包含ES模块(ECMAScript模块)的源代码文件,用于Node.js应用程序。
- 注释:exports:提供了一种方法来为不同的环境和 JavaScript 风格公开您的包模块,同时限制对其内部部分的访问。
{
"name": "my-lib",
"files": ["dist"],
"main": "./dist/my-lib.umd.js",
"module": "./dist/my-lib.mjs",
"exports": {
".": {
"import": "./dist/my-lib.mjs",
"require": "./dist/my-lib.umd.js"
}
}
}
进阶基础路径选项
- 该功能是实验性的,这个 API 可能在未来后续版本中发生变更而不遵循语义化版本号。请在使用它时注意维护 Vite 的版本。
- 对更高级的使用场景,被部署的资源和公共文件可能想要分为不同的路径
- 生成的入口 HTML 文件(可能会在 SSR 中被处理)
- 生成的带有 hash 值的文件(JS、CSS 以及其他文件类型,如图片)
- 拷贝的 公共文件
- 单个静态的 基础路径 在这种场景中就不够用了。Vite 在构建时为更高级的基础路径选项提供了实验性支持,可以使用 experimental.renderBuiltUrl
experimental: {
renderBuiltUrl: (filename: string, { hostType: 'js' | 'css' | 'html' }) => {
if (hostType === 'js') {
return { runtime: `window.__toCdnUrl(${JSON.stringify(filename)})` }
} else {
return { relative: true }
}
}
}
- 如果 hash 后的资源和公共文件没有被部署在一起,可以根据该函数的第三个参数 context 上的字段 type 分别定义各个资源组的选项:
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
}
}
}