使用 vite 开发和构建 nodejs 应用
本文最后更新于:2023年6月19日 下午
场景
vite 作为现代 web 应用的构建工具,许多开发者将之用于开发 web 应用(react、vue),由于其本身的易用性和高性能,许多 web 框架甚至官方编写了插件(solid、astro),可以称得上是近年来 webpack 的成功的挑战者。但实际上,发展至今,vite 已经远不仅仅是一个 web 层的工具,它的周边生态正在蓬勃发展,衍生除了一系列周边的工具,在之前的 vite-不仅仅是一个构建工具 有所提及,这里专门针对开发 nodejs 应用来说明。
动机
vite 为什么适合开发 nodejs 应用?
首先,即便不使用 vite,你可能也需要使用 vitest 之类的工具进行单元测试,使用 tsx/ts-node 运行源代码调试,使用 tsup/esbuild 将代码 bundle 为最终要运行的 js。那么,如果使用了 vite,这些事情将在同一个生态中完成。
- vitest: 单元测试工具,支持 esm,支持 ts
- vite-node: ts 代码的运行工具,支持 vite 的各种特性,例如
?raw
之类的 - vite: 将 nodejs 应用打包最终运行的 js,可以选择性的捆绑依赖
使用
vitest 和 vite-node 都是现成的,可以开箱即用,所以下面重点关注 vite 构建相关的事情。
首先安装依赖
1 |
|
vitest
创建一个单元测试文件,例如 src/__tests__/index.test.ts
1 |
|
使用下面的命令运行 vitest
1 |
|
vite-node
可以这样说,你可以使用它替代 node 命令运行任何文件,它只是比 node 命令更加强大,包括
- 支持 ts/tsx/esm
- 在 esm 中有 cjs 的 polyfill,
__dirname
什么的可以直接使用 - 支持监视模式运行
- 支持 vite 本身的特性,例如
?raw
- 支持使用 vite 插件
例如创建一个 src/main.ts
文件
1 |
|
然后使用 vite-node 运行
1 |
|
vite
vite 想要构建 nodejs 应用,确实需要修改一些配置和插件,主要解决几个问题
- 为 esm 代码实现 cjs polyfill,包括
__dirname/__filename/require/self
- 正确捆绑 devDependencies 的依赖项,但排除 node/dependencies 的依赖
- 提供一个开箱即用的默认配置
然后我们分别解决这几个问题
构建时针对 cjs 特性做 polyfill
安装 magic-string,用于修改代码保持 sourcemap
1 |
|
然后再 renderChunk hook 中添加 polyfill 代码
1 |
|
正确捆绑依赖项
这里为了简化使用现有的 rollup-plugin-node-externals 插件,它可以排除 node 的依赖,也会自动根据 package.json 中的 dependencies 和 devDependencies 进行排除,但需要针对 vite 做一些小的兼容性修改。
安装依赖
1 |
|
简单代理封装一下
1 |
|
添加默认配置
由于吾辈有很多项目,所以不希望每次都填写配置,而是通过约定 + 支持配置的方式来解决这个问题,所以简单实现一个 vite 插件。
1 |
|
合并插件
最终,我们将这些插件合并到一起,就可以使用 vite 构建 nodejs 应用了。
1 |
|
然后在 vite.config.ts 中使用
1 |
|
现在,我们可以使用 vite 构建 nodejs 应用了
1 |
|
享受 vite 带来的一切吧!
吾辈发布了一个 vite 插件 @liuli-util/vite-plugin-node,已经解决了上面的几个问题。
局限性
好吧,这里其实仍然存在一些问题,包括
- vite 没有官方支持构建 node 应用,项目的主要目标也不是它
- vite-plugin-node 还有许多问题,例如没有自动 polyfill
__dirname
之类的 - vite 相比 esbuild 的性能仍然差了一个数量级
没什么选择是尽善尽美的,但吾辈现在选择相信 vite。
遇到的问题
- zx 构建之后无法运行 – chalk 没有正确的配置 – 无法识别
imports
中的node
字段 – 维护者不在乎,需要考虑更换为 ansi-colors,ref: https://github.com/chalk/chalk/issues/535 - koa-bodyparser 构建之后存在问题 – 没有正确支持 esm – 等待 https://github.com/koajs/bodyparser/pull/152 合并
未来的目标
- 多入口点支持