score:70
i set up a proxy to achieve this:
you have a regular express webserver that serves the index.html on any route, except if its an asset route. if it is an asset, the request gets proxied to the web-dev-server
your react hot entrypoints will still point directly at the webpack dev server, so hot reloading still works.
let's assume you run webpack-dev-server on 8081 and your proxy at 8080. your server.js file will look like this:
"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);
now make your entrypoints in the webpack config like so:
entry: [
'./src/main.js',
'webpack/hot/dev-server',
'webpack-dev-server/client?http://localhost:8081'
]
note the direct call to 8081 for hotreload
also make sure you pass an absolute url to the output.publicpath
option:
output: {
publicpath: "http://localhost:8081/assets/",
// ...
}
score:-1
this worked for me: just simply add the webpack middlewares first and the app.get('*'...
index.html resolver later,
so express will first check if the request matches one of the routes provided by webpack (like: /dist/bundle.js
or /__webpack_hmr_
) and if not, then it will move to the index.html
with the *
resolver.
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)
})
score:1
historyapifallback
can also be an object instead of a boolean, containing the routes.
historyapifallback: navdata && {
rewrites: [
{ from: /route-1-regex/, to: 'route-1-example.html' }
]
}
score:1
may be not in all cases, but seems the publicpath: '/'
option in the devserver is easiest solution to fix deep routes issue, see: https://github.com/reacttraining/react-router/issues/676
score:2
i'd like to add to the answer for the case when you run an isomorphic app (i.e. rendering react component server-side.)
in this case you probably also want to automatically reload the server when you change one of your react components. you do this with the piping
package. all you have to do is install it and add require("piping")({hook: true})
somewhere in the beginning of you server.js. that's it. the server will restart after you change any component used by it.
this rises another problem though - if you run webpack server from the same process as your express server (as in the accepted answer above), the webpack server will also restart and will recompile your bundle every time. to avoid this you should run your main server and webpack server in different processes so that piping would restart only your express server and won't touch webpack.
you can do this with concurrently
package. you can find an example of this in react-isomorphic-starterkit. in the package.json he has:
"scripts": {
...
"watch": "node ./node_modules/concurrently/src/main.js --kill-others 'npm run watch-client' 'npm run start'"
},
which runs both servers simultaneously but in separate processes.
score:12
for a more recent answer, the current version of webpack (4.1.1) you can just set this in your webpack.config.js like such:
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
}
};
the important part is historyapifallback: true
. no need to run a custom server, just use the cli:
"scripts": {
"start": "webpack-dev-server --config ./webpack.config.js --mode development"
},
score:13
if you're running webpack-dev-server using cli, you can configure it through webpack.config.js passing devserver object:
module.exports = {
entry: "index.js",
output: {
filename: "bundle.js"
},
devserver: {
historyapifallback: true
}
}
this will redirect to index.html everytime it 404 is encountered.
note: if you're using publicpath, you'll need to pass it to devserver too:
module.exports = {
entry: "index.js",
output: {
filename: "bundle.js",
publicpath: "admin/dashboard"
},
devserver: {
historyapifallback: {
index: "admin/dashboard"
}
}
}
you can verify that everything is setup correctly by looking at the first few lines of the output (the part with "404s will fallback to: path").
score:28
for anyone else that may still be looking for this answer. i put together a simple proxy bypass which achieves this without much hassle and the config goes into the webpack.config.js
i am sure there are much more elegant ways to test for local content using regex, but this works for my needs.
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';
}
}
}
}
}
score:106
you should set historyapifallback
of webpackdevserver
as true for this to work. here's a small example (tweak to fit your purposes):
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);
});
Source: stackoverflow.com
Related Query
- How to allow for webpack-dev-server to allow entry points from react-router
- How to configure webpack dev server with react router dom v4?
- How to tell webpack dev server to serve index.html for any route
- React / Sentry for Error Reporting - How to not send errors from dev / localhost
- Proxying requests from client react app to server with create-react-app and webpack dev server
- How to go back to react router v5 from react router v6 for nested dashboard?
- How to fetch data from server using JavaScript? (adding backend to React app for the first time)
- How to set state at the server for data from API using react redux
- Express static server returns html for bundle.js for react build from webpack
- How do I fix the webpack file for the React Router issue?
- How to make the webpack dev server run on port 80 and on 0.0.0.0 to make it publicly accessible?
- How to setup apache server for React route?
- How to redirect from axios interceptor with react Router V4?
- How do I change webpack dev server's default port from 8080 to a different port?
- React tutorial - how do I start the node server for a reactJs application?
- How to set NODE_ENV from package.json for react
- How to update webpack config for a react project created using create-react-app?
- Webpack 4 and react loadable does not seems to create correct chunk for server side rendering
- React Router with - Ant Design Sider: how to populate content section with components for relevant menu item
- Using React Router and Webpack 2 how to require external libraries only on certain routes?
- How to pass the match when using render in Route component from react router (v4)
- React Navigation: How to update navigation title for parent, when value comes from redux and gets updated in child?
- CDN links for React packages and how to import it when using react using the scripts from CDN
- How would I test for a react router route param in react-testing-library?
- how can I show customized error messaged from server side validation in React Admin package?
- How to implement scroll restoration for React Router SPA
- How to get Webpack Dev Server to display images stored locally?
- Webpack dev server React Content Security Policy error
- How can I pass data from express server to react views?
- How to export Component for server side rendering in React
More Query from same tag
- Cannot read property 'Vector'/'Draw' of undefined in React JS
- How to set a HTML element ID on a material-ui component?
- MUI Input doesn't allow oninput attribute
- React Function vs Template re-render
- Sendinblue create contact 'TypeError: Failed to fetch' error (using React)
- Problem with Reducer that contains few different values
- How to fix type issue for conditional rendering?
- duplicate entry while using push on array
- Plotting heatmap with available attributes instead of range D3 React
- Waiting for useState hook increment counter using Promises
- Modal is not closing in ant-design
- unable to destructuring two objects simultaneously
- React JS - Replace matching string and add string to next matching string
- Conditional rendering to choose display setup
- How to automatic load .feature files
- Utilize external script function in React?
- Using client-only routes with page templates coming from Contentful
- typescript Object is possibly null when getting files from event
- How to wait for state to not be undefiened in ReactJS?
- how do you escape jsx a component so that it renders as typed instead of computed?
- What do the React docs mean by the following statement?
- How to use the Time period in date time
- Unable to understand the difference between different monaco editor packages integration
- Controlled TextField loosing focus after every character from keyboard
- How to show value, when using date type in TextField?
- Delete object from Firebase, React, ES6
- How do I utilize dot notation when rendering components?
- Component not rendering after using <Link> though the URL gets changed
- React change state for all elements except for the chosen one
- How to pass two parameters to custom event handler in React?