美文网首页React Native
使用react-router做延迟加载路由配置

使用react-router做延迟加载路由配置

作者: 张培_ | 来源:发表于2017-12-16 20:43 被阅读415次

情景描述

  • 客户要求我们首次打开页面的时候必须在1s之内
  • 可是项目很大,首页加载模块体积大首屏加载时间长
  • 为了解决这个问题项目中使用按需加载路由配置这种方式
  • 将router写成了如下的样子
import {AppContainer} from 'containers'

export const routes = {
const errorLoading = _ => _ // console.error('Dynamic loading failed' + err)

const loadRoute = cb =>
  module => cb(null, module.default)


export const routes = {
  component: AppContainer,
  path: '/',
  indexRoute: {
    getComponent(location, callback) {
      import('./containers/User/LandingPageContainer')
        .then((module) => {
          callback(null, module.default)
        })
        .catch(err => errorLoading(err))
    }
  },
  childRoutes: [
    {
      path: '/admin',
      getChildRoutes(partialNextState, callback) {
        import('./containers/Admin/routes')
          .then(loadRoute(callback))
          .catch(err => errorLoading(err))
      },
      onEnter: checkInvalidRoleAndRedirect
    },
    {
      path: '/wms/create',
      getComponent(nextState, callback) {
        import('./containers/WMS/CreateOrderContainer')
          .then(loadRoute(callback))
          .catch(err => errorLoading(err))
      }
    }
  ]
}
  • 导致我完全不能明白。。。。

解释

  • Q1:这种写法和以前的使用标签区别是啥呢?
<BrowserRouter>
      <Route path="/tacos" component={Tacos}/>
    </div>
</BrowserRouter>
  • A1:区别:

    • 使用标签的写法webpack会把所有的文件全部打包在一个main.*****.js文件,也就是说这时候庞大的项目中所有js代码全部都被打包到一个js文件中。会造成的问题
      • 当用户请求首页,首页的代码以及项目中所有的代码全部都在main.****.js文件中。
      • 为了将首页render出来,必须将这个非常大的js文件请求回来
      • 因此非常耗时
    • 使用项目中的写法
      • webpack会通过import()这个方法作为code spliting的分割点,然后将庞大的项目根据分割点分成若干的chunk.js文件。
      • 然后当你访问首页的时候
      • 我们只需要请求首页的chunk.js文件即可
      • 这时候每次请求的内容大大减少,时间就会减小
  • Q2: 按需加载又是什么样的概念呢?

  • A2: 按需加载很好理解,需要什么加载什么,问题在于如何保证你需要的都能加载进来,你不需要的都不加载进来呢?重点在于我们通过webpack将文件打包成静态文件,部署到服务器,要做到按需加载(按需请求),就必须要求webpack做到合适的分隔项目并且将他们打包到不同的文件(chunk文件中)所以要实现好的按需加载必须要要求webpack能够做好将不同的代码打包到不同的文件。


  • Q3:那么webpack又是如何分割项目并打包到不同的文件中呢?
  • A3:webpack提供了code splitting特性,此特性能够把代码分离到不同的bundle文件实现按需加载。在webpack的官网介绍了三种实现code splitting,采用动态导入的方式,结合es6提出的import(和promise)作为code splitting分割点,将不同本部分分别打包在不同的chunk文件中。
    • ps:webpack主要有两种代码分割的分割点选择方式:
      • 1.import
      • 2.require.ensure

  • Q4:import是什么和我们之前的模块引入使用import不是一个东西吗?
  • A4:两种import分别是同步和异步加载模块(也可以看做静态和动态的引入模块),两种引入方式的最大区别在:
    • import App from './component/app':编译时加载模块,因此必须写在每个模块的最上方,写在编译时候不会执行的地方就会失效(比如写在if里面),只能做静态引入不能做动态引入
    • import('./component/app').then((module)=>{console.log('this is dynamic import module',module.default)}).catch(err=> 'dynamic import failed'):是运行时加载模块(和require一样),所以只有import()和require能够做到动态引入
      • require和import之间的区别又是什么呢?
        • require:是同步的
        • import:返回的是promise是异步的

  • Q5:那么使用webpack做按需加载需要配置什么吗? 代码中又要做什么样的改变呢?
  • A5:改变需要分成两个部分:
    • webpack配置上的改变:配置需要做的改变基本没有,顶多就是配置一下chunk文件的名字
    ```js
    entry: {
        chunkFilename: '[name].[chunkhash:5].chunk.js',
        //给生成的chunk文件确定命名规范,name在没有设置的时候默认使用id
        //chunkhash:5 5位hash码
    
    }
    - 代码上的改变:这里主要针对react实现按需加载,如果想要对react实现按需加载,那么就需要webpack和react-router之间的配合。so react-router实现按需加载该怎么配置(主要分成两个部分):
    - 实现组件的按需引入:react-router提供了方法代替相应属性实现对相应路由组件的异步挂载
      - getComponent: 代替Route标签的component实现当访问到当前路径的时候再执行该方法加载组件
        - 参数有两个
          - location:是一个对象包含当前的所有路由中能获取的信息
          - callback:回调函数,用于异步引入组件成功后调用
            - 参数有两个: 
              - error(如果没有error这个参数在调用的时候写成null,如果不写成null,那么在当前路由下就会报出Require.ensure error的错误)
              - 组件:请注意如果你是用的是import引入组件那么promise返回的数据应该是整个module对象,而不是你的组件
                - 如果在module使用default暴露:那么callback的第二参数必须是module.default
                - 如果在module中使用export const a、export const那么第二个参数必须是module.a或者module.b
      - getChildRoutes:代替某个Route的子组件实现异步加载child组件(大有作用!! 下一篇简书介绍)
      - getIndexRoute: 但是实践过后发现使用失败不知道为什么,所以换成了`indexRoute: { getComponent()}`
    - 写明code splitting的分割点:之前提到过有两种分割方式
      - 使用webpack 提供的require.ensure实现:用这个方法定义分割点独立打包chunk
      - 使用es6的动态import实现:参数是引入module的地址   方法返回promise 回调函数的参数中包含module
    ```js
      import AppContainer from './components/AppContainer'
      import LandingPageContainer from './containers/User/LandingPageContainer'
      import CreateOrderContainer from './containers/WMS/CreateOrderContainer'
      <Router>
         <Route path='/' component={AppContainer}>
           <IndexRoute component={LandingPageContainer} />
           <Route path='/wms/creat' component={CreateOrderContainer} />
         </Route>
      </Router>
      //原来的写法  所有的组件都是静态引入,也就意味这在编译的时候就必须将所有引入的文件(也就是项目中所有的组件)打包在一个js文件中,当浏览器没有缓存的时候,第一次请求就要把一个很大的js文件请求回来
      
    

  • Q6:那么对于第三方模块如何实现性能的提升呢?
  • A6: 采用将所有的第三方库的全部都打包到一个js文件,原因:
    - 由于这一部分内容不怎么需要变化,所以打包好之后就放在一个js文件中不动了
    - 这样既有利于缓存而且不需要重复打包。
    - 但是剥离第三方库主要对于开发的时候会加快打包速度
    - 可以使用commonChunkPlugin来实现

相关文章

  • 使用react-router做延迟加载路由配置

    情景描述 客户要求我们首次打开页面的时候必须在1s之内 可是项目很大,首页加载模块体积大首屏加载时间长 为了解决这...

  • Angular的路由延迟加载

    Angular的路由延迟加载 angular的路由延迟加载大致分为两类CanActivate和CanLoad。这两...

  • vue3+vite自动加载路由

    1、使用 import.meta.glob加载所有vue文件 2、使用addRoute挂载动态路由 3、路由配置

  • 关于React-Router使用心得

    使用react-router也有半年时间了,这里做一个心得记录。 1.路由配置 一般在项目中路由配置文件放置于ro...

  • React 中好用的库

    React-router: 路由库 react-router-config: 统一管理配置我们的路由

  • 前端学习笔记四十一-移动APP(5)react-router和A

    一、react-router 要使用 react-router路由模块,先安装依赖包yarn add react-...

  • react 踩过的坑

    使用路由 提示 'Link' is not exported from 'react-router' 源代码如下 ...

  • MyBatis延迟加载

    延迟加载 使用场合 ⼀对多,多对多:通常情况下采⽤延迟加载⼀对⼀(多对⼀):通常情况下采⽤⽴即加载 配置 原理 使...

  • vue的路由和路由守卫

    router 和 路由守卫 路由配置 分模块配置 404 配置 懒加载 active-class 路由守卫(跟 a...

  • 单例模式

    延迟加载 延迟加载是指等到真正使用时去创建实例,不使用时不创建实例 对比延迟加载(懒汉式)和非延迟加载(饿汉式):...

网友评论

    本文标题:使用react-router做延迟加载路由配置

    本文链接:https://www.haomeiwen.com/subject/okdewxtx.html