1. 自动清理构建目录产物
每次在构建的时候不会清理目录,这会造成构建的输出目录的输出文件越来越多
- 通过npm scripts清理构建目录
在每次构建前先删除dist
目录,可在package.json
中的scripts
配置:
rm -rf ./dist && webpack
或
rimraf ./dist && webpack
但是这种方法需要手动操作
- 通过
clean-webpack-plugin
插件自动清理构建目录
这个插件会在每次构建的时候删除output指定的输出目录
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
output: {
filename: ....,
path: __dirname + '/dist' //clean-webpack-plugin插件会自动清除这个目录
},
plugins: [
new CleanWebpackPlugin();
]
}
⚠️为啥上面引入插件是 { CleanWebpackPlugin }
?
clean-webpack-plugin
(https://github.com/johnagan/clean-webpack-plugin) 在5.29的时候发布了3.0版本,用法变了。
2. 自动补齐css3样式前缀
- css3的属性为什么需要前缀?
因为浏览器的标准并没有完全统一 。
浏览器内核 | css3前缀 |
---|---|
Trident | -ms |
Geko | -moz |
Webkit | -webkit |
Presto | -o |
// 比如给一个元素设置border-radius属性
.box{
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
-o-border-radius: 10px;
border-radius: 10px;
}
手动添加很麻烦
- 通过使用autoprefixer插件自动补齐css3的前缀
这是代码生成后再进行后缀处理
autoprefixer需要配合postcss-loader
使用
npm i postcss-loader autoprefixer -D
module.exports = {
// ....
module: {
rules: [
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
plugins:() => [
require('autoprefixer')({
browsers: ['last 2 version', '> 1%', 'iOS 7'] // 兼容浏览器版本
})
]
}
}
]
}
]
}
}
3. 移动端CSS的px转换成rem
页面适配问题
- 以前通过css媒体查询实现响应式布局
缺点:需要写多套适配样式代码
@media screen and (max-width: 980px) { .header {
width: 900px; }
}
@media screen and (max-width: 480px) {
.header {
height: 400px; }
}
@media screen and (max-width: 350px) {
.header {
height: 300px; }
}
rem是什么?
W3C对rem的定义: font-size of the root element
rem是相对单位
px是绝对单位
点击查看rem em px的区别 >>
- 使用
px2rem-loader
将px转换成rem - 页面渲染时需要计算根元素的font-size的值
- 可以借助手淘的lib-flexible库
- https://github.com/amfe/lib-flexible
npm i px2rem-loader -D
npm i lib-flexible -S
- html 的script需要引入安装的lib-flexible库的代码(下面会讲怎么将库资源内联近代码)
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
{
loader: 'px2rem-loader',
options: {
remUnit: 75, // rem相对于px转换的倍数 1rem = 75px
remPrecision: 8 // px转换为rem小数点的位数
}
}
]
}
]
}
}
4. 静态资源内联
资源内联的意义:
-
代码层面:
页面框架初始化脚本
上报相关打点
css内联避免页面闪动 -
请求层面:
减少HTTP网络请求数
小图片或字体内联(url-loader)
一、HTML和JS的内联
都使用raw-loader
因为内联进来的代码可能存在一些ES6的属性,所以需要先使用babel-loader进行转换在内联进去
- 内联HTML
<script>${require('raw-loader!babel-loader!./meta.html')}</script>
- 内联JS(比如上述需要内联的lib-flexbile库)
<script>${require('raw-loader!babel-loader!../node_modules/lib-flexible')}</script>
二、CSS内联的两种方案
- 借助style-loader加参数
module.exports = {
// ....
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: 'style-loader',
options: {
insertAt: 'top', //样式插入到<head>标签内
singleton: true // 是否将所有的style标签合成一个
}
},
'css-loader'
]
}
]
}
}
- 使用html-inline-css-webpack-plugin插件
npm i html-inline-css-webpack-plugin -D
⚠️使用这个插件内联css,那么就不会单独抽离css了,则mini-css-extract-plugin将失效
const HtmlInlineCssWebpackplugin = require('html-inline-css-webpack-plugin').default;
module.exports = {
// ..
plugins: [
new HtmlInlineCssWebpackplugin()
]
}
5. 多页面应用打包方案
每次页面跳转的时候,后台服务器都会返回一个新的html文档,这种类型的网站就是多页网站,也叫做多页应用。
-
多页应用的优势:
每个页面之间是解藕的
对SEO更加友好 -
在webpack里如何打包多页面:
- 每个页面对应一个entry,一个html-webpack-plugin
这样的缺点:每次增加一个页面都需要更改webpack配置
- 动态获取entry和设置html-webpack-plugin数量(利用glob.sync)
entry: glob.sync(path.join(__dirname, './src/*/*.js'))
npm i glob -D
6. 使用sourcemap
- 作用: 通过source map可以定位到源代码(方便调试)
- 开发环境默认开启,线上环境默认关闭
source map关键字:
- eval: 使用eval包裹模块代码
- source-map: 产生.map文件
- cheap: 不包含列信息(比如报错时候会定位到多少行多少列,使用cheap就只能定位到多少行,无法定位到多少列)
- inline-source-map: 将.map作为DataURI嵌入,不单独生成.map文件(将.map文件inline进了输出文件最后一行)
- module:包含loader的sourcemap
使用:
module.exports = {
devtool: 'eval'
}
如果不开启source map在带啊嘛中打断点无法定位到源代码,而是会定位到打包后到代码,不方便调试。
7. 提取公共资源
-
基础库分离,
-
比如:将react react-dom基础包通过cdn引入,不导入bundle中
-
方法一:使用html-webpack-externals-plugin将基础包通过cdn引入,不打入bundle中
-
webpack4内置的一个功能非常大的插件代替了CommonsChunkPlugin插件
chunks参数说明:
- async 异步引入的库进行分离(默认)
- initial 同步引入的库进行分离
- all 所有引入的库进行分离(推荐)
// 以下是默认参数值
module.exports = {
optimization : {
splitChunks : {
chunks: 'async',
minSize: 30000, // 抽离的公共包最小的大小
maxSize: 0,
minChunks: 1, // 公共文件最小使用次数(大于这个值才会提取成公共文件)
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
}
}
}
}
}
8. tree shaking(摇树优化)
(对模块代码静态分析)
-
概念:一个模块可能有多个方法,只要其中某个方法使用到了,则整个文件都会被打到bundle里面去,tree shaking就是只把用到的方法打入bundle,没用到到方法会在uglify阶段被擦出掉。
-
使用:webpack4默认支持,在
.babelrc
里面设置modules: false
即可, 在production mode
的情况下默认开启 -
要求:必须是ES6的语法,CJS的方式不支持
-
理解DCE(Dead Code Elimination) ->无用代码擦除
无用代码举例: -
代码不会被执行,不可到达
-
代码执行的结果不会被用到
-
代码只会影响死变量(只读不写)
if(false) {
console.log(这段代码永远不会被执行到);
}
- tree shaking原理:
- 1.利用 ES6模块的特点:
- 只能作为模块顶层的语句出现
- import 的模块只能是字符串常量
- import binding是immutable的
- 2.代码擦除:
- uglify阶段无用代码擦除
- 1.利用 ES6模块的特点:
9. Scope Hoisting使用和原理分析
- 存在现象: 构建后的代码存在大量闭包代码