Webpack未转译部分node_modules的ES6代码,如何排查嵌套依赖?
解决Webpack中嵌套依赖未被Babel转译的问题
我来帮你搞定这个问题——你遇到的是Webpack+Babel打包时很常见的嵌套依赖转译坑,咱们分成两个方向来解决:
一、追踪嵌套依赖的上层库
要找到那个未转译的嵌套依赖是被哪个上层包引入的,用包管理工具的命令就能轻松搞定:
- 如果你用npm,直接在项目根目录运行:
比如发现未转译的是npm ls <未转译的依赖包名>foo-bar,就执行npm ls foo-bar,命令会输出完整的依赖树,清晰显示它的上层依赖链。 - 如果你用yarn,命令更直观:
它会直接告诉你这个包被哪些依赖引用,以及对应的版本和引入原因。yarn why <未转译的依赖包名>
二、确保所有模块转译为ES5的简便方法
你之前手动加依赖到include列表的方法可行,但遇到嵌套依赖就很麻烦,这里有几个更高效的方案:
方案1:智能转译(推荐)
与其逐个添加需要转译的依赖,不如反向操作——排除那些已经预编译为ES5的成熟库,转译剩下的所有模块。修改你的babel-loader规则:
{ test: /\.jsx?/, include: [APP_DIR], exclude: /node_modules\/(react|react-dom|redux|lodash|axios)/, // 列出确定是ES5的库 loader: 'babel-loader', query: { presets: ['es2015', 'react', 'stage-2'] } }
这样既不会浪费时间转译已经处理好的库,又能覆盖所有嵌套的未转译依赖。
方案2:强制转译所有node_modules(简单但打包变慢)
如果你的项目不大,打包时间不是问题,可以直接把整个node_modules加入include:
{ test: /\.jsx?/, include: [APP_DIR, /node_modules/], loader: 'babel-loader', query: { presets: ['es2015', 'react', 'stage-2'] } }
注意:这个方法会大幅增加打包时间,因为很多库本来就是ES5的,没必要再转译。
方案3:优先使用ES5版本的依赖
有些库在package.json里会同时提供ES6(module字段)和ES5(main字段)版本,Webpack默认优先加载module字段的ES6代码。你可以修改Webpack的resolve配置,让它优先用main字段的ES5版本:
var config = { // 其他配置... resolve: { mainFields: ['main', 'module'] // 先找main字段的ES5文件 }, // 其他配置... }
这个方法能从根源上避免很多ES6语法的问题,不需要额外转译。
针对你现有配置的修改建议
结合你的webpack.config.js,推荐你用方案1+方案3的组合,修改后的配置大概是这样:
var webpack = require('webpack'); var path = require('path'); const UglifyJSPlugin = require('uglifyjs-webpack-plugin') var BUILD_DIR = path.resolve(__dirname, 'static/public/js'); var APP_DIR = path.resolve(__dirname, 'static/js'); var CSS_DIR = path.resolve(APP_DIR, 'css'); var config_function = function(env){ var config = { entry: ['babel-polyfill', APP_DIR + '/index.js'], output: { path: BUILD_DIR, filename: env && env.prod ? 'bundle.min.js' : 'bundle.js' }, resolve: { mainFields: ['main', 'module'] // 新增:优先加载ES5版本 }, plugins: env && env.prod ? [ new UglifyJSPlugin({ uglifyOptions:{ ecma: 5, mangle: { safari10: true }, compress: true } }) ]: [], module: { loaders: [{ test: /\.jsx?/, include: [APP_DIR], exclude: /node_modules\/(react|react-dom|redux|lodash)/, // 排除已预编译的库 loader: 'babel-loader', query: { presets: ['es2015', 'react', 'stage-2'] } } , { test: /\.scss$/, loaders: ['style-loader', 'css-loader', 'sass-loader'] }, { test: /\.json$/, loader: 'json-loader' }, { test: /\.less$/, include: CSS_DIR, loaders: ['style-loader', 'css-loader', 'less-loader'] }, { test: /\.css$/, loaders: ['style-loader', 'css-loader'] }] } }; return config; } module.exports = config_function;
内容的提问来源于stack exchange,提问作者Thomas Martres
相关产品推荐
相关产品推荐

