您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

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)。


联系我
置顶