Redux 代码分割
在大型 Web 应用程序中,通常需要将应用程序拆分为多个可以按需加载的 JS 包。 这种称为“分割”的策略通过减小初次加载时的 JS 的包的大小,来提高应用程序的。
要使用 R 进行拆分,我们希望能够将 reducer 动态到 store。 但是,R 实际上只有 root reducer 。 这个 root reducer 通常是在初始化应用程序时通过 combineReducers() 或类似的。 为了动态更多的 reducer,我们需要再次该来重新 root reducer。 下面,我们将讨论可以此问题的一些,并推荐提供此的两个库。
基本原则
接下来通过R 使用 replaceReducer 的样例给你讲解关于R基本原则里使用 replaceReducer 的技巧。
R store 暴露出 replaceReducer ,该使用新的 root reducer 替代当前活动的 root reducer。该将替换内部 reducer 的引用,并 dispatch action 以初始化新加入的 reducer:
const newRootReducer = combineReducers({ existingSlice: existingSliceReducer, newSlice: newSliceReducer }) store.replaceReducer(newRootReducer)
Reducer 注入
接下来跟大家一起介绍下如何定义 injectReducer 以及使用 'Reducer Manager'的具体样例。
我们可能想从应用程序的任何地方 store.replaceReducer()。因此,它使我们可以很轻易的定义可重用的 injectReducer() 。该能够保持对所有现有 slice reducer 的引用,并可将新 reducer 附加到 store 实例。
import { createStore } from 'r' // 定义将始终存在于应用程序中的 Reducer const staticReducers = { users: usersReducer, posts: postsReducer } // Conure the store export default function conureStore(initialState) { const store = createStore(createReducer(), initialState) // 对象以跟踪已的异步 Reducer store.asyncReducers = {} //创建注入 reducer // 此 async reducer,并创建新的组合 reducer store.injectReducer = (key, asyncReducer) => { store.asyncReducers[key] = asyncReducer store.replaceReducer(createReducer(this.asyncReducers)) } // 返回后的 store return store } function createReducer(asyncReducers) { return combineReducers({ ...staticReducers, ...asyncReducers }) }
现在,只需要 store.injectReducer 即可向 store 新的 reducer。
另一种是创建 'Reducer Manager' 对象,它跟踪所有已的 Reducer 并暴露出 reduce() 。 请参考以下示例:
export function createReducerManager(initialReducers) { // 创建将 key 映射到 reducer 的对象 const reducers = { ...initialReducers } // 创建初始 CombinedReducer let combinedReducer = combineReducers(reducers) // 存储 key 的数组,用于 reducer 时 state 中对应的数据 const keysToRemove = [] return { getReducerMap: () => reducers, // 这个 root reducer 在该对象中暴露出 // 并将传递给 store reduce: (state, action) => { // 如果已任何 reducer,请先清理 state 中对应的值 if (keysToRemove.length > 0) { state = { ...state } for (let key of keysToRemove) { delete state[key] } keysToRemove = [] } // Delegate to the combined reducer return combinedReducer(state, action) }, // 具有指定 key 的新 reducer add: (key, reducer) => { if (!key || reducers[key]) { return } // 将 reducer 到 reducer 映射中 reducers[key] = reducer // 新的 combined reducer combinedReducer = combineReducers(reducers) }, // 使用指定的 key reducer remove: key => { if (!key || !reducers[key]) { return } // 从 reducer 映射中它 delete reducers[key] // 将 key 到要清理的 key 列表中 keysToRemove.push(key) // 新的 combined reducer combinedReducer = combineReducers(reducers) } } } const staticReducers = { users: usersReducer, posts: postsReducer } export function conureStore(initialState) { const reducerManager = createReducerManager(staticReducers) // 使用 root reducer 创建 store,该 root reducer 是 manager 暴露出的。 const store = createStore(reducerManager.reduce, initialState) // 可选:将 reducer manager 到 store 上,以便于访问 store.reducerManager = reducerManager }
要新的 reducer,现在可以 store.reducerManager.add("asyncState", asyncReducer)。
要 reducer 现在可以 store.reducerManager.remove("asyncState")。
库和框架
以下有一些优秀的库可以帮助您上述:
: 提供用于构建动态 R store 的工具,动态 reducer 和 sagas,以及与 React 绑定以帮助您与 React 组件的关联。
: 该库引入了“R Module”的概念,它是一组应该动态加载的 R 部件(Reducer,middleware)。 它还暴露出 React 高阶组件用来在应用组件加载后加载“Module”。 此外,它还与诸如 r-thunk 和r-saga 之类的库集成,以使这些库可以动态加载他们的部件(thunk,sagas)。