FED

©FrontEndDev.org
2015 - 2024
web@2.23.0 api@2.21.1

解决 vite build 在 pnpm 工程下出现 fsevents.node Unexpected character 的问题

问题现象

近期在使用 vite 开发一个 通用型插件,用于实现 基于文件系统驱动路由的 react 页面应用。包管理工具使用的是 pnpm@9.6.0,打包工具是 vite@5.3.5

在构建的时候出现以下错误:

▷ pnpm run build

> unplugin-react-pages@0.1.0 build /unplugin-react-pages
> NODE_ENV=production vite build

vite v5.3.5 building for production...
✓ 63 modules transformed.
x Build failed in 5.00s
error during build:
[commonjs--resolver] node_modules/.pnpm/fsevents@2.3.3/node_modules/fsevents/fsevents.node (1:0): Unexpected character '�' (Note that you need plugins to import files that are not JavaScript)
file: /unplugin-react-pages/node_modules/.pnpm/fsevents@2.3.3/node_modules/fsevents/fsevents.js:1:0

1: ����@<�
          ��*...
   ^
4* 
  h���/System/Library/Frameworks/CoreFoundation.framework/Versions...
3: ���H��1�H���L���L���H�����L�E�L��H��1�����uH�E�H�[A^A_]��}f.�UH��AWAVSPI��H��I��H�H...

RollupError: Unexpected character '�'
    at getRollupError (file:///unplugin-react-pages/node_modules/.pnpm/rollup@4.19.1/node_modules/rollup/dist/es/shared/parseAst.js:392:41)
    at ParseError.initialise (file:///unplugin-react-pages/node_modules/.pnpm/rollup@4.19.1/node_modules/rollup/dist/es/shared/node-entry.js:11471:28)
    at convertNode (file:///unplugin-react-pages/node_modules/.pnpm/rollup@4.19.1/node_modules/rollup/dist/es/shared/node-entry.js:13167:10)
    at convertProgram (file:///unplugin-react-pages/node_modules/.pnpm/rollup@4.19.1/node_modules/rollup/dist/es/shared/node-entry.js:12511:12)
    at Module.setSource (file:///unplugin-react-pages/node_modules/.pnpm/rollup@4.19.1/node_modules/rollup/dist/es/shared/node-entry.js:14332:24)
    at async ModuleLoader.addModuleSource (file:///unplugin-react-pages/node_modules/.pnpm/rollup@4.19.1/node_modules/rollup/dist/es/shared/node-entry.js:18984:13)
 ELIFECYCLE  Command failed with exit code 1.

解决方案 1(推荐)

因为本工程是 library 类型,一般外部依赖都不需要捆绑在一起的,因此需要在 vite.config 的 rolluOptions 内配置 external 将外部依赖排除即可。通常我们使用 vite-plugin-externalize-deps 配置一下:

// vite.config.ts
import { externalizeDeps } from 'vite-plugin-externalize-deps';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    externalizeDeps({
      deps: true,
      devDeps: true,
      peerDeps: true,
      optionalDeps: true,
      nodeBuiltins: true,
    }),
  ],
});

解决方案 2

fsevents package

Native access to MacOS FSEvents in Node.js

The FSEvents API in MacOS allows applications to register for notifications of changes to a given directory tree. It is a very fast and lightweight alternative to kqueue.

This is a low-level library. For a cross-platform file watching module that uses fsevents, check out Chokidar.

image.png

fsevents 入口会引用该文件:

image.png

而 vite 在构建引用二进制文件时目前会有问题,即使加上排除也不行:

export default defineConfig({
// ...
optimizeDeps: { exclude: ["fsevents"] },
// ...
})

而 fsevents 是 chokidar 的可选依赖:

image.png

那就索性不安装该依赖试试,在 package.json 里添加:

...
"optionalDependencies": {
    "fsevents": "*"
}
...

最后构建成功。