两种解决方案最大的区别在于方案2支持SSR(Server Side Rendering);
// 使用前
import { add } from './math';
console.log(add(16, 26));
// 使用后
import("./math").then(math => {
console.log(math.add(16, 26));
});
function importModule(url) {
return new Promise((resolve, reject) => {
const script = document.createElement("script");
const tempGlobal = "__tempModuleLoadingVariable" + Math.random().toString(32).substring(2);
script.type = "module";
script.textContent = `import * as m from "${url}"; window.${tempGlobal} = m;`;
script.onload = () => {
resolve(window[tempGlobal]);
delete window[tempGlobal];
script.remove();
};
script.onerror = () => {
reject(new Error("Failed to load module script with URL " + url));
delete window[tempGlobal];
script.remove();
};
document.documentElement.appendChild(script);
});
}
import React, { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
</div>
);
}
思考:既然import()已经帮我们做了这么一个代码分割。那么我们为什么还需要用React.lazy()
包一下?
答案:就是要把import()返回的是promise对象 转换成可以调用的组件
import loadable from '@loadable/component'
const OtherComponent = loadable(() => import('./OtherComponent'))
function MyComponent() {
return (
<div>
<OtherComponent />
</div>
)
}
思考:可以看到与React.lazy()方式主要差异就是他不需要包裹层,那么他是如何实现的?
答案: 定义了一个函数,函数返回一个普通react组件A。组件内部维护一个更新状态,默认是false,组件内部调用函数传参中返回的promise,当promise触发结束时。更新状态改为true,A组件渲染返回的子组件
思考:那么他可以实现包裹层中组件没有加载完出等待效果嘛?
答案: 当然可以,@loadable/component提供更完善的功能;