react实现分片打包

前言

React开发过程中,大部分都是单页面应用,不做代码分片的话,所有的js文件都打成一个庞大的bundlejs文件,随着项目内容的不断增多,首屏空白时间就会变得越来越长。
因此可以对代码进行分片,打包时生成多个js文件,每次页面只请求所需要的js文件,用户体验大大提升。

法一:Loadable实现(不推荐)

在React16.6之前懒加载流行使用Loadable包。

  • 安装依赖
npm i react-loadable -S
  • 路由配置
import React from 'react';
import Loadable from 'react-loadable';

const Loading = () => <div>loading</div>;  // 定义一个组件,在组件加载前展示,组件加载完成之后消失

const Index = Loadable({
  loader: () => import('../views/Index/Index'),
  loading: Loading
});

const PageOne = Loadable({
  loader: () => import('../views/PageOne/PageOne'),
  loading: Loading
});

const PageTwo = Loadable({
  loader: () => import('../views/PageTwo/PageTwo'),
  loading: Loading
});

export default [
  {
    path: '/',
    component: Index,
    exact: true,
    title: '首页',
  },
  {
    path: '/PageOne',
    component: PageOne,
    exact: true,
    title: '登录',
  },
  {
    path: '/PageTwo',
    component: PageTwo,
    exact: true,
    title: '登录',
  },
];
  • App.js
import React, { Component } from 'react';
import {
  Route,
  Switch,
  Redirect,
  BrowserRouter as Router
} from 'react-router-dom';
// 这里的是路由配置文件
import routes from './router/index';
export default class App extends Component {
  render() {
    return (
        <Router>
            <Switch>
              {
                routes.length > 0 && routes.map((route) => {  //遍历路由数组
                  const {
                    path,
                    component:C,  // 这样写,是为了以下写法中,用C来代替标签如<Home />,因为不能<component />
                    exact,
                  } = route;
                  return (
                    <Route
                      exact={exact}
                      key={path}
                      path={path}
                      render={(props) => {
                        // 实际上这里会处理很多的业务逻辑,如权限和登录(无token自动跳转到登录页),相当于vue的导航守卫
                        // console.log(props);
                        return (<C />);
                      }}
                    />
                  );
                })
              }
              {/* 默认进入/时自动匹配到/Home */}
              <Redirect
                exact
                from="/"
                to={'/'}
              />
              {/* 默认无效路径时自动匹配到首页 */}
              <Redirect to="/" />
            </Switch>
        </Router>
    );
  }
}

如果react是高版本,会出现这样的警告,所以不推荐使用此方法
在这里插入图片描述

法二: 使用react的lazy,Suspense方法实现分片打包

  • 路由配置
import { lazy } from 'react';
const PageOne = lazy(() => import('../views/PageOne/PageOne'));
const PageTwo = lazy(() => import('../views/PageTwo/PageTwo'));
const Index = lazy(() => import('../views/Index/Index'));

export default [
  {
    path: '/',
    component: Index,
    exact: true,
    title: '首页',
  },
  {
    path: '/PageOne',
    component: PageOne,
    exact: true,
    title: '登录',
  },
  {
    path: '/PageTwo',
    component: PageTwo,
    exact: true,
    title: '登录',
  },
];
  • App.js,引入并使用Suspense包裹要懒加载的组件(Route)
import React, { Suspense, Component } from 'react';
import {
  Route,
  Switch,
  Redirect,
  BrowserRouter as Router
} from 'react-router-dom';
// 这里的是路由配置文件
import routes from './router/index';
export default class App extends Component {
  render() {
    return (
        <Router>
          <Suspense fallback={<div>loading</div>}>
            <Switch>
              {
                routes.length > 0 && routes.map((route) => {  //遍历路由数组
                  const {
                    path,
                    component:C,  // 这样写,是为了以下写法中,用C来代替标签如<Home />,因为不能<component />
                    exact,
                  } = route;
                  return (
                    <Route
                      exact={exact}
                      key={path}
                      path={path}
                      render={(props) => {
                        // 实际上这里会处理很多的业务逻辑,如权限和登录(无token自动跳转到登录页),相当于vue的导航守卫
                        // console.log(props);
                        return (<C />);
                      }}
                    />
                  );
                })
              }
              {/* 默认进入/时自动匹配到/Home */}
              <Redirect
                exact
                from="/"
                to={'/'}
              />
              {/* 默认无效路径时自动匹配到首页 */}
              <Redirect to="/" />
            </Switch>
          </Suspense>
        </Router>
    );
  }
}

对redux进行分割

对页面进行分割后,可以进一步的切割页面所需要的数据,我们使用store的replaceReducer方法 在store.js中,添加一个维护当前reducer的对象,和一个更新reduer的方法。

let asyncReducers = {};
export const getNewReducer = (newModuleInfo) => {
  asyncReducers[newModuleInfo.name] = newModuleInfo.reducer;

  store.replaceReducer(combineReducer({
    ...asyncReducers,
  }))
}

在reducerC文件中,需要调用该方法

import { getNewReducer } from './store.js';
const state = { value: '' };

const reducer = (state = state, action) => {
  switch(action.type) {
    case 'setValue':
      return { ...state, value: action.value };
    default:
      return state;
  }
}

export default getNewReducer({ name: 'reducerC', reducer });

文章参考
https://juejin.im/post/6844903953721737224
https://www.jianshu.com/p/164be62145a7
https://segmentfault.com/a/1190000020247862?utm_source=tag-newest
https://blog.csdn.net/xutongbao/article/details/84822315

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值