Maison  >  Article  >  interface Web  >  Import dynamique de React et Redux (avec code)

Import dynamique de React et Redux (avec code)

不言
不言avant
2019-03-23 09:51:132458parcourir

Le contenu de cet article concerne l'importation dynamique de React et Redux (avec code). Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer, j'espère. ça vous aide.

Séparation du code et importation dynamique

Pour les grandes applications Web, l'organisation du code est très importante. Il permet de créer un code performant et facile à comprendre. L'une des stratégies les plus simples est la séparation des codes. À l'aide d'outils tels que Webpack, vous pouvez diviser votre code en parties plus petites, divisées en deux stratégies différentes, statique et dynamique.

Avec la séparation statique des codes, chaque partie différente de l'application est d'abord traitée comme un point d'entrée donné. Cela permet à Webpack de diviser chaque point d'entrée en un bundle distinct au moment de la construction. C'est parfait si nous savons quelles parties de notre application seront les plus consultées.

L'importation dynamique utilise la méthode d'importation de Webpack pour charger le code. Étant donné que la méthode d'importation renvoie une promesse, vous pouvez utiliser l'attente asynchrone pour gérer le résultat renvoyé.

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

Bien qu'il s'agisse d'un exemple très peu naturel, vous pouvez voir à quel point cette méthode est simple. En utilisant Webpack pour faire le gros du travail, nous pouvons diviser l'application en différents modules. Le code dont nous avons besoin n'est chargé que lorsque l'utilisateur clique sur une partie spécifique de l'application.

Si nous combinons cette approche avec les structures de contrôle que React nous offre, nous pouvons effectuer un fractionnement de code via un chargement paresseux. Cela nous permet de retarder le chargement du code jusqu'à la dernière minute, réduisant ainsi le chargement initial de la page.

Gestion du chargement différé avec React

Afin d'importer notre module, nous devons décider quelle API nous devons utiliser. Étant donné que nous utilisons React pour restituer du contenu, commençons par là.

Ce qui suit est une API simple qui utilise l'espace de noms de la vue pour exporter les composants du module.

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

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

Maintenant que nous utilisons la méthode d'importation pour charger ce fichier, nous pouvons facilement accéder au composant de vue du module, par exemple

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

Cependant, nous n'avons toujours pas utilisé la méthode. dans React pour retarder le chargement des modules. Pour ce faire, créez un composant LazyLoadModule. Ce composant sera responsable de l'analyse et du rendu du composant de vue pour un module donné.

// 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);

  }
}

Ce qui suit est une vue de l'utilisation du composant LazyLoadModule pour charger un module :

// 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'))

Ce qui suit est un exemple en ligne, qui ajoute une exception manutention .

https://codesandbox.io/embed/…

En utilisant React pour gérer le chargement de chaque module, nous pouvons charger paresseusement des composants à tout moment dans l'application, cela inclut les modules imbriqués .

Utilisation de Redux

Jusqu'à présent, nous avons démontré comment charger dynamiquement les modules d'une application. Cependant, nous devons encore saisir les données correctes dans notre module au moment du chargement.

Voyons comment connecter le magasin Redux au module. Nous avons créé une API pour chaque module en exposant le composant de vue de chaque module. Nous pouvons étendre cela en exposant des réducteurs pour chaque module. Nous devons également exposer un nom sous lequel l'état de notre module existera dans le magasin de l'application.

// 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,
}

L'exemple ci-dessus montre comment notre module obtient l'état dont il a besoin pour le rendu.

Mais nous devons d'abord faire davantage de travail sur notre magasin. Nous devons pouvoir enregistrer le réducteur du module lorsque le module est chargé. Ainsi, lorsque notre module dispatche aura un action , notre store sera mis à jour. Nous pouvons utiliser la méthode replaceReducer pour y parvenir.

Tout d'abord, nous devons ajouter deux méthodes supplémentaires, registerDynamicModule et unregisterDynamicModule à notre boutique.

// 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;
}

Comme vous pouvez le voir, le code lui-même est très simple. Nous avons ajouté deux nouvelles méthodes à notre store. Chacune de ces méthodes remplace alors intégralement le réducteur dans notre magasin.

Voici comment créer une extension store :

import createStore from './store'

const rootReducer = {
    foo: fooReducer
}

const store = createStore(rootReducer)

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

Ensuite, le LazyLoadModule doit être mis à jour pour qu'il puisse être disponible dans notre store Enregistrez le module réducteur.

Nous pouvons obtenir props via store. C'est simple, mais cela signifie qu'il faut récupérer notre store à chaque fois, ce qui peut entraîner des bugs. Dans cet esprit, laissez le composant LazyLoadModule obtenir le store pour nous.

Lorsque le composant react-redux ajoute le store au contexte, utilisez simplement les contextTypes dans le LazyLoadModule pour l'obtenir.

// 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视频教程栏目!

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer