Vite

Vite 2.0 带着 esbuild,以及对 React 项目的支持来了,我被这个打包耗时对比图打动,于是决定尝试一下。

用之前了解了一下 Vite 的受限:

  1. 只支持 ESM,其他例如 CJS 等可以用插件兼容 (ESM?)
  2. 对浏览器原生倒模块能力的依赖
    • Chrome >=61
    • Firefox >=60
    • Safari >=11
    • Edge >=16
  3. 生态一般

感觉对将要新启的项目没什么影响。

1. esbuild 不支持 React 17 新的 jsx transform

React 17 提供了一个新的 JSX 转义方式,是和 Babel 合作搞的。

简单来讲就是不需要在每个 .jsx 中引入 React,不用 import React from 'react';
在编译的时候,babel 会自动引入:

1
import { jsx as _jsx } from 'react/jsx-runtime';

然而,Vite 没有。如果想在项目里使用同样的能力,就需要在 vite.config.ts 中配置:

1
2
3
esbuild: {
jsxInject: `import React from 'react'` // esbuild 暂时不支持 React 17 新的 jsx transform,暂时这样
},

假装也可以做到。。。

2. 路径别名一定要斜线开头

绝对路径会看起来对项目结构和代码理解更清晰一些,但 Vite 不能支持 @ 开头,只能 / 开头来引入。

1
2
3
4
5
6
7
8
9
10
11
module.exports = {
resolve: {
alias: {
'/@/': path.resolve(__dirname, 'src'); // 别名必须以斜线开头和结尾
},
// 或者:
alias: [
{ find: /^~/, replacement: '' },
],
},
}

原因是,
Vite 的 Dev Server 用的是浏览器自己对于 ESM 的引入方式。当用到一下方式引入依赖的时候:

1
import { Suspense, lazy } from 'react';

浏览器并不知道 react 库在 node_modules 里,它只能用相对和绝对路径去找。此处 Vite 1.0 是在本地起了一个 koa 服务,代理这些模块。Vite 2.0 也是一个 node 服务,当浏览器读取到 html 文件并执行到 import xxx 时,才向该服务去请求这个模块,这就保证了只有在真正使用到这个模块的时候,浏览器才会请求并解析这个模块,将按需加载做到极致。

这个服务起来之前,Vite 会用 esbuild 去预构建依赖,来加速浏览器请求相应模块的速度。

Vite 对所有 import 都做了处理,用带有 @modules 的前缀重写它们。

3. 本地开发和打包出来的是两个东西

虽然 esbuild 快得惊人,并且已经是一个在构建库方面比较出色的工具,但一些针对构建 应用 的重要功能仍然还在持续开发中。

所以,本地开发的时候得益于 esbuild 相当快的热更新、项目启动速度,但是生产环境还是用的 Rollup。难免会有一些不一样的表现。

4. 接入微前端操作困难

由于开发模式只支持 ESM,接入微前端(例如乾坤框架时)需要打包成 UMD,所以过程很麻烦,体验很不好,一度让我想用回 Webpack。

总结

开发时的体验还是很好的,React 项目可以非常快速地启动以及 HMR,尤其是二次启动。而且修改打包器的配置(vite.config.ts),都不需要 CTL + C 重启服务。
但是考虑到生产环境以及一些对打包方式有特别需求的场景,就不太香了。还是更期待以后的迭代。