Разделение Webpack. Контент не отображается - фрагменты не загружены

Прошел день, я пытаюсь решить эту надоедливую, но, я уверен, простую проблему. Я пытаюсь разделить свой bundle.js на фрагменты, чтобы оптимизировать время загрузки веб-сайта.

Вот мой файл webpack.config:

module.exports = {
devServer: {
historyApiFallback: true
},
entry: {
index: ["./src/index.js"],
vendor: [
  "react",
  "react-dom",
  "react-redux",
  "react-router",
  "react-router-dom",
  "redux"
]
},
output: {
path: __dirname + '/public/views',
filename: "[name].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",
  filename: "vendor.js",
  minChunks: Infinity
}),
new webpack.optimize.CommonsChunkPlugin({
  name: "meta",
  chunks: ["vendor"],
  filename: "meta.js"
}),
new webpack.NamedModulesPlugin(),
new HtmlWebpackPlugin({
  title: "Deals",
  filename:  __dirname + "/views/index.ejs",
  template: __dirname + "/views/template.ejs",
  inject: false
}),
new PreloadWebpackPlugin({
  rel: "preload",
  as: "script",
  include: "all"
}),
new webpack.optimize.OccurrenceOrderPlugin(),
]
};

Вот мой упрощенный файл index.ejs, созданный с помощью запуска кода веб-пакета, результат template.ejs:

<!DOCTYPE html>
<html lang="en">

<head>

    <link href="/pace.css" rel="stylesheet" />
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=yes">
    <meta charset="utf-8">
    <link rel="stylesheet" href="/style.css">
    <link rel="canonical" href="http://verygoodprof.fr/" />
    <link rel="preload" as="script" href="/views/index.js">
    <link rel="preload" as="script" href="/views/vendor.js">
    <link rel="preload" as="script" href="/views/meta.js">
</head>

<body>

    <noscript>
        <a href="http://enable-javascript.com/">Javascript must me enabled to use this site.</a>
    </noscript>

    <div class="text-center root" id="root">

    </div>

</body>

</html>

Здесь я вижу, что у меня есть предварительно загруженные фрагменты, динамически написанные, как я хотел, и эти фрагменты находятся в правильной папке, созданной после запуска кода веб-пакета.

А вот мой файл index.js (React), заявленный как индексная запись в файле webpack.config.

ReactDOM.render(
  <Provider store={createStoreWithMiddleware(reducers)}>
    <AppInit>
      <BrowserRouter>
        <div style={{ height: "100%" }}>
          <ProfRegisteringModal />
          <Switch>
            {/* <Route path="/inscription/:user" component={Registering} />
            <Route path="/inscription" component={Registering} />
            <Route path="/connexion" component={SigningIn} />
            <Route path="/equipe" component={TeamPres} />
            <Route path="/" component={AppContainer} /> */}
            <Route
              path="/inscription/:user"
              getComponent={(location, callback) => {
                require.ensure(
                  [],
                  function(require) {
                    callback(
                      null,
                      require("./components/registering/registering_landing_page.js")
                    );
                  },
                  "registerChunk"
                );
              }}
            />
            <Route
              path="/inscription"
              getComponent={(location, callback) => {
                require.ensure(
                  [],
                  function(require) {
                    callback(
                      null,
                      require("./components/registering/registering_landing_page.js")
                    );
                  },
                  "registerChunk"
                );
              }}
            />
            <Route
              path="/connexion"
              getComponent={(location, callback) => {
                require.ensure(
                  [],
                  function(require) {
                    callback(
                      null,
                      require("./containers/registering/signing_in.js")
                    );
                  },
                  "signinChunk"
                );
              }}
            />
            <Route
              path="/equipe"
              getComponent={(location, callback) => {
                require.ensure(
                  [],
                  function(require) {
                    callback(null, require("./components/team_pres.js"));
                  },
                  "teampresChunk"
                );
              }}
            />
            <Route
              path="/"
              getComponent={(location, callback) => {
                require.ensure(
                  [],
                  function(require) {
                    callback(null, require("./containers/app_container.js"));
                  },
                  "appContainerChunk"
                );
              }}
            />
          </Switch>
        </div>
      </BrowserRouter>
    </AppInit>
  </Provider>,
  document.querySelector(".root")
);

Первое, что я заметил, это то, что куски, которые должны быть построены, правильно созданы для поставщика и мета, но не для моих внутренних реагирующих компонентов. Но это не главная проблема, дело в том, что при локальном запуске сервера я вообще не вижу свое реагирующее приложение. Файл index.ejs загружается правильно, когда я проверяю консоль.

