404 Error when page gets refreshed/revisited - javascript

Tried using history mode in vue.js to remove hash sign from the URL. Downside of this is when the page got refreshed / revisited, it occurs 404 Not Found. There's a documentation from the website about the History Mode and fixing it but I'm having trouble understanding it, sorry.
What I want is remove the history mode from the code, at the same time hash symbol gets removed from the url and 404 Error will be fixed.
I will provide the code below from the index.js that the web has. (Note: The website is already built this way and it was passed onto me since the developer that made this had problems.)
Vue.use(VueRouter);
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch((err) => err);
};
const router = new VueRouter({
mode:"history",
routes,
});
const isLogin = true;
router.beforeEach((to, from, next) => {
document.title = to.meta.title;
if (to.name == "login" || isLogin) {
next();
} else {
next("/login");
}
});
router.beforeResolve((to, from, next) => {
next();
});
router.afterEach((to, from) => {
});
export default router;
Do I need to do a new set of codes for me to able to do what I want? 404 Error fixed when page got refreshed / revisited, hash symbol gets removed from URL.

The default mode for Vue Router is hash mode. It uses a URL hash to simulate a full URL so that the page won’t be reloaded when the URL changes. Comment or remove mode: "history"
const router = new VueRouter({
//mode:"history",
routes,
});
See the example case here https://www.bezkoder.com/integrate-vue-spring-boot/

I encountered this problem some time ago, you just have to configure the vue router mode and install a package for the server, and configure the server as well. I leave the official guide here.
Vue router config:
const router = new VueRouter({
mode: 'history',//Set the mode to 'history'
routes: [...]
})
Server config (NOT express):
const http = require('http')
const fs = require('fs')
const httpPort = 80
http.createServer((req, res) => {
fs.readFile('index.html', 'utf-8', (err, content) => {
if (err) {
console.log('We cannot open "index.html" file.')
}
res.writeHead(200, {
'Content-Type': 'text/html; charset=utf-8'
})
res.end(content)
})
}).listen(httpPort, () => {
console.log('Server listening on: http://localhost:%s', httpPort)
})
For express node.js sever: For Node.js/Express, consider using connect-history-api-fallback middleware.

Related

How can I localize routes with the nextJs and next-i18next like an URL alias?

I'm using NextJs 10.0.5 with next-i18next 8.1.0 to localize my application. As we all know nextJs 10 has subpath routing for internationalized routing. In addition, I need to change the page names by language. For example, I have a contact-us file inside the pages folder. When I change the language to Turkish, I have to use localhost:3000/tr/contact-us. However, I want to use localhost:3000/bize-ulasin to access the contact-us page when the language is Turkish. So there are two URLs and only one page file.
It works when I use custom routing with express js in the server.js file. However, when I want to access the "locale" variable within the getStaticProps function in the contact-us file, I cannot access it. The getStaticProps function returns undefined for "locale" variable when I use localhost:3000/bize-ulasin URL.
server.js
const { createServer } = require("http");
const { parse } = require("url");
const next = require("next");
const app = next({ dev: process.env.NODE_ENV !== "production" });
const handle = app.getRequestHandler(app);
app.prepare().then(() => {
createServer((req, res) => {
const parsedUrl = parse(req.url, true);
const { pathname, query } = parsedUrl;
if (pathname === "/bize-ulasin") {
app.render(req, res, "/contact-us", query);
}else{
handle(req, res, parsedUrl);
}
}).listen(3000, (err) => {
if (err) throw err;
console.log("> Ready on http://localhost:3000");
});
});
/pages/contact-us-file
import { Fragment } from "react";
import Head from "next/head";
import { useTranslation } from "next-i18next";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
const ContactUs = () => {
const { t } = useTranslation("common");
return (
<Fragment>
<Head>
<title>Contact-Us</title>
</Head>
</Fragment>
);
};
export const getStaticProps = async ({ locale }) => {
console.log(locale); // When I use the URL localhost: 3000/bize-ulasin, it returns undefined.
return {
props: {
...(await serverSideTranslations(locale, ["common"])),
},
};
};
export default ContactUs;
How can I access the "locale" variable with getStaticProps? Or, how can I use the following URLs with the same page file?
->localhost:3000/contact-us
->localhost:3000/bize-ulasin
I also faced the same problem today. That's how I solved the issue.
First of all, delete the server.js file. With Next.JS 10, using server.js will create conflict with the i18n routes and you won't be able to get the locale data in getStaticProps.
NextJS has a beautiful method named rewrites. We will use that instead of our server.js file. For example, if you have a page named contact-us-file, we can rewrite our next.config.js file as
const { i18n } = require('./next-i18next.config')
module.exports = {
i18n,
async rewrites() {
return [
{
source: '/contact-us',
destination: '/en/contact-us-file',
},
{
source: '/bize-ulasin',
destination: '/tr/contact-us-file',
},
]
},
}
As you are already using Next-i18next, I hope you are familiar with the file that I am importing.
Now If you try to navigate localhost:3000/contact-us and localhost:3000/bize-ulasin you should be able to access your contact us page.

