webpack对我们来说即熟悉又陌生,说他熟悉是因为几乎现在所有的项目中都用到了他,说他陌生是因为对于webpack繁多的配置项又不是很清楚,今天我们就来一起缕一下webpack中的配置项都是做什么,如何有针对性的做到性能优化,提升开发体验。
首先上一盘儿基本配置
const path = require("path");
const miniCssExtractPlugin = require("mini-css-extract-plugin");
const htmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const webpack = require("webpack");
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "./dist"),
filename: "[name]-[hash:6].js",
},
mode: "development",
module: {
rules: [
{
test: /\.css$/,
include: path.resolve(__dirname, "./src"),
use: ["style-loader", "css-loader"],
},
],
},
resolve: {
alias: {
"@": path.resolve(__dirname, "./src/style"),
},
modules: [path.resolve(__dirname, "./node_modules")],
extensions: [".js", ".json", ".jsx", ".vue"], //后缀列表 希望大家不要省略后缀,因为会浪费查询时间。
},
devServer: {
contentBase: "./dist",
open: true,
port: 8081,
proxy: {
"/api": {
target: "http://localhost:9092/",
},
},
hot: true,
hotOnly: true,
},
devtool: "inline-source-map", //更容易追踪到错误的信息
plugins: [
new htmlWebpackPlugin({
template: "./src/index.html",
filename: "index.html",
}),
new CleanWebpackPlugin(), //清理目录
new webpack.HotModuleReplacementPlugin(), //启用热更新模块
],
};
入口文件是entry: "./src/index.js", 出口文件是在dist目录,bundle文件是用的hash模式;
mode模式是用的开发development;
module的rules里让webpack支持了css模块,less模块还有图片和第三方字体模块,js模块通过babel来实现语意转化;
//...
rules: [
{
test: /\.css$/,
include: path.resolve(__dirname, "./src"),
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
include: path.resolve(__dirname, "./src"),
use: [
// miniCssExtractPlugin.loader,
"style-loader",
"css-loader",
"postcss-loader",
"less-loader",
],
},
{
test: /\.(png|jpe?g|gif)$/,
include: path.resolve(__dirname, "./src"),
use: {
loader: "url-loader",
options: {
name: "[name].[ext]",
outputPath: "images/",
limit: 2048,
},
},
},
{
test: /\.woff2$/,
include: path.resolve(__dirname, "./src"),
use: "file-loader",
},
{
test: /\.js$/,
include: path.resolve(__dirname, "./src"),
use: "babel-loader",
},
],
//...
devServer来实现本地服务器的一个功能;
devtool: surceMap功能,可以将编译后的代码映射到原始的代码位置;
plugins里使用的htmlWebpackPlugin,可以配置生成html文件的标题
//...
new htmlWebpackPlugin({
template: "./src/index.html",
filename: "index.html",
inject: ""//true body head false,
favicon: 'path/to/my_favicon.ico',
minify: {
removeAttributeQuotes: true // 移除属性的引号
},
cache:true //默认是true的,表示内容变化的时候生成一个新的文件
showErrors: true //当webpack报错的时候,会把错误信息包裹再一个pre中,默认是true
chunks: ["main"],
excludeChunks: ['devor.js'] , //排除掉一些js
}),
///...
① template指定你生成的文件所依赖哪一个html文件模板,模板类型可以是html、jade、ejs等
② inject的值true body head false
- true 默认值,script标签位于html文件的 body 底部;
- body script标签位于html文件的 body 底部;
- head script标签位于html文件的 head中;
- false 不插入生成的js文件,这个几乎不会用到的;
③ favicon 显而易见是为我们生产的html配置favicon ,值是一个路径
④ minify 使用minify会对生成的html文件进行压缩,默认值是false
⑤ chunks 主要用于多入口文件,当你有多个入口文件,编译后生成多个打包后的文件,那么chunks 就能选择你要使用那些js文件
⑥⑦⑧⑨⑩
随着我们的项目越来越多,集成的插件和loader越来越多,打包的时间是越来越久了,所以webpack性能优化,主要分两点:
1 优化开发体验
2 优化输出质量
优化开发体验,我们可以对配置文件,做一个功能上的拆分:
我们按功能划分webpack.base.config/webpack.dev.config/webpack.prod.config,从名字上可以猜出来是做什么用的,接下来我们看下那些功能是需要放在基础的功能配置里面呢
//webpack.base.config.js
entry: "./src/index.js",
module: {
rules: [
{
test: /\.(png|jpe?g|gif)$/,
include: path.resolve(__dirname, "./src"),
use: {
loader: "url-loader",
options: {
name: "[name].[ext]",
outputPath: "images/",
limit: 2048,
},
},
}
],
},
plugins: [
new htmlWebpackPlugin({
template: "./src/index.html",
filename: "index.html",
chunks: ["main"],
}),
new CleanWebpackPlugin(),
]
//webpack.dev.config.js
//...
output: {
path: path.resolve(__dirname, "./dev"),
filename: "[name]-[hash:6].js",
},
mode: "development",
module: {
rules: [
{
test: /\.less$/,
include: path.resolve(__dirname, "./src"),
use: ["style-loader", "css-loader", "postcss-loader", "less-loader"],
},
],
},
resolve: {
alias: {
"@": path.resolve(__dirname, "./src/style"),
},
modules: [path.resolve(__dirname, "./node_modules")],
extensions: [".js", ".json", ".jsx", ".vue"], //后缀列表 希望大家不要省略后缀,因为会浪费查询时间。
},
devServer: {
contentBase: "./dist",
open: true,
port: 8081,
proxy: {
"/api": {
target: "http://localhost:9092/",
},
},
hot: true,
hotOnly: true,
},
devtool: "inline-source-map",
plugins: [new webpack.HotModuleReplacementPlugin()],
//...
//..webpack.prod.config
output: {
path: path.resolve(__dirname, "./build"),
filename: "[name]-[hash:6].js",
},
mode: "production",
module: {
rules: [
{
test: /\.less$/,
include: path.resolve(__dirname, "./src"),
use: [
miniCssExtractPlugin.loader,
"css-loader",
"postcss-loader",
"less-loader",
],
},
],
},
optimization: {
usedExports: true,
},
resolve: {
alias: {
"@": path.resolve(__dirname, "./src/style"),
},
modules: [path.resolve(__dirname, "./node_modules")],
extensions: [".js", ".json", ".jsx", ".vue"], //后缀列表 希望大家不要省略后缀,因为会浪费查询时间。
},
plugins: [
new miniCssExtractPlugin({
filename: "css/index-[contenthash:6].css",
}),
new purifycss({
paths: glob.sync([
path.resolve(__dirname, "./src/*.html"),
path.resolve(__dirname, "./src/*.js"),
]),
}),
new optimizeCss({
cssProcessor: require("cssnano"),
}),
],
//..
按功能拆分之后,看一下怎么合并呢?
npm install webpack-merge -D
给各个环境的配置起一个名字 const prodConfig,在dev中导入base配置,和安装的merge插件,使用module.exports合并导出
const { merge } = require("webpack-merge");
const baseConfig = require("./webpack.base.config.js");
//..
module.exports = merge(baseConfig, devConfig);
接下来我们怎么使用呢
//package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"mpa": "cross-env NODE_ENV=Davy webpack --config ./webpack.mpa.config.js --env.development",
"server": "webpack-dev-server ",
"dev-new": "webpack --config ./webpack.dev.config.js",
"build-new": "webpack --config ./webpack.prod.config.js"
},
在这里我们解释一下,croess-env跨平台写入环境变量,通过注入变量的方式,往往我们都需要借助croess-env来解决这种各平台的兼容问题,可以跟据NODE_ENV=Davy变量来写判断了,从而可以达到跟据一个配置还对不同的环境输出,那么这个变量我们是如何获得的呢,可以看到我们将脚本命令写在mpa下了,在webpack.mpa.config.js文件中中通过 console.log(process.env.NODE_ENV)传进来的变量

说完merge合并,下面看一下代码压缩
css压缩
post-css 生态非常强大,有各种css插件,有压缩的,有处理Css的,它本身不做任何压缩处理
代码压缩
去掉冗余样式 tree shaking,可以检查没有用的Css 或js 在打包的时候 去除掉
npm i glob-all purify-css pruifycss-webpack
//..
new purifycss({
paths: glob.sync([
path.resolve(__dirname, "./src/*.html"), //选择摇src目录下的html文件
path.resolve(__dirname, "./src/*.js"),
]),
}),
//..
压缩js
optimization: {
usedExports: true, //开启js tree shaking
}
//开启了之后,在打包的js文件中,我们可以看到 /*! exports provided: default */
//注意在开发模式下是没有效果的,但是通过这个注释我们可以看到生效了
网站性能优化的分析工具
读懂核心指标
chrome lighthouse(灯塔)
npm install -g lighthouse
//谷歌判断网站性能优化的核心指标
webpack中文文档 : https://webpack.html.cn/plugins/hot-module-replacement-plugin.html
网友评论