什么是按需导入(懒加载)、动态导入
约 1121 字大约 4 分钟
2025-03-15
总结
- webpack 配置代码拆分
- Es6 原生支持 Import() 动态导入
- 各种框架内的异步组件实现
一、概念
- 按需加载、懒加载: 在 Webpack 中,按需加载(也称为代码分割或懒加载)是一种将代码拆分成多个 bundle 的技术,使得应用在初始加载时只加载必要的代码,其他代码在需要时再动态加载。这种方式可以显著减少初始加载时间,提升应用性能。
- 动态导入: 而动态导入其实就是 按需加载 + 逻辑判断 ,比如我们需要根据一个变量值,确定导入不同的页面,这就叫做动态导入
二、实现方法
首先我们要配置 webpack 支持;
1、配置 webpack
Webpack 提供了多种配置选项来优化按需加载的行为。
1.1、配置代码分割、输出支持动态 chunk
通过 output.chunkFilename
和 SplitChunksPlugin
实现动态代码分割和缓存支持。
module.exports = {
output: {
filename: "[name].bundle.js",
chunkFilename: "[name].chunk.js", // 动态 chunk 的文件名
path: __dirname + "/dist",
},
optimization: {
splitChunks: {
chunks: "all", // 提取公共依赖
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
name: "vendors",
chunks: "all",
},
},
},
},
};
1.2、预加载和预取
- 预加载(Preload): 在当前页面加载时立即加载资源。
- 预读取(Prefetch): 在浏览器空闲时加载资源。
import(/* webpackPrefetch: true */ "./Module");
import(/* webpackPreload: true */ "./Module");
2、框架、代码支撑
2.1、使用 import()
动态导入
import()
是 ECMAScript 提出的动态导入语法,他是一个异步方法,返回值是 promise 对象。
Webpack 支持将其作为代码分割点,实现按需加载。
// 普通导入(同步加载)
// import Module from './Module';
// 动态导入(按需加载)
button.addEventListener("click", () => {
// import()返回promise对象
import("./Module")
.then((module) => {
module.default(); // 使用模块
})
.catch((err) => {
console.error("模块加载失败", err);
});
});
Webpack 会将
import()
导入的模块打包成单独的 chunk 文件。当代码执行到
import()
时,Webpack 会动态加载对应的 chunk 文件。
2.2、React 中的 React.lazy
和 Suspense
在 React 应用中,可以使用 React.lazy
和 Suspense
实现组件的按需加载。
import React, { Suspense } from "react";
// 使用 React.lazy 动态导入组件
const LazyComponent = React.lazy(() => import("./LazyComponent"));
function App() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
</div>
);
}
React.lazy
接受一个返回import()
的函数,动态加载组件。Suspense
用于在组件加载过程中显示 fallback 内容(如加载动画)。
2.3、Vue 中的异步组件
在 Vue 中,可以通过动态 import()
实现组件的按需加载。
- 动态引入:
const AsyncComponent = () => import("./AsyncComponent.vue");
new Vue({
components: {
AsyncComponent,
},
});
- Vue3
<suspense>
和defineAsyncComponent
:
<template>
<div>
<suspense>
<template #default>
<async-component />
</template>
<template #fallback>
<div>正在加载...</div>
</template>
</suspense>
</div>
</template>
<script setup>
import { defineAsyncComponent } from "vue";
const AsyncComponent = defineAsyncComponent(() =>
import("./AsyncComponent.vue")
);
</script>
- Vue 会自动将动态导入的组件打包成单独的 chunk 文件。
- 当组件被渲染时,Webpack 会动态加载对应的 chunk 文件。
2.4、路由级别的按需加载
在单页面应用(SPA)中,通常会将路由对应的组件按需加载,以减少初始加载时间。
- React Router 示例:
import React, { Suspense } from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
const Home = React.lazy(() => import("./Home"));
const About = React.lazy(() => import("./About"));
function App() {
return (
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/about" component={About} />
</Switch>
</Suspense>
</Router>
);
}
- Vue Router 示例:
const Home = () => import("./Home.vue");
const About = () => import("./About.vue");
const routes = [
{ path: "/", component: Home },
{ path: "/about", component: About },
];
const router = new VueRouter({
routes,
});
三、总结
Webpack 的按需加载通过动态 import()
实现代码分割,适用于组件、路由等场景。结合 React、Vue 等框架的懒加载功能,可以显著提升应用性能。通过合理的 Webpack 配置(如 SplitChunksPlugin
和预加载),可以进一步优化按需加载的效果。
1、按需加载的优势
- 减少初始加载时间:只加载必要的代码,提升页面加载速度。
- 优化用户体验:避免页面卡顿,特别是在网络较慢或设备性能较低的情况下。
- 节省带宽:减少不必要的资源请求,降低服务器压力。
2、注意事项
- 代码分割粒度:过细的代码分割可能导致过多的 HTTP 请求,反而影响性能。
- 加载状态管理:动态加载组件时,需要处理加载中的状态(如显示加载动画)。
- 兼容性:动态
import()
在旧浏览器中可能不支持,需通过 Babel 或 polyfill 兼容。
更新日志
2025/8/24 08:17
查看所有更新日志
e7112
-1于