React-router4 使用bundle-loader实现按需加载(code-splitting)

一、参考链接:

 1.官网:https://reacttraining.com/react-router/web/guides/code-splitting/code-splitting-server-rendering

2.某文章:http://blog.csdn.net/mjzhang1993/article/details/79094594

二、源码链接:http://download.csdn.net/download/dknightl/10240961

三、代码

 1.Bundle.js
  Bundle组件会接受一个名为  load  的  props
  load值一是一个组件异步加载的方法  load -> function (cb) {...cb(/* 异步加载的组件 */)},由bundle-loader封装
  这个方法需要传入一个回调函数作为参数
  回调函数会在在方法内异步接收加载完的组件
import React from 'react';

class Bundle extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      // 默认为空
      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({
        mod: mod.default ? mod.default : mod
      });
    });
  }

  render() {
    // 不为空,则渲染传入的子组件函数
    return this.state.mod ? this.props.children(this.state.mod) : null;
  }
}


export default Bundle;
2.lazyLoad.js
 这个包装函数接受两个值,一个为经过bundle-loader封装的组件,另一个是组件的属性
import React from 'react';
import Bundle from './Bundle';


// 默认加载组件,可以直接返回 null 
const Loading = () => 
Loading...
; /*    包装方法,第一次调用后会返回一个组件(函数式组件)    由于要将其作为路由下的组件,所以需要将 props 传入             {Comp => (Comp ? : )}     */  const lazyLoad = (loadComponent,props) => {//Bundle  包含的是一个函数子组件 由Bundle.js里的this.props.children(this.state.mod)渲染   return(           {Comp => (Comp ? : )}     );} export default lazyLoad;
3.路由使用
有两种使用方式,一种是webpack配置(见下面第四点),
另一种是在组件内直接引用bundle-loader(下面代码没注释的就是)
//import Home from './page/Home.bundle';//这种方式需要配置webpack的loader
//import Detail from './page/Detail.bundle';//这种方式需要配置webpack的loader

//--------------------------------------------------

import Detail from 'bundle-loader?lazy&name=home!./page/Detail.bundle';
import Home from 'bundle-loader?lazy&name=home!./page/Home.bundle';


  
// }/> { return lazyLoad(Home, { dispatch:dispatch, getState:getState, questionList:value.question } ); }}/> { return lazyLoad(Detail, { pid:props.location.id, questionList:value.question, dispatch:dispatch, answer:value.answer } ); }}/>
4.如果使用webpack配置
注意这段代码要放在js的loader之前,不然可能会报错,这段配合下面这两句引用使用
//import Home from './page/Home.bundle';//这种方式需要配置webpack的loader
//import Detail from './page/Detail.bundle';//这种方式需要配置webpack的loader
       {
                test: /\.bundle\.js$/,
                loader: 'bundle-loader',
                options: {
                    lazy: true,
                    name: '[name]'
                }
            }
完整的webpack.config.js
//__dirname是node.js中的一个全局变量,它指向当前执行脚本所在的目录
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const autoprefixer = require('autoprefixer')

let extractCSS = new ExtractTextPlugin('main.css');

module.exports = {//注意这里是exports不是export
    devtool: 'source-map',//本地调试react
    devServer: {
        contentBase: "./build",//本地服务器所加载的页面所在的目录
        historyApiFallback: true,//不跳转
        port:8888,//设置默认监听端口,如果省略,默认为”8080“
        inline: true//实时刷新
    }, 

    entry: __dirname + "/src/main.js",//唯一入口文件,就像Java中的main方法
    output: {//输出目录
        path: __dirname + "/build",//打包后的js文件存放的地方
        filename: "bundle.js"//打包后的js文件名
    },


    module: {
        //loaders加载器
        rules: [
            {
                test: /\.bundle\.js$/,
                loader: 'bundle-loader',
                include:/page/,
                options: {
                    lazy: true,
                    name: '[name]'
                }
            },{
                test: /\.(js|jsx)$/,//一个匹配loaders所处理的文件的拓展名的正则表达式,这里用来匹配js和jsx文件(必须)
                exclude: /node_modules/,//屏蔽不需要处理的文件(文件夹)(可选)
                use: 'babel-loader'//loader的名称(必须)
            },{ 
                test: /\.(css|less)$/, 
                use:extractCSS.extract({
                        fallback: "style-loader",
                        use: [{
                            loader: "css-loader",
                            options: {
                                modules: true, // 指定启用css modules
                                localIdentName: '[name]__[local]--[hash:base64:5]' // 指定css的类名格式
                            }

                        },{
                            loader: "postcss-loader",
                            options: {
                                plugins: () => [autoprefixer(
                                  { browsers: ['iOS >= 7', 'Android >= 4.1', 
                                     'last 10 Chrome versions', 'last 10 Firefox versions', 
                                     'Safari >= 6', 'ie > 8'] 
                                  }
                                )],
                            },
                        },{
                            loader: "less-loader"
                        }],
                })
            },{
                test: /\.(eot|svg|ttf|woff|woff2|png)\w*/,// font awesome loader
                use: 'file-loader'
            }

        ]
    },
    plugins: [
        extractCSS,
        new HtmlWebpackPlugin({
            template: __dirname + "/src/index.tmpl.html"//new 一个这个插件的实例,并传入相关的参数
        })
    ]
};





你可能感兴趣的:(个人,react,webpack)