react link exact doom javascript reactjs webpack react-router

javascript - link - Cómo permitir que el servidor webpack-dev-server permita puntos de entrada desde el router de reacción



react-router-dom (9)

Estoy creando una aplicación que usa webpack-dev-server en desarrollo junto con reaction-router.

Parece que webpack-dev-server se basa en la suposición de que tendrá un punto de entrada pública en un lugar (es decir, "/"), mientras que react-router permite una cantidad ilimitada de puntos de entrada.

Quiero los beneficios del servidor webpack-dev, especialmente la función de recarga en caliente que es excelente para la productividad, pero aún quiero poder cargar las rutas establecidas en el router de reacción.

¿Cómo podría uno implementarlo de modo que trabajen juntos? ¿Podría ejecutar un servidor express en frente de webpack-dev-server de tal forma que permita esto?


Configuré un proxy para lograr esto:

Usted tiene un servidor web expreso regular que sirve el index.html en cualquier ruta, excepto si es una ruta de activo. si es un activo, la solicitud recibe un proxy del servidor web-dev

sus puntos de entrada calientes reaccionarán apuntarán directamente al servidor de desarrollo webpack, por lo que la recarga aún funciona.

Supongamos que ejecuta webpack-dev-server en 8081 y su proxy en 8080. Su archivo server.js se verá así:

"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);

Ahora haga sus puntos de entrada en la configuración de la carpeta web así:

entry: [ ''./src/main.js'', ''webpack/hot/dev-server'', ''webpack-dev-server/client?http://localhost:8081'' ]

tenga en cuenta la llamada directa a 8081 para hotreload

también asegúrese de pasar una url absoluta a la opción output.publicPath :

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


Debe establecer WebpackDevServer of WebpackDevServer como verdadero para que esto funcione. Aquí hay un pequeño ejemplo (ajuste para sus propósitos):

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


Esto funcionó para mí: simplemente agregue primero el middleware webpack y la app.get(''*''... index.html resolver más tarde,

entonces express primero comprobará si la solicitud coincide con una de las rutas proporcionadas por el paquete web (como: /dist/bundle.js o /__webpack_hmr_ ) y si no, se moverá al index.html con el * resolver.

es decir:

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


Me gustaría agregar a la respuesta para el caso cuando ejecuta una aplicación isomorfa (es decir, representa el componente Reaccionar en el servidor).

En este caso, probablemente también quiera recargar automáticamente el servidor cuando cambie uno de sus componentes React. Usted hace esto con el paquete de piping . Todo lo que tiene que hacer es instalarlo y agregar require("piping")({hook: true}) en algún lugar al comienzo de su server.js . Eso es. El servidor se reiniciará después de cambiar cualquier componente utilizado por él.

Sin embargo, esto plantea otro problema: si ejecuta el servidor de paquetes web desde el mismo proceso que su servidor Express (como en la respuesta aceptada anteriormente), el servidor de paquetes web también se reiniciará y volverá a compilar su paquete cada vez. Para evitar esto, debe ejecutar el servidor principal y el servidor de paquetes web en diferentes procesos para que la canalización reinicie solo su servidor Express y no toque el paquete web. Puedes hacer esto con un paquete concurrently . Puede encontrar un ejemplo de esto en react-isomorphic-starterkit . En el package.json él tiene:

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

que ejecuta ambos servidores simultáneamente pero en procesos separados.


Para cualquier otra persona que aún pueda estar buscando esta respuesta. Junté una derivación proxy simple que logra esto sin mucha molestia y la configuración entra en el webpack.config.js

Estoy seguro de que hay formas mucho más elegantes de probar el contenido local utilizando expresiones regulares, pero esto funciona para mis necesidades.

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


Para una respuesta más reciente, la versión actual de webpack (4.1.1) puede simplemente configurar esto en su webpack.config.js como tal:

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

La parte más importante es historyApiFallback: true . No es necesario ejecutar un servidor personalizado, solo use el cli:

"scripts": { "start": "webpack-dev-server --config ./webpack.config.js --mode development" },



Si está ejecutando webpack-dev-server usando CLI, puede configurarlo a través de webpack.config.js pasando el objeto devServer:

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

Esto redirigirá a index.html cada vez que se encuentre 404.

NOTA: Si está utilizando publicPath, también tendrá que pasarlo a devServer:

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

Puede verificar que todo esté configurado correctamente mirando las primeras líneas de la salida (la parte con "404s volverá a la ruta : ruta ").


historyApiFallback también puede ser un objeto en lugar de un booleano, que contiene las rutas.

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