ホームページ  >  記事  >  ウェブフロントエンド  >  React と Redux の動的インポート (コード付き)

React と Redux の動的インポート (コード付き)

不言
不言転載
2019-03-23 09:51:132458ブラウズ

この記事で紹介する内容は、React と Redux の動的インポート (コード付き) に関するもので、一定の参考価値があります。必要な友人は参考にしてください。 、お役に立てば幸いです。

コードの分離と動的インポート

大規模な Web アプリケーションの場合、コードの編成は非常に重要です。高性能でわかりやすいコードの作成に役立ちます。最も単純な戦略の 1 つはコード分離です。 Webpack などのツールを使用すると、コードを小さな部分に分割し、静的と動的という 2 つの異なる戦略に分割できます。

静的コード分離では、アプリケーションのさまざまな部分が最初に特定のエントリ ポイントとして扱われます。これにより、Webpack はビルド時に各エントリ ポイントを個別のバンドルに分割できます。これは、アプリのどの部分が最も閲覧されるかがわかっている場合に最適です。

動的インポートでは、Webpack のインポート メソッドを使用してコードを読み込みます。 import メソッドは Promise を返すため、非同期待機を使用して返された結果を処理できます。

// getComponent.js
async function getComponent() {
   const {default: module} = await import('../some-other-file')
   const element = document.createElement('p')
   element.innerHTML = module.render()
   return element
}

これは非常に不自然な例ですが、この方法がいかに簡単であるかがわかります。 Webpack を使用して面倒な作業を行うことで、アプリケーションをさまざまなモジュールに分割できます。必要なコードは、ユーザーがアプリケーションの特定の部分をクリックしたときにのみロードされます。

このアプローチを React が提供する制御構造と組み合わせると、遅延読み込みを通じてコード分割を行うことができます。これにより、コードの読み込みを最後の瞬間まで遅らせることができ、最初のページ読み込みを軽減できます。

React による遅延読み込みの処理

モジュールをインポートするには、どの API を使用するかを決定する必要があります。 React を使用してコンテンツをレンダリングしていることを考慮して、そこから始めましょう。

以下は、ビュー名前空間を使用してモジュール コンポーネントをエクスポートする単純な API です。

// my-module.js
import * as React from 'react'

export default {
    view: () => <p>My Modules View</p>
}

import メソッドを使用してこのファイルをロードしたので、

async function getComponent() {
    const {default} = await import('./my-module')
    return React.createElement(default.view)
})

などのモジュールのビュー コンポーネントに簡単にアクセスできます。ただし、React ではこのメソッドをまだ使用していません。モジュールを遅延ロードします。これを行うには、LazyLoadModule コンポーネントを作成します。このコンポーネントは、特定のモジュールのビュー コンポーネントの解析とレンダリングを担当します。

// 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) return <p>Loading module...</p>;
    if (module.view) return React.createElement(module.view);

  }
}

以下は、LazyLoadModule コンポーネントを使用してモジュールをロードする方法を示しています。

// my-app.js

import {LazyLoadModule} from './LazyLoadModule'

const MyApp = () => (
    <p className=&#39;App&#39;>
        <h1>Hello</h1>
        <LazyLoadModule resolve={() => import('./modules/my-module')} />
    </p>
)

ReactDOM.render(<MyApp />, document.getElementById('root'))

以下は、いくつかの例外処理を追加するオンライン例です。

https://codesandbox.io/embed/...

React を使用して各モジュールの読み込みを処理することにより、アプリケーション内でいつでも、ネストされたコンポーネントを含むコンポーネントを遅延読み込みできます。モジュール。

Redux の使用

これまで、アプリケーションのモジュールを動的にロードする方法を説明してきました。ただし、ロード時にモジュールに正しいデータを入力する必要があります。

redux ストアをモジュールに接続する方法を見てみましょう。各モジュールのビュー コンポーネントを公開することで、各モジュールの API を作成しました。各モジュールのレデューサーを公開することでこれを拡張できます。また、モジュールの状態がアプリケーションのストアに存在するための名前を公開する必要もあります。

// 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}) => <p>{foo}</p>)

const fooReducer = (state = 'Some Stuff') => {
    return state
}
const reducers = {
    'foo': fooReducer,
}

export default {
    name: 'my-module',
    view,
    reducers,
}

上の例は、モジュールがレンダリングに必要な状態を取得する方法を示しています。

しかし、まず ストア でさらに作業を行う必要があります。モジュールがロードされるときに、モジュールの reducer を登録できる必要があります。したがって、モジュール dispatcheaction を実行すると、store が更新されます。これを実現するには、 replaceReducer メソッドを使用します。

まず、2 つの追加メソッド registerDynamicModuleunregisterDynamicModule をストアに追加する必要があります。

// 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 に 2 つの新しいメソッドを追加します。これらの各メソッドは、storereducer を完全に置き換えます。

拡張機能 store を作成する方法は次のとおりです:

import createStore from './store'

const rootReducer = {
    foo: fooReducer
}

const store = createStore(rootReducer)

const App = () => (
    <Provider store={store}>
        ...
    </Provider>
)

次に、 # で使用できるように LazyLoadModule を更新する必要があります。 ##store reducer モジュールを ## に登録します。

storeprops を通じて取得できます。これは単純ですが、毎回 store を取得する必要があることを意味し、バグが発生する可能性があります。これを念頭に置いて、LazyLoadModule コンポーネントに store を取得させます。

react-redux コンポーネントが store をコンテキストに追加するときは、## Get で contextTypes を使用するだけです。 #LazyLoadModule にあります。

// lazyModule.js 
export class LazyLoadModule extends React.component {
    ...
    async componentDidMount() {
        ...
        const {store} = this.context
    }
}

LazyLoadModule.contextTypes = {
    store: PropTypes.object,
}

现在可以从 LazyLoadModule 的任何实例访问我们的 store。 剩下的唯一部分就是把 reducer 注册到 store 中。 记住,我们是这样导出每个模块:

// my-module.js
export default {
    name: 'my-module',
    view,
    reducers,
}

更新 LazyLoadModulecomponentDidMountcomponentWillUnmount 方法来注册和注销每个模块:

// 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 的动态导入,我们可以将代码分离添加到我们的应用程序中。这意味着我们的应用程序的每个部分都可以注册自己的 components 和 reducers,这些 components 和 reducers将按需加载。此外,我们还减少了包的大小和加载时间,这意味着每个模块都可以看作是一个单独的应用程序。

本篇文章到这里就已经全部结束了,更多其他精彩内容可以关注PHP中文网的JavaScript视频教程栏目!

以上がReact と Redux の動的インポート (コード付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。