webpack4.x从0开始构建多页项目(一)-项目说明.
webpack4.x从0开始构建多页项目(二)-多页实现.
webpack4.x从0开始构建多页项目(三)-插件及loader配置.
1.转换 ES6 代码,解决浏览器兼容问题
用 babel 转换 ES6 代码需要使用到 babel-loader ,我们需要安装一系列的依赖:
cnpm i babel-core babel-loader babel-preset-env --save-dev
使用 babel-polyfill 解决兼容性问题
npm i babel-polyfill babel-plugin-transform-runtime --save-dev
在webpack.rules.conf.js中添加如下配置
{test: /\.js$/,exclude: /(node_modules)/,include: /src/, //限制范围,提高打包速度use: [{loader: 'babel-loader',options: {presets: ['@babel/preset-env',],plugins: ['@babel/transform-runtime']}}]},
然后在根目录新建一个babel配置文件 .babelrc:
{"presets": [["@babel/preset-env",{"useBuiltIns": "usage","modules": false}]],"plugins": [["@babel/plugin-transform-runtime",{"corejs": false,"helpers": false,"regenerator": false,"useESModules": false}]],"comments": false
}
2.使用scss编译css,自动添加前缀
安装依赖
cnpm i mini-css-extract-plugin css-loader style-loader postcss-loader sass-loader node-sass --save-dev
//分离css,webpack4推荐的分离css的插件
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
在webpack.rules.conf.js中添加如下配置
{test: /\.(css|scss|sass)$/,use: process.env.NODE_ENV === "development" ? ["style-loader", "css-loader", "sass-loader", "postcss-loader"] :[MiniCssExtractPlugin.loader, "css-loader", "postcss-loader", "sass-loader"],include: /src/, //限制范围,提高打包速度exclude: /node_modules/},
然后在根目录新建一个配置文件 postcss.config.js:
module.exports = {plugins: [require('autoprefixer')]
};
3.消除冗余的css(需要引入一个额外包glob用于扫描路径)
cnpm i purifycss-webpack purify-css -D
const PurifyCssWebpack = require('purifycss-webpack');
// 在plugins中配置new purifyCssWebpack({paths: glob.sync(path.join(__dirname, "../src/pages/*/*.html"))}),
4.压缩 js
cnpm install uglifyjs-webpack-plugin --save-dev
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
// 在optimization中配置
optimization: {minimizer: [new UglifyJsPlugin({cache: true,parallel: true,// sourceMap: true // set to true if you want JS source maps}),]
},
5.压缩 CSS
cnpm i -D optimize-css-assets-webpack-plugin
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
// 在optimization中配置
optimization: {minimizer: [new OptimizeCSSAssetsPlugin({})]
}
6.清理 dist 目录
每次构建,我们的 /dist 文件夹都会保存生成的文件,然后就会非常杂乱。
通常,在每次构建前清理 /dist 文件夹,是比较推荐的做法
cnpm install clean-webpack-plugin --save-dev
const CleanWebpackPlugin = require('clean-webpack-plugin');
// 在plugins中配置
new cleanWebpackPlugin(['dist'], {root: path.resolve(__dirname, '../'), //根目录// verbose Write logs to console.verbose: true, //开启在控制台输出信息// dry Use boolean "true" to test/emulate delete. (will not remove files).// Default: false - remove filesdry: false,
}),
7.加载图片与图片优化
在css引入图片运行打包发现如下错误:
ERROR in ./src/assets/images/test.jpg 1:0
Module parse failed: Unexpected character '?' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
(Source code omitted for this binary file)
解决方案:file-loader处理文件的导入
cnpm install --save-dev file-loader
// 在rules中配置
{test: /\.(png|svg|jpg|gif)$/,use: ['file-loader']
}
更进一步处理图片成 base64
cnpm install --save-dev url-loader
cnpm install image-webpack-loader --save-dev
// 在rules中配置
{test: /\.(png|svg|jpg|gif|jpeg|ico|woff|woff2|eot|ttf|otf)$/,use: [{loader: "url-loader",options: {limit: 5 * 1024, //小于这个时将会已base64位图片打包处理// 图片文件输出的文件夹publicPath: "../images",outputPath: "images"}},{loader: 'image-webpack-loader', // 进行图片优化}]
}
8.字体的处理(同图片)
由于 css 中可能引用到自定义的字体,处理也是跟图片一致。
// 在rules中配置
{test: /\.(woff|woff2|eot|ttf|otf)$/,use: ['file-loader']
}
9.webpack4.x 提取公共代码
当一部分代码需要反复被用到,反复请求浪费资源,将公共代码 抽离,需要时读取缓存即可
webpack4 最大的改动就是废除了CommonsChunkPlugin 引入了 optimization.splitChunks
//splitChunks//常用配置
splitChunks: {chunks: "async”,//默认作用于异步chunk,值为all/initial/async/function(chunk),值为function时第一个参数为遍历所有入口chunk时的chunk模块,chunk._modules为chunk所有依赖的模块,通过chunk的名字和所有依赖模块的resource可以自由配置,会抽取所有满足条件chunk的公有模块,以及模块的所有依赖模块,包括cssminSize: 30000, //表示在压缩前的最小模块大小,默认值是30kbminChunks: 1, // 表示被引用次数,默认为1;maxAsyncRequests: 5, //所有异步请求不得超过5个maxInitialRequests: 3, //初始话并行请求不得超过3个automaticNameDelimiter:'~',//名称分隔符,默认是~name: true, //打包后的名称,默认是chunk的名字通过分隔符(默认是~)分隔cacheGroups: { //设置缓存组用来抽取满足不同规则的chunk,下面以生成common为例common: {name: 'common', //抽取的chunk的名字chunks(chunk) { //同外层的参数配置,覆盖外层的chunks,以chunk为维度进行抽取},test(module, chunks) { //可以为字符串,正则表达式,函数,以module为维度进行抽取,只要是满足条件的module都会被抽取到该common的chunk中,为函数时第一个参数是遍历到的每一个模块,第二个参数是每一个引用到该模块的chunks数组。自己尝试过程中发现不能提取出css,待进一步验证。},priority: 10, //优先级,一个chunk很可能满足多个缓存组,会被抽取到优先级高的缓存组中minChunks: 2, //最少被几个chunk引用reuseExistingChunk: true,// 如果该chunk中引用了已经被抽取的chunk,直接引用该chunk,不会重复打包代码enforce: true // 如果cacheGroup中没有设置minSize,则据此判断是否使用上层的minSize,true:则使用0,false:使用上层minSize}}
}
chunks: 表示显示块的范围,有三个可选值:initial(初始块)、async(按需加载块)、all(全部块),默认为all;
minSize: 表示在压缩前的最小模块大小,默认是30kb;
minChunks: 表示被引用次数,默认为1;
maxAsyncRequests: 最大的按需(异步)加载次数,默认为1;
maxInitialRequests: 最大的初始化加载次数,默认为1;
name: 拆分出来块的名字(Chunk Names),默认由块名和hash值自动生成,如果是true,将自动生成基于块和缓存组键的名称。如果是字符串或函数将允许您使用自定义名称。如果名称与入口点名称匹配,则入口点将被删除。
automaticNameDelimiter:'',名称分隔符,默认是
cacheGroups: 缓存组。
在此次多页配置中配置如下:
optimization: {splitChunks: { //分割代码块cacheGroups: { //抽离自己编写的脚本的公共代码(css,js)commons: { //公共模块 name: "commons",chunks: "initial", //入口处开始提取代码minSize: 0, //代码最小多大,进行抽离minChunks: 2, //代码复 2 次以上的抽离},vendor: { // 抽离第三方插件test: /node_modules/, // 指定是node_modules下的第三方包chunks: 'initial',name: 'vendor', // 打包后的文件名,任意命名 // 设置优先级,防止和自定义的公共代码提取时被覆盖,不进行打包priority: 10}}}},
修改多页面配置的chunks为
Object.keys(entrys).forEach(function (element) {htmlArray.push({_html: element,title: '',//增加'vendor','commons'chunks: ['vendor','commons', element]})
})
10.在webpack中使用jquery
安装依赖
cnpm i expose-loader --save-dev
cnpm i jquery --save
在webpack.rules.conf.js中添加如下配置
//把关于jquery和expose-loader的配置放在所有的Loader之前,也就是第一个加载
{// 得到jquery模块的绝对路径test: require.resolve('jquery'),// 将jquery绑定为window.jQueryloader: 'expose-loader?jQuery!expose-loader?$'}
在想引入jquery的页面加入如下代码
import $ from 'expose-loader?$!jquery'
注意:expose-loader的写法已经有了更新,之前的写法是
{test: require.resolve('jquery'),loader: 'expose?jQuery!expose?$'
},