Как разрешить webpack-dev-server разрешать точки входа из react-router
Я создаю приложение, которое использует webpack-dev-server в разработке вместе с react-router.
кажется, что webpack-dev-server построен вокруг предположения, что у вас будет общедоступная точка входа в одном месте (т. е."/"), тогда как react-router позволяет использовать неограниченное количество точек входа.
Я хочу воспользоваться преимуществами webpack-dev-сервера, особенно функцией горячей перезагрузки, которая отлично подходит для производительности, но я все еще хочу иметь возможность загружать маршруты, установленные в реагировать-маршрутизатор.
Как можно реализовать это так, чтобы они работали вместе? Не могли бы вы запустить экспресс-сервер перед webpack-dev-server таким образом, чтобы разрешить это?
9 ответов:
Я настроил прокси для достижения этой цели:
у вас есть обычный экспресс-веб-сервер, который обслуживает индекс.html на любом маршруте, за исключением если его маршрут актива. если это актив, то запрос проксируется на web-dev-server
ваши горячие точки входа react по-прежнему будут указывать непосредственно на сервер 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);теперь сделайте ваши точки входа в конфигурации 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/", // ... }
вы должны установить
historyApiFallbackofWebpackDevServerкак верно для этой работы. Вот небольшой пример (настройка в соответствии с вашими целями):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); });
для тех, кто все еще может искать этот ответ. Я собрал простой прокси-байпас, который достигает этого без особых хлопот, и конфигурация переходит в веб-пакет.конфиг.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 на стороне сервера.)
в этом случае вы, вероятно, также хотят, чтобы автоматически перезагрузить сервер при изменении одного из компонентов реакции. Вы делаете это с
pipingпакета. Все, что вам нужно сделать, это установить его и добавитьrequire("piping")({hook: true})где-то в начале сервер.js. Вот и все. Сервер будет перезапущен после изменения любого компонента, используемого оно.однако возникает еще одна проблема - если вы запускаете сервер webpack из того же процесса, что и ваш экспресс-сервер (как в принятом ответе выше), сервер webpack также перезапустится и каждый раз будет перекомпилировать ваш пакет. Чтобы избежать этого, вы должны запустить свой основной сервер и сервер webpack в разных процессах, чтобы трубопровод перезапускал только ваш экспресс-сервер и не касался 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) })

Comments