自动清理构建目录产物
- 每次构建的时候不会清理目录,造成构建的输出目录output文件越来越多
在启动命令追加 rm -rf ./dist/ && weback (*不建议使用)
clean-webpack-plugin
默认删除output指定的目录
npm i clean-webpack-plugin@2.0.2 -D
webpack配置 ```javascript const CleanWebPackPlugin = require(“clean-webpack-plugin”)
plugins: [ new CleanWebPackPlugin() ]
<a name="PRWyp"></a>### 自动补齐CSS3前缀- CSS3 属性兼容各大浏览器内核- 使用 postcss-loader 和 autoprefixer```javascriptnpm i postcss-loader@3.0.0 autoprefixer@9.5.1 -D
webpack配置
{
test: /.less$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader',
{
loader: "postcss-loader",
options: {
// "ident": "postcss",
"plugins": () => [
//postcss 需要的插件
require('autoprefixer')({
browsers: ['last 1 version', '>1%', 'ios 7']
})
]
}
}
]
}
移动端CSS px 转 rem 适配
- w3c 出现了 rem 自动适配不同分辨率的移动端设备
- 使用px2rem-loader 将 px 转换为 rem
lib-flexible: 动态计算 rem 根元素的单位
npm i px2rem-loader@0.1.9 -D npm i lib-flexible@0.3.2 -Swebpack 配置
{ test: /.less$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'less-loader', { loader: "postcss-loader", options: { // "ident": "postcss", "plugins": () => [ //postcss 需要的插件 require('autoprefixer')({ browsers: ['last 1 version', '>1%', 'ios 7'] }) ] } }, { loader: "px2rem-loader", options: { remUnit: 75, //1个rem 代表 75px remPrecision: 8 //px转rem 时小数点后8位 } } ] },在 未打包的html 顶部引入 lib-flexible: 动态计算 rem 根元素的单位
资源内联
资源内联的意义
代码层面
- 将页面框架的初始化脚本打包压缩到输出的构建产物
- 上报相关的打点
- css内联 避免页面闪动,页面优化,减少白屏时间
- 请求层: 减少HTTP网络请求数
- 小图片或者字体内联(url-loader中参数 limit :小于 limit 则内联到文件中)
-
HTML | JS 内联
raw-loader 内联html或者js
npm i raw-loader@0.5.1 -D//内联 html <script${ require('raw-loader!babel-loader./xxx.html')}></script> //内联 js <script${ require('raw-loader!babel-loader../../node_modules/lib-flexible/flexible.js')}></script>CSS 内联
借助 style-loader
{ loader: 'style-loader', options: { insertAt: 'top', //样式插入到<head> singleton: true, //将所有 style 标签合成一个 } }借助 html-inline-css-webpack-plugin (一般用这个)
多页面应用打包
打包思路
每个页面对应一个entry, 一个 html-webpack-plugin
-
打包方案
动态获取 entry 和 设置 html-webpack-plugin 数量
- 利用 glob.sync, 动态获取 入口文件 ```javascript entry: glob.sync(path.join(__dirname, ‘./src/*/index.js’))
entry: { index: ‘./src/index/index.js’, search: ‘./src/search/index.js’ }
const setMPA = () => {
const entry = {}
const htmlWebPackPlugIn = []
const entryFiles = glob.sync(path.join(dirname, ‘./src//index.js’))
entryFiles.forEach((index) => {
const match = index.match(/src\/(.)\/index.js/)
const pageName = match && match[1]
entry[pageName] = index
htmlWebPackPlugIn.push(
new HtmlWebPackPlugIn({
template: path.join(dirname, src/${pageName}/index.html),
filename: ${pageName}.html,
chunks: [pageName], // 将打包生成的所有资源(JS/CSS)自动引入到html
inject: true,
minify: {
// 移除空格
collapseWhitespace: true,
// 移除注释
removeComments: true,
}
})
)
})
return {
entry,
htmlWebPackPlugIn
}
}
```javascript
npm i glob@7.1.4 -D
source-map
- 在项目开发中通过sourcemap定位到源码位置去调试
开发环境开启,线上环境关闭
eval: 使用 eval 包裹模块代码
- source map: 产生.map 文件
- cheap: 不包含列信息
- inline: 将.map文件作为 DataURL 嵌入,不单独生成.map 文件
-
提取页面公共资源
基础库分离
将 react,react-dom 基础包通过 cdn 引入,不打入 bundle 中(推荐使用)
- 虽然可以使用 splitChunksPlugin 进行分离,但是构建后文件还存在该库,影响 资源的 请求下载
- 使用 html-webpack-externals-plugin
```sql const HtmlWebpackExternalsPlugin = require(‘html-webpack-externals-plugin’);npm i html-webpack-externals-plugin@3.8.0 -D
module.exports = { // 其它省略… plugins: [ new HtmlWebpackExternalsPlugin({ externals: [ { module: ‘react’, entry: ‘https://now8.gtimg.com/now/lib/16.2.0/react.min.js‘, global: ‘React’ }, { module: ‘react-dom’, entry: ‘https://now8.gtimg.com/now/lib/16.2.0/react-dom.min.js‘, global: ‘ReactDom’ } ] }) ], // 其它省略… }
然后在对应的html文件中引入react react-dom
```html
<!-- html-webpack-externals-plugin将 react,react-dom分离,基础包通过 cdn 引入 -->
<script type="text/javascript" src="https://now8.gtimg.com/now/lib/16.2.0/react.min.js"></script>
<script type="text/javascript" src="https://now8.gtimg.com/now/lib/16.2.0/react-dom.min.js"></script>
- 使用 splitChunks 分离
- 记得在 HtmlWebPackPlugIn 中添加 打包生成的 chunks vendor
```javascript
optimization: {
splitChunks: {
cacheGroups: { // 缓存组会继承splitChunks的配置,但是test、priorty和reuseExistingChunk只能用于配置缓存组。
vendor: { // key 为entry中定义的 入口名称
} } } }chunks: "all", // 必须三选一: "initial"(初始化) | "all" | "async"(默认就是异步) test: /(react|react-dom)/, // 正则规则验证,如果符合就提取 chunk name: "vendor", // 要缓存的 分隔出来的 chunk 名称 // minSize: 0, // minChunks: 1,
- 记得在 HtmlWebPackPlugIn 中添加 打包生成的 chunks vendor
```javascript
optimization: {
splitChunks: {
cacheGroups: { // 缓存组会继承splitChunks的配置,但是test、priorty和reuseExistingChunk只能用于配置缓存组。
vendor: { // key 为entry中定义的 入口名称
new HtmlWebPackPlugIn({
template: path.join(__dirname, src/${pageName}/index.html),
filename: ${pageName}.html,
chunks: [‘vendor’, pageName], // 将打包生成的所有资源(JS/CSS)自动引入到html
inject: true,
minify: {
// 移除空格
collapseWhitespace: true,
// 移除注释
removeComments: true,
}
})
<a name="t3xLy"></a>
#### 公共脚本分离
[参考](https://www.cnblogs.com/sunshq/p/11051675.html)
- 利用 splitChunksPlugin 进行公共脚本分离
- **chunks 参数说明**
- **async 异步引入的库进行分离(默认)**
- **initial 同步引入的库分离**
- **all 所有引入的库分离 (推荐使用)**
```sql
optimization: {
splitChunks: {
chunks: "initial", // 代码块类型 必须三选一: "initial"(初始化) | "all"(默认就是all) | "async"(动态加载)
minSize: 0, // 最小尺寸,默认0
minChunks: 1, // 最小 chunk ,默认1
maxAsyncRequests: 1, // 最大异步请求数, 默认1
maxInitialRequests: 1, // 最大初始化请求书,默认1
name: () => {}, // 名称,此选项课接收 function
cacheGroups: { // 缓存组会继承splitChunks的配置,但是test、priorty和reuseExistingChunk只能用于配置缓存组。
priority: "0", // 缓存组优先级,即权重 false | object |
vendor: { // key 为entry中定义的 入口名称
chunks: "initial", // 必须三选一: "initial"(初始化) | "all" | "async"(默认就是异步)
test: /react|lodash/, // 正则规则验证,如果符合就提取 chunk
name: "vendor", // 要缓存的 分隔出来的 chunk 名称
minSize: 0,
minChunks: 1,
enforce: true,
reuseExistingChunk: true // 可设置是否重用已用chunk 不再创建新的chunk
}
}
}
}
