Вложенные маршруты React Router v4 не работают с webpack-dev-server - PullRequest
0 голосов
/ 13 июня 2019

Я пытаюсь настроить вложенные маршруты для моего приложения реакции, как это

  • / -> Домашняя страница
  • /about -> О странице
  • /protected -> защищенная страница по умолчанию
  • /protected/page1 -> защищенная страница 1

Отлично работает в codeandbox (https://codesandbox.io/s/react-router-nested-route-utqy7) React 16.8.1 React Router 4.3.1

Но когда я настраиваю то же самое с помощью webpack-dev-server (3.7.1), он может достичь только / и не может добраться до остальных маршрутов.

Моя файловая структура имеет вид

├── package.json
├── src
│   ├── index.jsx
│   └── index.html
├── webpack
│   ├── paths.js
│   ├── webpack.common.js
│   └── webpack.dev.js
└── webpack.config.js

paths.js

const path = require('path');

module.exports = {
  outputPath: path.resolve(__dirname, '../', 'build'),
  entryPath: path.resolve(__dirname, '../', 'src/index.jsx'),
  templatePath: path.resolve(__dirname, '../', 'src/index.html'),
};

webpack.common.js

const webpack = require('webpack');
const convert = require('koa-connect');
const history = require('connect-history-api-fallback');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
const commonPaths = require('./paths');

module.exports = {
  entry: commonPaths.entryPath,
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        loader: 'babel-loader',
        exclude: /(node_modules)/,
      },
    ],
  },
  serve: {
    add: app => {
      app.use(convert(history()));
    },
    content: commonPaths.entryPath,
    dev: {
      publicPath: commonPaths.outputPath,
    },
    open: true,
  },
  resolve: {
    modules: ['src', 'node_modules'],
    extensions: ['*', '.js', '.jsx', '.css', '.scss'],
  },
  plugins: [
    new webpack.ProgressPlugin(),
    new HtmlWebpackPlugin({
      template: commonPaths.templatePath,
    }),
    new ScriptExtHtmlWebpackPlugin({
      defaultAttribute: 'async',
    }),
  ],
};

webpack.dev.js

const webpack = require('webpack');
const commonPaths = require('./paths');

module.exports = {
  mode: 'development',
  output: {
    filename: '[name].js',
    path: commonPaths.outputPath,
    chunkFilename: '[name].js',
  },
  module: {
    rules: [
      {
        test: /\.(css|scss)$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
          },
          'sass-loader',
        ],
      },
    ],
  },
  devServer: {
    contentBase: commonPaths.outputPath,
    compress: true,
    hot: true,
  },
  plugins: [new webpack.HotModuleReplacementPlugin()],
};

webpack.config.js

const webpackMerge = require('webpack-merge');
const common = require('./webpack/webpack.common');

const devConfig = require(`./webpack/webpack.dev.js`);
module.exports = webpackMerge(common, devConfig);

index.jsx

import React from "react";
import { render } from "react-dom";
import { BrowserRouter, Route } from "react-router-dom";

const Homepage = () => (
  <div>
    <h1>Home Page</h1>
  </div>
);
const AboutPage = () => (
  <div>
    <h1>About</h1>
  </div>
);
const Protected = () => (
  <div>
    <h1>Protected default page</h1>
  </div>
);
const ProtectedPage1 = () => (
  <div>
    <h1>ProtectedPage1</h1>
  </div>
);

render(
  <BrowserRouter>
    <div>
      <Route path="/" component={Homepage} exact />
      <Route path="/about" component={AboutPage} />

      <Route
        path="/protected"
        render={({ match: { url } }) => (
          <div>
            <Route path={`${url}/`} component={Protected} exact />
            <Route path={`${url}/page1`} component={ProtectedPage1} />
          </div>
        )}
      />
    </div>
  </BrowserRouter>,
  document.getElementById('app')
);

Я думаю, что некоторые пути неверны в моей конфигурации, я просто не могу понять, где находитсянеправильно.

Ответы [ 2 ]

0 голосов
/ 26 июля 2019

Попробуйте добавить:

<base href="/" />

к тегу <head> вашего index.html.Таким образом, он всегда будет искать /main.js связку, даже для вложенных маршрутов.

0 голосов
/ 14 июня 2019

Я наконец-то выяснил причину, по которой webpack-dev-server не может обслуживать вложенные маршруты.

Как одностраничное приложение, когда вы посещаете /somepath вашего приложения реагирования, оно фактически откатывается к/ и передайте путь для реакции маршрутизатора.React router переместит вас к /somepath с помощью API истории браузера.

webpack-dev-server по какой-то неизвестной причине по умолчанию не включает это поведение «откат к истории API».

Итак, нам нужно добавить historyApiFallback: true, к devServer конфигурации веб-пакета.

Теперь все маршруты верхнего уровня, такие как /somepath, должны работать, но для вложенных маршрутов, таких как /somepath/morepath, этого недостаточно.

При использовании стандартного веб-пакета -При настройке dev-server скомпилированный html-шаблон будет указывать на связанный js, например <script type="text/javascript" src="main.js"></script>.Обратите внимание на src="main.js", который предполагает, что main.js находится на том же пути, что и index.html.Предположение верно для пути верхнего уровня /somepath, но для вложенных маршрутов /somepath/morepath это предположение приведет к доступу html-файла к main.js, как /somepath/main.js.

Итак, мы заканчиваем поискомспособ указать определенное место для файла HTML, когда он собирается получить доступ к JS в комплекте.И это работа publicPath.Добавление publicPath: '/', в блок вывода конфигурации webpack.Он сообщит html, что он всегда обращается к main.js из папки /, и скомпилированный html будет <script type="text/javascript" src="/main.js"></script>.Это именно то, что мы ищем.

...