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

15 篇文章 0 订阅
7 篇文章 0 订阅
一、参考链接:

 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 = () => <div>Loading...</div>;


/*
   包装方法,第一次调用后会返回一个组件(函数式组件)
   由于要将其作为路由下的组件,所以需要将 props 传入
      <Bundle load={loadComponent}>
      {Comp => (Comp ? <Comp {...props} /> : <Loading />)}
   </Bundle>
*/ 
const lazyLoad = (loadComponent,props) =>
{//Bundle  包含的是一个函数子组件 由Bundle.js里的this.props.children(this.state.mod)渲染
  return(
   <Bundle load={loadComponent}>
      {Comp => (Comp ? <Comp {...props} /> : <Loading />)}
   </Bundle>
);}


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

<BrowserRouter>
  <div>


      <Route exact  path="/" render={()=>   
        <Redirect to="/home"/>               
        // <Home dispatch={dispatch} getState={getState} questionList={value.question}></Home>
      }/>
      <Route path="/home" render={()=>{
        return lazyLoad(Home, {
            dispatch:dispatch,
            getState:getState,
            questionList:value.question
          }
        );
      }}/>                         
      <Route path="/detail" render={(props)=>{
        return lazyLoad(Detail, {
                    pid:props.location.id,
                    questionList:value.question,
                    dispatch:dispatch,
                    answer:value.answer
                }
              );
      }}/>
  </div>
</BrowserRouter> 
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 一个这个插件的实例,并传入相关的参数
        })
    ]
};





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值