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

zzzyeukh  于 2023-02-04  发布在  Webpack
关注(0)|答案(9)|浏览(136)

我正在创建一个应用程序,在开发中使用webpack-dev-server和react-router。
webpack-dev-server似乎是基于这样一个假设构建的,即您将在一个位置(即“/”)拥有一个公共入口点,而react-router则允许无限数量的入口点。
我想要webpack-dev-server的好处,特别是热重载特性,这对生产力是很大的,但我仍然希望能够加载react-router中设置的路由。
如何实现它,使它们一起工作?你能在webpack-dev-server前面运行一个express服务器来实现这一点吗?

lmyy7pcs

lmyy7pcs1#

你应该将WebpackDevServerhistoryApiFallback设置为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);
});
ej83mcc0

ej83mcc02#

我设置了一个代理来实现这一点:
您有一个常规的express web服务器,它在任何路由上提供index.html,除非它是一个资产路由。如果它是一个资产,则请求将被代理到web-dev-server
你的react热入口点仍然会直接指向webpack dev服务器,所以热重载仍然有效。
假设您在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选项传递了一个绝对的url:

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

rekjcdws3#

对于其他可能还在寻找这个答案的人,我整理了一个简单的代理旁路,它可以不费吹灰之力地实现这一点,配置文件会进入webpack.config.js
我相信有更优雅的方法来使用regex测试本地内容,但这符合我的需要。

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';
        }
      }
    }
  }
}
bq3bfh9z

bq3bfh9z4#

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

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"
    }
  }
}

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

zdwk9cvp

zdwk9cvp5#

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

idfiyjo86#

对于运行同构应用程序(即在服务器端呈现React组件)的情况,我想补充一下答案。
在这种情况下,您可能还希望在更改React组件时自动重新加载服务器。您可以使用piping包来实现这一点。您所要做的就是安装它并在 server.js 的开头添加require("piping")({hook: true})。仅此而已。在更改服务器所使用的任何组件后,服务器将重新启动。
但是,如果您从与express服务器相同的进程运行webpack服务器,则会出现另一个问题(如以上被接受的答案),webpack服务器也将重新启动并且每次都重新编译你的包。2为了避免这种情况,你应该在不同的进程中运行你的主服务器和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'"
  },

其同时运行两个服务器但在单独的进程中运行。

7vhp5slm

7vhp5slm7#

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

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

7uhlpewt8#

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

jc3wubiy

jc3wubiy9#

这对我很有效:只需先添加Webpack中间件,然后再添加app.get('*'...index.html解析器,
so 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)
})

相关问题