打包遇到了2次这个错,第1次是umi+dva的react项目,第2次是普通react-app项目。
不过2次报错有一丢丢区别,而且相隔很久,所以第2次遇到时,一时间没有反应过来。
// umi项目报错
Failed to minify the bundle. Error: index.a0a9eebd.js from UglifyJs
// 普通react-app项目
Failed to minify the code from this file:
./node_modules/sm-crypto/src/sm2/sm3.js:8
参考博客
不积跬步–Error index.a0a9eebd.js from UglifyJs 的解决过程
uglify 压缩报错问题及 es5-imcompatible-versions
原因
- build打包时,在编译之后,还会对代码进行压缩。但是 UglifyJs 并不能压缩es6的代码。而
webpack
默认打包的时候,一般都不会对node_modules
里面的包进行babel
的编译,即将es6转为es5。 - 所以业界有一个默认的规定是你发布包之前应该先把发布的包编译成
es5
的代码,然后再发布上去。 - 但是就是有一些包并不会遵守这条约定,没有转成 es5 就发上去,比如 query-string@6。
- 然后压缩工具 uglify 又只支持 es5 的语法,遇到
const
、let
、()=>
类似的语法,就抛错了。- 可以试试将依赖包里面的let改为var,看看可不可以编译成功。
- 这个时候你就需要自己找到这个包,然后进行针对处理。
umi项目:parse5包
-
umi提供了extraBabelIncludes进行配置,不过extraBabelIncludes并不支持ts文件的编译。
-
但是要定位到具体那一包有问题,并不容易。
-
而且还发现,cnpm安装的依赖和yarn安装的依赖,效果很不一样。
yarn(可行)
-
yarn安装依赖,F12在源代码index.js里面搜索,可以看到注释,标注以下部分来自来一个依赖包。
-
配置到.webpackrc,成功打包编译。
// https://www.npmjs.com/package/parse5?activeTab=versions "extraBabelIncludes":[ "node_modules/parse5" ]
cnpm(不推荐使用,处理失败)
-
cnpm安装依赖之后,连start启动都不行
-
不过,它的报错信息里面输出了具体是哪一个包有问题
./node_modules/_dom-serializer@2.0.0@dom-serializer/lib/esm/index.js Module parse failed: Unexpected token (135:21) You may need an appropriate loader to handle this file type. | if (elem.parent && | foreignModeIntegrationPoints.has(elem.parent.name)) { | opts = { ...opts, xmlMode: false }; | } | }
-
所以,处理起来很简单。
-
配置到.webpackrc,可以成功打包编译。
"extraBabelIncludes":[ "node_modules/_dom-serializer", "node_modules/_domhandler", "node_modules/_domutils", "node_modules/_entities" ]
-
但是测试发现,有些页面会白屏,比如手写签名
扩展
umi文档:extraBabelIncludes
-
配置额外需要做 babel 编译的 npm 包或目录
-
umi/roadhog 默认也是仅用 babel 编译项目文件,但提供了额外的 extraBabelInclude 配置可以指定 node_modules 下的文件。比如:
{ "extraBabelIncludes:" [ "node_modules/a", "node_modules/b" ] }
怎么处理ts文件:workspaces中的子包进行动态编译配置(别名配置)后编译报错?
webpack的配置
config.module.rules.get('ts-in-node_modules').include.add([join(__dirname, '../drbt-core')])
普通react-app项目:sm-crypto包
-
打包是使用的webpack
-
// webpack.config.js module.exports = { // ... module: { rules: [ // ... { test: /\.js$/, loader: 'babel-loader', // 注意这里的 include // 除了 src 还包含了额外的 node_modules 下的两个包 include: [ resolve('src'), resolve('node_modules/A'), resolve('node_modules/B') ] }, // ... ] }, // ... }
1.配置config\webpack.config.prod.js
const paths = require('./paths');
module.exports = {
module: {
strictExportPresence: true,
rules: [
{
test: /\.(js|jsx|mjs)$/,
// include: paths.appSrc,
include: [paths.appSrc, paths.smSrc],
loader: require.resolve('babel-loader'),
options: {
compact: true,
},
}
]
}
}
- 解释:paths.smSrc在另外的文件中定义:config\paths.js
const path = require('path');
const fs = require('fs');
const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
module.exports = {
appSrc: resolveApp('src'),
smSrc: resolveApp('node_modules/sm-crypto')
};
2.npm run build 继续报错
Failed to compile.
./node_modules/sm-crypto/src/index.js
Module build failed: Error: Couldn't find preset "es2015" relative to directory "...\\node_modules\\sm-crypto"
at Array.map (<anonymous>)
-
安装依赖,重新打包成功
yarn add babel-preset-es2015 --dev 或者 npm install babel-preset-es2015 --save-dev 或者直接在package.json添加,然后yarn "devDependencies": { "babel-preset-es2015": "^6.24.1", }
-
原因
-
sm-crypto里还是使用的babel-preset-es2015,但是当前react项目已升级为babel-preset-env。
-
可以手动修改第3方包,然后放在本地安装(自定义本地包)
-
-
如何升级babel-preset-es2015为 babel-preset-env
首先卸载原来的 preset,然后安装 babel-preset-env: npm uninstall --save-dev babel-preset-es2015 npm install --save-dev babel-preset-env@next 接下来将你的 .babelrc 文件中“es2015”修改“env” { "presets": [ "env" ], ... }
-
-
yarn add babel-preset-env --dev npm install babel-preset-env --save-dev 修改package.json "devDependencies": { // "babel-preset-es2015": "^6.24.1", "babel-preset-env": "^1.7.0", } 修改.babelrc { // "presets": ["es2015"] "presets": ["env"] } 将修改之后的包从node_modules整个拷贝到当前项目里 修改package.json "dependencies": { // "sm-crypto": "0.3.11", "sm-crypto": "file:package/sm-crypto", } rimraf node_modules //删除依赖 yarn //重新安装依赖 安装之后,yarn.lock的地址也会发生变动 "sm-crypto@file:package/sm-crypto": version "0.3.11" dependencies: jsbn "^1.1.0"
-
扩展
npm 加载本地包 file 加载本地 package dependencies
-
当我们npm下来一些三方的插件来使用,有时候会发现里面的逻辑有时候并不是我们想要的或者需要修改部分逻辑去适合我们自己的项目,这个时候我们就需要修改这个插件里面的源码了,但是我们直接修改在node_modules中的源码的时候,会发现有时候再次npm install时候或者有时候直接修改src里面的源码的时候,根本没有起作用,这时候我们分为两种情况去分析
-
1.直接修改src源码无效果的情况
这种情况其实只能说明我们没有修改对地方,我们要看的是这个插件里package.json里面的这样一行代码
"main": "xxxx/xxxxx"
找到这行就知道这个插件的入口是什么了,这样我们去修改相对应的代码就可以生效
-
2.修改源码之后,当初逻辑已经成功了,但是再次npm install的时候,原来修改的效果消失
这种情况其实还是蛮头疼的,不怕一万就怕万一,那这种情况该这么处理呢?
①、这个时候我们需要把npm下来的这个插件的所有代码复制出来,然后用我们的vscode等编译器把他跑起来,在这个源码上把所有我们想要的逻辑全部添加上去,然后重新打包。
②、然后在自己的项目里建立一个文件夹,我的是用的npmfile命名的文件夹,把刚才修改的插件源码放进去,记住只放主要的代码,什么demo代码这些就不需要放进去了,影响包的大小,但是插件的package.json一定要放进来。
③、去自己项目的package.json的dependencies的map里找到相对应的我们修改的插件名字,修改更目录地址,比如:"vue-slim-better-scroll": "file:./src/npmfile/vue-slim-better-scroll" file:后面就是我们修改后的源码所放的地方
④、然后npm install,然后跑起来,这样就不会被还原代码啦
# 卸载已安装的 要很久
npm uninstall react-color
# 安装本地的 根目录下
npm i ./react-color