Как разрешить webpack-dev-server разрешать точки входа от react-router
Я создаю приложение, которое использует webpack-dev-server в разработке вместе с react-router.
кажется, что webpack-dev-server построен вокруг предположения, что у вас будет открытая точка входа в одном месте (т. е."/"), тогда как react-router позволяет неограниченное количество точек входа.
Мне нужны преимущества webpack-dev-server, особенно функция горячей перезагрузки, которая отлично подходит для производительности, но я все равно хочу иметь возможность загружать маршруты, установленные в реагировать-маршрутизатор.
Как можно реализовать его так, чтобы они работали вместе? Не могли бы вы запустить экспресс-сервер перед webpack-dev-server таким образом, чтобы разрешить это?
9 ответов
Я установил прокси-сервер для достижения этого:
у вас есть обычный веб-сервер express, который обслуживает индекс.html на любом маршруте, кроме если его маршрут актива. если это актив, запрос проксируется на web-dev-server
ваши react hot entrypoints по-прежнему будут указывать непосредственно на сервер webpack dev, поэтому горячая перезагрузка все еще работает.
предположим, вы запускаете webpack-dev-server на 8081 и ваш прокси-сервер на 8080. Ваш сервер.файл 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);
теперь сделайте ваши entrypoints в конфигурации webpack следующим образом:
entry: [
'./src/main.js',
'webpack/hot/dev-server',
'webpack-dev-server/client?http://localhost:8081'
]
обратите внимание на прямой вызов 8081 для hotreload
также убедитесь, что вы передаете абсолютный url-адрес :
output: {
publicPath: "http://localhost:8081/assets/",
// ...
}
вы должны установить historyApiFallback
of 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);
});
для тех, кто все еще может искать этот ответ. Я собрал простой обход прокси, который достигает этого без особых хлопот, и конфигурация переходит в webpack.конфиг.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';
}
}
}
}
}
Если вы используете webpack-dev-server с помощью CLI, вы можете настроить его через webpack.конфиг.JS передача объекта devServer:
module.exports = {
entry: "index.js",
output: {
filename: "bundle.js"
},
devServer: {
historyApiFallback: true
}
}
это перенаправит на индекс.html каждый раз, когда он встречается 404.
Примечание: Если вы используете 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.конфиг.Яш вроде такого:
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"
},
Я хотел бы добавить к ответу для случая, когда вы запускаете изоморфное приложение (т. е. рендеринг React component server-side.)
в этом случае вы, вероятно, также хотите автоматически перезагрузить сервер при изменении одного из компонентов React. Вы делаете это с piping
пакета. Все, что вам нужно сделать, это установить его и добавить require("piping")({hook: true})
где-то в начале сервер.js. Вот и все. Сервер перезапустится после изменения любого компонента, используемого он.
это вызывает еще одну проблему, хотя-если вы запустите сервер webpack из того же процесса, что и ваш экспресс-сервер (как в принятом ответе выше), сервер webpack также перезапустится и будет перекомпилировать ваш пакет каждый раз. Чтобы избежать этого, вы должны запустить основной сервер и сервер webpack в разных процессах, чтобы трубопроводы перезапускали только ваш сервер express и не касались webpack. Вы можете сделать это с помощью . Вы можете найти пример этого в react-isomorphic-starterkit. В пакета.в JSON он:
"scripts": {
...
"watch": "node ./node_modules/concurrently/src/main.js --kill-others 'npm run watch-client' 'npm run start'"
},
который запускает оба сервера одновременно, но в отдельных процессах.
historyApiFallback
также может быть объектом вместо логического, содержащего маршруты.
historyApiFallback: navData && {
rewrites: [
{ from: /route-1-regex/, to: 'route-1-example.html' }
]
}
может быть не во всех случаях, но кажется publicPath: '/'
опция в devServer-это самое простое решение для устранения проблемы с глубокими маршрутами, см.:https://github.com/ReactTraining/react-router/issues/676
это сработало для меня: просто добавьте промежуточные программы webpack и .HTML-код решателя позднее
so express сначала проверит, соответствует ли запрос одному из маршрутов, предоставляемых webpack (например:/dist/bundle.js
или /__webpack_hmr_
) а если нет, то он будет двигаться к index.html
С *
сельсин.
ie:
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)
})