You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// vite 生成的代码import*as__glob__0_0from'./dir/foo.js'import*as__glob__0_1from'./dir/bar.js'constmodules={'./dir/foo.js': __glob__0_0,'./dir/bar.js': __glob__0_1,}
vite相比较于webpack的优势
vite产生的背景
当我们开始构建越来越大型的应用时,需要处理的 JavaScript 代码量也呈指数级增长。包含数千个模块的大型项目相当普遍。基于 JavaScript 开发的工具就会开始遇到性能瓶颈:通常需要很长时间(甚至是几分钟!)才能启动开发服务器,即使使用模块热替换(HMR),文件修改后的效果也需要几秒钟才能在浏览器中反映出来。如此循环往复,迟钝的反馈会极大地影响开发者的开发效率和幸福感。
Vite 旨在利用生态系统中的新进展解决上述问题:浏览器开始原生支持 ES 模块,且越来越多 JavaScript 工具使用编译型语言编写。
缓慢的服务器启动
当冷启动开发服务器时,基于打包器的方式启动必须优先抓取并构建你的整个应用,然后才能提供服务。
Vite 通过在一开始将应用中的模块区分为 依赖 和 源码 两类,改进了开发服务器启动时间。
依赖 大多为在开发时不会变动的纯 JavaScript。一些较大的依赖(例如有上百个模块的组件库)处理的代价也很高。依赖也通常会存在多种模块化格式(例如 ESM 或者 CommonJS)。
Vite 将会使用 esbuild 预构建依赖。esbuild 使用 Go 编写,并且比以 JavaScript 编写的打包器预构建依赖快 10-100 倍。
源码 通常包含一些并非直接是 JavaScript 的文件,需要转换(例如 JSX,CSS 或者 Vue/Svelte 组件),时常会被编辑。同时,并不是所有的源码都需要同时被加载(例如基于路由拆分的代码模块)。
Vite 以 原生 ESM 方式提供源码。这实际上是让浏览器接管了打包程序的部分工作:Vite 只需要在浏览器请求源码时进行转换并按需提供源码。根据情景动态导入代码,即只在当前屏幕上实际使用时才会被处理。
缓慢的更新
基于打包器启动时,重建整个包的效率很低。原因显而易见:因为这样更新速度会随着应用体积增长而直线下降。
一些打包器的开发服务器将构建内容存入内存,这样它们只需要在文件更改时使模块图的一部分失活[1],但它也仍需要整个重新构建并重载页面。这样代价很高,并且重新加载页面会消除应用的当前状态,所以打包器支持了动态模块热替换(HMR):允许一个模块 “热替换” 它自己,而不会影响页面其余部分。这大大改进了开发体验 —— 然而,在实践中我们发现,即使采用了 HMR 模式,其热更新速度也会随着应用规模的增长而显著下降。
在 Vite 中,HMR 是在原生 ESM 上执行的。当编辑一个文件时,Vite 只需要精确地使已编辑的模块与其最近的 HMR 边界之间的链失活[1](大多数时候只是模块本身),使得无论应用大小如何,HMR 始终能保持快速更新。
Vite 同时利用 HTTP 头来加速整个页面的重新加载(再次让浏览器为我们做更多事情):源码模块的请求会根据 304 Not Modified 进行协商缓存,而依赖模块请求则会通过 Cache-Control: max-age=31536000,immutable 进行强缓存,因此一旦被缓存它们将不需要再次请求。
vite的缺点
开发服务器和生产环境构建之间输出和行为可能不一致
生产环境仍然需要打包
尽管原生 ESM 现在得到了广泛支持,但由于嵌套导入会导致额外的网络往返,在生产环境中发布未打包的 ESM 仍然效率低下(即使使用 HTTP/2)。为了在生产环境中获得最佳的加载性能,最好还是将代码进行 tree-shaking、懒加载和 chunk 分割(以获得更好的缓存)。
生产环境不使用ESBuild打包
虽然 esbuild 快得惊人,并且已经是一个在构建库方面比较出色的工具,但一些针对构建 应用 的重要功能仍然还在持续开发中 —— 特别是代码分割和 CSS 处理方面。就目前来说,Rollup 在应用打包方面更加成熟和灵活。尽管如此,当未来这些功能稳定后,我们也不排除使用 esbuild 作为生产构建器的可能。
vite的组成
Vite 意在提供开箱即用的配置,同时它的 插件 API 和 JavaScript API 带来了高度的可扩展性,并有完整的类型支持。
vite的初始化
使用 NPM:
使用 Yarn:
使用 PNPM:
vite的功能
对非常基础的使用来说,使用 Vite 开发和使用一个静态文件服务器并没有太大区别。然而,Vite 还通过原生 ESM 导入提供了许多主要用于打包场景的增强功能。
NPM依赖解析和预构建
原生 ES 导入不支持下面这样的裸模块导入:
但是Vite会检测到这些裸模块的导入,并执行下面的操作:
node_modules
预构建(模块中多个import预构建成为单个文件,减少网络加载的文件数量)的模块放入缓存中,以便浏览器能够正确导入它们。并且依赖是强缓存的。预构建缓存
.vite
Vite 会将预构建的依赖缓存到 node_modules/.vite。它根据几个源来决定是否需要重新运行预构建步骤:
包管理器的 lockfile 内容,例如 package-lock.json,yarn.lock,pnpm-lock.yaml,或者 bun.lockb
补丁文件夹的修改时间
可能在 vite.config.js 相关字段中配置过的
NODE_ENV 中的值
只有在上述其中一项发生更改时,才需要重新运行预构建。
如果出于某些原因,你想要强制 Vite 重新构建依赖,你可以用 --force 命令行选项启动开发服务器,或者手动删除 node_modules/.vite 目录。
浏览器缓存
解析后的依赖请求会以 HTTP 头
max-age=31536000,immutable
强缓存,以提高在开发时的页面重载性能。一旦被缓存,这些请求将永远不会再到达开发服务器。如果安装了不同的版本(这反映在包管理器的 lockfile 中),则附加的版本 query 会自动使它们失效。如果你想通过本地编辑来调试依赖项,你可以:通过浏览器调试工具的 Network 选项卡暂时禁用缓存;
重启 Vite dev server,并添加
--force
命令以重新构建依赖;重新载入页面。
模块热更新
Vite 提供了一套原生 ESM 的 HMR API。 具有 HMR 功能的框架可以利用该 API 提供即时、准确的更新,而无需重新加载页面或清除应用程序状态。Vite 内置了 HMR 到 Vue 单文件组件(SFC) 和 React Fast Refresh 中。也通过 @prefresh/vite 对 Preact 实现了官方集成。
注意,你不需要手动设置这些 —— 当你通过
create-vite
创建应用程序时,所选模板已经为你预先配置了这些。TypeScript
Vite 天然支持引入
.ts
文件。不进行类型检测!
Vite 仅执行 .ts 文件的转译工作,并不执行 任何类型检查。并假定类型检查已经被你的 IDE 或构建过程处理了。
Vite 之所以不把类型检查作为转换过程的一部分,是因为这两项工作在本质上是不同的。转译可以在每个文件的基础上进行,与 Vite 的按需编译模式完全吻合。相比之下,类型检查需要了解整个模块图。把类型检查塞进 Vite 的转换管道,将不可避免地损害 Vite 的速度优势。
Vite 的工作是尽可能快地将源模块转化为可以在浏览器中运行的形式。为此,我们建议将静态分析检查与 Vite 的转换管道分开。
使用esbuild转译
Vite 使用 esbuild 将 TypeScript 转译到 JavaScript,约是
tsc
速度的 20~30 倍,同时 HMR 更新反映到浏览器的时间小于 50ms。转译时的注意事项
tsconfig.json
中compilerOptions
下的一些配置项需要特别注意。isolatedModules
:true
useDefineForClassFields
:true
Vue
JSX
.jsx
和.tsx
文件同样开箱即用。JSX 的转译同样是通过 esbuild。你可以使用
jsxInject
(这是一个仅在 Vite 中使用的选项)为 JSX 注入 helper,以避免手动导入:CSS
导入
.css
文件将会把内容插入到<style>
标签中,同时也带有 HMR 支持。也能够以字符串的形式检索处理后的、作为其模块默认导出的 CSS。Vite 通过
postcss-import
预配置支持了 CSS@import
内联,Vite 的路径别名也遵从 CSS@import
。Sass 和 Less 文件也支持
@import
别名和 URL 自动重新设置基准以确保正确性CSS预处理器
Vite 同时提供了对
.scss
,.sass
,.less
,.styl
和.stylus
文件的内置支持。没有必要为它们安装特定的 Vite 插件,但必须安装相应的预处理器依赖:PostCSS
如果项目包含有效的 PostCSS 配置 (任何受 postcss-load-config 支持的格式,例如 postcss.config.js),它将会自动应用于所有已导入的 CSS。
CSS Modules
任何以
.module.css
为后缀名的 CSS 文件都被认为是一个 CSS modules 文件。导入这样的文件会返回一个相应的模块对象:配置 CSS modules 的行为。选项将被传递给 postcss-modules。
禁用CSS注入页面
静态资源处理
导入一个静态资源会返回解析后的 URL:
添加一些特殊的查询参数可以更改资源被引入的方式:
JSON
JSON 可以被直接导入 —— 同样支持具名导入:
Glob导入
Vite 支持使用特殊的
import.meta.glob
函数从文件系统导入多个模块:以上将会被转译为下面的样子:
你可以遍历 modules 对象的 key 值来访问相应的模块:
匹配到的文件默认是懒加载的,通过动态导入实现,并会在构建时分离为独立的 chunk。如果你倾向于直接引入所有的模块(例如依赖于这些模块中的副作用首先被应用),你可以传入
{ eager: true }
作为第二个参数:以上会被转译为下面的样子:
默认是模块形式导入,也支持字符串形式导入资源/支持将资源作为URL加载
内置的构建优化
CSS代码分割
Vite 会自动地将一个异步 chunk 模块中使用到的 CSS 代码抽取出来并为其生成一个单独的文件。这个 CSS 文件将在该异步 chunk 加载完成时自动通过一个 标签载入,该异步 chunk 会保证只在 CSS 加载完毕后再执行。
预加载指令生成
Vite 会为入口 chunk 和它们在打包出的 HTML 中的直接引入自动生成
<link rel="modulepreload">
指令。异步Chunk加载优化
Vite 将使用一个预加载步骤自动重写代码,来分割动态导入调用,以实现当 A 被请求时,C 也将 同时 被请求:
插件
Vite 可以使用插件进行扩展,这得益于 Rollup 优秀的插件接口设计和一部分 Vite 独有的额外选项。这意味着 Vite 用户可以利用 Rollup 插件的强大生态系统,同时根据需要也能够扩展开发服务器和 SSR 功能。
添加插件
若要使用一个插件,需要将它添加到项目的 devDependencies 并在 vite.config.js 配置文件中的 plugins 数组中引入它。
强制插件排序
为了与某些 Rollup 插件兼容,可能需要强制修改插件的执行顺序,或者只在构建时使用。这应该是 Vite 插件的实现细节。可以使用
enforce
修饰符来强制插件的位置:pre
:在 Vite 核心插件之前调用该插件post
:在 Vite 构建插件之后调用该插件按需应用
默认情况下插件在开发 (serve) 和生产 (build) 模式中都会调用。如果插件在服务或构建期间按需使用,请使用 apply 属性指明它们仅在 'build' 或 'serve' 模式时调用:
其它
public 目录
如果你有下列这些资源:
那么你可以将该资源放在指定的 public 目录中,它应位于你的项目根目录。该目录中的资源在开发时能直接通过 / 根路径访问到,并且打包时会被完整复制到目标目录的根目录下。
目录默认是
<root>/publi
c,但可以通过publicDir
选项 来配置。请注意:
public
中的资源永远应该使用根绝对路径 —— 举个例子,public/icon.png
应该在源码中被引用为/icon.png
。public
中的资源不应该被 JavaScript 文件引用。自定义构建
构建过程可以通过多种 构建配置选项 来自定义构建。具体来说,你可以通过 build.rollupOptions 直接调整底层的 Rollup 选项:
产物分块策略
你可以通过配置
build.rollupOptions.output.manualChunks
来自定义 chunk 分割策略(查看 Rollup 相应文档)。在 Vite 2.8 及更早版本中,默认的策略是将 chunk 分割为 index 和 vendor。这对一些 SPA 来说是好的策略,但是要对所有应用场景提供一种通用解决方案是非常困难的。从 Vite 2.9起,manualChunks
默认情况下不再被更改。你可以通过在配置文件中添加splitVendorChunkPlugin
来继续使用 “分割 Vendor Chunk” 策略:环境变量
Vite 在一个特殊的
import.meta.en
v 对象上暴露环境变量。Vite 使用
dotenv
从你的 环境目录 中的下列文件加载额外的环境变量:为了防止意外地将一些环境变量泄漏到客户端,只有以 VITE_ 为前缀的变量才会暴露给经过 vite 处理的代码。例如下面这些环境变量:
vite开发环境与生产环境之间的区别
//TODO
vite SSR
// TODO
参考
The text was updated successfully, but these errors were encountered: