React中代码分割的4种实现⽅式
⽬录
前⾔
import()
React.lazy
import() + React Loadable
UmiJS 按需加载
总结
前⾔
在 React 应⽤中,我们通常的做法是直接将某个模块导⼊到页⾯中,这样做导致的结果是打包出来的包体积过⼤。尤其是在引⼊了体积巨⼤的第三个库的情况下,打包后的包体积会⼗分巨⼤。因此,我们需要关注我们的应⽤中所包含的代码,以避免因体积过⼤⽽导致加载时间过长。
对代码进⾏分割能够“懒加载”当前⽤户所需要的内容,能够显著提⾼应⽤的性能。尽管并没有减少应⽤的整体代码体积,但可以避免加载⽤户永远不需要的代码,并在初始加载的时候可以减少所需加载的代码量。
下⾯,我们分别来介绍下在 React 中实现代码分割的⼏种⽅式。
import()
import() 是 Webpack 提供的⽤于分割代码的⼀个⽅法。该⽅法的返回结果是Promise,当⽂件加载完成后悔将模块导出给promise.then ⽅法的回调。
例如有⼀个 math 模块,导出了 add⽅法和 minus ⽅法:
export const add = (a, b) => {
return a + b;
}
export const minus = (a, b) => {
return a - b;
}
通常的做法是在页⾯直接引⼊模块:
import { add } from './math'
console.log(add(5, 10));
使⽤ import 动态导⼊模块:
import('./math').then((math) => {
console.log(math.add(5, 10))
})
当 Webpack 解析到该语法时,会⾃动进⾏代码分割。如果是使⽤ Create React App 创建的 React 应⽤,import 功能已开箱即⽤。
import React, { Component } from 'react';
class App extends Component {
handleClick = () => {
import('./math')
.then(({ add }) => {
add(5, 10)
})
.catch(err => {
// Handle failure
});
};
render() {
return (
<div>
<button onClick={this.handleClick}>两数相加</button>
</div>
);
}
}
export default App;
react router 动态路由
React.lazy
React.lazy ⽅法可以让我们动态加载组件,有助于缩减打包后 bundle 的体积,并延迟加载在初次渲染时未⽤到的组件。React.lazy 接受⼀个函数,这个函数需要动态调⽤ import()。它必须返回⼀个 Promise,该 Promise 需要 resolve ⼀个 export default 的 React 组件。
const AsyncComponent = React.lazy(() => import('./OtherComponent'));
React.lazy 返回的是⼀个异步组件不能单独使⽤,需要配合 React.Suspense 使⽤。当这个异步组件的状态是 pending 时显⽰的是 Suspense 中 fallback 的内容,只有 resolve 时才会显⽰加载好的组件。如此使得我们可以在使⽤ lazy 组件时做优雅降级(如在 fallback添加 loading 效果等)。
import React, { Suspense } from 'react';
const AsyncComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<div>
<Suspense fallback={<div&</div>}>
<AsyncComponent />
</Suspense>
</div>
);
}
import() + React Loadable
是⼀个轻量级的代码分割组件,它是⼀个⾼阶组件,能让你的应⽤程序在渲染之前动态的加载任何模块。
使⽤ import() + React Loadable ,能优雅的实现基于 react-router 4.x 版本的路由分割:
import Loadable from 'react-loadable';
const LoadableBar = Loadable({
loader: () => import('./components/Bar'),
loading() {
return <div&</div>
}
});
class MyComponent extends React.Component {
render() {
return <LoadableBar/>;
}
}
在实际业务开发中,我们通常会使⽤⼀些框架来快速开发React应⽤。在这些框架中,通常都会提供按需加载的功能。下⾯,我们来看看 UmiJS 框架中的按需加载。
UmiJS 按需加载
UmiJS 是⼀个可扩展的企业级前端应⽤框架,它以路由为基础,⽀持配置式路由和约定式路由。UmiJS 封装了⼀个 dynamic 组件来实现代码分割。
启⽤按需加载
UmiJS 的按需加载功能默认是关闭的,需要在使⽤之前通过配置开启。在 UmiJS 项⽬中添加如下的配置开启:
export default {
dynamicImport: {},
}
使⽤按需加载
⾸先封装⼀个异步组件:
import { dynamic } from 'umi';
export default dynamic({
loader: async function() {
// 这⾥的注释 webpackChunkName 可以指导 webpack 将该组件 HugeA 以这个名字单独拆出去
const { default: HugeA } = await import(/* webpackChunkName: "external_A" */ './HugeA');
return HugeA;
},
});
然后使⽤封装好的异步组件:
import React from 'react';
import AsyncHugeA from './AsyncHugeA';
export default () => {
return <AsyncHugeA />;
}
总结
到此这篇关于React中代码分割的⽂章就介绍到这了,更多相关React代码分割内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!