using React router with Next JS route

i have simple question , i am new in Next.JS
we have a project and my web application manage routes in BackEnd with Next JS
now my problem is here , i want use React-Router-dom in one section
forexample before im working with Laravel and React
in Laravel I set My Route like This
Route::get('/reactPage/*' ...)
and then use Clien route with react
but i dont know how handle this with Next JS
( more details => for example i want user click to some link after that user see a page with some link inside of them , if user click that link , react-router-dom handle route and no any request send to Server )
I would recommend using the Next router. You do need to create a custom server in order to overload the default Next routing, but its a trivial task:
// server.js
const { createServer } = require('http');
const next = require('next');
const routes = require('./routes');
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handler = routes.getRequestHandler(app);
app.prepare().then(() => {
createServer(handler).listen(port, err => {
if (err) {
throw err;
}
console.log(`> Ready on http://localhost:${port}`);
});
});
Then you can define routes, which I do in the routes.js file:
// routes.js
const nextRoutes = require('next-routes');
const routes = (module.exports = nextRoutes());
routes
.add('landing', '/')
.add('profile', '/profile', 'profile');

next.js app with custom server is not rendering correctly

I'm new to next.js so maybe I'm missing something very stupid. I want to use custom routes so I created a server.js file and changed my package.json command to node server.js. This is the entire server.js file:
const express = require("express");
const next = require("next");
const createLocaleMiddleware = require("express-locale");
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();
app
.prepare()
.then(() => {
const server = express();
server.get("/", createLocaleMiddleware(), (req, res) => {
res.redirect(`/${req.locale.language}/home`);
});
server.get("/:lang/home", (req, res) => {
const actualPage = "/";
const queryParams = { locale: req.params.lang };
app.render(req, res, actualPage, queryParams);
});
server.listen(3000, err => {
if (err) throw err;
console.log("> Ready on http://localhost:3000");
});
})
.catch(ex => {
console.error(ex.stack);
process.exit(1);
});
I believe that according to the docs, this should work. I just want to render the index page with the users locale on the specified route ('/:lang/home'). I'm using react-intl for the i18n.
Now I get the following error in the console (client side):
It's in dutch but it's just saying it can't find any of the specified files. So now the HMR is not working anymore, routing is not working anymore (with Router.push). The only thing it does correctly is loading the index page (I can see it in the browser).
I also tried to enable and disable this flag from the docs:
module.exports = {
useFileSystemPublicRoutes: false
}
Sadly, no effect.
Am I missing something? Is it because I'm redirecting? Or is this not to way to handle routing? If someone could provide some pointers that would be great :)
Thanks in advance!
You are missing server.get('*', handle) as you can see in the custom server express example. This is absolutely required :)

Get middleware mount point from request in Express

I have an Express application with a router, here is the example of the router:
const router = require('express-promise-router')();
const users = require('./users');
const validate = require('./validate');
router.get('/users', users.list);
router.get('/users/:id', users.get);
// other routes here
module.exports = router;
Now I want to add a middleware that validates each query, like that (this is not the working example, it's just to show the idea of what I want to accomplish):
const schemas = {
'/users': 'some validation schema',
'/users/:id': 'another validation'
}
module.exports = (req, res, next) => {
const url = req.originalUrl; // This is where I'm stuck.
if (!schemas[url]) {
// throw new error that validation failed
}
// validating somehow
if (!req.validate(schemas[url])) {
// throw new error that validation failed
}
return next();
}
And for this, I need to get the middlelware mount folder (like '/users/:id' for '/users/557'). I've tried to use req.originalUrl, but it returns the full URL path instead of the mount folder.
How can I achieve this? And if there's no way, how can I write my validation middleware another way to make it work?
Inside req.route you will get the path of API.
Check this screenshot

How can i get Client IP Address from React App that run on Express.JS

I use this react boilerplate. It's running on express web server.
I can get client IP address in JavaScript file that process in server
But I wonder how can I pass that value to React Frontend script?
Please shed me some light.
UPDATE
Now, i can use it by using javascript template engine and replace IP before rendering.
Here is the code
app.get('*', (req, res) => {
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
fs.readFile(path.join(compiler.outputPath, 'index.html'), (err, file) => {
if (err) {
res.sendStatus(404);
} else {
const compileStr = Mustache.render(file.toString(), { userIpAddress: ip });
res.send(compileStr);
}
});
});
However, in production, it's using sendFile() and i cannot get fs module on production :-(
const addProdMiddlewares = (app, options) => {
const publicPath = options.publicPath || '/';
const outputPath = options.outputPath || path.resolve(process.cwd(), 'build');
// compression middleware compresses your server responses which makes them
// smaller (applies also to assets). You can read more about that technique
// and other good practices on official Express.js docs http://mxs.is/googmy
app.use(compression());
app.use(publicPath, express.static(outputPath));
app.get('*', (req, res) => res.sendFile(path.resolve(outputPath, 'index.html')));
};

Categories