zoukankan      html  css  js  c++  java
  • [转] react-router4 实现按需加载

    按需加载的背景

    https://juejin.im/post/58f9717e44d9040069d06cd6?utm_source=tuicool&utm_medium=referral

    React Router 是一个非常出色的路由解决方案,同时也非常容易上手。但是当网站规模越来越大的时候,首先出现的问题是 Javascript 文件变得巨大,这导致首页渲染的时间让人难以忍受。实际上程序应当只加载当前渲染页所需的 JavaScript,也就是大家说的“代码分拆" — 将所有的代码分拆成多个小包,在用户浏览过程中按需加载。

    老的方案

    这里所说的老是指使用react-router低于4的版本。

    在低版本(小于4)的react-router中直接提供了按需加载的方案,示例如下:

    const rootRoute = {
      path: '/',
      indexRoute: {
        getComponent(nextState, cb) {
          require.ensure([], (require) => {
            cb(null, require('components/layer/HomePage'))
          }, 'HomePage')
        },
      },
      getComponent(nextState, cb) {
        require.ensure([], (require) => {
          cb(null, require('components/Main'))
        }, 'Main')
      },
      childRoutes: [
        require('./routes/baidu'),
        require('./routes/404'),
        require('./routes/redirect')
      ]
    }
    
    ReactDOM.render(
      (
        <Router
          history={browserHistory}
          routes={rootRoute}
          />
      ), document.getElementById('app')
    );

    核心代码是router.getComponent,然而在react-router4中,没有router.getComponent了,这样我们该如何实现按需加载呢?

    react-router4的实现方案

    根据官网的介绍:

    One great feature of the web is that we don’t have to make our visitors download the entire app before they can use it.
    You can think of code splitting as incrementally downloading the app. While there are other tools for the job, we’ll use Webpack and the bundle loader in this guide.

    我们要借助bundle-loader来实现按需加载。

    首先,新建一个bundle.js文件:

    import React, { Component } from 'react'
    
    export default class Bundle extends React.Component {
    
        state = {
            // short for "module" but that's a keyword in js, so "mod"
            mod: null
        }
    
        componentWillMount() {
            this.load(this.props)
        }
    
        componentWillReceiveProps(nextProps) {
            if (nextProps.load !== this.props.load) {
                this.load(nextProps)
            }
        }
    
        load(props) {
            this.setState({
                mod: null
            })
            props.load((mod) => {
                this.setState({
                    // handle both es imports and cjs
                    mod: mod.default ? mod.default : mod
                })
            })
        }
    
        render() {
            if (!this.state.mod)
                return false
            return this.props.children(this.state.mod)
        }
    }

    然后,在入口处使用按需加载:

    
    // ...
    
    // bundle模型用来异步加载组件
    import Bundle from './bundle.js';
    
    // 引入单个页面(包括嵌套的子页面)
    // 同步引入
    import Index from './app/index.js';
    // 异步引入
    import ListContainer from 'bundle-loader?lazy&name=app-[name]!./app/list.js';
    
    const List = () => (
        <Bundle load={ListContainer}>
            {(List) => <List />}
        </Bundle>
    )
    
    // ...
    
        <HashRouter>
            <Router basename="/">
                <div>
                    <Route exact path="/" component={Index} />
                    <Route path="/list" component={List} />
                </div>
            </Router>
        </HashRouter>
    
    // ...

    webpack.config.js文件配置

    output: {
        path: path.resolve(__dirname, './output'),
        filename: '[name].[chunkhash:8].bundle.js',
        chunkFilename: '[name]-[id].[chunkhash:8].bundle.js',
    },

    完整代码示例

    bundle.js

    react-molin

  • 相关阅读:
    BZOJ 1024: [SCOI2009]生日快乐
    BZOJ 3038: 上帝造题的七分钟2
    BZOJ 2005: [Noi2010]能量采集
    费用流&网络流模版
    BZOJ 1070: [SCOI2007]修车
    BZOJ 3039: 玉蟾宫
    BZOJ 1022: [SHOI2008]小约翰的游戏John
    BZOJ 2456: mode
    BZOJ 1015: [JSOI2008]星球大战starwar
    Unity实现IOS原生分享
  • 原文地址:https://www.cnblogs.com/chris-oil/p/7783662.html
Copyright © 2011-2022 走看看