2014-10-05 79 views
90

我正在創建一個應用程序,該應用程序在開發中與react-router一起使用webpack-dev-server。如何允許webpack-dev-server允許來自react-router的入口點

看來,webpack-dev-server是圍繞假設你將在一個地方(即「/」)有公共入口點而建立的,而react-router允許無限量的入口點。

我想要webpack-dev-server的好處,特別是熱重載功能,它對生產力非常好,但我仍然希望能夠在react-router中加載路由設置。

如何實現它,使它們一起工作?你能以這種方式在webpack-dev-server前面運行一個快速服務器嗎?

+0

我的東西在這裏一個非常哈克版本,但它是脆弱的,只允許簡單的途徑來匹配:https://github.com/natew/react-base(請參閱使-webpack-config)和(app/routes.js) – 2014-10-05 14:50:10

+0

你是否設法解決這個問題Nathan?如果是這樣如何?請嘗試在這裏回答我的問題http://stackoverflow.com/questions/31091702/why-do-we-need-a-proxy-on-an-express-js-server-in-order-to-get-webpack -hot-reloa。謝謝..! – SudoPlz 2015-06-27 18:08:11

回答

64

我成立了一個代理來實現這一目標:

你有一個正規快件網絡服務器,供應中的index.html上的任何路線,除非其資產路線。如果它是一項資產,請求會被代理到web-dev-server上,您的反應仍然會直接指向webpack dev服務器,因此熱重新加載仍然有效。

讓我們假設你運行在8081的WebPack-DEV-服務器和您在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/", 
     // ... 
    } 
+1

嘿,這太棒了。在此之前我實際上已經到過這個設置,並且會發佈一個答案,但我認爲你做得更好了。 – 2014-10-07 19:09:11

+1

一個問題,排序無關,所以如果需要,我可以打開一個新問題,但我注意到,現在webpack dev服務器的控制檯輸出沒有流式傳輸。之前,你可以看着它編譯並看到百分比上升,現在它只是在編譯後屏蔽輸出。 – 2014-10-07 19:09:47

+0

幹得好。這正是它應該如何完成的。我添加了關於'output.publicPath'選項的註釋,該選項也應該是絕對URL。 – 2014-10-09 09:00:44

82

您應該將historyApiFallback設置爲WebpackDevServer,因爲這是正確的。這裏有一個小例子(調整到適合你的目的):

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

你會錯過index.html頂部的狀態欄,但是這個效果很棒:) – swennemen 2015-02-22 16:00:27

+4

這應該是被接受的答案。從webpack開發者服務器docs:_「如果您使用的是HTML5歷史API,您可能需要爲您的index.html代替404響應,這可以通過設置historyApiFallback來完成:true」_如果我正確理解了這個問題,將解決問題。 – Sebastian 2016-04-14 16:18:18

+0

這麼簡單...謝謝! – smnbbrv 2016-06-17 08:29:52

2

我想,當你運行一個同構的應用程序添加到答案的情況下

(即呈現陣營組件服務器端)。

在這種情況下,您可能還想在更改其中一個React組件時自動重新加載服務器。您可以使用piping包進行此操作。你所要做的就是安裝它並在你開始的某個地方添加require("piping")({hook: true})server.js。而已。更改其使用的任何組件後,服務器將重新啓動。

這會引發另一個問題 - 如果您從express服務器的相同進程運行webpack服務器(如上面接受的答案),webpack服務器也會重新啓動並且每次都會重新編譯您的bundle。爲避免這種情況,您應該在不同的進程中運行主服務器和webpack服務器,以便管道系統只會重啓您的快速服務器,並且不會觸及webpack。 您可以使用concurrently包進行此操作。你可以在react-isomorphic-starterkit找到一個這樣的例子。在包中。JSON他有:

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

這同時運行兩個服務器,但在單獨的進程。

+0

這是否意味着某些文件正在被觀看兩次?如共享同構/通用文件? – 2015-11-27 06:22:22

15

對於任何可能仍在尋找此答案的人。我放了一個簡單的代理旁路,實現這一點,沒有太多的麻煩和配置進入webpack.config.js

我相信有更多優雅的方式來測試本地內容使用正則表達式,但這適用於我需要。

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

這將重定向:

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'; 
     } 
     } 
    } 
    } 
} 
+0

工作得很好 – Nath 2016-10-03 10:32:34

+0

工作很好!謝謝! – 2016-10-19 07:50:20

+1

這應該是正確的答案! – Crysfel 2017-01-24 22:53:17

4

如果您使用CLI運行的WebPack-dev的服務器,你可以通過傳遞devServer對象webpack.config.js配置它到每次遇到404時index.html。

注:如果您使用publicPath,你需要將它傳遞給devServer太:

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

您可以驗證一切都設置正確通過查看第一輸出的幾行(帶有「404s的部分將回退到:路徑」)。

enter image description here

1

historyApiFallback也可以是一個對象,而不是一個布爾值,含有該路由。

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

這爲我工作:只需在第一次添加的WebPack中間件和app.get('*'... index.html的分解後,

所以快車將首先檢查該請求是否匹配由的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) 
})