entry / output
module.exports = {
entry: './index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index.bundle.js'
}
}
// 或
module.exports = {
entry: [
index: './index.js',
main: './main.js'
],
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].bundle.js'
}
}Loader
(1) url-loader
// 将图片转成base64
// 需导入url-loader、file-loader
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192
}
}
]
}
]
}
}(2) babel-loader
// 需导入babel-loader
module.exports = {
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_module|bower_components)/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: [
// 转换react jsx
'@babel-plugin-transform-react-jsx'
]
}
}
]
}
]
}
}(3) sass-loader
// 需导入sass-loader、node-sass
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
}
]
}
}Plugin
(1) miniCssExtractPlugin
// 作用:把css从js文件分离出来
module.exports = {
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css'
})
]
module: {
rules: [
{
test: /\.scss$/,
use: [
process.env.NODE_ENV !== 'production' ?
'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader'
]
}
]
}
}(2) DefinePlugin
// 用于定义公共变量,例如服务器地址
module.exports = {
plugins: [
new webpack.DefinePlugin({
'SERVER_URL': JSON.stringify('http://www.baidu.com')
})
]
}(3) HtmlWebpackPlugin
// 需导入html-webpack-plugin
module.exports = {
plugins: [
new HtmlWebpackPlugin({
title: 'website title',
filename: 'index.html',
template: 'template.html'
})
]
}
// 模板语法举例
<%= htmlWebpackPlugin.options.title %>Hot Module Replacement
// 需要导入webpack-dev-server
module.exports = {
devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true,
port: 8080
}
}
附:webpack打包优化实践
性能查看工具
(1)
webpack-bundle-analyzer
:以图表的形式展示各包的内部情况;(2)
speed-measure-webpack-plugin
:给出各个Plugins
和各个Loaders
的耗时;entry
优化(1) 把公共模块合成单独的入口
注意:这里只是合成,但这些模块还是没有从主文件
index
中抽离。entry: {
vendor: [
'react',
'react-dom',
'react-router-dom',
'react-router',
'redux',
'react-redux',
'echarts'
],
index: paths.appIndexJs,
polyfills: require.resolve('./polyfills')
},optimization
优化
(1) 使用splitChunks
抽离代码(结合webpack-bundle-analyzer
来操作)
optimization: { |
(2) 优化minimizer
性能
js
压缩混淆是webpack
编译中最耗时的任务之一,可以开启多线程与缓存,同时关闭sourceMap
。
minimizer: [ |
打包时间、加载时间的优化方向
(1) 细节优化
babel-plugin-import 按需加载
例如
antd
、lodash
、material-ui
,可以使用 ;排除无用语言包
例如
date-fns
使用 ContextReplacementPlugin。特定的库有专门的
webpack
插件例如 antd 使用 antd-dayjs-webpack-plugin 替换 moment 成 dayjs,例如 lodash 使用 lodash-webpack-plugin 进一步减小打包体积。
配置
noParse
像
jquery
这种npm
包就是一个单文件的依赖,可以配module.noParse
,这样webpack
就不会去解析其中的依赖关系。
(2) 大优化
路由懒加载
require.ensure()
、import()
一些动态加载插件都是使用
import()
来实现。但要注意:react-loadable
本身并不实现动态加载,只实现一个加载流程框架,代码的动态导入功能是外部调用传入的。合理配置
exclude
属性例如:
babel-loader
我们一般配置exclude:/node_modules/
,告诉webpack
模块路径匹配/node_modules/
的模块不用babel-loader
处理。使用
DllPlugin
将依赖单独打包(作用类似splitChunks
)使用
DllPlugin
将依赖单独打包成dll.bundle.js
,同时会生成一份json
配置表,用来告诉webpack
在编译时排除这些模块;再用
add-asset-html-webpack-plugin
将dll.bundle.js
通过script
标签插到index.html
,这样你开发时打包的代码只有业务代码,大大减少了打包体积。配置
external
所谓
external
就是告诉webpack
哪些模块我会通过script
加载的,在打包的时候不用处理这些依赖,例如lodash
,moment
,有条件的公司可以将这些依赖部署到 CDN 上。最后用add-asset-html-webpack-plugin
将这些script
打包到html
上。利用多线程
使用
babel
编译TypeScript
,fork-ts-checker-webpack-plugin
检查TypeScript
类型,而不是使用ts-loader
串行编译和检查类型;使用
thread-loader
让loader
跑在线程池里(有限制)。
其它情况
(1)
electron
因为 webpack 使用 babel 来编译代码,所以优化 babel 配置也是优化 webpack 打包配置。例如
babel-preset-env
用到了browserslist
来针对兼容环境提供polyfill
和转换语法。假设你是写 electron 项目,那就可以配置 browerslist 兼容到 electron 对应版本即可;
而且 electron 环境下就不要配置 postcss 的 autoprefixer 插件去自动添加浏览器头了。
(2) 其它配置
对于有些插件例如
@babel/plugin-proposal-class-properties
,还可以配置loose
选项来减小转换后的代码体积。非
webpack
优化(微前端)工具:qiankun
参考资料: