theme: channing-cyan
问题
??在 Nest 项目中,我使用了 file-type 来识别文件类型。就像这样子:
ts- import { fileTypeFromFile } from 'file-type'
这时候控制台就出现了报错:
cmd- module.exports = require("file-type");
- ^
- Error [ERR_REQUIRE_ESM]: require() of ES Module xxx\node_modules\file-type\index.js from yyy not supported.
- Instead change the require of index.js in yyy to a dynamic import() which is available in all CommonJS modules.
Nest 使用的是 CommonJs 模块,加载 ESModule 的模块时出现了错误。这里是说我们使用了require导入 ESModule,但是我们用的 file-type 明明是 ESModule 模块。
解决方法
出现这个问题的原因是 Nest-CLI 内置的 Webpack 把所有import语句都编译成 CommonJs 的形式了。file-type 这个包是 ESModule 形式的,解决方法自然是自定义 Webpack 配置,阻止它把 ESModule 的模块打包成 commonjs 的形式。
这里使用 webpack-node-externals 这个 Webpack 第三方包(??反正它不是 loader,也不是 plugin)。它主要用于排除项目中的内置模块和 node_modules 中的第三方模块,会为被排除的模块创建一个外部函数。例如,我们排除了 file-type 这个库,在打包完成后的 ./dist/main.js 中,在最外层的代码可以找到 file-type 这个库中导出的函数:
ts- // ...
- async function fileTypeFromStream(stream) {
- return new FileTypeParser().fromStream(stream);
- }
- async function fileTypeFromBuffer(input) {
- return new FileTypeParser().fromBuffer(input);
- }
- async function fileTypeFromBlob(blob) {
- return new FileTypeParser().fromBlob(blob);
- }
- // ...
修改 Webpack 配置
找到项目根目录的 nest-cli.json,compilerOptions加入webpack和webpackConfigPath的属性:
json- {
- "$schema": "https://json.schemastore.org/nest-cli",
- "collection": "@nestjs/schematics",
- "sourceRoot": "src",
- "compilerOptions": {
- "deleteOutDir": true,
- "webpack": true,
- "webpackConfigPath": "./webpack.config.js"
- }
- }
./webpack.config.js 就是自定义 Webpack 配置的路径,在项目根目录新建 webpack.config.js。使用 webpack-node-externals 来忽略转换指定的模块或者文件,把涉及到的包都扔进去。
ts- const fs = require('fs')
- const path = require('path')
- const nodeExternals = require('webpack-node-externals');
- const appDirectory = fs.realpathSync(process.cwd());
- module.exports = function (options, webpack) {
- console.log('My Webpack Config ...');
- return {
- ...options,
- resolve: {
- extensions: [".ts", ".js"],
- alias: {
- 'src': path.resolve(appDirectory, 'src')
- }
- },
- externals: [
- nodeExternals({
- allowlist: ['file-type', /^strtok3/, 'peek-readable', 'token-types']
- })
- ],
- }
- }
重新运行就跑起来了。
结语
初次用 Nest 做了个练习性的小项目,一开始对 Nest 中 webpack 的配置又不太了解,遇到问题还是花了不少时间的。这也是熟悉了一下 Node.js 的打包。
有什么不足请批评指正… 大家的阅读是我发帖的动力。
本文首发于我的博客:deer.shika-blog.xyz/