【问题标题】:How to allow for webpack-dev-server to allow entry points from react-router如何允许 webpack-dev-server 允许来自 react-router 的入口点
【发布时间】:2014-11-29 23:23:25
【问题描述】:

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

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

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

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

【问题讨论】:

  • 我这里有一个非常hacky的版本,但它很脆弱,只允许简单的路由匹配:github.com/natew/react-base(参见 make-webpack-config)和(app/routes.js)
  • 你设法解决了 Nathan 的这个问题吗?如果有怎么办?请尝试在这里stackoverflow.com/questions/31091702/… 回答我的问题。谢谢你..!

标签: javascript reactjs webpack react-router


【解决方案1】:

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

您有一个常规的快速网络服务器,可以在任何路由上为 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 进行热重载

还要确保将绝对 URL 传递给 output.publicPath 选项:

 output: {
     publicPath: "http://localhost:8081/assets/",
     // ...
 }

【讨论】:

  • 嘿,这太棒了。实际上,我在此之前不久就到达了这个设置,并打算发布一个答案,但我认为你做得更好。
  • 一个问题,有点不相关,所以如果需要我可以打开一个新问题,但我注意到现在来自 webpack 开发服务器的控制台输出没有流式传输。以前,您可以观看它编译并看到百分比上升,现在它只是在编译后阻塞输出。
  • 做得好。这正是它应该做的。我添加了一个关于 output.publicPath 选项的注释,它也应该是一个绝对 URL。
  • 改用内置的webpack proxy 会更容易。因此,您不会干预服务器本身,而是让服务器。相反,您只需在 webpack 配置中添加一点(3-5 行)。感谢您仅出于开发目的修改开发脚本,并保持生产代码(server.js)安静(与您的版本不同)和imo这是正确的方法。
  • 这个答案仍然是正确的,虽然有点过时了。现在有更直接的方法,找historyApiFallback
【解决方案2】:

您应该将historyApiFallbackWebpackDevServer 设置为true,这样才能正常工作。这是一个小例子(根据您的目的进行调整):

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

【讨论】:

  • 您会错过 index.html 顶部的状态栏,但这很好用 :)
  • 这应该是公认的答案。来自 webpack 开发服务器文档:“如果您使用的是 HTML5 历史 API,您可能需要提供 index.html 来代替 404 响应,这可以通过设置 historyApiFallback: true 来完成” 如果我正确理解问题,这将解决问题。
  • 这么简单...谢谢!
  • @smnbbrv 没有问题。它实际上在下面使用connect-history-api-fallback,如果需要,您可以传递一个带有中间件特定选项的对象,而不仅仅是true
  • 或者如果您使用的是 cli,webpack-dev-server --history-api-fallback
【解决方案3】:

我想在你运行同构应用程序(即在服务器端渲染 React 组件)时添加答案。

在这种情况下,您可能还希望在更改其中一个 React 组件时自动重新加载服务器。您可以使用 piping 包执行此操作。您所要做的就是安装它并在server.js 开头的某处添加require("piping")({hook: true})。而已。服务器将在您更改其使用的任何组件后重新启动。

这会引发另一个问题——如果你从与你的 express 服务器相同的进程运行 webpack 服务器(如上面接受的答案),webpack 服务器也将重新启动,并且每次都会重新编译你的包。为避免这种情况,您应该在不同的进程中运行您的主服务器和 webpack 服务器,以便管道只会重新启动您的 express 服务器并且不会触及 webpack。 您可以使用 concurrently 包来执行此操作。您可以在react-isomorphic-starterkit 中找到这方面的示例。在 package.json 中,他有:

"scripts": {
    ...
    "watch": "node ./node_modules/concurrently/src/main.js --kill-others 'npm run watch-client' 'npm run start'"
  },

同时运行两台服务器,但在不同的进程中。

【讨论】:

  • 这是否意味着某些文件被观看了两次?比如共享的同构/通用文件?
【解决方案4】:

对于可能仍在寻找此答案的其他任何人。我整理了一个简单的代理绕过,可以轻松实现这一目标,并且配置进入 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';
        }
      }
    }
  }
} 

【讨论】:

  • 对我来说效果很好
  • 工作得很好!.. 谢谢!
  • 这只是完美的答案,快速简单。
  • 感谢代码!这与仅将“historyApiFallback:true”添加到同一个devServer对象之间有区别吗? (除了能够进一步定制它之外)。只是好奇
【解决方案5】:

如果你使用 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 will fallback to: path”的部分)。

【讨论】:

    【解决方案6】:

    historyApiFallback 也可以是一个对象而不是布尔值,包含路由。

    historyApiFallback: navData && {
      rewrites: [
          { from: /route-1-regex/, to: 'route-1-example.html' }
      ]
    }
    

    【讨论】:

      【解决方案7】:

      可能并非在所有情况下,但似乎 devServer 中的 publicPath: '/' 选项是修复深度路由问题的最简单解决方案,请参阅:https://github.com/ReactTraining/react-router/issues/676

      【讨论】:

        【解决方案8】:

        这对我有用:只需先添加 webpack 中间件,然后再添加 app.get('*'... index.html 解析器,

        所以 express 将首先检查请求是否匹配 webpack 提供的路由之一(例如:/dist/bundle.js/__webpack_hmr_),如果不匹配,那么它将使用 * 解析器移动到 index.html

        即:

        app.use(require('webpack-dev-middleware')(compiler, {
          publicPath: webpackConfig.output.publicPath,
        }))
        app.use(require('webpack-hot-middleware')(compiler))
        app.get('*', function(req, res) {
          sendSomeHtml(res)
        })
        

        【讨论】:

          【解决方案9】:

          对于更新的答案,当前版本的 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"
            },
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-12-29
            • 1970-01-01
            • 2021-12-29
            • 1970-01-01
            • 1970-01-01
            • 2020-01-01
            • 2017-04-06
            相关资源
            最近更新 更多