美文网首页
react大型项目的按需加载和代码拆分。

react大型项目的按需加载和代码拆分。

作者: TouchMe丶 | 来源:发表于2019-03-31 11:02 被阅读0次

    REACT中的按需加载

    按需加载,顾名思义,需要什么我们才加载什么资源。传统的单页应用(SPA)在首屏就会加载整个应用所有页面的结构,样式与逻辑。所以首屏的加载速度会大大降低,从而影响用户体验。有什么方法能让首屏加载变快呢?其中最最重要的就是spa的按需加载了,也可以叫相应页面的异步加载。

    方法1:使用react-loadable模块辅助进行按需加载

    本项目用的create-react-app来构建
    这个方法是我最常用的。其中用到了一个react-router官方提供的第三方库,react-loadable。这个库主要是用来帮助我们完成按需加载的。
    react-loadable
    具体用法,参照官方给出的example。
    安装之后,我们首先在需要按需加载的组件的同文件夹下创建一个loadable.js文件,如下

    import React from "react";
    import Loadable from 'react-loadable';
    
    const LoadableComponent = Loadable({
      loader: () => import('./'), //这里相当于再加同文件夹下的index.js
      loading(){//这里是加载进行时,页面上要显示的ui
        return <div>正在加载</div>
      }
    });
    export default ()=> <LoadableComponent/>
    

    然后,在入口文件中,我们写上关于路由的改变

    //Detail变成一个异步组件了
    import Detail from "./pages/detail/loadable.js";
    //以及
    <Route exact path="/detail/:id" component={Detail}></Route>
    

    注意,由于Detail是loadable.js导出的模块,经过上面的包装,就会让loadable.js内的模块获取到props,但同时,props没法传入到真正的Detail,所以在Detail组件中,我们无法获取到react-router提供的history,进而没法进行一些关于路由的操作。
    所以在Detail组件文件中,我们进行以下操作:

    import { withRouter } from "react-router-dom";
    //加载一个react-router-dom提供的withRouter对Detail进行包裹
    export default withRouter(Detail);
    

    方法一会把Detail的相关逻辑拆分出去,然后再首屏加载的时候对该部分进行忽略,等到我们进入detail页面,再进行加载。达到了代码拆分的目的。

    方法2:import()方法:

    import()函数是es6模块化标准之后才出现的新的特性。以前的import方法只能在文件中加载另一个文件导出的模块。现在,应用import()方法,我们可以在括号里面写相应加载函数,可以起到运行时加载的作用,就实现了了相应的按需加载功能。配合webpack相应的配置,同时实现代码拆分。
    首先,我们在工具文件夹utils当中,写一个asyncload高阶组件,放在asyncload文件夹下的asyncComponent.js中.
    让我们来写一个名为AsynComponent的高阶组件。它接收一个函数,函数返回平常的组件。经过包装后返回。

    import React,{ PureComponent } from "react";
    
    export default function AsyncComponent(importComponent){
      class AsyncComponent extends PureComponent{
        constructor(props) {
          super(props);
          this.state = {
            component:null
          };
        }
        async componentDidMount(){
          const { default:component } = await importComponent();
          this.setState({
            component:component
          });
        }
        render(){
          const C = this.state.component;
          return C ? <C {...this.props}/> : null
        }
      }
      return AsyncComponent;
    }
    

    然后再入口文件app.js中:

    // import()异步加载
    import AsyncComponent from "./utils/asyncload/asyncComponent";
    const BasicImport = AsyncComponent(() => import("./pages/imports"));
    //import()方法加载了imports里面的index.js,并返回一个promise
    
    <Route exact path="/impt" component={BasicImport}></Route>
    

    这样也能把impt对应的impt代码分隔开来。构建的时候就能看到,多了相应的js文件。并且不会再首屏加载。

    相关文章

      网友评论

          本文标题:react大型项目的按需加载和代码拆分。

          本文链接:https://www.haomeiwen.com/subject/xsgdbqtx.html