简体   繁体   English

Webpack和React getComponent()不会异步加载组件

[英]Webpack & React getComponent() not loading asynchronously component

I am using Webpack 3.7.1 and React 15.6.1 and I am trying to load different components dynamically. 我正在使用Webpack 3.7.1和React 15.6.1,并且试图动态加载不同的组件。

What I would like to do 我想做什么

  • Loading the components asynchronously from the different chunks webpack created when code splitting 从代码拆分时创建的不同Webpack块异步加载组件

What i did 我做了什么

  • Using getComponent() and import() to generate the chunks 使用getComponent()import()生成块
  • Configured the webpack.config file properly so that the chunks are created (code splitting) 正确配置了webpack.config文件,以便创建块(代码拆分)

The issue 问题

  • Chunks are generated but not loaded properly when accessing a route 访问路径时会生成块, 但未正确加载
  • getComponent() does not seem to work getComponent()似乎不起作用

My Webpack.config file 我的Webpack.config文件

module.exports = {
  devServer: {
    historyApiFallback: true
  },
  entry: {
    app:"./src/index.js",
    vendor: [
      "axios",
      "react",
      "react-dom",
      "react-redux",
      "react-router",
      "react-router-dom",
      "redux"
    ]
  },
  output: {
    path: __dirname + '/public/views',
    filename: '[name].js',
    chunkFilename: '[chunkhash].chunk.js',
    publicPath: "/views/"
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: "babel-loader",
        exclude: [/node_modules/, /pdfmake.js$/]
      },
      {
        test: /\.json$/,
        loader: "json-loader"
      }
    ]
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: "vendor",
      minChunks: Infinity
    }),
    new webpack.NamedModulesPlugin(),
    new HtmlWebpackPlugin({
      filename:  __dirname + "/views/index.ejs",
      template: __dirname + "/views/template.ejs",
      inject: 'body',
      chunks: ['vendor', 'app'],
      chunksSortMode: 'manual'
    }),
    new PreloadWebpackPlugin({
      rel: "preload",
      include: ["vendor", "app"]
    }),
    new webpack.optimize.OccurrenceOrderPlugin(),
  ]
};

My index.js file (root of my react app) 我的index.js文件(我的应用程序的根目录)

import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { createStore, applyMiddleware } from "redux";
import { BrowserRouter, Route, Switch } from "react-router-dom";

import promise from "redux-promise";
import reducers from "./reducers";
import AppInit from "./containers/appInit";



import ProfRegisteringModal from "./containers/modals/register_prof_explanation_modal";

const createStoreWithMiddleware = applyMiddleware(promise)(createStore);

function errorLoading(err) {
  console.error("Dynamic page loading failed", err);
}

function loadRoute(cb) {
  return module => cb(null, module.default);
}

console.log("testst");

ReactDOM.render(
  <Provider store={createStoreWithMiddleware(reducers)}>
    <AppInit>
      <BrowserRouter>
        <div style={{ height: "100%" }}>
          <ProfRegisteringModal />
          <Switch>
            <Route
              path="/inscription/:user"
              getComponent={(location, callback) => {
                import(
                  "./components/registering/registering_landing_page.js"
                )
                  .then(loadRoute(cb))
                  .catch(errorLoading);
              }}
            />
            <Route
              path="/inscription"
              getComponent={(location, callback) => {
                import(
                  "./components/registering/registering_landing_page.js"
                )
                  .then(loadRoute(cb))
                  .catch(errorLoading);
              }}
            />
            <Route
              path="/connexion"
              getComponent={(location, callback) => {
                import("./containers/registering/signing_in.js")
                  .then(loadRoute(cb))
                  .catch(errorLoading);
              }}
            />
            <Route
              path="/equipe"
              getComponent={(location, callback) => {
                import("./components/team_pres.js")
                  .then(loadRoute(cb))
                  .catch(errorLoading);
              }}
            />
            <Route
              path="/"
              getComponent={(location, callback) => {
                import("./containers/app_container.js")
                  .then(loadRoute(cb))
                  .catch(errorLoading);
              }}
            />
          </Switch>
        </div>
      </BrowserRouter>
    </AppInit>
  </Provider>,
  document.querySelector(".root")
);

This file got correctly loaded as I can see the console.log("test") appearing in my console. 该文件已正确加载,因为我可以看到console.log(“ test”)出现在控制台中。

None of the components are correctly loaded when accessing any of the routes. 访问任何路由时,没有正确加载任何组件。

Thank you very much for your help 非常感谢您的帮助

I think what your code is missing is a way to trigger an update. 我认为您的代码缺失是触发更新的一种方法。 I remember solving this issue by creating a wrapper around the import() promise. 我记得通过围绕import()承诺创建包装器来解决此问题。

// AsyncComponent.js

export default function wrapper(importComponent) {
  class AsyncComponent extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        Comp: null
      };
    }
    componentDidMount() {
      importComponent()
        .then(Comp => this.setState({
          Comp
        }))
        .catch(err => this.setState({
          error: err
        }));
    }
    render() {
      if(this.state.error) {
        return <h2> Loading error
            <button onClick={e => this.componentDidMount()}> Try again </button>
          </h2>
      }
      const Comp = this.state.Comp;
      return Comp ?
        <Comp {...this.props} /> :
        <div> Still Loading: You can add a spinner here </div>
    }
  }
  return AsyncComponent;
}


// Routes.js

import AsyncComponent from './component/AsyncComponent';

const Users   = AsyncComponent(() => import(/* webpackChunkName:"users"  */ './Users'))
const Home    = AsyncComponent(() => import(/* webpackChunkName:"home"   */ './Home'))
const Equipe  = AsyncComponent(() => import(/* webpackChunkName:"equipe" */ './Equipe'))


<Route path='/users' component={Users} />
<Route path='/equipe' component={Equipe} />

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM