cannot GET error 404 on reload? - javascript

my react router is working fine with dev env, this is what I did in webpack dev server:
historyApiFallback: {
index: 'index.html',
}
so in production mode I wanted to do the same, I did it in express like this:
const indexPath = path.join(__dirname, '../public/index.html')
const publicPath = express.static(path.join(__dirname, '../public'))
app.use('/public', publicPath)
app.use('/graphql', graphQLHTTP(async (req) => {
let { user } = await getUser(req.headers.authorization);
if(!user) {
user = 'guest'
}
return {
schema,
pretty: true,
graphiql: true,
context: {
user,
}
}
}));
app.get('/', function (_, res) { res.sendFile(indexPath) });
I did not change anything with react-router-dom so I am am assuming the error is in my express config. so what's the equivalent of historyApiFallback in production mode? below is my webpack bundle config:
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js',
publicPath: '/public/'
},
in my html I reference the bundle like this:
<script type="text/javascript" src="/public/bundle.js"></script>
I think a have the right config but when I reload I get cannot GET Error 404?

You should add this line to your app:
app.get('*', function (_, res) { res.sendFile(indexPath) });
Or you should use this package better: https://github.com/bripkens/connect-history-api-fallback
You should read more about history mode:
To get rid of the hash, we can use the router's history mode, which leverages the history.pushState API to achieve URL navigation without a page reload:
When using history mode, the URL will look "normal," e.g. http://oursite.com/user/id. Beautiful!
Here comes a problem, though: Since our app is a single page client-side app, without a proper server configuration, the users will get a 404 error if they access http://oursite.com/user/id directly in their browser. Now that's ugly.
Not to worry: To fix the issue, all you need to do is add a simple catch-all fallback route to your server. If the URL doesn't match any static assets, it should serve the same index.html page that your app lives in. Beautiful, again!

Related

Router on vanilla JS for SPA that uses history api?

I need a vanilla js router for a spa site. Here on the github I found it seems like an ideal implementation, but there is one problem. This implementation, and everything that I found on the Internet, works well only with hash, through the history api that I need, they refuse to work, tell me what I'm doing wrong, or tell me another working implementation.
So I just take the Router class code, and set the routes I need:
const router = new Router({
mode: 'history',
root: '/'
});
router
.add('', () => {
console.log('deafult page');
}).add('settings', () => {
console.log('settings page');
}).add(/task-list/, () => {
console.log('task-list page');
})
And only the console.log('deafult page') is executed, if I enter http://localhost:3000/settings in the line, then it will give me Cannot GET /settings
if i use click event
document.addEventListener('click',()=>router.navigate('settings'))
then the link will become http://localhost:3000/settings, but the code console.log('settings page'); will not work
Just need to add webpack settings
devServer: {
contentBase: './dist',
port: 3000,
historyApiFallback: true, // its enable SPA routing through historyApi
}

Multiple React apps on express

