延迟加载或“按需”加载是优化网站或应用程序的绝佳方法。这种做法本质上是在逻辑断点处拆分代码,然后在用户执行需要或将需要新代码块的操作时加载代码。这加快了应用程序的初始加载速度,并减轻了其整体重量,因为某些代码块可能永远不会被加载。
让我们以 代码拆分 中的示例为例,并对其进行一些调整以更清楚地说明这个概念。那里的代码确实会导致生成一个单独的块 lodash.bundle.js
,并在脚本运行时技术上“延迟加载”它。问题是加载该捆绑包不需要任何用户交互,这意味着每次加载页面时都会触发请求。这对我们帮助不大,并且会对性能产生负面影响。
让我们尝试一些不同的方法。我们将添加一个交互,以便在用户单击按钮时将一些文本记录到控制台。但是,我们将等到第一次发生交互时才加载该代码 (print.js
)。为此,我们将回到 代码拆分 中的 最终的动态导入示例 并将 lodash
保留在主块中。
项目
webpack-demo
|- package.json
|- package-lock.json
|- webpack.config.js
|- /dist
|- /src
|- index.js
+ |- print.js
|- /node_modules
src/print.js
console.log(
'The print.js module has loaded! See the network tab in dev tools...'
);
export default () => {
console.log('Button Clicked: Here\'s "some text"!');
};
src/index.js
+ import _ from 'lodash';
+
- async function getComponent() {
+ function component() {
const element = document.createElement('div');
- const _ = await import(/* webpackChunkName: "lodash" */ 'lodash');
+ const button = document.createElement('button');
+ const br = document.createElement('br');
+ button.innerHTML = 'Click me and look at the console!';
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
+ element.appendChild(br);
+ element.appendChild(button);
+
+ // Note that because a network request is involved, some indication
+ // of loading would need to be shown in a production-level site/app.
+ button.onclick = e => import(/* webpackChunkName: "print" */ './print').then(module => {
+ const print = module.default;
+
+ print();
+ });
return element;
}
- getComponent().then(component => {
- document.body.appendChild(component);
- });
+ document.body.appendChild(component());
现在让我们运行 webpack 并查看我们新的延迟加载功能
...
Asset Size Chunks Chunk Names
print.bundle.js 417 bytes 0 [emitted] print
index.bundle.js 548 kB 1 [emitted] [big] index
index.html 189 bytes [emitted]
...
许多框架和库都有自己关于如何在它们的方法中完成此操作的建议。以下是一些示例