1.移动端px自动转rem
下载px2rem-loader
npm i px2rem-loader -D
页面渲染时计算根元素的font-size使用手机淘宝的lib-flexible
npm i lib-flexible -S
并将其内联在网页内(raw-loader下节会讲解)
webpack.config.js
module.exports = {
module: {
rules: [{
test: /\.css$/,
use: [
MinicssExtractPlugin.loader, //此处用MinicssExtractPlugin.loader替代'style-loader'
'css-loader',
{
loader: 'postcss-loader',
options: {
plugins: [require('autoprefixer')]
}
},
{
loader:'px2rem-loader',
options:{
remUnit:75,
remPrecision:8
}
}
]
},
]
}
}
2.静态资源内联—raw-loader
css,js,图片等静态资源内联到html内,css内联避免页面闪动
下载raw-loader(raw-loader返回的是一个字符串)
npm i [email protected] -D
内联js:
html页面(raw-loader!babel-loader!后面是js文件路径)
内联css:
方案一:借助style-loader
webpack.config.js
module.exports = {
module: {
rules: [{
test: /\.css$/,
use: [
{
loader:'css-loader',
options:{
insertAt:'top',//——>样式插入到head
singleton:true //——>将所有的style标签合并成一个
}
},
'css-loader',
{
loader: 'postcss-loader',
options: {
plugins: [require('autoprefixer')]
}
}
]
},
]
}
}
方案二:html-inline-css-webpack-plugin
npm i html-inline-css-webpack-plugin -D
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HTMLInlineCSSWebpackPlugin = require("html-inline-css-webpack-plugin").default;
module.exports = {
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
}),
new HtmlWebpackPlugin(),
new HTMLInlineCSSWebpackPlugin(),
],
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader"
]
}
]
}
}
3.tree shaking的使用和原理
摇树原理就是把有用的打包到bundle里去,把没用的在uglify阶段删除。摇树原理用到了DCE
DCE (Elimination) 包括以下几种形式:
- 代码不会执行,不可到达
- 代码执行结果不会被用到
- 代码只会影响死变量(只写不读)
生产环境下默认开启tree-shaking
css摇树,需要配合css提取插件使用
我自己尝试了一下感觉并不好用,引了bootstrap结合自己的css,结果只能获取其中一个样式,另一个样式被干掉了,目前没有找到解决方法,于是先放弃了css摇树
找到上面的解决方法就是通过glob-all传入多个参数,处理多路径文件
安装:
npm install -D purifycss-webpack purify-css glob-all
webpack.config.js
const glob = require('glob-all');
const purifycssWebpack = require('purifycss-webpack');
// Make sure this is after ExtractTextPlugin!
new purifycssWebpack({
paths: glob.sync([path.resolve('./src/*.html'),path.resolve('./src/*.js')])
}),
注
:注意插件顺序:html文件生成 > css提取 > css摇树
4.scope hoisting使用和原理分析
模块转化分析:
- 被webpack转换后的模块会带上一层包裹
- import会转换成__webpack_require
scope hoisting原理:
将所有模块的代码按照引用顺序放在一个函数作用域里,然后适当的重命名一些变量以防止变量名冲突。
通过scope hoisting可以减少函数声明代码和内存开销
scope hoisting使用
Webpack4 mode设为production会默认开启scope hoisting;必须是es6语法,commonjs不支持
5.代码分割
使用场景
- 抽离相同代码到同一个共享块
- 脚本懒加载,使得初始下载的代码更小
懒加载js脚本
方式一:commonJS: require.ensure
方式二:ES6:动态 import
(目前还没有原生支持,需要babel转换)
下载插件:
npm install @babel/plugin-syntax-dynamic-import --save-dev
{
plugins:['@babel/plugin-syntax-dynamic-import'],
}
6.多页面打包通用方案
动态获取 entry 和设置 html-webpack-plugin 数量
利用glob.sync
npm i glob -D
//引入glob
const glob=require('glob');
const path = require('path');
//引入html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin');
//动态设置entry,htmlwebpackplugin
const setMPA=()=>{
const entry={};
const HtmlWebpackPlugins=[];
const entryFiles=glob.sync(path.join(__dirname,'./src/*/index.js'));
Object.keys(entryFiles).map((index)=>{
const entryFile=entryFiles[index];
const match=entryFile.match(/src\/(.*)\/index\.js/);
const pageName=match&&match[1];
entry[pageName]=entryFile;
HtmlWebpackPlugins.push(
new HtmlWebpackPlugin({
filename: path.join(__dirname, `dist/${pageName}.html`),//输出文件名
template: path.join(__dirname,`src/${pageName}/index.html`),
chunks:[pageName],//我的理解是一个入口就是一个chunk
inject: true,//是否注入css,js,true表示在打包完成的 [pageName].html 内自动引入 chunks 为 [pageName] 的css,js
minify: { //压缩html
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true,
minifyCss: true, //——>此处的minifyCss/js是为了压缩[pageName].html页面内的内嵌css/js,并不会对外链的css/js有影响
minifyJs: true
},
// 通过CommonsChunkPlugin持续处理多个块的必要条件
chunksSortMode: 'dependency',
})
)
})
return {entry,HtmlWebpackPlugins}
}
const {entry,HtmlWebpackPlugins} = setMPA();
module.exports = {
entry:entry,
plugins:[].concat(HtmlWebpackPlugins)//将HtmlWebpackPlugins添加到plugins的数组中
}
7.devtool:
一般来说:生产环境推荐使用
none
.
对于开发环境推荐使用cheap-module-source-map
、eval-source-map
source-map
,inline-source-map
会暴露源码.
nosources-source-map
会隐藏源码
8.提取公共资源
基础库分离,减少代码冗余,提高加载速度
通过cdn导入,不打包在包内
利用 SplitChunksPlugin
进行公共脚本分离
他是webpack4内置的,替代 CommonsChunkPlugin
插件,CommonsChunkPlugin 已弃用
module.exports = {
optimization: {
splitChunks: {
chunks: 'async',
minSize: 30000, //——>最小尺寸必须大于此值,默认30000B
maxSize: 0,
minChunks: 1, //—>其他entry引用次数大于此值,默认1,个人理解minChunks指的是被不同entry引入的次数,为1时,适合分离 node_moudles 里的第三方库
maxAsyncRequests: 5, //——> 异步请求的chunks不应该超过此值
maxInitialRequests: 3, //—-->entry文件请求的chunks不应该超过此值(请求过多,耗时)
automaticNameDelimiter: '~', //——>自动命名连接符
name: true, //——>生成文件名
cacheGroups: { //——>它决定生成的文件
commons: { // 抽离自己写的公共代码
chunks: "initial",
name: "common", // 打包后的文件名,任意命名
minChunks: 2,//最小引用2次
minSize: 0 // 只要超出0字节就生成一个新包
},
vendors: { // 抽离第三方插件
test: /[\\/]node_modules[\\/]/, //限制范围,可以是正则,匹配出需要分离的包
name: 'vendor', // 打包后的文件名,任意命名
priority: 10 //优先级,多个分组冲突时决定把代码放在哪块,防止和自定义的公共代码提取时被覆盖,不进行打包
}
}
}
}
}
chunks 值为initial
, async
或 all
- initial 入口chunk,同步引入的库进行分离
- async 异步chunk,异步引入的库进行分离,忽略同步引入的库(默认)
- all: 所有引入的库进行分离(推荐)
我的个人博客,有空来坐坐