Babel 7.18无法转译项目根目录外sharedlib组件的配置求助
问题描述
我在project1的Babel根目录外放置了一个sharedlib组件,此前使用webpack打包该项目时未出现问题,但配置Babel后出现如下报错:
Asset Size Chunks Chunk Names lib1.out.js 63.1 KiB main [emitted] main lib1.out.js.map 43.2 KiB main [emitted] [dev] main Entrypoint main = lib1.out.js lib1.out.js.map [../sharedlib/index.js] 43 bytes {main} [built] [../sharedlib/util.js] 554 bytes {main} [built] [./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {main} [built] [./src/lib1.js] 435 bytes {main} [built] + 56 hidden modules ERROR in ../sharedlib/util.js Module not found: Error: Can't resolve '@babel/runtime-corejs3/core-js-stable/promise' in 'D:\test_babel\sharedlib' @ ../sharedlib/util.js 3:0-69 13:13-21 @ ../sharedlib/index.js @ ./src/lib1.js ERROR in ../sharedlib/util.js Module not found: Error: Can't resolve '@babel/runtime-corejs3/helpers/classCallCheck' in 'D:\test_babel\sharedlib' @ ../sharedlib/util.js 1:0-76 7:4-19 @ ../sharedlib/index.js @ ./src/lib1.js ERROR in ../sharedlib/util.js Module not found: Error: Can't resolve '@babel/runtime-corejs3/helpers/createClass' in 'D:\test_babel\sharedlib' @ ../sharedlib/util.js 2:0-70 10:2-14 @ ../sharedlib/index.js @ ./src/lib1.js
可复现该问题的示例项目已上传至GitHub公开仓库。
项目结构
ROOT ├─project1 │ │ babel.config.js │ │ demo.html │ │ demo.js │ │ package-lock.json │ │ package.json │ │ webpack.config.js │ │ │ ├─node_modules │ └─src │ lib1.js │ └─sharedlib index.js util.js package.json
现有配置
project1/package.json配置如下,已将sharedlib配置为本地模块:"sharedlib": "file:../sharedlib"
{ "name": "lib1.js", "version": "1.0.0", "description": "test project1", "main": "lib1.js", "dependencies": { "@babel/runtime-corejs3": "^7.18.3", "sharedlib": "file:../sharedlib" }, "devDependencies": { "@babel/core": "^7.18.2", "@babel/plugin-transform-runtime": "^7.18.2", "@babel/preset-env": "^7.18.2", "babel-loader": "^8.2.5", "babel-loader-exclude-node-modules-except": "^1.2.1", "webpack": "^4.39.3", "webpack-cli": "^3.3.8" }, "scripts": { "clean": "rimraf dist", "prebuild": "npm run clean", "prerelease": "npm run clean", "build": "webpack --mode development", "release": "webpack --mode production" } }
webpack.config.js配置内容如下:
const path = require('path'); module.exports = { devtool: 'source-map', entry: './src/lib1.js', output: { path: __dirname, filename: `lib1.out.js`, library: 'Lib1', libraryTarget: 'umd', libraryExport: 'default', globalObject: 'this', }, module: { rules: [ { test: /\.m?js$/, exclude: /node_modules/, // include: [ // path.resolve(__dirname, 'src'), // path.resolve(__dirname, 'node_modules/sharedlib') // ], use: { loader: "babel-loader" } } ] } };
如果注释掉exclude配置、启用include配置,编译不再报错,但打包产物中的util.js并未被转译,仍为ES6代码。已经将node_modules/sharedlib目录加入include范围,其中的文件却未被转译。
babel.config.js配置内容如下:
module.exports = { presets: [ ["@babel/preset-env", { targets: { ie: 10 }, debug: true }] ], plugins: [ [ "@babel/plugin-transform-runtime", { corejs: 3 } ] ] };
诉求
sharedlib来自第三方,不希望修改其目录内容,也不想在其目录下安装@babel/runtime-corejs3,需要仅通过修改project1的配置实现sharedlib代码的转译。
解决方案
问题由两个核心配置逻辑缺陷导致:
- 依赖解析逻辑问题:
@babel/plugin-transform-runtime默认从被转译文件所在目录递归查找@babel/runtime-corejs3依赖,sharedlib目录本身没有安装该包,直接触发模块找不到错误。 - Babel配置生效范围问题:Babel 7的
babel.config.js默认仅对当前项目根目录(即project1目录)内的文件生效,通过file:../sharedlib安装的本地依赖在node_modules下只是软链,实际源码在project1目录外,默认不会读取project1下的babel配置,这就是路径加到include里依然不转译的核心原因。
具体修改步骤
1. 调整webpack配置
修改webpack.config.js,将sharedlib的真实源码路径加入转译范围,强制babel-loader使用当前项目的babel配置,同时调整模块解析优先级,优先从当前项目的node_modules查找依赖:
const path = require('path'); // 获取sharedlib真实源码的绝对路径 const sharedLibPath = path.resolve(__dirname, '../sharedlib'); module.exports = { devtool: 'source-map', entry: './src/lib1.js', output: { path: __dirname, filename: `lib1.out.js`, library: 'Lib1', libraryTarget: 'umd', libraryExport: 'default', globalObject: 'this', }, module: { rules: [ { test: /\.m?js$/, exclude: /node_modules/, include: [ path.resolve(__dirname, 'src'), // 加入sharedlib真实源码路径,不要使用node_modules下的软链路径 sharedLibPath ], use: { loader: "babel-loader", options: { // 强制使用当前项目的babel配置 configFile: path.resolve(__dirname, 'babel.config.js'), // 关闭自动查找上层babelrc的逻辑,避免配置加载失效 babelrc: false } } } ] }, // 调整模块解析优先级,优先从当前项目node_modules查找依赖 resolve: { modules: [ path.resolve(__dirname, 'node_modules'), 'node_modules' ] } };
2. 调整babel配置
修改babel.config.js,给@babel/plugin-transform-runtime开启absoluteRuntime参数,强制注入的runtime依赖使用绝对路径指向当前项目安装的runtime包,从根源避免跨目录查找依赖失败的问题:
module.exports = { presets: [ ["@babel/preset-env", { targets: { ie: 10 }, debug: true }] ], plugins: [ [ "@babel/plugin-transform-runtime", { corejs: 3, // 新增该配置,使用绝对路径引用runtime模块 absoluteRuntime: true } ] ] };
修改完成后重新执行构建命令即可,sharedlib下的代码会按照ie10的目标规则正常转译,全程不需要修改sharedlib目录下的任何内容,也不需要在sharedlib目录安装额外依赖。
内容的提问来源于stack exchange,提问作者xybei

