首页 文章

React-hot-loader不能与React-router-dom一起使用

提问于
浏览
0

所以我最终设置了一个工作项目:

  • 电子( 2.0.2

  • React( 16.4.0

  • React-router-dom( 4.2.2

  • Webpack( 4.11.0

  • React-hot-loader( 4.2.0

就在我开始开发一些反应组件时,我注意到我的项目不会热重新加载正确 . 如果我在基本网址上调整了某些内容( / ),它会正确更新,但是如果我在辅助网址上更新某些内容,请说 /test 网络包编译,但我收到消息 Cannot GET /test .

我已经尝试了很多,我似乎无法弄清楚我做错了什么 . 我查看 react-router-dom ,因为热重新加载是版本 3.x 的一个问题,但他们说现在应该解决它(在 4.x - > It works here..) . 我也在我的 index.html 中添加了 <base href="/"/> ,所以不是这样 .

Can anyone tell me what I am doing wrong?


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'文本的简单反应组件 .

Anyone who sees anything that I am missing or doing wrong?

1 回答

  • 0

    感谢this tutorial我找到了一种方法来调整我的项目并使热负载工作 . 它甚至使我的代码更清洁,我的构建脚本更简单 .


    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 是为dev服务器动态创建的(通过HtmlWebpackPlugin),并且您无法对 vendor.dllapp.bundlemore here)的正确包导入进行硬编码 .


    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
      ]
    });
    

    我改变了什么:

    • 我将入口点移动到 webpack.common .

    • 我从 entry 删除了 'react-hot-loader/patch'

    • (可选)我为 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热重新加载器),这样我每次更新一些代码时也会丢失组件中的状态 .

    你去吧我希望这能帮助任何人(除了我自己) .

相关问题