摘要:動態(tài)導(dǎo)入使用的是的方法來加載代碼。使用到目前為止,我們已經(jīng)演示了如何動態(tài)加載應(yīng)用程序的模塊。還需要公開一個名稱,在該名稱下我們的模塊狀態(tài)將存在于應(yīng)用程序的中。剩下的唯一部分就是把注冊到中。
想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你!
代碼分離與動態(tài)導(dǎo)入對于大型 Web應(yīng)用程序,代碼組織非常重要。 它有助于創(chuàng)建高性能且易于理解的代碼。 最簡單的策略之一就是代碼分離。 使用像 Webpack 這樣的工具,可以將代碼拆分成更小的部分,它們分為兩個不同的策略,靜態(tài)和動態(tài)。
通過靜態(tài)代碼分離,首先將應(yīng)用程序的每個不同部分作為給定的入口點(diǎn)。 這允許 Webpack 在構(gòu)建時將每個入口點(diǎn)拆分為多帶帶的包。 如果我們知道我們的應(yīng)用程序的哪些部分將被瀏覽最多,這是完美的。
動態(tài)導(dǎo)入使用的是 Webpack 的 import 方法來加載代碼。由于 import 方法返回一個 promise,所以可以使用async wait 來處理返回結(jié)果。
// getComponent.js async function getComponent() { const {default: module} = await import("../some-other-file") const element = document.createElement("div") element.innerHTML = module.render() return element }
雖然這是一個很不自然的例子,但是可以看到這是一個多么簡單的方法。通過使用 Webpack 來完成繁重的工作,我們可以將應(yīng)用程序分成不同的模塊。當(dāng)用戶點(diǎn)擊應(yīng)用程序的特定部分時,才加載我們需要的代碼。
如果我們將這種方法與 React 提供給我們的控制結(jié)構(gòu)相結(jié)合,我們就可以通過延遲加載來進(jìn)行代碼分割。這允許我們將代碼的加載延遲到最后一分鐘,從而減少初始頁面加載。
使用 React 處理延遲加載為了導(dǎo)入我們的模塊,我們需要決定應(yīng)該使用什么 API。考慮到我們使用 React 來渲染內(nèi)容,讓我們從這里開始。
下面是一個使用 view 命名空間導(dǎo)出模塊組件的簡單API。
// my-module.js import * as React from "react" export default { view: () =>My Modules View}
現(xiàn)在我們使用導(dǎo)入方法來加載這個文件,我們可以很容易地訪問模塊的 view 組件,例如
async function getComponent() { const {default} = await import("./my-module") return React.createElement(default.view) })
然而,我們?nèi)匀粵]有使用 React 中的方法來延遲加載模塊。通過創(chuàng)建一個 LazyLoadModule 組件來實(shí)現(xiàn)這一點(diǎn)。該組件將負(fù)責(zé)解析和渲染給定模塊的視圖組件。
// lazyModule.js import * as React from "react"; export class LazyLoadModule extends React.Component { constructor(props) { super(props); this.state = { module: null }; } // after the initial render, wait for module to load async componentDidMount() { const { resolve } = this.props; const { default: module } = await resolve(); this.setState({ module }); } render() { const { module } = this.state; if (!module) returnLoading module...; if (module.view) return React.createElement(module.view); } }
以下是使用 LazyLoadModule 組件來加載模塊的視圖方式:
// my-app.js import {LazyLoadModule} from "./LazyLoadModule" const MyApp = () => () ReactDOM.render(Hello
import("./modules/my-module")} /> , document.getElementById("root"))
下面是一個線上的示例,其中補(bǔ)充一些異常的處理。
https://codesandbox.io/embed/...
通過使用 React 來處理每個模塊的加載,我們可以在應(yīng)用程序的任何時間延遲加載組件,這包括嵌套模塊。
使用 Redux到目前為止,我們已經(jīng)演示了如何動態(tài)加載應(yīng)用程序的模塊。然而,我們?nèi)匀恍枰诩虞d時將正確的數(shù)據(jù)輸入到我們的模塊中。
讓我們來看看如何將 redux 存儲連接到模塊。 我們已經(jīng)通過公開每個模塊的視圖組件為每個模塊創(chuàng)建了一個 API。 我們可以通過暴露每個模塊的 reducer 來擴(kuò)展它。 還需要公開一個名稱,在該名稱下我們的模塊狀態(tài)將存在于應(yīng)用程序的store 中。
// my-module.js import * as React from "react" import {connect} from "react-redux" const mapStateToProps = (state) => ({ foo: state["my-module"].foo, }) const view = connect(mapStateToProps)(({foo}) =>{foo}) const fooReducer = (state = "Some Stuff") => { return state } const reducers = { "foo": fooReducer, } export default { name: "my-module", view, reducers, }
上面的例子演示了我們的模塊如何獲得它需要渲染的狀態(tài)。
但是我們需要先對我們的 store 做更多的工作。我們需要能夠在模塊加載時注冊模塊的 reducer。因此,當(dāng)我們的模塊 dispatche 一個 action 時,我們的 store 就會更新。我們可以使用 replaceReducer 方法來實(shí)現(xiàn)這一點(diǎn)。
首先,我們需要添加兩個額外的方法,registerDynamicModule 和 unregisterDynamicModule 到我們的 store 中。
// store.js import * as redux form "redux" const { createStore, combineReducers } = redux // export our createStore function export default reducerMap => { const injectAsyncReducers = (store, name, reducers) => { // add our new reducers under the name we provide store.asyncReducers[name] = combineReducers(reducers); // replace all of the reducers in the store, including our new ones store.replaceReducer( combineReducers({ ...reducerMap, ...store.asyncReducers }) ); }; // create the initial store using the initial reducers that passed in const store = createStore(combineReducers(reducerMap)); // create a namespace that will later be filled with new reducers store.asyncReducers = {}; // add the method that will allow us to add new reducers under a given namespace store.registerDynamicModule = ({ name, reducers }) => { console.info(`Registering module reducers for ${name}`); injectAsyncReducers(store, name, reducers); }; // add a method to unhook our reducers. This stops our reducer state from updating any more. store.unRegisterDynamicModule = name => { console.info(`Unregistering module reducers for ${name}`); const noopReducer = (state = {}) => state; injectAsyncReducers(store, name, noopReducer); }; // return our augmented store object return store; }
如你所見,代碼本身非常簡單。 我們將兩種新方法添加到我們的 store 中。 然后,這些方法中的每一種都完全取代了我們 store 中的 reducer。
以下是如何創(chuàng)建擴(kuò)充 store:
import createStore from "./store" const rootReducer = { foo: fooReducer } const store = createStore(rootReducer) const App = () => (... )
接下來,需要更新 LazyLoadModule ,以便它可以在我們的 store 中注冊 reducer 模塊。
我們可以通過 props 獲取 store。這很簡單,但這意味著我們每次都必須檢索我們的 store,這可能會導(dǎo)致 bug。記住這一點(diǎn),讓 LazyLoadModule 組件為我們獲取 store。
當(dāng) react-redux
// lazyModule.js export class LazyLoadModule extends React.component { ... async componentDidMount() { ... const {store} = this.context } } LazyLoadModule.contextTypes = { store: PropTypes.object, }
現(xiàn)在可以從 LazyLoadModule 的任何實(shí)例訪問我們的 store。 剩下的唯一部分就是把 reducer 注冊到 store 中。 記住,我們是這樣導(dǎo)出每個模塊:
// my-module.js export default { name: "my-module", view, reducers, }
更新 LazyLoadModule 的 componentDidMount和 componentWillUnmount 方法來注冊和注銷每個模塊:
// lazyModule.js export class LazyLoadModule extends React.component { ... async componentDidMount() { ... const { resolve } = this.props; const { default: module } = await resolve(); const { name, reducers } = module; const { store } = this.context; if (name && store && reducers) store.registerDynamicModule({ name, reducers }); this.setState({ module }); } ... componentWillUnmount() { const { module } = this.state; const { store } = this.context; const { name } = module; if (store && name) store.unRegisterDynamicModule(name); } }
線上示例如下:
https://codesandbox.io/s/znx1...
通過使用 Webpack 的動態(tài)導(dǎo)入,我們可以將代碼分離添加到我們的應(yīng)用程序中。這意味著我們的應(yīng)用程序的每個部分都可以注冊自己的 components 和 reducers,這些 components 和 reducers將按需加載。此外,我們還減少了包的大小和加載時間,這意味著每個模塊都可以看作是一個多帶帶的應(yīng)用程序。
原文:
https://codeburst.io/dynamic-...
你的點(diǎn)贊是我持續(xù)分享好東西的動力,歡迎點(diǎn)贊!
交流干貨系列文章匯總?cè)缦?,覺得不錯點(diǎn)個Star,歡迎 加群 互相學(xué)習(xí)。
https://github.com/qq44924588...
我是小智,公眾號「大遷世界」作者,對前端技術(shù)保持學(xué)習(xí)愛好者。我會經(jīng)常分享自己所學(xué)所看的干貨,在進(jìn)階的路上,共勉!
關(guān)注公眾號,后臺回復(fù)福利,即可看到福利,你懂的。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/102841.html
摘要:日常項(xiàng)目直接使用是完全沒有問題的,可是隨著項(xiàng)目的日益壯大,組件數(shù)量的逐漸增長,組件之間的嵌套使得數(shù)據(jù)的管理越來越繁重。最后數(shù)據(jù)保存進(jìn)了中的,頁面也會根據(jù)的改變自動更新。 以下文章均為個人近期所學(xué)心得,自學(xué)react、redux,逐漸找到自己的方向,現(xiàn)將自己的方向方式寫出來,以供大家學(xué)習(xí)參考,肯定會有不足,歡迎批評指正。 日常項(xiàng)目直接使用react是完全沒有問題的,可是隨著項(xiàng)目的日益壯大...
摘要:但這并不是最佳的方式。最佳的方式是使用提供的和方法。也就是說,與的與完全無關(guān)。另外,如果使用對做屬性類型檢查,方法和方法為添加的屬性是存在的。注意,的變化不會引起上述過程,默認(rèn)在組件的生命周期中是固定的。 轉(zhuǎn)載注: 本文作者是淘寶前端團(tuán)隊(duì)的葉齋。筆者非常喜歡這篇文章,故重新排版并轉(zhuǎn)載到這里,同時也加入了一些自己的體會。 原文地址:http://taobaofed.org/blog/...
摘要:前言一直混跡社區(qū)突然發(fā)現(xiàn)自己收藏了不少好文但是管理起來有點(diǎn)混亂所以將前端主流技術(shù)做了一個書簽整理不求最多最全但求最實(shí)用。 前言 一直混跡社區(qū),突然發(fā)現(xiàn)自己收藏了不少好文但是管理起來有點(diǎn)混亂; 所以將前端主流技術(shù)做了一個書簽整理,不求最多最全,但求最實(shí)用。 書簽源碼 書簽導(dǎo)入瀏覽器效果截圖showImg(https://segmentfault.com/img/bVbg41b?w=107...
摘要:安裝配置加載器配置配置文件配置支持自定義的預(yù)設(shè)或插件只有配置了這兩個才能讓生效,單獨(dú)的安裝是無意義的。 showImg(https://segmentfault.com/img/bVbjGNY?w=2847&h=1931); 想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你! 最新React全家桶實(shí)戰(zhàn)使用配置指南 這篇文檔 是呂小明老師結(jié)合以往的項(xiàng)目經(jīng)驗(yàn) 加上自己本身...
閱讀 1943·2021-11-24 09:39
閱讀 3528·2021-09-28 09:36
閱讀 3299·2021-09-06 15:10
閱讀 3455·2019-08-30 15:44
閱讀 1162·2019-08-30 15:43
閱讀 1809·2019-08-30 14:20
閱讀 2721·2019-08-30 12:51
閱讀 2042·2019-08-30 11:04