簡體   English   中英

React-hot-loader無法與React-router-dom一起使用

[英]React-hot-loader doesn't work with React-router-dom

因此,我終於建立了一個工作項目:

  • 電子( 2.0.2

  • 反應( 16.4.0

  • React-router-dom( 4.2.2

  • Webpack( 4.11.0

  • React-hot-loader( 4.2.0

就在我開始開發一些React組件時,我注意到我的項目不會正確地熱加載。 如果我調整了基本URL( / )上的內容,則可以正確更新,但是如果我更新了輔助URL上的內容,請說/test webpack可以編譯,但是我收到消息Cannot GET /test

我已經嘗試了很多,但似乎無法弄清楚自己在做什么錯。 我研究了react-router-dom ,因為在3.x版本中熱重載是一個問題,但是他們說應該立即解決(在4.x > 可以在這里工作。 )。 另外,我在index.html添加了<base href="/"/> ,不是這樣。

誰能告訴我我在做什么錯?


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”文本的簡單響應組件。

有人看到我缺少的東西或做錯了什么嗎?

多虧了本教程,我找到了一種適應項目並進行熱加載的方法。 它甚至使我的代碼更簡潔,我的構建腳本也簡化了。


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.dllapp.bundle的正確捆綁導入進行硬編碼( 更多信息請 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. 我從entry刪除了'react-hot-loader/patch'

  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 hot-reloader),因此每次我也都會丟失組件中的狀態更新了一些代碼。

所以你去了。 我希望這會幫助任何人(除了我自己)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM