Create React App中的代码分割实践

Code Splite

在上一次开发一个大型的SPA网站的时候,因为加载了大量的第三方库,导致webpack打包出来的bundle.js异常的大,时候祭出了code splite来减少js的大小了。所谓的Code splite其实就是所谓js的懒加载。因为我们的技术栈使用react + redux + redux-thunk配合create-react-app来搭建的,所以我们就说说Create React App如何来做代码分割。

首先需要申明的是代码分割不是一颗银弹,不要过度优化你的程序除非你的程序到了需要优化的程度,或者想我这样就是想瞎折腾学习学习。如果在开发React过程中发现打包出来的bundle.js越来越大,多半是和我们一样引入了很多组件导致程序在第一次加载的过慢。

思考以下如下的场景:在用户使用一个比较大的程序,当用户只是在登录界面,没有必要将整个程序都加载出来。Create React App起始已经内置了代码分割功能来动态加载import。Import来动态加载组件通常配合React Router。我们通过设置React Router来根据Url路径来做到按需加载组件。

JS的模块化规范

代码分割其实加载的一个模块,require/export出生在野生规范,被广泛使用在CommonJS、AMD、CMD等等, import/export则是名门正派由ECMAScript版本进来。

本质的差别:

  • CommonJS还是ES6 Module输出都可以看成是一个具备多个属性或者方法的对象
  • default是ES6 Module所独有的关键字,export default fs输出默认的接口对象
  • ES6 module中导入模块的属性或者方法是强绑定,包括基础类型,而CommonJS则是普通的值传递或者引用传递。

Async Component

首先我们创建一个包装的Async Component。

import React, {Component} from 'react';

export default function asyncComponent(importComponent) {
  class AsyncComponent extends Component {
    constructor(props) {
      super(props);

      this.setState(component : null)
    }

    async componentDidMount() {
      const {default: component} = await importComponent();

      this.setState({component: component})
    }

    render() {
      const C = tis.state.component;

      return C
        ? <C {...this.props}/>
        : null
    }
  }
  return AsyncComponent;
}
复制代码

之前我们都是静态的加载组件

import Home from './containers/Home';
复制代码

现在我们使用 asyncComponent来动态加载我们需要的组件

const AsyncHome = asyncComponent(() => import ('./container/Home'))
复制代码

比较两者的区别,我们会发现在动态加载起始我们只是包装了一个函数,将一个函数传入,当包装的函数加载完成后在生命周期的componentDidMount()来import我们真正需要的组件。

然后我们来看看将组件使用在routes

之前我们是直接加载的静态组件

<Route path = '/' exact component = {Home}/>
// <Route path = '/' exact component = {AsyncHome}/>
复制代码

总结

import React from "react";
import { Route, Switch } from "react-router-dom";
import asyncComponent from "./components/AsyncComponent";
import AppliedRoute from "./components/AppliedRoute";
import AuthenticatedRoute from "./components/AuthenticatedRoute";
import UnauthenticatedRoute from "./components/UnauthenticatedRoute";

const AsyncHome = asyncComponent(() => import("./containers/Home"));
const AsyncLogin = asyncComponent(() => import("./containers/Login"));
const AsyncNotes = asyncComponent(() => import("./containers/Notes"));
const AsyncSignup = asyncComponent(() => import("./containers/Signup"));
const AsyncNewNote = asyncComponent(() => import("./containers/NewNote"));
const AsyncNotFound = asyncComponent(() => import("./containers/NotFound"));

export default ({ childProps }) =>
  <Switch>
    <AppliedRoute
      path="/"
      exact
      component={AsyncHome}
      props={childProps}
    />
    <UnauthenticatedRoute
      path="/login"
      exact
      component={AsyncLogin}
      props={childProps}
    />
    <UnauthenticatedRoute
      path="/signup"
      exact
      component={AsyncSignup}
      props={childProps}
    />
    <AuthenticatedRoute
      path="/notes/new"
      exact
      component={AsyncNewNote}
      props={childProps}
    />
    <AuthenticatedRoute
      path="/notes/:id"
      exact
      component={AsyncNotes}
      props={childProps}
    />
    {/* Finally, catch all unmatched routes */}
    <Route component={AsyncNotFound} />
  </Switch>

复制代码

通过运行npm run build 我们会看到 代码切割的js 分别是 build/static.js/1.chunk.js 之类的,说明我们已经已经完成了代码切割。

react-loadable

如果你讲上面的asyncComponent放入了线上环境很有可能会被主观打死,因为上面的代码仅供参考,因为是异步加载所以有很多异常的corner case没有考虑在其中。其实已经有大神给我们写好的react-loadable,使用起来相当方便,再次我也不在赘述了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值