Skip to content
New issue

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

如何异步加载组件 #13

Open
zp1112 opened this issue May 12, 2018 · 1 comment
Open

如何异步加载组件 #13

zp1112 opened this issue May 12, 2018 · 1 comment
Labels

Comments

@zp1112
Copy link
Owner

zp1112 commented May 12, 2018

异步组件加载

我们知道react或者是其他用于写单页应用的框架都是组件化的概念,每个路由每个页面就是一个个大组件,webpack在打包的时候,将所有的文件都打包进一个bundle里面,但是我们往往在a页面的时候不需要加载b页面的东西,理想情况下,用户访问一个页面时,该页面应该只需要加载自己使用到的代码,为了提高性能,webpack支持代码分片,将js代码打包到多个文件中按需加载。
按需加载的方式有两种,一个是 webpack提供的require.ensure(),一个是 ES6提案的import()
下面我们写一个asyncComponent异步加载方法,分别使用这两种方式实现。其实是写了一个高阶组件,高阶组件的理解可以看这篇文章

webpack提供的require.ensure()

webpack提供了require.ensure(),webpack 在编译时,会静态地解析代码中的 require.ensure(),同时将模块添加到一个分开的 chunk 当中。这个新的 chunk 会被 webpack 通过 jsonp 来按需加载。

// asyncCmponent.js
import React, { Component } from 'react';

export default function asyncComponent (importFunc) {
  return class App extends Component {
    constructor(props) {
      super(props);
      this.state = {
        component: null
      }
    };
    componentDidMount = () => {
      importFunc().then(mod => {
        this.setState({
          component: mod.default || mod
        })
      });
    }
    render = () => {
      const C = this.state.component;
      return (
        C ? <C {...this.props} /> : null
      )
    }
  }
}

调用

import asyncCmponent from './asyncCmponent.js';

const App = asyncCmponent(() => require.ensure([], (require) => require('./App')));
ReactDOM.render(
  <Provider store={store}>
      <App />
   </Provider>, 
   document.getElementById('root')
);

打开浏览器,可以看到除了bundle.js还多了个1.js,且bundle的体积被拆分出来了。
image

ES6提案的import()

es6中我们知道import是用于加载使用export命令定义的模块,import和require的区别在于import是在静态解析阶段执行的,所以它是一个模块之中最早执行的,而require是动态加载的,运行时加载模块,import命令无法取代require的动态加载功能。require到底加载哪一个模块,只有运行时才知道。import命令做不到这一点。因此,有一个提案,建议引入import()函数,完成动态加载。详情请看《es6入门》
import()函数返回的是一个promise。

// 只需修改componentDidMount部分
componentDidMount = () => {
      importFunc().then(mod => {
        this.setState({
          component: mod.default || mod
        })
      })
    }

调用

const App = asyncCmponent(() => import('./App')));

打开浏览器,可以看到同样的效果。boom!!!

@zp1112 zp1112 added the react label May 12, 2018
@meibin08
Copy link

meibin08 commented Dec 5, 2018

很棒!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants