120

反応ルーターと一緒に開発で webpack-dev-server を使用するアプリを作成しています。

webpack-dev-server は、1 つの場所 (つまり "/") にパブリック エントリ ポイントがあるという前提に基づいて構築されているようですが、react-router ではエントリ ポイントを無制限に使用できます。

webpack-dev-server の利点、特に生産性に優れたホット リロード機能が必要ですが、react-router で設定されたルートをロードできるようにしたいです。

それらが連携して動作するように実装するにはどうすればよいでしょうか? これを許可するような方法で、webpack-dev-server の前で高速サーバーを実行できますか?

4

9 に答える 9

105

historyApiFallbackこれを機能させるにはWebpackDevServer、 を 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);
});
于 2015-02-20T07:27:10.420 に答える
70

これを実現するためにプロキシを設定しました:

アセット ルートを除き、任意のルートで index.html を提供する正規表現 Web サーバーがあります。アセットの場合、リクエストは web-dev-server にプロキシされます

反応するホット エントリポイントは引き続き 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'
 ]

hotreload の 8081 への直接呼び出しに注意してください

また、絶対 URL をoutput.publicPathオプションに渡すようにしてください。

 output: {
     publicPath: "http://localhost:8081/assets/",
     // ...
 }
于 2014-10-06T14:14:10.797 に答える
13

CLI を使用して webpack-dev-server を実行している場合は、devServer オブジェクトを渡す webpack.config.js を介して構成できます。

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」の部分) を見ると、すべてが正しくセットアップされていることを確認できます。

ここに画像の説明を入力

于 2017-05-29T13:43:47.777 に答える
12

より最近の回答、現在のバージョンの 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"
  },
于 2018-03-27T01:59:09.287 に答える
2

同形アプリを実行する場合(つまり、Reactコンポーネントをサーバー側でレンダリングする場合)の回答に追加したいと思います。

この場合、React コンポーネントの 1 つを変更したときに、サーバーを自動的にリロードすることも必要になるでしょう。これはpipingパッケージで行います。インストールして、server.jsrequire("piping")({hook: true})の先頭に追加するだけです。それでおしまい。サーバーが使用するコンポーネントを変更すると、サーバーが再起動します。

ただし、これは別の問題を引き起こします-エクスプレスサーバーと同じプロセスからwebpackサーバーを実行すると(上記の受け入れられた回答のように)、webpackサーバーも再起動し、毎回バンドルを再コンパイルします. これを回避するには、メイン サーバーと webpack サーバーを別々のプロセスで実行して、パイピングがエクスプレス サーバーのみを再起動し、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'"
  },

両方のサーバーを同時に実行しますが、別々のプロセスで実行します。

于 2015-05-19T12:55:19.560 に答える
1

すべての場合ではないかもしれませんがpublicPath: '/'、devServer のオプションが深いルートの問題を修正する最も簡単な解決策のようです。https ://github.com/ReactTraining/react-router/issues/676 を参照してください

于 2017-10-16T13:04:03.423 に答える