1. 压缩 index.html
压缩 index.html ,通过 html-webpack-plugin 实现。通过属性 options.minify 实现,该属性在 production 模式自动设定为 ture ,所以有两种方式实现 。
- 修改 webpack 打包模式为
production:生产环境默认配置 - 设置
options.minify为 true:开发环境配置,方便对比效果
压缩前
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>8. 性能优化</title>
<meta name="viewport" content="width=device-width, initial-scale=1"></head>
<body>
<!-- vue 挂载元素 -->
<div id="app"></div>
<script src="main.bundle.js"></script></body>
</html>
修改 webpack.config.js
new HtmlWebpackPlugin({
//指定模板路径
template: path.resolve(process.cwd(), 'public/index.html'),
minify: true
}),
压缩后
<!doctype html><html><head><meta charset="utf-8"><title>8. 性能优化</title><meta name="viewport" content="width=device-width,initial-scale=1"></head><body><div id="app"></div><script src="main.bundle.js"></script></body></html>
2. 压缩 JavaScript
生产环境下默认使用 TerserPlugin ,并且也是代码压缩方面比较好的选择。
压缩前
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
.....
/******/ });
压缩后
!function(t){var e={};function n(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}}; ...... new r.a({render:t=>t(p)}).$mount("#app")}]);
3. 减少 JavaScript :tree-shaking
参考文档描述:通过 import 和 export 语法,我们已经找出需要删除的“未引用代码(dead code)”,然而,不仅仅是要找出,还要在 bundle 中删除它们。为此,我们需要将 mode 配置选项设置为 production 得出结论 tree-shaking 在 production 模式默认开启,development 模式关闭。下面仅作验证。
3.1 准备 js 文件
<!--修改 textPrint.js-->
export function textPrint(){
console.log("textPrint")
}
export function textPrint2(){
console.log("textPrint2")
}
3.2 导入并使用 js 文件
<!--App.vue-->
<script>
import {textPrint} from "./js/textPrint";
export default {
name: "App",
methods:{
textClick(){
textPrint()
}
}
}
</script>
3.3 设置 development 模式,并打包
可看到未使用的 textPrint2 函数也在打包文件中。
<!-- mian.boundle.js 部分内容-->
/***/ "./src/js/textPrint.js":
/*!*****************************!*\
!*** ./src/js/textPrint.js ***!
\*****************************/
/*! exports provided: textPrint, textPrint2 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"textPrint\", function() { return textPrint; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"textPrint2\", function() { return textPrint2; });\nfunction textPrint(){\r\n console.log(\"textPrint\")\r\n}\r\nfunction textPrint2(){\r\n console.log(\"textPrint2\")\r\n}\n\n//# sourceURL=webpack:///./src/js/textPrint.js?");
/***/ }),
3.4 设置 production 模式,并打包
打开 mian.boundle.js ,代码已经经过压缩并混淆。可看到只有已使用的 textPrint,未使用的 textPrint2 函数不在打包文件中。
4. 提取 css
在管理资源-加载 CSS中提到:在多数情况下,可以进行 CSS 提取,以便在生产环境中节省加载时间。提取 CSS 通过 mini-css-extract-plugin 完成。
- 版本选择:
1.6.2 - 2.x 版本开始要求 webpack5
4.1 安装
yarn add mini-css-extract-plugin@1.6.2 -D
4.2 修改 webpack.config.js
根据建议
- production 模式使用 mini-css-extract-plugin
- development/webpack-dev-server 使用 style-loader ,速度更快
- mini-css-extract-plugin 和 style-loader 不能一起使用
<!--仅展示变更内容-->
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
//定义模式变量,区别加载plugin、loader
const mode = "production";
const devMode = mode !== "production";
module.exports = {
// 指定打包模式:development、production
mode: mode,
// entry 对象是用于 webpack 查找启动并构建 bundle。其上下文是入口文件所处的目录的绝对路径的字符串。
entry: './src/main.js',
......
plugins: [......].concat(devMode?[]:[new MiniCssExtractPlugin()]),//开发模式不提取 CSS
......
module: {
rules: [
//添加 vue 支持
{
test: /\.vue$/,
loader: 'vue-loader'
},
//添加 css 支持
{
test: /\.css$/i,
// use: ['style-loader', 'css-loader']
// 开发模式:style-loader ;生产模式:MiniCssExtractPlugin
use: [ devMode?"style-loader":MiniCssExtractPlugin.loader, 'css-loader']
},
......
]
}
};
4.3 执行打包
打包成功后,dist 文件夹下会生成独立的css文件:main.css,内容如下
/*加载字体*/
@font-face {
/*名称可自定义*/
font-family: "MyFont";
/*填写真实路径*/
src:url(c05a24bab81b62ecb5db2ffcef97e5a1.ttf);
font-weight: 600;
font-style: normal;
}
.hello[data-v-7ba5bd90] {
color: red;
/*引用字体*/
font-family: "MyFont";
}
5. 压缩 css:css-抽取分割
在 生产环境-最小化 CSS 中提到需要压缩CSS,通过 optimize-css-assets-webpack-plugin 实现压缩功能。
5.1 安装
yarn add optimize-css-assets-webpack-plugin -D
5.2 修改 webpack.config.js
<!--仅展示变更内容-->
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
//定义模式变量,区别加载plugin、loader
const mode = "production";
const devMode = mode !== "production";
module.exports = {
......
optimization: {
//开发模式不提取 CSS
minimizer: [].concat(devMode?[]:[new OptimizeCSSAssetsPlugin({})])
},
......
};
5.3 执行打包
打包成功后,dist 文件夹下会生成压缩后独立的css文件:main.css,内容如下
@font-face{font-family:MyFont;font-style:normal;font-weight:600;src:url(c05a24bab81b62ecb5db2ffcef97e5a1.ttf)}.hello[data-v-7ba5bd90]{color:red;font-family:MyFont}
6. 压缩图片:image-webpack-loader
管理资源-加载图片看到可以使用 image-webpack-loader 和 url-loader 压缩和优化图像加载。
6.1 安装
yarn add image-webpack-loader -D
6.2 修改 webpack.config.js
<!--仅展示修改部分-->
//添加 图片 支持
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
},
{
loader: 'image-webpack-loader',
options: {
// webpack@2.x and newer
disable: devMode,
},
},
],
},
6.3 添加图片资源并加载
<!--仅展示修改部分-->
<!--App.vue-->
<template>
<div class="hello" @click="textClick">
Hello webpack !
<img :src="iconImage">
<img :src="iconImage2">
<img :src="chartImage">
</div>
</template>
<script>
import {textPrint} from "./js/textPrint";
import iconImage from "./image/icon.jpg";
import iconImage2 from "./image/image2.jpeg";
import chartImage from "./image/chart.png";
export default {
name: "App",
data(){
return {
iconImage,iconImage2,chartImage
}
},
methods:{
textClick(){
textPrint()
}
}
}
</script>
6.4 执行打包
打包成功后,dist 文件夹下会生成压缩后图片文件,和原图片相比,体积都有减少,且图片均可正常查看
7. 优化图片加载:url-loader
url-loader 和 file-loader 类似, 但是在文件体积小于设定值时可以生成 DataURL 。
7.1 安装
yarn add url-loader -D
7.2 修改 webpack.config.js
<!--仅展示修改部分-->
//添加 图片 支持
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
//单位:bytes (icon 图片压缩后的体积2小于 25K)
limit: 25 *1024,
},
},
{
loader: 'image-webpack-loader',
options: {
// webpack@2.x and newer
disable: devMode,
},
},
],
},
7.3 执行打包
打包成功后,dist 文件夹下会生成压缩后图片文件,和上一次打包结果相比,图片少了1张(icon.jpg),由于压缩后体积小于设置的 25KB ,被转换成 DataURL 保存到 main.boundle.js 文件中。
<!--main.boundle.js 部分代码-->
// CONCATENATED MODULE: ./src/image/icon.jpg
/* harmony default export */ var icon = ("data:image/jpeg;base64,/9j/4AAQSC ...... ZTA0hJNM/7pf/2Q==");
// CONCATENATED MODULE: ./src/image/image2.jpeg
/* harmony default export */ var image2 = (__webpack_require__.p + "04d45412dbd83a892814b6f22b6fa7ab.jpeg");
// CONCATENATED MODULE: ./src/image/chart.png
/* harmony default export */ var chart = (__webpack_require__.p + "4e86cf63c020e3fcda7d732d1f0e82e3.png");
// CONCATENATED MODULE: ./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=script&lang=js&