Webpack 基础配置与懒加载
一、引言
Webpack 是一个强大的模块打包工具,在当前项目中,它负责将各种资源(如 JavaScript、CSS、图片等)打包成浏览器可以理解的形式。合理的 Webpack 配置能够提高项目的构建效率、优化资源加载,而懒加载则是优化项目性能的重要手段之一。本文将详细解释当前工程中的 Webpack 基础配置,并引申出懒加载的相关内容。
二、Webpack 基础配置
2.1 入口与出口配置
在 d:\workspace\elpis\app\webpack\config\webpack.base.js
文件中,定义了 Webpack 的基础配置。
js
webpack.base.js
// 动态构造 pages 入口文件
const pageEntries = {};
// 动态构造 htmlWebpackPluginList 渲染模板
const htmlWebpackPluginList = [];
// 获取 app/pages 下所有的入口文件 (entry.xx.js)
const entryList = path.resolve(process.cwd(), "./app/pages/**/entry.*.js");
glob.sync(entryList).forEach((file) => {
const entryName = path.basename(file, ".js");
// 构造 entry
pageEntries[entryName] = file;
htmlWebpackPluginList.push(
// html-webpack-plugin 插件 辅助注入打包后的 boundle 文件到tpl文件中
new HtmlWebpackPlugin({
// 产物 最终模板 输出路径
filename: path.resolve(
process.cwd(),
"./app/public/dist/",
`${entryName}.tpl`
),
// 指定要使用的模板文件
template: path.resolve(process.cwd(), "./app/views/entry.tpl"),
// 注入的代码块
chunks: [entryName],
})
);
// 构造最终渲染的页面文件
});
module.exports = {
// 入口文件
entry: pageEntries,
// 出口文件 产物输出路径,开发和生产环境输出不一致,须在各自环境中配置
output: {},
// ...其他配置...
};
- 入口(entry) :通过
glob
模块动态获取app/pages
目录下所有以entry.
开头的.js
文件作为入口文件,将它们的路径存储在pageEntries
对象中。这样做的好处是可以方便地管理多个页面的入口,无需手动逐个添加。 - 出口(output) :在基础配置中,
output
部分仅占位,具体的输出路径和文件名在开发和生产环境的配置文件中进行设置。
2.2 模块加载规则
js
webpack.base.js
module.exports = {
// ...其他配置...
// 模块加载解析器
module: {
rules: [
{
test: /.vue$/,
use: "vue-loader",
},
{
test: /.js$/,
include: [path.resolve(process.cwd(), "./app/pages")], //只针对 业务代码 进行babel转换 加快webpack打包速度
use: { loader: "babel-loader" },
},
{
test: /.(png|jpe?g|gif)(?.+)?$/,
use: {
loader: "url-loader",
options: {
limit: 1024, // 1024 以下的图片打包成 base64 格式
esModule: false,
},
},
},
{
test: /.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /.(eot|svg|ttf|woff|woff2)(?\S*)?$/,
use: "file-loader",
},
],
},
// ...其他配置...
};
- Vue 文件处理 :使用
vue-loader
处理.vue
文件,将 Vue 组件的各个部分(模板、脚本、样式)进行打包。 - JavaScript 文件处理 :使用
babel-loader
对app/pages
目录下的.js
文件进行转换,确保代码在不同浏览器中的兼容性。 - 图片处理 :使用
url-loader
处理图片文件,当图片大小小于 1024 字节时,将其打包成 base64 格式,减少 HTTP 请求。 - CSS 和 Less 处理 :使用
style-loader
、css-loader
和less-loader
处理 CSS 和 Less 文件,将样式文件打包到 JavaScript 中。 - 字体文件处理 :使用
file-loader
处理字体文件,将其复制到输出目录。
2.3 模块解析与别名配置
js
webpack.base.js
module.exports = {
// ...其他配置...
// 模块解析具体行为
resolve: {
extensions: [".js", ".vue", ".less", ".css"],
alias: {
$pages: path.resolve(process.cwd(), "./app/pages"),
$common: path.resolve(process.cwd(), "./app/pages/common"),
$widgets: path.resolve(process.cwd(), "./app/pages/widgets"),
$store: path.resolve(process.cwd(), "./app/pages/store"),
},
},
// ...其他配置...
};
- 扩展名解析 :
resolve.extensions
配置允许在导入模块时省略指定的扩展名,提高开发效率。 - 别名配置 :通过
resolve.alias
配置别名,方便在代码中引用特定目录下的模块,减少路径的书写。
2.4 插件配置
js
webpack.base.js
module.exports = {
// ...其他配置...
// 配置 webpack 插件
plugins: [
// 配置 vue-loader 插件 处理.vue文件必须配置
// 将定义过的其他规则复制并应用到.vue文件里 /.js$/ 他会将该规则定义到.vue中的<script>模块内
new VueLoaderPlugin(),
// 配置 ProvidePlugin 插件 将第三方库暴露到window全局 contenxt下
// 这样就可以在业务代码中直接使用 window.Vue 来使用Vue
new webpack.ProvidePlugin({ Vue: "vue", axios: "axios", _: "lodash" }),
// 配置 DefinePlugin 插件 定义全局变量
new webpack.DefinePlugin({
__VUE_OPTIONS_API__: "true", // 支持vue解析optionsApi
__VUE_PROD_DEVTOOLS__: "false", // 禁用Vue调试工具
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: "false", // 禁用Vue生产环境下显示 水合 信息
}),
...htmlWebpackPluginList,
],
// ...其他配置...
};
- VueLoaderPlugin :处理
.vue
文件的必要插件,确保 Vue 组件的各个部分能够正确打包。 - ProvidePlugin :将第三方库(如
Vue
、axios
、lodash
)暴露到全局作用域,方便在业务代码中直接使用。 - DefinePlugin :定义全局变量,用于配置 Vue 的一些特性,如是否支持
options API
、是否启用调试工具等。 - HtmlWebpackPlugin:用于生成 HTML 文件,并将打包后的 JavaScript 和 CSS 文件注入到 HTML 中。
2.5 代码分割配置
js
webpack.base.js
module.exports = {
// ...其他配置...
// 配置 打包输出优化 (代码分割|模块合并|缓存|TreeShaking|压缩等优化策略)
optimization: {
/**
* 代码分割 配置
* 把 js 文件打包成3中类型
* 1. vendor: 第三方lib库,基本不会改动,除非依赖版本升级
* 2. common: 业务组件代码公共部分抽离,改动较少
* 3. entry.{page}: 不同页面 entry 里面业务组件代码差异部分,会经常改动
* 目的:把改动和引用频率不一样的 js 区分出来,以达到更好利用浏览器缓存效果
*/
splitChunks: {
chunks: "all", //对同步和异步模块都进行分割
maxAsyncRequests: 10, // 按需加载时最大并行请求数
maxInitialRequests: 10, // 一个入口最大并行请求数
cacheGroups: {
vendor: {
// 打包第三方依赖库
name: "vendor", // 模块名称
test: /[\/]node_modules[\/]/, //打包 node_modules下的模块
priority: 20, // 优先级,值越大优先级越高
enforce: true, // 强制打包
reuseExistingChunk: true, // 复用已存在的模块
},
common: {
// 公共模块
test: /[\\/](common|widgets)[\\/]/,
name: "common", // 模块名称
minChunks: 2, // 被引用次数大于等于2次的模块
minSize: 1, // 最小分割文件大小(1 byte)
priority: 10, // 优先级,值越大优先级越高
reuseExistingChunk: true, // 复用已存在的模块
},
},
},
// 将 webpack 运行时生产的代码打包到 runtime.js 中,减少 main.js 的体积
runtimeChunk: true,
},
};
- 代码分割 :通过
splitChunks
配置将 JavaScript 文件分割成不同的类型,包括第三方库(vendor
)、公共模块(common
)和页面特定的代码(entry.{page}
),提高浏览器缓存的利用率。 - 运行时代码分割 :
runtimeChunk
配置将 Webpack 运行时代码打包到单独的文件中,减少主文件的体积。
三、懒加载
3.1 懒加载的概念
懒加载(Lazy Loading)是一种优化技术,它允许在需要时才加载模块,而不是在应用启动时一次性加载所有模块。这样可以减少初始加载时间,提高应用的响应速度。
3.2 项目中的懒加载实现
在当前项目中,路由组件的懒加载通过动态导入(Dynamic Import)实现。例如,在 d:\workspace\elpis\app\pages\dashboard\entry.dashboard.js
文件中:
js
entry.dashboard.js
// 头部菜单路由
routes.push({
path: "/iframe",
component: () => import("./complex-view/iframe-view/iframe-view.vue"),
});
routes.push({
path: "/schema",
component: () => import("./complex-view/schema-view/schema-view.vue"),
});
// custom 自定义路由
routes.push({
path: "/todo",
component: () => import("./todo/todo-view.vue"),
});
// 侧边栏菜单路由
routes.push({
path: "/sider",
component: () => import("./complex-view/sider-view/sider-view.vue"),
children: [
{
path: "/iframe",
component: () => import("./complex-view/iframe-view/iframe-view.vue"),
},
{
path: "/schema",
component: () => import("./complex-view/schema-view/schema-view.vue"),
},
{
// custom 自定义路由
path: "/todo",
component: () => import("./todo/todo-view.vue"),
},
],
});
通过 () => import('...')
的语法,Webpack 会将这些组件打包成单独的文件,并在需要时动态加载。例如,当用户访问 /iframe
路由时,才会加载 iframe-view.vue
组件。
3.3 懒加载的优势
- 减少初始加载时间:只加载当前页面所需的模块,避免一次性加载所有模块,从而减少初始加载时间。
- 提高应用性能:减少了首屏加载的资源量,提高了应用的响应速度,提升用户体验。
- 节省带宽:用户只下载他们实际需要的代码,节省了带宽资源。
3.4 懒加载的注意事项
- 错误处理 :在使用懒加载时,需要处理加载失败的情况,例如网络问题导致模块加载失败。可以通过
.catch()
方法捕获错误并进行相应的处理。 - 预加载:对于一些可能会被频繁访问的模块,可以考虑使用预加载(Preloading)技术,在浏览器空闲时提前加载这些模块,以进一步提高性能。
四、总结
Webpack 的基础配置为项目的构建和打包提供了强大的支持,通过合理配置入口、出口、模块加载规则、插件和代码分割等,可以提高项目的构建效率和性能。懒加载作为一种重要的优化技术,能够进一步提升应用的响应速度和用户体验。在实际项目中,应根据项目的需求和特点,合理运用 Webpack 配置和懒加载技术。