Все работало отлично при использовании простого файла bundle.js со всем внутри (без фрагментов). С index.ejs, указывающим на него как

<script src="/views/bundle.js"></script>

Большое спасибо за Вашу помощь !

РЕДАКТИРОВАТЬ

Этот файл webpack.config заставил его работать (спасибо @margaretkru):

module.exports = {
  devServer: {
    historyApiFallback: true
  },
  entry: {
    app:"./src/index.js",
    vendor: [
      "axios",
      "jquery",
      "react",
      "react-dom",
      "react-redux",
      "react-router",
      "react-router-dom",
      "redux"
    ]
  },
  output: {
    path: __dirname + '/public/views',
    filename: "[name].js",
    publicPath: "/views/"
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: "babel-loader",
        exclude: [/node_modules/, /pdfmake.js$/]
      },
      {
        test: /\.json$/,
        loader: "json-loader"
      }
    ]
  },
  plugins: [
    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(),
  ]
};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(),
  ]
};

Настоящая проблема заключалась не в упорядочении загруженных скриптов, а в том, что я фактически не загружал скрипты после их «предварительной загрузки»: помогла строка «inject» HTMLWebpackPlugin, поскольку она ввела эти две строки:

<script src="/views/vendor.js"/> 
<script src="/views/app.js"/> 

в моем теле index.ejs


person Louis    schedule 16.01.2018    source источник
comment
поэтому я вижу, что порядок загрузки скриптов в index.ejs неверен, сначала должны быть загружены vendor.js и meta.js и только ПОТОМ index.js. Но я не понимаю, почему порядок неправильный.   -  person margaretkru    schedule 16.01.2018


Ответы (1)


Неверный порядок загрузки скриптов в index.ejs. Теперь есть:

<link rel="preload" as="script" href="/views/index.js">
<link rel="preload" as="script" href="/views/vendor.js">

Это означает, что ваше index.js будет загружено до vendor.js, в результате чего ваше приложение вообще не появится. Сначала должны быть загружены все зависимости вашего приложения (vendor.js) и только потом index.js, так как вам нужно, чтобы зависимости присутствовали при выполнении вашего пользовательского кода. Так должно быть:

<link rel="preload" as="script" href="/views/vendor.js">
<link rel="preload" as="script" href="/views/index.js">

Редактировать:

Как мы в конце концов выяснили, проблема была не в порядке скриптов, а в том, что скрипты на самом деле не были загружены в html. Для этого их нужно добавить как чанки в HtmlWebpackPlugin и внедрить в index.html:

 new HtmlWebpackPlugin({
      title: "Deals",
      filename:  __dirname + "/views/index.ejs",
      template: __dirname + "/views/template.ejs",
      inject: 'body',
      chunks: ['vendor', 'index']
    })

Более того, конфигурация чанка meta была удалена полностью. Вся остальная конфигурация (включая PreloadWebpackPlugin) была в порядке.

person margaretkru    schedule 16.01.2018
comment
Спасибо за ваш ответ. Однако предложение, которое вы сделали, не работает. Порядок по-прежнему не правильный, и даже если я изменю порядок вручную в index.ejs, сайт не загружается - person Louis; 16.01.2018
comment
вы видите какие-либо ошибки в консоли? не могли бы вы опубликовать их, если вы делаете? - person margaretkru; 16.01.2018
comment
Вы правы, я мог бы удалить его? Я думал, что это что-то, чтобы связать другие куски? - person Louis; 16.01.2018
comment
Я не уверен, что вы имеете в виду :) Я бы выбрал эту конфигурацию, самую простую, и проверьте, работает ли она. Если он не попытается полностью удалить PreloadWebpackPlugin и посмотреть, изменится ли что-то. - person margaretkru; 16.01.2018
comment
Давайте продолжим обсуждение в чате. - person Louis; 16.01.2018
comment
Кстати, реальная проблема заключалась не в упорядочении загруженных скриптов, а в том, что я фактически не загружал скрипты после их предварительной загрузки: строка ввода HTMLWebpackPlugin помогла, так как она ввела эти две строки: ‹script src=/views/vendor. js/› ‹script src=/views/app.js/› в моем теле index.ejs - person Louis; 16.01.2018
comment
Идеальный! Я обновил ответ, чтобы он мог помочь другим, если они столкнутся с той же проблемой :) - person margaretkru; 16.01.2018