如何允许 webpack-dev-server 允许来自 react-router 的入口点

IT技术 javascript reactjs webpack react-router
2021-04-03 15:45:00

我正在创建一个在开发中使用 webpack-dev-server 和 react-router 的应用程序。

似乎 webpack-dev-server 是围绕这样一个假设构建的,即您将在一个地方(即“/”)有一个公共入口点,而 react-router 允许无限数量的入口点。

我想要 webpack-dev-server 的好处,尤其是对生产力很有帮助的热重载功能,但我仍然希望能够加载 react-router 中设置的路由。

怎样才能实现它,让他们一起工作?你能在 webpack-dev-server 前面运行一个快速服务器以允许这样做吗?

6个回答

你应该设置historyApiFallbackWebpackDevServer这个作为真正的工作。这是一个小示例(根据您的目的进行调整):

var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');

var config = require('./webpack.config');


var port = 4000;
var ip = '0.0.0.0';
new WebpackDevServer(webpack(config), {
    publicPath: config.output.publicPath,
    historyApiFallback: true,
}).listen(port, ip, function (err) {
    if(err) {
        return console.log(err);
    }

    console.log('Listening at ' + ip + ':' + port);
});
或者,如果您使用的是 cli, webpack-dev-server --history-api-fallback
2021-05-22 15:45:00
这应该是公认的答案。来自 webpack 开发服务器文档:“如果您使用的是 HTML5 历史 API,您可能需要提供 index.html 来代替 404 响应,这可以通过设置 historyApiFallback: true 来完成”如果我正确理解了这个问题,这将解决问题。
2021-05-27 15:45:00
这么简单……谢谢!
2021-05-27 15:45:00
你会错过 index.html 顶部的状态栏,但这很好用 :)
2021-06-15 15:45:00
@smnbbrv 没有问题。它实际上在下面使用了connect-history-api-fallback,如果需要,您可以传递具有中间件特定选项的对象,而不仅仅是true.
2021-06-20 15:45:00

我设置了一个代理来实现这一点:

您有一个常规快递网络服务器,可以在任何路线上提供 index.html,除非它是资产路线。如果它是资产,则请求会被代理到 web-dev-server

你的 react hot 入口点仍然会直接指向 webpack 开发服务器,所以热重载仍然有效。

假设您在 8081 上运行 webpack-dev-server,在 8080 上运行代理。 server.js 文件将如下所示:

"use strict";
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./make-webpack-config')('dev');

var express = require('express');
var proxy = require('proxy-middleware');
var url = require('url');

## --------your proxy----------------------
var app = express();
## proxy the request for static assets
app.use('/assets', proxy(url.parse('http://localhost:8081/assets')));

app.get('/*', function(req, res) {
    res.sendFile(__dirname + '/index.html');
});


# -----your-webpack-dev-server------------------
var server = new WebpackDevServer(webpack(config), {
    contentBase: __dirname,
    hot: true,
    quiet: false,
    noInfo: false,
    publicPath: "/assets/",

    stats: { colors: true }
});

## run the two servers
server.listen(8081, "localhost", function() {});
app.listen(8080);

现在在 webpack 配置中创建入口点,如下所示:

 entry: [
     './src/main.js',
     'webpack/hot/dev-server',
     'webpack-dev-server/client?http://localhost:8081'
 ]

请注意直接拨打 8081 进行 hotreload

还要确保您将绝对网址传递给该output.publicPath选项:

 output: {
     publicPath: "http://localhost:8081/assets/",
     // ...
 }
一个问题,有点不相关,所以如果需要,我可以打开一个新问题,但我注意到现在来自 webpack 开发服务器的控制台输出没有流式传输。以前,您可以观看它编译并看到百分比上升,现在它只是在编译后阻止输出。
2021-06-07 15:45:00
使用内置的webpack 代理会更容易因此,您不会干扰服务器本身,而是将服务器保留为. 相反,您只需在 webpack 配置中添加一点(3-5 行)即可。多亏了这一点,您仅出于开发目的修改了开发脚本,而让生产代码 (server.js) 保持平静(与您的版本不同),而 imo 这是正确的方法。
2021-06-11 15:45:00
干得漂亮。这正是它应该做的。我添加了一个关于该output.publicPath选项的注释,它也应该是一个绝对 url。
2021-06-12 15:45:00
嘿,这太棒了。我实际上在此之前不久就到达了这个设置,并打算发布一个答案,但我认为你做得更好。
2021-06-13 15:45:00
这个答案虽然有点过时,但仍然是正确的。现在可以使用更直接的方法,请查找historyApiFallback.
2021-06-18 15:45:00

对于可能仍在寻找此答案的其他任何人。我整理了一个简单的代理绕过,它可以轻松实现这一点,并且配置进入 webpack.config.js

我确信有更优雅的方法来使用正则表达式测试本地内容,但这适合我的需要。

devServer: {
  proxy: { 
    '/**': {  //catch all requests
      target: '/index.html',  //default target
      secure: false,
      bypass: function(req, res, opt){
        //your custom code to check for any exceptions
        //console.log('bypass check', {req: req, res:res, opt: opt});
        if(req.path.indexOf('/img/') !== -1 || req.path.indexOf('/public/') !== -1){
          return '/'
        }

        if (req.headers.accept.indexOf('html') !== -1) {
          return '/index.html';
        }
      }
    }
  }
} 
对我来说效果很好
2021-05-25 15:45:00
这只是完美的答案,快速而简单。
2021-05-28 15:45:00
工作得很好!...谢谢!
2021-05-31 15:45:00
感谢您的代码!这与仅将“historyApiFallback:true”添加到同一个 devServer 对象之间有区别吗?(除了明显能够进一步定制它)。只是好奇
2021-06-18 15:45:00

如果你使用 CLI 运行 webpack-dev-server,你可以通过 webpack.config.js 传递 devServer 对象来配置它:

module.exports = {
  entry: "index.js",
  output: {
    filename: "bundle.js"
  },
  devServer: {
    historyApiFallback: true
  }
}

这将在每次遇到 404 时重定向到 index.html。

注意:如果您使用的是 publicPath,则还需要将其传递给 devServer:

module.exports = {
  entry: "index.js",
  output: {
    filename: "bundle.js",
    publicPath: "admin/dashboard"
  },
  devServer: {
    historyApiFallback: {
      index: "admin/dashboard"
    }
  }
}

您可以通过查看输出的前几行来验证一切设置是否正确(带有“404s 将回退到:路径”的部分)。

在此处输入图片说明

对于最近的答案,当前版本的 webpack (4.1.1) 你可以像这样在 webpack.config.js 中设置它:

const webpack = require('webpack');

module.exports = {
    entry: [
      'react-hot-loader/patch',
      './src/index.js'
    ],
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: ['babel-loader']
            },
            {
                test: /\.css$/,
                exclude: /node_modules/,
                use: ['style-loader','css-loader']
            }
        ]
    },
    resolve: {
      extensions: ['*', '.js', '.jsx']  
    },
    output: {
      path: __dirname + '/dist',
      publicPath: '/',
      filename: 'bundle.js'
    },
    plugins: [
      new webpack.HotModuleReplacementPlugin()
    ],
    devServer: {
      contentBase: './dist',
      hot: true,
      historyApiFallback: true
    }
  };

重要的部分是historyApiFallback: true无需运行自定义服务器,只需使用 cli:

"scripts": {
    "start": "webpack-dev-server --config ./webpack.config.js --mode development"
  },