We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
简单来说,就是例如我们的页面中,有一个组件内部实现逻辑非常庞大,引入了 许多其他的包,导致该页面整体体积过大,影响首屏渲染速度,此时我们期望优先加载 其他内容,最后再去加载这块组件内容,避免首屏渲染时间过长。也就是从chunks再拆分出 部分逻辑,单独生成一个script文件,在我们需要的时机进行请求该模块的script文件,再将 它显示出来,这样就是代码分割,动态引入的一个经典场景。
动态导入,本质上是来自于ECMA关于异步import语法的提案,该语法是让import支持异步引入。 例如import('./xxxfile').then(res=>{}),使得import语法promise异步化,res中就可以拿到 该模块的语法资源,再由开发者对其进行处理,例如,在webpack的实现中,引入一个react组件的res是这样的 一个JS对象:
import('./xxxfile').then(res=>{})
其中default便是该模块默认到处的内容,也就是我们默认导出的组件了。
1.模拟一下场景,我们有一个需要被拆分的 react 组件 DynamicTest.js
import React from 'react'; import styles from './DynamicTest.less'; function DynamicTest() { // 实际案例中,这里的实现逻辑可能非常复杂,我们想把它单独拎出来 return <div className={styles.root}>动态加载组件内容</div>; } export default DynamicTest;
以及其组件样式文件 ./DynamicTest.less, 现在我们期望把这个文件和其样式文件单独从打包chunk中拆分出来。
./DynamicTest.less
原来的webpack输出:
chunk.js chunk.css
期望的webpack输出:
chunk.js chunk.css DynamicTest.js DynamicTest.chunk.css
2.对动态导入的逻辑进行封装
在对DynamicTest进行动态导入的时候,我们期望能实现以下功能 createLoadable:
DynamicTest
也就是以下的调用例子,createLoadable传入以上需求的配置,返回一个可动态导入的react组件:
const DynamicTest = createLoadable({ // loader(func),返回动态导入的文件路径 // 其中 /* webpackChunkName: "DynamicTest" */ 是webpack规定的,来命名打包后文件的名字 loader: () => import(/* webpackChunkName: "DynamicTest" */ './DynamicTest'), // loading(reactComponent) react组件,props是loading(正在加载)以及err(发生错误) // 我们可以根据其props进行样式定制化 loading: ({loading,err})=> loading ? 'loading' : err ? 'error': null, // delay(ms) 延迟加载的时间 delay: 5000, });
在我们的页面中,调用DynamicTest组件
export default () => { return ( <Wrapper> <DynamicTest/> </Wrapper> ); };
import React, { useState, useEffect } from 'react'; // loader组件,控制动态引入的状态 function Loader({ loader, loading, delay, loadedComponentProps }) { // import进来的模块内容 const [loaded, setLoaded] = useState(null); // err引入发生的错误,isLoading是否正在加载中 const [err, setErr] = useState(null); const [isLoading, setLoading] = useState(false); const load = () => { loader() .then(_loaded => { // log =>{__esModule: true, Symbol(Symbol.toStringTag): "Module", default: ƒ} setLoaded(_loaded); }) .catch(_err => { setErr(_err); }) .finally(() => { setLoading(false); }); }; useEffect(() => { setLoading(true); let h = null; if (delay) { h = setTimeout(load, delay); } else { load(); } return () => { clearTimeout(h); }; }, []); // 加载中或者错误 // 返回占位符组件 if (isLoading || err) { return React.createElement(loading, { isLoading, err }); } // 加载成功 // 返回加载成功后的组件 if (loaded) { const loadedComponent = loaded && loaded.__esModule ? loaded.default : loaded; return React.createElement(loadedComponent, loadedComponentProps); } return null; } // 默认的占位符组件 const DefaultLoading = ({ loading, error }) => { // 组件正在异步加载的时候 if (loading) return <div>Loading</div>; // 组件加载发生了错误的时候 if (error) return <div>Unknown error occurred</div>; return null; }; /** * @method createLoadable * @desc 通过import动态导入的语法,返回一个React组件,在合适的时机展示loading与err以及异步加载组件的内容 * @param {loadr|fn} () => import('./DynamicTest') 动态引入 * @param {loading|component} 占位符组件,会被注入isLoading、err的props * @param {delay|ms} 延迟加载的时间 * */ const createLoadable = ({ loader, loading = DefaultLoading, delay = 0 }) => { return props => React.createElement(Loader, { loader, loading, delay, loadedComponentProps: props, }); }; export default createLoadable;
createLoadable的实现简而言之,就是创建了一个react组件loader,该组件帮助我们来管理import动态导入时的状态, 加载中、加载失败、以及加载完成,再去选择展示的组件,以及加上了延迟加载的功能需要。
1.使用webpack,修改
output: { chunkFilename: '[name].bundle.js', }
2.使用webpack-chain
config.output.chunkFilename('[name].bundle.js');
output中的chunkFilename其实就是entry中没有的其他chunk的命名规则。
以上便是在react中如何使用webpack的动态导入特性的一个实践例子了,其实就是利用了webpack对import异步化语法的支持, 文件拆分的逻辑由webpack完成,我们通过编写一个组件来管理动态引入可能出现的几种状态,来显示我们期望的内容,甚至还可以 在导入失败的时候重新加载。
webpack关于动态导入的的文档: https://webpack.js.org/guides/code-splitting/#dynamic-imports
以上需求的一个更好的实现,UMIJS中动态导入的功能也基于此项目 https://github.com/jamiebuilds/react-loadable
The text was updated successfully, but these errors were encountered:
https://github.com/Lemonreds/react-components/tree/master/src/pages/comp/examples/createLoadable 源码例子
Sorry, something went wrong.
No branches or pull requests
代码分割,动态导入的场景
简单来说,就是例如我们的页面中,有一个组件内部实现逻辑非常庞大,引入了
许多其他的包,导致该页面整体体积过大,影响首屏渲染速度,此时我们期望优先加载
其他内容,最后再去加载这块组件内容,避免首屏渲染时间过长。也就是从chunks再拆分出
部分逻辑,单独生成一个script文件,在我们需要的时机进行请求该模块的script文件,再将
它显示出来,这样就是代码分割,动态引入的一个经典场景。
动态导入的实现原理
动态导入,本质上是来自于ECMA关于异步import语法的提案,该语法是让import支持异步引入。

例如
import('./xxxfile').then(res=>{})
,使得import语法promise异步化,res中就可以拿到该模块的语法资源,再由开发者对其进行处理,例如,在webpack的实现中,引入一个react组件的res是这样的
一个JS对象:
其中default便是该模块默认到处的内容,也就是我们默认导出的组件了。
实践例子
1.模拟一下场景,我们有一个需要被拆分的 react 组件 DynamicTest.js
以及其组件样式文件
./DynamicTest.less
,现在我们期望把这个文件和其样式文件单独从打包chunk中拆分出来。
原来的webpack输出:
期望的webpack输出:
2.对动态导入的逻辑进行封装
在对
DynamicTest
进行动态导入的时候,我们期望能实现以下功能 createLoadable:也就是以下的调用例子,createLoadable传入以上需求的配置,返回一个可动态导入的react组件:
在我们的页面中,调用DynamicTest组件
createLoadable的实现简而言之,就是创建了一个react组件loader,该组件帮助我们来管理import动态导入时的状态,
加载中、加载失败、以及加载完成,再去选择展示的组件,以及加上了延迟加载的功能需要。
预览
其他:如何修改打包后的分片文件名
1.使用webpack,修改
2.使用webpack-chain
config.output.chunkFilename('[name].bundle.js');
output中的chunkFilename其实就是entry中没有的其他chunk的命名规则。
总结
以上便是在react中如何使用webpack的动态导入特性的一个实践例子了,其实就是利用了webpack对import异步化语法的支持,
文件拆分的逻辑由webpack完成,我们通过编写一个组件来管理动态引入可能出现的几种状态,来显示我们期望的内容,甚至还可以
在导入失败的时候重新加载。
参考
webpack关于动态导入的的文档:
https://webpack.js.org/guides/code-splitting/#dynamic-imports
以上需求的一个更好的实现,UMIJS中动态导入的功能也基于此项目
https://github.com/jamiebuilds/react-loadable
The text was updated successfully, but these errors were encountered: