用户浏览时代码拆分/预加载内容?
Code Splitting / Preloading Content while user is browsing?
使用像 Webpack 这样的工具,我们可以启用代码拆分,并且只
在需要时异步加载我们的应用程序代码。
带有 react-router 的 react 应用程序上下文中的示例。
Load initial page.
-> go to new route
---> webpack loads in the component file required asynchronous.
Webpack 一直等到需要代码才能发起请求。
我的问题是,加载基本应用程序代码后,我们是否可以开始加载其余代码,甚至在用户启动到新路由的转换之前?
我的观点是,这将阻止用户等待 webpack 块下载。
-> Load initial page
--> user sitting idle or browsing on home page
----> Start loading application code for rest of the application
---> user goes to new route (faster UX because code has already download in the background)
我希望这是有道理的
是的,你可以做到这一点。我将展示其中一种可能的解决方案。
首先让我们创建 backgroundLoader
用于排队所需的块:
const queue = [];
const delay = 1000;
let isWaiting = false;
function requestLoad() {
if (isWaiting) {
return;
}
if (!queue.length) {
return;
}
const loader = queue.pop();
isWaiting = true;
loader(() => {
setTimeout(() => {
isWaiting = false;
requestLoad();
}, delay)
});
}
export default (loader) => {
queue.push(loader);
requestLoad();
}
此函数将延迟 1 秒在后台加载您的块(您可以调整它 - 例如 5 秒后开始弹出队列或随机排列块数组)。
接下来你必须在排队函数backgroundLoader
中注册你的require.ensure
:
import render from './render'; // not relevant in this example
import backgroundLoader from './backgroundLoader';
let lightTheme = (cb) => {
require.ensure([], () => {
cb(require('./themeA.css'));
}, 'light');
}
let darkTheme = (cb) => {
require.ensure([], () => {
cb(require('./themeB.css'));
}, 'dark');
}
let pinkTheme = (cb) => {
require.ensure([], () => {
cb(require('./themeC.css'));
}, 'pink');
}
backgroundLoader(lightTheme);
backgroundLoader(darkTheme);
backgroundLoader(pinkTheme);
export default (themeName) => { // router simulation
switch(themeName) {
case 'light':
lightTheme(render);
break;
case 'dark':
darkTheme(render);
break;
case 'pink':
pinkTheme(render);
break;
}
};
一旦你在 switch
语句中需要你的块,你就会传递包含 resolve 函数的 render
函数。在 backgroundLoader
中,此函数将为空,导致仅将块加载到应用程序的 head
。
您可以在 WebpackBin 上看到此示例的完整代码(您可以检查网络以了解块是如何在后台加载的)
使用像 Webpack 这样的工具,我们可以启用代码拆分,并且只 在需要时异步加载我们的应用程序代码。
带有 react-router 的 react 应用程序上下文中的示例。
Load initial page.
-> go to new route
---> webpack loads in the component file required asynchronous.
Webpack 一直等到需要代码才能发起请求。
我的问题是,加载基本应用程序代码后,我们是否可以开始加载其余代码,甚至在用户启动到新路由的转换之前?
我的观点是,这将阻止用户等待 webpack 块下载。
-> Load initial page
--> user sitting idle or browsing on home page
----> Start loading application code for rest of the application
---> user goes to new route (faster UX because code has already download in the background)
我希望这是有道理的
是的,你可以做到这一点。我将展示其中一种可能的解决方案。
首先让我们创建 backgroundLoader
用于排队所需的块:
const queue = [];
const delay = 1000;
let isWaiting = false;
function requestLoad() {
if (isWaiting) {
return;
}
if (!queue.length) {
return;
}
const loader = queue.pop();
isWaiting = true;
loader(() => {
setTimeout(() => {
isWaiting = false;
requestLoad();
}, delay)
});
}
export default (loader) => {
queue.push(loader);
requestLoad();
}
此函数将延迟 1 秒在后台加载您的块(您可以调整它 - 例如 5 秒后开始弹出队列或随机排列块数组)。
接下来你必须在排队函数backgroundLoader
中注册你的require.ensure
:
import render from './render'; // not relevant in this example
import backgroundLoader from './backgroundLoader';
let lightTheme = (cb) => {
require.ensure([], () => {
cb(require('./themeA.css'));
}, 'light');
}
let darkTheme = (cb) => {
require.ensure([], () => {
cb(require('./themeB.css'));
}, 'dark');
}
let pinkTheme = (cb) => {
require.ensure([], () => {
cb(require('./themeC.css'));
}, 'pink');
}
backgroundLoader(lightTheme);
backgroundLoader(darkTheme);
backgroundLoader(pinkTheme);
export default (themeName) => { // router simulation
switch(themeName) {
case 'light':
lightTheme(render);
break;
case 'dark':
darkTheme(render);
break;
case 'pink':
pinkTheme(render);
break;
}
};
一旦你在 switch
语句中需要你的块,你就会传递包含 resolve 函数的 render
函数。在 backgroundLoader
中,此函数将为空,导致仅将块加载到应用程序的 head
。
您可以在 WebpackBin 上看到此示例的完整代码(您可以检查网络以了解块是如何在后台加载的)