系列文章目录
webpack
前言
目录
一、webpack5
升级webpack5 以及周边插件后,代码需要做出的调整
package.json 的 dev-server 命令改了
"dev": "webpack server --config build/webpack.dev.js"
升级新版本 const {merge} = require('webpack-merge')
升级新版本 const {CleanWebpackPlugin} = require('clean-webpack-plugin')
`module.rules`中 loader:['xx-loader'] 换成 use:['xx-loader']
filename: 'bundle.[contenthasj:8].js' 其中 ‘h’ 小写,不能大写
loader执行顺序是 从后往前
二、webpack配置多入口
webpack.common.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { srcPath } = require('./paths');
module.exports = {
entry: {
index: path.join(srcPath, 'index.js'),
other: path.join(srcPath, 'other.js')
},
module: {
rules: [
]
},
plugins: [
// 单入口
new HtmlWebpackPlugin({
template: path.join(srcPath, 'index.html'),
filename: 'index.html'
}),
// 多入口-生成 index.html
new HtmlWebpackPlugin({
template: path.join(srcPath, 'index.html'),
filename: 'index.html',
// chunks 表示该页面要引用哪些 chunk
chunks: ['index'] // 只引用 index.js
}),
// 多入口-生成 other.html
new HtmlWebpackPlugin({
template: path.join(srcPath, 'other.html'),
filename: 'other.html',
chunks: ['other'] // 只引用 other.js
}),
]
}
webpack.prod.js
const path = require('path');
const webpack = require('webpack')
const {CleanWebpackPlugin} = requore('clean-webpack-plugin')
const webpackCommonConf = require('./webpack.common.js')
const { smart } = require('webpack-merge');
const {secPath, distPath } = require('./paths');
module.exports = smart(webpackCommonConf, {
mode: 'production',
output: {
// filename: 'bundle.[contentHash:8].js',
filename: '[name].[contentHash:8].js', // name即多入口时
path: distPath,
},
module: {
rules: [
// 图片-考虑 base64 编码的情况
{
test: /\.(png|jpg|jpeg|gif)$/,
use: {
loder: 'url-loader',
options: {
// 小于 5kb 的图片用 base64 格式产出
limit: 5*1024,
// 打包到 img 目录下
outputPath: './img1/',
}
}
}
]
},
plugins: [
new CleanWebpackPlugin(), // 会默认清空 output.path 文件夹
new webpack.DefinePlugin({
// window.ENV = 'production'
ENV: JSON.stringify('production')
})
]
})
三、抽离压缩css/分割代码chunk
webpack.prod.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserJSPlugin = require('terser-weebpack-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack');
plugins: [
new CleanWebpackPlugin(),
new webpack.DefinePlugin({
ENV: JSON.stringify('production')
}),
// 抽离 css
new MiniCssExtractPlugin({
filename: 'css/main.[contentHash:8].css'
})
],
optimization: {
// 压缩 css
minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
// 分割代码块
splitChunks: {
chunks: 'all',
// initial 入口 chunk,对于异步导入的文件不处理
// async 异步 chunk,只对异步导入的文件处理
// all 全部 chunk
// 缓存分组
cacheGroups: {
// 第三方模块
vendor: {
name: 'vendor', // chunk名称
priority: 1, // 权限更高,优先抽离,重要
test: /node_modules/,
minSize: 0, // 大小限制
minChunks: 1, // 最少复用过几次
},
// 公共的模块
common: {
name: 'common', // chunk名称
priority: 0, // 优先级
minSize: 0,
minChunks: 2
}
}
}
}
四、异步加载JS
// 引入动态数据 - 懒加载
setTimeout(() => {
import('./data.js'.then(res => {
console.log(res.default.message); // 注意default
}))
}, 1500);
五、处理 react/vue
react preset-react
vue vue-loader
.babelrc
{
"presets": ['@babel/preset-react'],
"plugins": []
}
六、module chunk bundle 区别
- module: 各个源码文件,webpack中一切皆模块
- chunk: 多模块合并成的,如 entry import() splitChunk
- bundle: 最终的输出文件
七、webpack性能优化
优化 babel-loader
{
test: /\.js$/,
use: ['babel-loader?cacheDirectory'], // 开启缓存
include: path.resolve(__dirname, 'src'), // 明确范围
// 排除范围, include 和 exclude 两者选一个即可
// exclude: path.resolve(__dirname, 'node_modules')
}
IgnorePlugin 避免引入无用模块
// 例如 moment 只引入中文
import moment from 'moment';
import 'moment/locale/zh-cn'; // 手动引入中文语言包
moment.lacale('zh-cn')
console.log('locale', moment.locale())
console.log('locale', moment.format('ll'))
webpack.prod.js
// 忽略 moment 下的 /locale 目录
new webpack.IgnorePlugin(/\.\/locale/, /moment/)
noParse 避免重复打包
module.exports = {
module: {
// 独立完整的‘react.min.js’ 文件就没有采用模块化
// 忽略对‘react.min.js’ 文件的递归解析处理
noParse: [/react\.min\.js$/],
}
}
happyPack 多进程打包
- JS单线程,开启多进程打包
- 提高构建速度(特别是多核CPU)
const HappyPack = require('happypack');
module.export = smart(webpackCommonConf, {
mode: 'xxxx', // 开发、生产
output: {
filename: '[name].[contentHash:8].js',
path: disPatch,
},
module: {
rules: [
{
test: /\.js$/,
use: ['happypack/loader?id=babel'],
include: srcPath,
}
]
},
plugins: [
new HappyPack({
// 用唯一的标识符 id 来代表当前的 HappyPack 是用来处理一类特定的文件
id: 'babel',
// 如何处理 .js 文件,用法和 Loader 配置中一样
loaders: ['babel-loader?cacheDirectory']
})
]
})
ParallelUglifyPlugin 多进程压缩JS
- webpack 内置 Uglify 工具压缩JS
- JS 单线程,开启多进程压缩更快
- 和happyPack 同理
module.export = smart(webpackCommonConf, {
mode: 'xxxx', // 开发、生产
output: {
filename: '[name].[contentHash:8].js',
path: disPatch,
},
module: {
rules: []
},
plugins: [
// 使用 ParallelUglifyPlugin 并行压缩输出的JS代码
new ParallelUglifyPlugin({
// 传递给 UglifyJS 的参数
// (还是使用 UglifyJS 压缩,只不过帮助开启了多进程)
uglifyJS: {
output: {
beautify: false, // 最紧凑的输出
comments: false, // 删除所有的注释
},
compress: {
// 删除所有 console 语句,可以兼容 ie 浏览器
drop_console: true,
// 内嵌定义了但是只用到一次的变量
collapse_vars: true,
// 提取出出现多次但是没有定义成变量去引用的静态值
reduce_vars: true
}
}
})
]
})
自动刷新
热更新
- 自动刷新:整个网页全部刷新,速度较慢
- 自动刷新:整个网页全部刷新,状态会丢失
- 热更新:新代码生效,网页不刷新,状态不丢失
DllPlugin 动态链接库插件
- webpack已内置 DllPlugin 支持
- DllPlugin - 打包出dll文件
- 通过DllRefercePlugin - 使用 dll 文件
webpack性能优化
- 小图片 base64 编码
- bundle加hash
- 懒加载
- 提取公共代码
- IngorePlugin
- 使用 CDN 加速
- 使用 production(1.自动开启代码压缩 2.vue/react等会自动删掉调试代码 3.启动 Tree-Shaking)
- Scope Hosting
八、Tree-Shaking
mode: "production" 自动 Tree-Shaking 不打包无用代码
ES6 Module 才能让 Tree-Shaking 生效
commonjs 不行
九、ES6 Module 和 commonjs 区别
- ES6 Module 静态引入,编译时引入
- commonjs 动态引入,执行时引入
- 只有 ES6 Module 才能静态分析,实现 Tree-Shaking
十、Scope Hosting
多个函数合并成一个函数,作用域减少
- 代码体积更好
- 创建函数作用域更少
- 代码可读性更好
十一、babel
preset 作为 Babel 插件的组合
plugins 补充插件
babel-polyfill
是 core.js(标准库,集合了es6/es7) 和 regenerator (generator异步函数)两个集合
Babel 7.4 之后弃用babel-polyfill 推荐直接使用core.js regenerator
babel-polyfill会污染全局环境
按需引入
babel-runtime
开发第三方库要用babel-runtime,重新取变量名 不会污染全局环境
总结
webpack知识点