文章目录
- 前言
- 包准备
- CDN 集成
- 代码分包
- Tree Shaking
- 原理
- 实现条件:
- 解决 treeShaking 无效方案:
- 示例代码:
- 热更新(HMR)
前言
Webpack 作为现代前端开发中的核心构建工具,提供了丰富的特性来帮助开发者优化和打包应用。本文将探讨 Webpack 的 CDN 集成、代码分包、Tree Shaking 以及热更新(HMR)等关键特性。
我们将使用前一篇文章中的代码,然后我们引入一些图片、css 等资源文件已经一些常用的第三方库,如
lodash
包准备
安装文件处理的 loader 和后续分析的包
yarn add webpack-bundle-analyzer terser-webpack-plugin url-loader file-loader -D
在 webpack.config.js 添加 处理文件的 loader , file-loader
module: {
rules: [
// ... 省略
{
test: /\.(jpg|png|jpeg|gif)$/,
use: ["file-loader"],
},
],
},
修改 list.vue
<template>
<div>
<img :src="jsJpg" />
<h3>前端三大框架:</h3>
<ul>
<li v-for="item in list" :key="item">{{ item }}</li>
</ul>
</div>
</template>
<script>
import jsJpg from '@/static/js.jpg'
export default {
name:'List',
data() {
return {
list: ["Vue", "React", "Angular"],
jsJpg
};
},
};
</script>
运行结果:
打包结果:
执行 yarn build
CDN 集成
CDN(内容分发网络)的使用可以显著提高资源加载速度,特别是对于静态资源。
我们可以有三种种方式来完成:
output
配置中的publicPath
这里我们如果没有 cdn,可以通过修改 hosts 文件的方式, 文件路径:C:\Windows\System32\drivers\etc
,添加内容127.0.0.1 ziyu.aliyun.com
, 最后我们添加启动端口
const mode =
process.env.NODE_ENV === "development" ? "development" : "production";
const isDev = process.env.NODE_ENV === "development";
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js",
publicPath: isDev ? "/" : "http://ziyu.aliyun.com:3000/",
},
添加前运行文件
打包运行后文件效果
- 配置
externals
属性将某些依赖项从打包文件中排除,并通过 CDN 链接直接引入。
externals: {
vue: "Vue",
"vue-router": "VueRouter",
}
在 html 文件中添加
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><%= htmlWebpackPlugin.options.title %></title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router@3.0.0/dist/vue-router.js"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
添加打包分析器:
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
plugins: [
// ...
new BundleAnalyzerPlugin({
analyzerMode: 'static',
reportFilename: 'report.html',
openAnalyzer: false,
}),
],
执行 yarn build
, 查看report.html
, 没有 vue和vue-router的代码
- 使用
html-webpack-plugin
插件,在生成的 HTML 文件中动态插入 CDN 资源链接。
// 1. 配置插件
new HtmlWebpackPlugin({
title: "vuew + webpack",
template: "./src/index.html",
}),
// 2. 配置html
// 可以随便添加cdn
代码分包
代码分包是 Webpack 优化应用加载性能的重要手段。通过将代码分割成多个包,可以实现按需加载,减少单次加载的数据量。
代码准备:
我们新建一个utils/calc.js
文件,然后补充代码:
export const sum = (a, b) => a + b;
常规使用: hello.vue 中引用
<template>
<button @click="calcRes">计算 : 5 +6 结果</button> {{ res }}
</template>
<script>
import { sum } from "../utils/calc";
export default {
data() {
return {
res: 0,
};
},
methods: {
calcRes() {
this.res = sum(5, 6);
},
},
};
</script>
打包结果
import()
分包:
<template>
<button @click="calcRes">计算 : 5 +6 结果</button> {{ res }}
</template>
<script>
import { sum } from "../utils/calc";
export default {
data() {
return {
res: 0,
};
},
methods: {
calcRes() {
this.res = import(/* webpackChunkName: "calc" */ "../utils/calc").then(
({ sum }) => {
this.res = sum(5, 6);
}
);
},
},
};
</script>
- 自动分包:Webpack 的
SplitChunksPlugin
插件可以自动分析模块依赖关系,将共享模块提取到单独的包中 , 供我们自定义更加细粒度的分包策略
optimization: {
splitChunks: {
chunks: 'all', // all, async, and initial
minChunks :10,
// 当包大于1000byte,就拆分
maxSize: 1000,
// 拆分的每个包不能小于500byte
minSize: 500,
cacheGroups:{
utils: {
test: /utils/,
filename: '[id]_utils.js'
}
}
},
},
- 多入口分包:通过
entry
属性手动定义多个入口点,Webpack 会为每个入口点生成一个独立的包。
Tree Shaking
Tree Shaking 是移除代码中未引用部分的过程,它利用了 ES2015 模块的静态结构特性。
原理
- 一是先
「标记」
出模块导出值中哪些没有被用过 - 二是使用
Terser 删掉这些没被用到的导出代码
实现条件:
- 使用 ES2015 模块:确保项目使用
import
和export
语法。 - 配置
sideEffects
:在package.json
中添加"sideEffects": false
字段,告诉 Webpack 哪些文件是纯模块,可以安全地进行 Tree Shaking。 - 在配置中开始标记
optimization.usedExports = true
, 将构建设置成生产模式mode ='production'
解决 treeShaking 无效方案:
@babel/preset-env
或babel-preset-env
不要将 target 设置为node
- 第三方包中的
"sideEffects": false
示例代码:
我们安装 loadsh-es
包来测试,它比 lodash 包更好的 tree-shaking
yarn add lodash-es
yarn add terser-webpack-plugin -D
<button @click="log">防抖函数</button>
<script>
import { debounce } from 'lodash-es';
export default {
methods: {
log: debounce(()=>console.log("log...."), 500),
}
}
</script>
更新配置文件:
optimization: {
minimize: true,
minimizer: [new TerserPlugin()],
usedExports: true,
},
打包结果:可以看到结果中只有loadsh-es
包的 debunce
函数
热更新(HMR)
热更新允许在开发过程中实时更新应用,而无需刷新页面。
- 配置
webpack-dev-server
:通过webpack-dev-server
提供热更新服务。 - 使用
HotModuleReplacementPlugin
:在 Webpack 配置中添加此插件,实现模块的热替换。
devServer:{
hot:true
}
plugins: [
new webpack.HotModuleReplacementPlugin()
]
mounted() {
if (module.hot) {
module.hot.accept('./Hello.vue', () => {
});
}
},