over 2 years ago

step 1

create-react-app code_splitting_router

step 2

cd code_splitting_router

step 3

yarn add react-router-dom

step 4
建立 components/AsyncComponent

import React, { Component } from 'react';

export default function asyncComponent(importComponent) {

  class AsyncComponent extends Component {

    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;
}

step 5
建立 containers/Home, NotFound, Posts

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

class Home extends Component {
  render() {
    return (
      <div>
        Home
      </div>
    );
  }
}

export default Home;
//containers/NotFound.js
import React, { Component } from 'react';

class NotFound extends Component {
  render() {
    return (
      <div>
        NotFound
      </div>
    );
  }
}

export default NotFound;
//containers/Posts.js
import React, { Component } from 'react';

class Posts extends Component {
  render() {
    return (
      <div>
        Home
      </div>
    );
  }
}

export default Posts;

step 6
修改 index.js

//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Route, Switch, BrowserRouter } from 'react-router-dom';
import asyncComponent from './components/AsyncComponent';

const AsyncHome = asyncComponent(() => import('./containers/Home'));
const AsyncPosts = asyncComponent(() => import('./containers/Posts'));
const AsyncNotFound = asyncComponent(() => import('./containers/NotFound'));

ReactDOM.render(
<BrowserRouter>
  <Switch>
    <Route path="/" exact component={AsyncHome} />
    <Route path="/posts/:id" exact component={AsyncPosts} />
    <Route component={AsyncNotFound} />
  </Switch>
</BrowserRouter>
  ,
  document.getElementById('root')
);

step 7

npm run build

效果
code_splitting_1

step 8

npm start

效果
code_splitting_2

或使用 react-loadable
step 1

yarn add react-loadable

step 2
修改index.js

//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Route, Switch, BrowserRouter } from 'react-router-dom';
import Loadable from 'react-loadable';

const MyLoadingComponent = ({isLoading, error}) => {
  // Handle the loading state
  if (isLoading) {
    return <div>Loading...</div>;
  }
  // Handle the error state
  else if (error) {
    return <div>Sorry, there was a problem loading the page.</div>;
  }
  else {
    return null;
  }
};

const AsyncHome = Loadable({
  loader: () => import('./containers/Home'),
  loading: MyLoadingComponent
});

const AsyncPosts = Loadable({
  loader: () => import('./containers/Posts'),
  loading: MyLoadingComponent
});

const AsyncNotFound = Loadable({
  loader: () => import('./containers/NotFound'),
  loading: MyLoadingComponent
});

ReactDOM.render(
<BrowserRouter>
  <Switch>
    <Route path="/" exact component={AsyncHome} />
    <Route path="/posts/:id" exact component={AsyncPosts} />
    <Route component={AsyncNotFound} />
  </Switch>
</BrowserRouter>
  ,
  document.getElementById('root')
);

參考來源
http://serverless-stack.com/chapters/code-splitting-in-create-react-app.html
https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#code-splitting
https://facebook.github.io/react/blog/2017/05/18/whats-new-in-create-react-app.html#code-splitting-with-dynamic-import

← 簡單描述 side-effects 解決 called setState() on an unmounted component 問題 →
 
comments powered by Disqus