当前位置: 首页 > 科技观察

基于Webpack2的React组件懒加载

时间:2023-03-17 14:34:15 科技观察

Chunks是Webpack的基本概念之一。最直观的概念是,在多条目配置中,单个条目将生成一个单独的Chunk。添加额外的插件配置后,Webpack会输出独立的块,比如独立的CSS包。Webpack内置了三种类型的Chunks:EntryChunks:EntryChunks是我们最常见的Chunks类型,包括Webpack运行时和应用程序需要立即加载的模块。NormalChunks:NormalChunks不包括Webpack运行时,主要是指应用程序运行时动态加载的模块。Webpack会创建一个像JSONP这样合适的加载器供我们动态加载。InitialChunks:InitialChunks本质上是NormalChunks,但它们会在应用程序初始化时加载。通常这种类型的块是由CommonsChunkPlugin生成的。bundle-loaderbundle-loader是Webpack出品的官方Loader之一。bundle-loader可用于加载异步代码块。基本用法如下://当一个bundle被请求时,Webpack会自动为我们加载它varwaitForChunk=require("bundle-loader!./file.js");//我们需要等待Chunk被加载loaded之前我们可以获取文件详情("bundle-loader?lazy&name=my-chunk!./file.js");我们可以很方便的使用bundle-loader来实现ReactRouterLazy加载模块,比如我们的路由设置如下:importHomePagefrom"./pages/HomePage";importAdminPagefrom"./pages/admin/AdminPage";importAdminPageSettingsfrom"。/pages/admin/AdminPageSettings";exportdefaultfunctionroutes(fromServer){return()}其中AdminPage会很麻烦,我们希望只有当用户真正请求地址/admin时,才会加载相关组件。这时候我们可以在Webpack配置中加入bundle-loader支持:{...module:{loaders:[{//use`test`tosplitasinglefile//or`include`tosplitawholefoldertest:/.*/,include:[path.resolve(__dirname,'pages/admin')],loader:'bundle?lazy&name=admin'}]}...}的配置会自动帮我们从主文件中去掉admin相关的组件代码,并且然后将其移动到1.admin.js文件中,然后在ReactRouter中,我们还需要定义组件加载函数:importHomePagefrom"./pages/HomePage";importAdminPagefrom"./pages/admin/AdminPage";importAdminPageSettingsfrom"./pages/admin/AdminPageSettings";constisReactComponent=(obj)=>Boolean(obj&&obj.prototype&&Boolean(obj.prototype.isReactComponent));constcomponent=(组件)=>{returnisReactComponent(组件)?{组件}:{getComponent:(loc,cb)=>component(comp=>cb(null,comp.default||comp))}};exportdefaultfunctionroutes(fromServer){return()}ReactLazyLoading组件包LazyLoading-React有时我们需要放一个重的组件设置为异步加载。这里我们将常见的懒加载操作封装为一个组件及其高层组件接口。源码参考LazilyLoad:importReactfrom'react';/classLazilyLoadextendsReact.Component{constructor(){super(...arguments);this.state={isLoaded:false,};}componentWillMount(){this.load(this.props);}componentDidMount(){this._isMounted=true;}componentWillReceiveProps(next){if(next.modules===this.props.modules)returnnull;this.load(next);}componentWillUnmount(){this._isMounted=false;}load(props){this.setState({isLoaded:false,});const{modules}=props;constkeys=Object.keys(modules);Promise.all(keys.map((key)=>modules[key]())).then((values)=>(keys.reduce((agg,key,index)=>{agg[key]=values[index];returnagg;},{}))).then((result)=>{if(!this._isMounted)returnnull;this.setState({modules:result,isLoaded:true});});}render(){if(!this.state.isLoaded)returnnull;returnReact.Children.only(this.props.children(this.state.modules));}}LazilyLoad.propTypes={children:React.PropTypes.func.isRequired,};exportconstLazilyLoadFactory=(组件、模块)=>{return(props)=>({(mods)=>});};exportconstimportLazy=(promise)=>(promise.then((result)=>result.default));exportdefaultLazilyLoad;CallbackLazilyLoad这里我们使用了类似于bundle-loader的回调方法进行懒加载,但是它会封装在组件的形式。importLazy主要是为了兼容Babel/ES2015。它只是返回默认属性值。有关示例代码,请参阅此处。render(){return...importLazy(System.import('../lazy/loaded_late.js'))}}>{({LoadedLate})=>{return}}...}高阶组件延迟加载在入门介绍中我们说过可以使用外部属性来配置jQuery的介绍,这里也可以使用要异步加载的高阶组件://@flowimportReact,{Component,PropTypes}from'react';import{LazilyLoadFactory}from'../../../common/utils/load/lazily_load';/***componentLoadedJquery*/exportdefaultclassLoadedJQueryextendsComponent{/***@function默认渲染函数*/render(){return(this.props.$(ref).css('background-color','red')}>jQueryloadingFinished

);}}exportdefaultLazilyLoadFactory(LoadedJQuery,{$:()=>System.import('jquery'),});这里我们传递加载的jQuery作为props参数把组件放到组件中使用,我们也可以使用这个方法来加载我们自定义的函数或者comp内容。以上两篇效果如下:【本文为专栏作者“张子雄”的原创文章,如需转载请通过联系作者】点此查看该作者更多好文