webpack4升级webpack5
借着公司项目,将webpack4升级到webpack5,下面是一些主要配置方式
webpack5新特性介绍
- 启动命令
- 持久化缓存
- 资源模块
- moduleIds & chunkIds的优化
- 更智能的tree shaking
- nodeJs的polyfill脚本被移除
- 模块联邦
npm i react-dev-utils webpackbar friendly-errors-webpack-plugin -D
npm i webpack webpack-cli webpack-dev-server webpack-merge -D
升级步骤
1、自定义开发环境
对于开发环境,我们更加灵活的自定义配置的方式
const webpack = require("webpack");
const WebpackDevServer = require('webpack-dev-server');
const compiler = webpack(config)
const devServer = new WebpackDevServer(compiler, devConfig)
devServer.listen(Config.port, host, err => {
if (err) {
return console.log(err);
}
console.log(chalk.cyan('Starting the development server...\n'));
});
2、端口号(可能被占用)
随着项目越来越多,端口号可能会出现重复,所以启动项目时发现端口号已经被占用,需要找到合适的可用端口进行启动项目
const portfinder = require('portfinder');
portfinder.getPortPromise()
.catch((err) => {
console.log('webpack启动错误', err)
})
.then((port) => {
// 没有被占用的端口号
console.log(port)
})
3、ip链接
需求:由于移动端或者pc端,经常会拿ip链接进行手机的调试,或者将ip链接发送给对方进行联调,这时如果开发工具者控制台有这样的ip链接就很方便
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
new MyFriendlyErrorsWebpackPlugin({
compilationSuccessInfo: {
messages: [
'App running at:',
`- Local: ${chalk.cyan(newWorkUrl(host, port, Config.prefix))}`,
`- Network: ${chalk.cyan(newWorkUrl(getNetworkIp(), port, Config.prefix))}`,
],
notes: [
'Note that the development build is not optimized.',
`To create a production build, run ${chalk.cyan('npm run build')}`,
]
},
}),
const os = require('os')
function getNetworkIp() {
let needHost = ''; // 打开的host
try {
// 获得网络接口列表
let network = os.networkInterfaces();
for (let dev in network) {
let iface = network[dev];
for (let i = 0; i < iface.length; i++) {
let alias = iface[i];
if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
needHost = alias.address;
}
}
}
} catch (e) {
needHost = 'localhost';
}
return needHost;
}
function prettyPrintHost(host) {
const isUnspecifiedHost = host === '0.0.0.0' || host === '::';
if (isUnspecifiedHost) {
return 'localhost';
}
return host
}
function newWorkUrl(host, port, prefix) {
return `http://${prettyPrintHost(host)}:${port}/${prefix ? prefix : ''}`
}
问题:
antv和webpack5之间有一些警告问题,一旦有了警告,那么friendly-errors-webpack-plugin就不会将我们的ip链接暴露出来,所以本地二次封装friendly-errors-webpack-plugin插件,达到目的
4、添加缓存
cache: {
type: 'filesystem', //'memory' | 'filesystem'
cacheDirectory: path.resolve(__dirname, '../node_modules/.cache/webpack'),
},
4.1、去除dll动态链接库
create-react-app以及vue-cli在webpack4.x的时候就已经移除dll,原因:就是webpack4.x的性能足够好,使用dll后收益非常小,而且dll还需要进行额外的繁琐配置
结论:我们也去除dll,配置中将所有关于dll的全部删除掉
5、关于图片和图标
去除file-loader和url-loader
{ // 图标的转化
test: /\.(woff|woff2|eot|ttf|otf|svg)$/i,
type: 'asset/resource'
},
{ // 图片的转化
test: /\.(jpe?g|png|gif|bmp)$/i,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8192,// 8kb
}
}
},
6、css的路径问题
因为css和images是单独打包成一个独立的文件夹,那么css中寻找图片路径是从css目录开始找的,所以需要配置下
isDevelopment ? {
loader: "style-loader",
options: { esModule: true },
} : {
loader: MiniCssExtractPlugin.loader,
options: { esModule: true, publicPath: '../' }, // 在原来配置的基础上添加publicPath属性
},
7、启动
"scripts": {
"dev": "node ./scripts/webpack.dev",
"build:hr": "webpack --config ./scripts/webpack.prod",
"start": "cross-env NODE_ENV=development npm run dev",
"build": "cross-env NODE_ENV=production npm run build:hr"
},
开发:npm run start
打包:npm run local/test/pre/build
8、css压缩插件
optimize-css-assets-webpack-plugin 在webpack5中不建议使用了
说明:如果使用webpack5版本,需要使用css-minimizer-webpack-plugin插件进行替换
细节问题
1、webpack5和cnpm有兼容性
因为webpack5里面的解析包是按照npm标准的@babel这样的格式,如果违反规则直接失败,而cnpm是_@babel多了一个下划线
结论:避免使用cnpm,使用npm和yarn的方式
2、webpack.NamedChunksPlugin被废弃
optimization: {
moduleIds: 'deterministic', // 模块名称的生成规则 -> 根据模块名称生成简短的hash值
chunkIds: 'deterministic', // 代码块名称的生成规则
}
3、watermark-dom
# webpack4引用
import watermark from 'watermark-dom'
watermark.loading({})
# webapack5
改成
import 'watermark-dom'
watermark.loading({})
原因:webpack4和webpack5对非【commonjs和esmodule】打包方式不一致,webpack5是直接将其注入到window属性中
4、mac启动项目默认打开一个tab
举例:如果本地已经启动了 http://localhost:8080/web/ 的项目,并且在浏览器中打开了(不关闭),如果我们将8080端口的项目关掉,在重新启动项目,则会在浏览器中找到刚才运行的项目页面开始编译,不会重新在浏览器中重新打开一个新的页面
const openBrowser = require('react-dev-utils/openBrowser');
devServer.listen(Config.port, host, err => {
if (err) {
return console.log(err);
}
console.log(chalk.cyan('Starting the development server...\n'));
+ openBrowser(`http://localhost:${port}/${Config.prefix}`)
});
5、清空控制台信息
原因:开发中,启动项目时,我们并不需要控制台这么多信息,本着简洁的原则需要:编译时间、以及项目链接
开发
new WebpackDevServer(compiler, {
overlay: false,
quiet: true,
})
生产
stats: {
all: false,
errors: true,
moduleTrace: true,
logging: 'error',
assets: true,
},
6 移除clean-webpack-plugin
- 5.20版本以后output新增特性clean,用于清除dist文件
{
output: {
clean: true, // Clean the output directory before emit.
}
}
移除插件
- add-asset-html-webpack-plugin 不再需要
- open-browser-webpack-plugin 新插件替换
- url-loader、file-loader 对于图片/图标webpack5有新的写法
- hard-source-webpack-plugin 不再需要,有新的缓存方式
添加插件
-
react-dev-utils 辅助工具
-
friendly-errors-webpack-plugin 启动提示
-
webpackbar 启动进度条/编译时间
升级前后编译对比
webpack版本 | 首次编译(s) | 二次启动(s) | 修改文件编译(s) | 打包时间(s) | 打包体积 | 备注 |
---|---|---|---|---|---|---|
4.41.0 | 25s左右 | 25s左右 | 1s左右 | 40左右 | 2730kb | |
5.43.0 | 25s左右 | 3s左右 | 1s左右 | 40左右 | 2669kb |
转载自:https://juejin.cn/post/6982860564851032077