React中代碼分割的4種實現(xiàn)方式
前言
在 React 應用中,我們通常的做法是直接將某個模塊導入到頁面中,這樣做導致的結(jié)果是打包出來的包體積過大。尤其是在引入了體積巨大的第三個庫的情況下,打包后的包體積會十分巨大。因此,我們需要關(guān)注我們的應用中所包含的代碼,以避免因體積過大而導致加載時間過長。
對代碼進行分割能夠“懶加載”當前用戶所需要的內(nèi)容,能夠顯著提高應用的性能。盡管并沒有減少應用的整體代碼體積,但可以避免加載用戶永遠不需要的代碼,并在初始加載的時候可以減少所需加載的代碼量。
下面,我們分別來介紹下在 React 中實現(xiàn)代碼分割的幾種方式。
import()
import() 是 Webpack 提供的用于分割代碼的一個方法。該方法的返回結(jié)果是Promise,當文件加載完成后悔將模塊導出給 promise.then 方法的回調(diào)。
例如有一個 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 動態(tài)導入模塊:
import('./math').then((math) => { console.log(math.add(5, 10)) })
當 Webpack 解析到該語法時,會自動進行代碼分割。如果是使用 Create React App 創(chuàng)建的 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}>兩數(shù)相加</button> </div> ); } } export default App;
React.lazy
React.lazy 方法可以讓我們動態(tài)加載組件,有助于縮減打包后 bundle 的體積,并延遲加載在初次渲染時未用到的組件。
React.lazy 接受一個函數(shù),這個函數(shù)需要動態(tài)調(diào)用 import()。它必須返回一個 Promise,該 Promise 需要 resolve 一個 export default 的 React 組件。
const AsyncComponent = React.lazy(() => import('./OtherComponent'));
React.lazy 返回的是一個異步組件 不能單獨使用,需要配合 React.Suspense 使用。當這個異步組件的狀態(tài)是 pending 時顯示的是 Suspense 中 fallback 的內(nèi)容,只有 resolve 時才會顯示加載好的組件。如此使得我們可以在使用 lazy 組件時做優(yōu)雅降級(如在 fallback添加 loading 效果等)。
import React, { Suspense } from 'react'; const AsyncComponent = React.lazy(() => import('./OtherComponent')); function MyComponent() { return ( <div> <Suspense fallback={<div>Loading...</div>}> <AsyncComponent /> </Suspense> </div> ); }
import() + React Loadable
React Loadable 是一個輕量級的代碼分割組件,它是一個高階組件,能讓你的應用程序在渲染之前動態(tài)的加載任何模塊。
使用 import() + React Loadable ,能優(yōu)雅的實現(xiàn)基于 react-router 4.x 版本的路由分割:
import Loadable from 'react-loadable'; const LoadableBar = Loadable({ loader: () => import('./components/Bar'), loading() { return <div>Loading...</div> } }); class MyComponent extends React.Component { render() { return <LoadableBar/>; } }
在實際業(yè)務開發(fā)中,我們通常會使用一些框架來快速開發(fā)React應用。在這些框架中,通常都會提供按需加載的功能。下面,我們來看看 UmiJS 框架中的按需加載。
UmiJS 按需加載
UmiJS 是一個可擴展的企業(yè)級前端應用框架,它以路由為基礎,支持配置式路由和約定式路由。UmiJS 封裝了一個 dynamic 組件來實現(xiàn)代碼分割。
啟用按需加載
UmiJS 的按需加載功能默認是關(guān)閉的,需要在使用之前通過配置開啟。在 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 />; }
總結(jié)
到此這篇關(guān)于React中代碼分割的文章就介紹到這了,更多相關(guān)React代碼分割內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
用react實現(xiàn)一個簡單的scrollView組件
這篇文章主要給大家介紹一下如何用 react 實現(xiàn)一個簡單的 scrollView組件,文中有詳細的代碼示例,具有一定的參考價值,需要的朋友可以參考下2023-07-07React中Suspense及l(fā)azy()懶加載及代碼分割原理和使用方式
這篇文章主要介紹了React中Suspense及l(fā)azy()懶加載及代碼分割原理和使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09useReducer?createContext代替Redux原理示例解析
這篇文章主要為大家介紹了useReducer?createContext代替Redux原理示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-11-11React父組件數(shù)據(jù)實時更新了,子組件沒有更新的問題
這篇文章主要介紹了React父組件數(shù)據(jù)實時更新了,子組件沒有更新的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03更強大的React 狀態(tài)管理庫Zustand使用詳解
這篇文章主要為大家介紹了更強大的React 狀態(tài)管理庫Zustand使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-10-10