创建React App,React Router v4,React Redux reducers代码拆分和source-map-explorer

时间:2018-11-27 20:06:42

标签: reactjs react-redux create-react-app code-splitting

我正试图通过对基于路由的组件和Redux缩减器应用代码拆分来减少我的最初的React React App捆绑包。

使用React lazy和Suspense可以完成和实现前者,而this article中详细介绍了后者。

这似乎在浏览器中很好用,即React组件似乎在运行时加载了reducer。

此外,出于分析目的,我安装了source-map-explorer,并在package.json中添加了一个脚本来分析我的JS包。

现在,每当我尝试运行npm run analyze时,捆绑软件似乎总是包含所有redux部分。

我在代码拆分化缩减器的方式上做错了吗,或者这仅仅是source-map-explorer的工作原理吗?

您可以在我的代码下方找到source-map-explorer输出的屏幕截图

package.json

...
"dependencies": {
    ...
    "lodash": "^4.17.11",
    "prop-types": "^15.6.2",
    "react": "^16.6.3",
    "react-app-polyfill": "^0.1.3",
    "react-dom": "^16.6.3",
    "react-redux": "^5.1.1",
    "react-router-dom": "^4.3.1",
    "redux": "^4.0.1",
    "redux-saga": "^0.16.2",
    ...
},
"devDependencies": {
    ...
    "react-scripts": "^2.1.1",
    "redux-devtools-extension": "^2.13.7",
    "source-map-explorer": "^1.6.0"
},
"scripts": {
    "analyze": "source-map-explorer build/static/js/main.*",
    "build": "react-scripts build",
    ...
},
...

store.js

import { applyMiddleware, combineReducers, createStore } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import createSagaMiddleware from 'redux-saga';
import throttle from 'lodash/throttle';
import { loadState, saveState } from './localStorage';
import reducerRegistry from './reducerRegistry';
import registerDefaultReducers from './reducers';
import rootSaga from './sagas';

export const configureStore = () => {
    const { REACT_APP_STATE_DRIVER } = process.env;
    const sagaMiddleware = createSagaMiddleware();
    let store;
    let persistedState;

    if(REACT_APP_STATE_DRIVER === "localStorage") {
        persistedState = loadState();
    }

    registerDefaultReducers();

    if(persistedState) {
        // We register additional reducers
        // in case they are needed from preloaded state
        Object.entries(persistedState).forEach(([name, reducer]) => {
            reducerRegistry.register(name, reducer);
        });
    }

    const reducers = reducerRegistry.getReducers();
    const rootReducers = combineReducers(reducers);

    if(persistedState) {
        store = createStore(
            rootReducers,
            persistedState,
            composeWithDevTools(
                applyMiddleware(sagaMiddleware)
            )
        );
    } else {
        store = createStore(
            rootReducers,
            composeWithDevTools(
                applyMiddleware(sagaMiddleware)
            )
        );
    }

    if(REACT_APP_STATE_DRIVER === "localStorage") {
        store.subscribe(throttle(() => {
            saveState(store.getState());
        }, 1000));
    }

    // We set an event listener for the reducer registry
    // So that whenever a new reducer gets added
    // We replace the reducers with the new ones
    reducerRegistry.setChangeListener((reducers) => {
        store.replaceReducer(combineReducers(reducers));
    });

    sagaMiddleware.run(rootSaga);

    return store;
}

const store = configureStore();

export default store;

reducers.js

import reducerRegistry from './reducerRegistry';
import auth from './auth/reducers';

// We only register the initial defaul reducers here,
// Leaving the other ones for async loading

export const defaultReducers = {
    auth,
};

const registerDefaultReducers = () => {
    Object.entries(defaultReducers).forEach(([name, reducer], idx) => {
        reducerRegistry.register(name, reducer);
    });
};

export default registerDefaultReducers;

reducerRegistry.js

export class ReducerRegistry {
    constructor() {
        this._emitChange = null;
        this._reducers = {};
    }

    getReducers() {
        return {
            ...this._reducers
        };
    }

    register(name, reducer) {
        if(this._reducers[name]) {
            return;
        }

        this._reducers = {
            ...this._reducers,
            [name]: reducer
        };

        if (this._emitChange) {
            this._emitChange(this.getReducers());
        }
    }

    setChangeListener(listener) {
        this._emitChange = listener;
    }
}

const reducerRegistry = new ReducerRegistry();

export default reducerRegistry;

Create.js 我尝试动态加载减速器的通用组件

import React from 'react';
import reducerRegistry from '../../../redux/reducerRegistry';
import users from '../../../redux/users/reducers';

reducerRegistry.register('users', users);

const Create = props => {
    // code omitted...
}

export default Create;

source-map-explorer输出 source-map-explorer output

0 个答案:

没有答案