最近在研究如何将 lowcode-engine 的 schema 生成 .vue 文件,在解析函数的过程中使用到了babel系列插件 @babel/types 等,结果项目运行时中出现 “process is not defined” 的错误。
对 Node 熟悉的人对 process 应该不陌生,process 对象是 Node 提供的一个全局变量,提供当前 Node 进程的信息。
process is not defined 意味着找不到这个全局对象,为什么会出现这种问题?
错误分析
项目架构是 Vite + Typescript,而之前在其他项目中使用 webpack 启动项目,也使用了 babel系列插件, 并没有这个问题。猜想问题大概率是出现在 Vite 的使用方式上。
Vite 环境变量
Vite 在一个特殊的 import.meta.env 对象上暴露环境变量,我们在业务代码中无法访问到 process.env。而 @babel/types 等插件要求在实现过程中直接访问了 process 对象,很明显,在 Vite 项目运行中,默认是读不到该对象,所以会出现 “process is not defined”。
解决方案
自定义共享选项
虽然无法在业务代码中访问到 process 对象,但是在 vite.config.js 配置文件中可以访问,可以通过修改配置文件解决该问题。
在 Vite 中,我们可以通过 define,定义全局常量替换方式,代码如下:
import { defineConfig } from 'vite'import { NodeGlobalsPolyfillPlugin } from "@esbuild-plugins/node-globals-polyfill";import { polyfillNode } from "esbuild-plugin-polyfill-node";export default defineConfig({ ... define: { 'process.env': process.env }, ....})
第三方插件
虽然通过自定义共享选项能解决 process 无法获取的问题,但是接着调试,会发现 @babel/generate 出现报错,Buffer is not defined。
Buffer 是 Node.js 中定义的一个类,用来创建专门存放二进制数据的缓冲区。
这里涉及另外一个问题,我在浏览器环境中调试项目,而不是在 Node 环境中,浏览器中读不到 Node 的对象也正常。
但为什么使用 webpack 时,常用的 Node 对象都能读到,而 Vite 不行?这就涉及到 Vite 和 Webpack 的原理了。
Vite 在开发模式下,并不会预先编译 Node 相关内容,如果想要支持,还需要用到第三方插件。
import { defineConfig } from 'vite'import { NodeGlobalsPolyfillPlugin } from '@esbuild-plugins/node-globals-polyfill'export default defineConfig({ ... optimizeDeps: { esbuildOptions: { define: { global: 'globalThis' }, plugins: [ NodeGlobalsPolyfillPlugin({ buffer: true }) ] } }
... })
写在最后
Vite 很多功能的拓展依靠插件,如果某个功能不支持,可以找找是不是已经有相关插件支持了。