我正在尝试从本地 Nodejs 包导入导出的成员。在使用 Vite(标准 CRA webpack 设置)之前这些工作正常,但自从切换到 Vite 后,我收到以下错误:
Uncaught SyntaxError:
The requested module '/@fs/Users/...{long_path}.../lib/shared/countries/build/index.js'
does not provide an export named 'countryListAllIsoData'
Vite 项目是使用
npm create vite@latest
使用 typescript、react、swc 预设进行设置的。虽然他们确实使用 Webpack 工作,但我不太清楚为什么他们不能使用 Vite 工作? Vite 要求我的项目将项目设置为模块(在
package.json
- "type": "module"
中)。模块中导入的工作方式是否会破坏我当前的代码?
我正在使用 VS Code,它似乎对模块的导入方式非常满意。没有显示任何错误,我可以毫无问题地转到导入的定义(让我相信所有内容都已正确导出)。
我导入如下:
import { countryListAllIsoData } from "countries";
tsconfig.json
文件未受影响(与 npm create vite@latest
创建时完全相同)。这同样适用于 package.json
文件,除了安装了一些模块(例如导致此问题的模块)。
导致此问题的本地包名为
countries
,相当小且简单。它有以下 package.json
文件:
/// package.json
{
"name": "countries",
"version": "1.0.0",
"description": "",
"main": "./build/index.js",
"exports": {
".": "./build/index.js"
},
"scripts": {
"build": "tsc",
"prepare": "npm run build"
},
"keywords": [],
"author": "Bram Vanbilsen",
"license": "UNLICENSED",
"devDependencies": {
"typescript": "^4.8.4"
}
}
tsconfig.json
文件:
{
"compilerOptions": {
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"module": "commonjs", /* Specify what module code is generated. */
"moduleResolution": "nodenext", /* Specify how TypeScript looks up a file from a given module specifier. */
"declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
"declarationMap": true, /* Create sourcemaps for d.ts files. */
"outDir": "./build", /* Specify an output folder for all emitted files. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
"strict": true, /* Enable all strict type-checking options. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}
index.ts
文件:
export const countryListAllIsoData = [...] as const;
我遇到了这个问题,并使用 Vite 别名修复了它。
在Vite配置中,为包名添加别名,并带有本地文件夹的绝对路径:
resolve: {
alias: {"countries":"/Users/...{long_path}.../lib/shared/countries"}
}
我也遇到过同样的问题并且能够解决它。
问题是 vite 与 e.g. 相比webpack 需要 ESM 模块才能工作,因为这是 Vite 与其他捆绑器相比如此快的主要原因。由于这个原因以及其他一些原因,Vite 将预先捆绑依赖项并执行从 UMD 或 CommonJS 模块到 ESM 模块的转换。
引自Vite文档-依赖预捆绑:
CommonJS 和 UMD 兼容性:在开发过程中,Vite 的开发人员将所有代码作为原生 ESM 提供服务。因此,Vite 必须首先将作为 CommonJS 或 UMD 提供的依赖项转换为 ESM。
但是,Vite 不会对链接(本地)依赖项执行此转换。因此,您必须确保仅使用 ESM 模块。
要解决此问题,您需要更改库语法的
tsconfig.json
以使用 ESM 模块,因此 "module"
不得为 commonjs
,但应该例如是 ES6
或 ESNext
等。您还需要将 "moduleResolution"
调整为 ES6
、ESNext
或 TypeScript >= 5.x.x Bundler
。
所以你的
tsconfig.json
应该看起来像这样:
{
"compilerOptions": {
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"module": "ESNext", /* Specify what module code is generated. */
"moduleResolution": "Bundler", /* Specify how TypeScript looks up a file from a given module specifier. */
"declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
"declarationMap": true, /* Create sourcemaps for d.ts files. */
"outDir": "./build", /* Specify an output folder for all emitted files. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
"strict": true, /* Enable all strict type-checking options. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}
但是,这需要将链接的 dep 导出为 ESM。如果没有,您可以在配置中将依赖项添加到
optimizeDeps.include
和 build.commonjsOptions.include
。
export default defineConfig({
optimizeDeps: {
include: ['linked-dep'],
},
build: {
commonjsOptions: {
include: [/linked-dep/, /node_modules/],
},
},
})
对链接的 dep 进行更改时,请使用
--force
命令行选项重新启动开发服务器以使更改生效。