I have a server on express.js and there is a static folder in its root directory, it contains several react apps, something like this:
app:
static:
react1
react2
I am trying to make sure that when accessing the /react1 and /react2 addresses, the express will display the required application.
app.js:
app.use (express.static(path.join(__ dirname, "static")));
app.use ("/", indexRouter);
index.router:
router.get('/react1', (req, res) => {
res.sendFile(path.join (__dirname, '..', 'static', 'react1', 'index.html'))
});
router.get('/react2', (req, res) => {
res.sendFile(path.join (__dirname, '..', 'static', 'react2', 'index.html'))
});
When I try to navigate through these handles, I get a blank page. What am I doing wrong?
Your app.js & index.router looks fine.
You might wanna add * to the router.
For instance
router.get('/react1/*', (req, res) => {
I think the issue is in how the static content is built.
Make sure to add PUBLIC_URL to build script in package.json.
For instance: "build": "PUBLIC_URL=/admin react-scripts build",
You can refer this youtube video for a detailed explanation.

Do I remove webpack-dev-server and hot-module middleware code during production build, or when I get ready for production?

As the title suggests, when I'm ready to host the code for production, should I remove all usages of webpack-dev-middleware and webpack-hot-middleware from my server code as they are dev-dependencies? What's the best way to set this up so maybe I don't have to worry about this?
This is a snapshot of my server code:
// webpack -> HMR
const webpack = require("webpack");
const webpackConfig = require("../webpack.config");
const compiler = webpack(webpackConfig);
// webpack HMR init
app.use(
require("webpack-dev-middleware")(compiler, {
noInfo: false,
publicPath: webpackConfig.output.publicPath,
})
);
app.use(require("webpack-hot-middleware")(compiler));
...
app.get("/", async (req, res) => {
const initialContent = await serverRender();
res.render("index", {
...initialContent,
});
});
app.listen(port, () => {
console.log(`Express application listening on port ${port}`);
});
You should wrap your HMR code (or really, any development/environment specific setting) into it's own area. I wouldn't recommend taking it out of your code as you may come back to the application and want to update something. Having HMR is a pretty nice luxery, so I would just have you code sniff out the environment, and if it's development, run the associated code. Otherwise, don't run it.
How do you detect the environment in an express.js app?

Vue router on page refresh gets 404

I am using Vue router with history mode. On button click on the current page I route it to next page. On second page when i reload i get a 404. Is there a way to handle this in Vue and redirect it to home page.
export default new Router({
mode: "history",
routes: [
{
path: "/",
name: "first",
component: First
},
{
path: "/abc",
name: "abc",
component: Second,
props: true
},
you can use hash mode inested of history mode to resolve the problem on your router
let router = new Router({
mode: "hash",
routes: [
{
//and the urls with path on here ...
if any one of is facing the issue even after trying above solution, please find below method.
If you have vue.config.js which has
module.exports = {
publicPath: process.env.PUBLIC_URL || "", // <-- this is wrong
...
};
either remove the vue.config.js or try removing the publicPath from the exports object.
Also you can try below method if you dont want to remove the publicPath
module.exports = {
publicPath: process.env.PUBLIC_URL || "/", // <-- this is correct now (and default)
transpileDependencies: ["vuetify"],
};
This is related to how the history mode in Vue Router works. I have created a writeup about it, with a solution as well.
Depends on your server implementation you need to enable URL Rewrites there. Here's how this would be implemented using Express/Node.js:
const express = require('express');
const app = express();
const port = 80;
const buildLocation = 'dist';
app.use(express.static(`${buildLocation}`));
app.use((req, res, next) => {
if (!req.originalUrl.includes(buildLocation)) {
res.sendFile(`${__dirname}/${buildLocation}/index.html`);
} else {
next();
}
});
app.listen(port, () => console.info(`Server running on port ${port}`));
For more info, check out https://blog.fullstacktraining.com/404-after-refreshing-the-browser-for-angular-vue-js-app/. HTH
This usually happens, when you deploy the page to a hosting server. Check the official docs for more background info and specifiy tipps for different hosting entvironments
https://router.vuejs.org/guide/essentials/history-mode.html
We have resolved this on backend, we have filter where we intercept the request and redirect it to home page. We have made it configurable.

Webpack dev server hot mode not working

Heres my config:
devServer: {
contentBase: '/web/dist/',
hot: true,
stats: {colors: true},
inline: true
}
And here's the gulp task im running:
gulp.task('build', ['clean', 'styles', 'bower', 'media', 'data', 'homepage'], function(done) {
es6promise.polyfill();
console.log('STARTING DEV SERVER...');
server = new WebpackDevServer(webpack(webpackDevConfig), webpackDevConfig.devServer);
server.listen(8080, '0.0.0.0', function (err, stats) {
if (err) {
throw new gutil.PluginError("webpack-dev-server", err);
}
console.log('DEV SERVER STARTED');
done();
});
});
Everything works as expected except the hot loading (no refresh or change when I make changes to files). What am I doing wrong here?
You need to add <script src="http://localhost:8080/webpack-dev-server.js"></script> to your index.html It is not added when you use the API
"Notice that webpack configuration is not passed to WebpackDevServer API, thus devServer option in webpack configuration is not used in this case. Also, there is no inline mode for WebpackDevServer API. <script src="http://localhost:8080/webpack-dev-server.js"></script> should be inserted to HTML page manually."
(http://webpack.github.io/docs/webpack-dev-server.html)
maybe you also need to add 'webpack/hot/dev-server' as an entrypoint to your webpack config
be sure to set
webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin());
in the webpackConfig as well
If you are using redux can try this.
For some random reason redux-devtools was not allowing hot reload for me. Try removing it from root component and redux compose config.
Note: Use redux devtool browser extension with this config in your store configuration: window.devToolsExtension ? window.devToolsExtension() : f => f
Also, must read: https://medium.com/#rajaraodv/webpacks-hmr-react-hot-loader-the-missing-manual-232336dc0d96#.ejpsmve8f
Or try hot reload 3:
example: https://github.com/gaearon/redux-devtools/commit/64f58b7010a1b2a71ad16716eb37ac1031f93915

Categories