React-hot-loader не работает с React-router-dom

Итак, я наконец создал рабочий проект с:

  • Электрон (2.0.2)

  • React (16.4.0)

  • React-router-dom (4.2.2)

  • Webpack (4.11.0)

  • React-hot-loader (4.2.0)

И как раз когда я начал разрабатывать некоторые реагирующие компоненты, я заметил, что мой проект не перезагружается правильно. Если я что-то настраиваю на базовом URL-адресе (/), он обновляется правильно, но если я обновляю что-то на дополнительном URL-адресе, скажем, /test, веб-пакет компилируется, но я получаю сообщение Cannot GET /test.

Я много пробовал и не могу понять, что делаю не так. Я изучил react-router-dom, так как горячая перезагрузка была проблемой еще в версии 3.x, но они говорят, что ее нужно решить сейчас (в 4.x -> Здесь работает ..). Также я добавил <base href = "/"/> в свой index.html, так что это не так.

Может ли кто-нибудь сказать мне, что я делаю не так?


Webpack.common.js (это объединено с Webpack.dev.js)

module.exports = {
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].bundle.js'
  },
  resolve: {
    modules: [path.resolve(__dirname), 'node_modules']
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
        options: {
          cacheDirectory: true,
          presets: ['env', 'react'],
          plugins: ['transform-runtime'],
          env: {
            development: {
              plugins: ['react-hot-loader/babel']
            },
            production: {
              presets: ['react-optimize']
            }
          }
        }
      }
    ]
  }
};

Webpack.dev.js

module.exports = merge(common, {
  mode: 'development',
  devtool: 'eval-source-map',
  entry: {
    'app': [
      'babel-polyfill',
      'react-hot-loader/patch',
      path.join(__dirname, 'src', 'index.js')
    ]
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin() // Enable hot module replacement
  ]
});

Index.js

import React from "react";
import ReactDOM from "react-dom";
import { AppContainer } from "react-hot-loader";

import { App } from "./app";

const render = Component => {
  ReactDOM.render(
    <AppContainer>
      <Component/>
    </AppContainer>,
    document.getElementById("root")
  );
};

render(App);

if (module.hot) {
  module.hot.accept("./app", () => {
    render(App);
  });
}

App.js (моя основная точка входа для моего приложения, поэтому я определяю свою базовую маршрутизацию)

import React, { Component } from 'react';
import { BrowserRouter, Route, NavLink } from 'react-router-dom';

import { Test } from './components/test';
import { Test2 } from './components/test2';

export class App extends Component {
  render() {
    return (
      <BrowserRouter>
        <div>
          <NavLink to = "/">Home</NavLink>
          <NavLink to = "/test">Test</NavLink>
          <div>
            <Route exact path = "/" component = {Test}/>
            <Route path = "/test" component = {Test2}/>
          </div>
        </div>
      </BrowserRouter>
    );
  }
}

А компоненты «test» и «test2» - это просто простые компоненты реакции с текстом «hello world».

Любой, кто видит что-то, чего я не понимаю или делаю неправильно?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
3 824
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Благодаря этот учебник я нашел способ адаптировать свой проект и заставить работать горячую загрузку. Это даже сделало мой код немного чище, а скрипты сборки - проще.


Webpack.common.js

Первое, что мне нужно было поменять, - это babel-loader. Я украл его из какого-то учебника, и он сработал, но я точно не знал, что он делает, поэтому я избавился от этого кода. Я также сделал компиляцию моего кода быстрее с помощью webpack.DllReferencePlugin.

Вот обновленный webpack.common.js:

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');

module.exports = {
  entry: {
    app: [
      'babel-polyfill',
      './src/index.js',
    ],
  },
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
        options: {
          plugins: ['react-hot-loader/babel'],
          cacheDirectory: true,
          presets: ['env', 'react'],
        },
      }
    ],
  },
  plugins: [
    new webpack.DllReferencePlugin({
      context: path.join(__dirname),
      manifest: require('../dist/vendor-manifest.json'),
    }),
    new HtmlWebpackPlugin({
      title: '<my-app-name>',
      filename: 'index.html',
      template: './public/index.html',
    }),
    new AddAssetHtmlPlugin({
      filepath: path.resolve(__dirname, '../dist/*.dll.js'),
      includeSourcemap: false // add this parameter
    })
  ],
};

AddAssetHtmlPlugin требуется, поскольку index.html создается динамически (HtmlWebpackPlugin) для сервера разработки, и вы не можете жестко запрограммировать правильный импорт пакета для vendor.dll и app.bundle (подробнее здесь).


webpack.dev.js

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

module.exports = merge(common, {
  mode: 'development',
  devtool: 'eval-source-map',
  devServer: {
    hot: true,
    contentBase: path.resolve(__dirname, 'dist'),
    historyApiFallback: true // Allow refreshing of the page
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(), // Enable hot reloading
  ]
});

Что я изменил:

  1. Я перенес точку входа на webpack.common.

  2. Я удалил 'react-hot-loader/patch' из entry

  3. (по желанию) Я добавил несколько параметров конфигурации для webpack-dev-server.


Index.js

Это файл, из-за которого произошел сбой горячей перезагрузки. В частности, часть if (module.hot) вызвала его отказ. Поэтому я изменил его на следующее:

import React from 'react';
import ReactDOM from 'react-dom';
import { AppContainer } from 'react-hot-loader';

import { App } from './app';

const render = () => {
  ReactDOM.render(
    <AppContainer>
      <App/>
    </AppContainer>,
    document.getElementById('app'),
  );
};

render(App);

if (module.hot) {
  module.hot.accept('./app', () => {
    const NextApp = require('./app').default; // Get the updated code
    render(NextApp);
  });
}

Причина, по которой это работает сейчас, заключается в том, что теперь я загружаю новое приложение и заменяю старое, тем самым сообщая горячему загрузчику, что произошли изменения. Я также мог бы просто использовать module.hot.accept(), но это сделало бы react-hot-loader бесполезным (вы используете горячий перезагрузчик webpack), и таким образом я также терял бы состояние в моих компонентах каждый раз, когда я обновлял какой-либо код.

Итак, поехали. Я надеюсь, что это поможет кому-нибудь (кроме меня).

Другие вопросы по теме