Heim  >  Artikel  >  Web-Frontend  >  Dynamischer Import von React und Redux (mit Code)

Dynamischer Import von React und Redux (mit Code)

不言
不言nach vorne
2019-03-23 09:51:132515Durchsuche

Der Inhalt dieses Artikels befasst sich mit dem dynamischen Import von React und Redux (mit Code). Freunde in Not können sich darauf beziehen es hilft dir.

Codetrennung und dynamischer Import

Bei großen Webanwendungen ist die Codeorganisation sehr wichtig. Es hilft dabei, leistungsstarken und leicht verständlichen Code zu erstellen. Eine der einfachsten Strategien ist die Codetrennung. Mit Tools wie Webpack können Sie Ihren Code in kleinere Teile aufteilen, die in zwei verschiedene Strategien unterteilt sind: statisch und dynamisch.

Bei der statischen Codetrennung wird jeder unterschiedliche Teil der Anwendung zunächst als gegebener Einstiegspunkt behandelt. Dadurch kann Webpack jeden Einstiegspunkt zur Erstellungszeit in ein separates Bundle aufteilen. Das ist perfekt, wenn wir wissen, welche Teile unserer App am häufigsten angesehen werden.

Der dynamische Import verwendet die Importmethode von Webpack, um Code zu laden. Da die Importmethode ein Versprechen zurückgibt, können Sie asynchrones Warten verwenden, um das Rückgabeergebnis zu verarbeiten.

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

Obwohl dies ein sehr unnatürliches Beispiel ist, können Sie sehen, wie einfach es ist. Indem wir Webpack für die schwere Arbeit verwenden, können wir die Anwendung in verschiedene Module aufteilen. Der von uns benötigte Code wird nur geladen, wenn der Benutzer auf einen bestimmten Teil der Anwendung klickt.

Wenn wir diesen Ansatz mit den Kontrollstrukturen kombinieren, die uns React bietet, können wir Code-Splitting durch Lazy Loading durchführen. Dadurch können wir das Laden des Codes bis zur letzten Minute verzögern und so den anfänglichen Seitenladevorgang reduzieren.

Lazy Loading mit React handhaben

Um unser Modul zu importieren, müssen wir entscheiden, welche API wir verwenden sollen. Wenn wir bedenken, dass wir React zum Rendern von Inhalten verwenden, beginnen wir dort.

Das Folgende ist eine einfache API, die den View-Namespace zum Exportieren von Modulkomponenten verwendet.

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

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

Da wir nun die Importmethode zum Laden dieser Datei verwenden, können wir wie

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

problemlos auf die Ansichtskomponente des Moduls zugreifen. Allerdings haben wir die Methode in React to Lazy immer noch nicht verwendet Laden Sie das Modul. Erstellen Sie dazu eine LazyLoadModule-Komponente. Diese Komponente ist für das Parsen und Rendern der Ansichtskomponente für ein bestimmtes Modul verantwortlich.

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

  }
}

Das Folgende ist eine Ansicht der Verwendung der LazyLoadModule-Komponente zum Laden eines Moduls:

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

Das Folgende ist ein Online-Beispiel, das einige Ausnahmebehandlungen hinzufügt.

https://codesandbox.io/embed/…

Durch die Verwendung von React zur Handhabung des Ladens jedes Moduls können wir Komponenten jederzeit in der Anwendung verzögert laden, dazu gehören auch verschachtelte Module .

Verwendung von Redux

Bisher haben wir gezeigt, wie man Module für unsere Anwendung dynamisch lädt. Allerdings müssen wir beim Laden noch die korrekten Daten in unser Modul eingeben.

Sehen wir uns an, wie man den Redux Store mit dem Modul verbindet. Wir haben für jedes Modul eine API erstellt, indem wir die Ansichtskomponente jedes Moduls verfügbar gemacht haben. Wir können dies erweitern, indem wir Reduzierer für jedes Modul verfügbar machen. Wir müssen auch einen Namen angeben, unter dem unser Modulstatus im Speicher der Anwendung vorhanden sein wird.

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

Das obige Beispiel zeigt, wie unser Modul den Status erhält, den es zum Rendern benötigt.

Aber wir müssen zuerst noch mehr an unserem Shop arbeiten. Wir müssen in der Lage sein, den Reduzierer des Moduls zu registrieren, wenn das Modul geladen wird. Wenn also unser Modul dispatche ein action hat, wird unser store aktualisiert. Um dies zu erreichen, können wir die Methode replaceReducer verwenden.

Zuerst müssen wir zwei zusätzliche Methoden, registerDynamicModule und unregisterDynamicModule, zu unserem Shop hinzufügen.

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

Wie Sie sehen können, ist der Code selbst sehr einfach. Wir haben unserem store zwei neue Methoden hinzugefügt. Jede dieser Methoden ersetzt dann den Reduzierer in unserem Shop vollständig.

So erstellen Sie eine Erweiterung store:

import createStore from './store'

const rootReducer = {
    foo: fooReducer
}

const store = createStore(rootReducer)

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

Als nächstes muss das LazyLoadModule aktualisiert werden, damit es in unserem Store Reduzierstück Modul.

Wir können

über props erreichen. Das ist einfach, aber es bedeutet, dass wir jedes Mal unser store abrufen müssen, was zu Fehlern führen kann. Lassen Sie vor diesem Hintergrund die Komponente storeLazyLoadModule den Store für uns übernehmen.

Wenn die

react-redux -Komponente den store zum Kontext hinzufügt, verwenden Sie einfach die contextTypes im LazyLoadModule um es zu bekommen.

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

Das obige ist der detaillierte Inhalt vonDynamischer Import von React und Redux (mit Code). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen