总览
Vite是一种新型前端构建工具,能够显著提升开发体验,它主要由两部分组成:
- 一个开发服务器,它基于原生ES模块提供了丰富的内建功能,如速度快到惊人的模块热更新。
- 一套构建指令,它使用Rollup打包你的代码,并且它是预配置的,可输出用于生产环境的高度优化过的静态资源。
Vite意在提供开箱即用的配置,同时它的 插件 API 和 JavaScript API 带来了高度的可扩展性,并有完整的类型支持。
浏览器支持
- 默认的构建目标浏览器是能 在 script 标签上支持原生 ESM 和 原生 ESM 动态导入。传统浏览器可以通过官方插件 @vitejs/plugin-legacy 支持 —— 查看 构建生产版本 章节获取更多细节。
在线试用 Vite
你可以通过 StackBlitz 在线试用 vite。它直接在浏览器中运行基于 Vite 的构建,因此它与本地开发几乎无差别,同时无需在你的机器上安装任何东西。你可以浏览 vite.new/{template} 来选择你要使用的框架。
目前支持的模板预设如下:
JavaScript | TypeScript |
---|---|
vanilla | vanilla-ts |
vue | vue-ts |
react | react-ts |
preact | preact-ts |
lit | lit-ts |
svelte | svelte-ts |
搭建第一个 Vite 项目
兼容性注意
Vite 需要 Node.js 版本 >= 14.6.0。然而,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版本。
使用 NPM:
$ npm create vite@latest
使用 Yarn:
$ yarn create vite
使用 PNPM:
$ pnpm create vite
然后按照提示操作即可!
你还可以通过附加的命令行选项直接指定项目名称和你想要使用的模板。例如,要构建一个 Vite + Vue 项目,运行:
# npm 6.x
npm create vite@latest my-vue-app --template vue
# npm 7+, extra double-dash is needed:
npm create vite@latest my-vue-app -- --template vue
# yarn
yarn create vite my-vue-app --template vue
# pnpm
pnpm create vite my-vue-app -- --template vue
查看 create-vite 以获取每个模板的更多细节:vanilla,vanilla-ts,vue,vue-ts,react,react-ts,preact,preact-ts,lit,lit-ts,svelte,svelte-ts。
社区模板
create-vite 是一个快速生成主流框架基础模板的工具。查看 Awesome Vite 仓库的 社区维护模板,里面包含各种工具和不同框架的模板。你可以用如 degit 之类的工具,使用社区模版来搭建项目。
npx degit user/project my-project
cd my-project
npm install
npm run dev
如果该项目使用 main 作为默认分支, 需要在项目名后添加 #main。
npx degit user/project#main my-project
index.html 与项目根目录
你可能已经注意到,在一个 Vite 项目中,index.html 在项目最外层而不是在 public 文件夹内。这是有意而为之的:在开发期间 Vite 是一个服务器,而 index.html 是该 Vite 项目的入口文件。
Vite 将 index.html 视为源码和模块图的一部分。Vite 解析 <script type="module" src="...">
,这个标签指向你的 JavaScript 源码。甚至内联引入 JavaScript 的 <script type="module">
和引用 CSS 的 <link href>
也能利用 Vite 特有的功能被解析。另外,index.html 中的 URL 将被自动转换,因此不再需要 %PUBLIC_URL%
占位符了。
与静态 HTTP 服务器类似,Vite 也有 “根目录” 的概念,即服务文件的位置,在接下来的文档中你将看到它会以 <root>
代称。源码中的绝对 URL 路径将以项目的 “根” 作为基础来解析,因此你可以像在普通的静态文件服务器上一样编写代码(并且功能更强大!)。Vite 还能够处理依赖关系,解析处于根目录外的文件位置,这使得它即使在基于 monorepo 的方案中也十分有用。
Vite 也支持多个 .html
作入口点的 多页面应用模式。
指定替代根目录
vite 以当前工作目录作为根目录启动开发服务器。你也可以通过 vite serve some/sub/dir
来指定一个替代的根目录。
命令行界面
在安装了 Vite 的项目中,可以在 npm scripts 中使用 vite 可执行文件,或者直接使用 npx vite
运行它。下面是通过脚手架创建的 Vite 项目中默认的 npm scripts:
{
"scripts": {
"dev": "vite", // 启动开发服务器,别名:`vite dev`,`vite serve`
"build": "vite build", // 为生产环境构建产物
"preview": "vite preview" // 本地预览生产构建产物
}
}
可以指定额外的命令行选项,如 —port 或 —https。运行 npx vite —help 获得完整的命令行选项列表。
功能
对非常基础的使用来说,使用 Vite 开发和使用一个静态文件服务器并没有太大区别。然而,Vite 还通过原生 ESM 导入提供了许多主要用于打包场景的增强功能。
NPM 依赖解析和预构建
原生 ES 导入不支持下面这样的裸模块导入:
import { someMethod } from 'my-dep'
上面的代码会在浏览器中抛出一个错误。Vite 将会检测到所有被加载的源文件中的此类裸模块导入,并执行以下操作:
- 预构建 它们可以提高页面加载速度,并将 CommonJS / UMD 转换为 ESM 格式。预构建这一步由 esbuild 执行,这使得 Vite 的冷启动时间比任何基于 JavaScript 的打包器都要快得多。
- 重写导入为合法的 URL,例如 /node_modules/.vite/deps/my-dep.js?v=f3sf2ebd 以便浏览器能够正确导入它们。
依赖是强缓存的
Vite 通过 HTTP 头来缓存请求得到的依赖,所以如果你想要编辑或调试一个依赖,请按照 这里 的步骤操作。
模块热重载
Vite 提供了一套原生 ESM 的 HMR API。 具有 HMR 功能的框架可以利用该 API 提供即时、准确的更新,而无需重新加载页面或清除应用程序状态。Vite 内置了 HMR 到 Vue 单文件组件(SFC) 和 React Fast Refresh 中。也通过 @prefresh/vite 对 Preact 实现了官方集成。
注意,你不需要手动设置这些 —— 当你通过 create-vite 创建应用程序时,所选模板已经为你预先配置了这些。
TypeScript
Vite 天然支持引入 .ts 文件。
Vite 仅执行 .ts 文件的转译工作,并 不 执行任何类型检查。并假设类型检查已经被你的 IDE 或构建过程接管了(你可以在构建脚本中运行 tsc —noEmit 或者安装 vue-tsc 然后运行 vue-tsc —noEmit 来对你的 *.vue 文件做类型检查)。
Vite 使用 esbuild 将 TypeScript 转译到 JavaScript,约是 tsc 速度的 20~30 倍,同时 HMR 更新反映到浏览器的时间小于 50ms。
使用 仅含类型的导入和导出 形式的语法可以避免潜在的 “仅含类型的导入被不正确打包” 的问题,写法示例如下:
import type { T } from 'only/types'
export type { T }
TypeScript 编译器选项
tsconfig.json
中compilerOptions
下的一些配置项需要特别注意。
isolatedModules
应该设置为 true。
这是因为 esbuild 只执行没有类型信息的转译,它并不支持某些特性,如 const enum 和隐式类型导入。
你必须在 tsconfig.json
中的 compilerOptions
下设置 "isolatedModules": true
。如此做,TS 会警告你不要使用隔离(isolated)转译的功能。
然而,一些库(如:vue)不能很好地与 "isolatedModules": true
共同工作。你可以在上游仓库修复好之前暂时使用 "skipLibCheck": true
来缓解这个错误。
useDefineForClassFields
从 Vite v2.5.0 开始,如果 TypeScript 的 target 是 ESNext,此选项默认值则为 true。这与 tscv4.3.2 及以后版本的行为 一致。这也是标准的 ECMAScript 的运行时行为。
但对于那些习惯其他编程语言或旧版本 TypeScript 的开发者来说,这可能是违反直觉的。 你可以参阅 TypeScript 3.7 发布日志 中了解更多关于如何兼容的信息。
如果你正在使用一个严重依赖 class fields 的库,请注意该库对此选项的预期设置。
大多数库都希望 "useDefineForClassFields": true
,如 MobX,Vue Class Components 8.x 等。
但是有几个库还没有兼容这个新的默认值,其中包括 lit-element。如果遇到这种情况,请将 useDefineForClassFields
设置为 false
。
影响构建结果的其他编译器选项
如果你的代码库很难迁移到 “isolatedModules”: true,或许你可以尝试通过第三方插件来解决,比如 rollup-plugin-friendly-type-imports。但是,这种方式不被 Vite 官方支持。
客户端类型
Vite 默认的类型定义是写给它的 Node.js API 的。要将其补充到一个 Vite 应用的客户端代码环境中,请添加一个 d.ts 声明文件:
/// <reference types="vite/client" />
同时,你也可以将 vite/client
添加到 tsconfig
中的 compilerOptions.types
下:
{
"compilerOptions": {
"types": ["vite/client"]
}
}
这将会提供以下类型定义补充:
- 资源导入 (例如:导入一个
.svg
文件) import.meta.env
上 Vite 注入的环境变量的类型定义import.meta.hot
上的 HMR API 类型定义
Vue
Vite 为 Vue 提供第一优先级支持:
- Vue 3 单文件组件支持:@vitejs/plugin-vue
- Vue 3 JSX 支持:@vitejs/plugin-vue-jsx
- Vue 2 支持:underfin/vite-plugin-vue2
CSS
导入 .css 文件将会把内容插入到