Vue Routes does not work properly in production - vue.js

I am new to vuejs. For my Vuejs application, I cannot access url like '/foo/apple' in the web hosting server, after I run the "npm run build". It shows error 404 I am using the HTML5 History Mode,(https://router.vuejs.org/guide/essentials/history-mode.html#example-server-configurations) and I implemented the "connect-history-api-fallback" like below in dev-server.js:
const express = require('express')
const app = express()
app.use(require('connect-history-api-fallback')())
My router/index.js
export default new Router({
mode: 'history',
{
path: '/Product',
name: 'Product',
component: Product,
},
{
path: '/Product/kraftbag',
name: 'Kraftbag',
component: Kraftbag
},
});
my website http://americandunnage.n55lwi.info/.
I have looked for a lot of posts regarding to this problem, but I still can find the solution.

you are likely missing the hashbang (#)
try #/foo/apple instead of /foo/apple
The default setting of the vue router is to use the hashbang method. This relies on using the index.html (or whatever defaults to / url) page, because everything after it is not taken as part of the url location but passed into the application. For example, in an anchor 1st heading this will go to a part of the page, and if you're already on that page, you will not be redirected.

Related

Loading problems when sharing a link on a site with Vue

I' ve created a website that uses Vue as front-end framwork and the CMS CosmisJS to manage the content. My site uses, among other things, Vue Router, Vuex and Vue Meta and is hosted on Netlify.
My site works fine, you can navigate between the different routes and the information loads without problems, however, when I share a link with a route, for example, http://example.com/route, the page simply doesn't load and shows me a Netlify error that says "Page Not Found" even though the route exists and can be visited if you navigate from the root route.
I can't figure out where the problem is. I thought it might be an error related to load times with API calls or some error in my Vue Router configuration, but I have made changes and the problem still persists.
Any idea what it could be?
Here is a simplified version of my Vue Router.
import Vue from "vue";
import VueRouter from "vue-router";
import CentroEstudios from "../views/CentroEstudios.vue";
import Nosotras from "../views/Nosotras.vue";
import Index from "../views/Index.vue";
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "Index",
component: Index,
},
{
path: "*",
name: "NotFound",
component: NotFound,
},
{
path: "/centro-de-estudios",
name: "Centro de Estudios",
component: CentroEstudios,
},
{
path: "/nosotras",
name: "Nosotras",
component: Nosotras,
},
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes,
});
export default router;
This is a consequence of using history mode on the router.
https://router.vuejs.org/guide/essentials/history-mode.html
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.
You need to configure Netlify to be compatible with history mode:
https://docs.netlify.com/routing/redirects/rewrites-proxies/#history-pushstate-and-single-page-apps
Here is another relevant post on the netlify support forum:
https://answers.netlify.com/t/vue-app-not-routing-correctly-when-deployed/6363
Or, if it's ok for the purposes of the website you're making, you can also just use the default hash mode and then you do not have this issue but you will have a hash before in all the URL paths.

show custom page during building process in vue js

i want to show a custom html page while building my vue js project (npm run build)
as you know while building process dist folder not exists and after build process we have dist folder .
how can i show a custom page until build is completely done?
i found this answer in a forum but how can i use that?
i dont think this is proper way!
axios.interceptors.response.use(function (response) {
if ( response.status === 503 ) {
return to maintenance page
}
return response;
});
Hi can you explain what do you want to achieve. It seems you are using VUE version that is lower than VUE CLI 3. If you want a custom page (error page, static page, 404 page, redirection page and etc.) you can still use vue router. Adding a page after a build is not a good idea since there is no route for that when you already build your project. Install vue router, create a router file or if you already have router add this.
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
import PageNotFound from '#/views/pages/NotFoundPage'
import 404Page from '#/views/pages/404Page.vue'
import StaticPage from '#/views/pages/StaticPage'
const router = new Router({
routes: [
{
path: '/static',
name: 'Static Page',
component: StaticPage
},
{
path: '/404',
name: '404 Page',
component: 404Page
},
{
path: '*',
name: 'PageNotFound',
component: PageNotFound
}
]
})
export default router
You just need to redirect the user using these from your view files
this.$router.push('/static')
this.$router.push('/404')
if there are no matching route the user will automatically redirected to Page Not Found page

Cannot figure out how vue-router works

I have a Vue.js project with the following router:
import Vue from 'vue';
import Router from 'vue-router';
import Overview from '#/components/Overview';
import Experiment from '#/components/ForExperiment';
Vue.use(Router);
export default new Router({
routes: [
{
path: '/',
redirect: 'test',
},
{
path: '/overview',
component: Overview,
},
{
path: '/overview/from/:from/to/:to',
name: 'overview',
component: Overview,
},
//... some other urls goes here.
{
path: '/test',
name: 'test',
component: Experiment,
},
],
});
If I open http://localhost:8080 in a browser I am redirected to http://localhost:8080/#/test. Why not just http://localhost:8080/test? Where does the '#' symbol come from?
And why if I open http://localhost:8080/test am I redirected to http://localhost:8080/test#/test?
And what is even more strange, if I open http://localhost:8080/overview I am redirected to http://localhost:8080/overview#/test, so the Overview component is not displayed.
What can cause these strange effects?
Vue router has different modes. The default mode when a browser is detected is hash. The current route is determined by the hash part of the url. The upside of this approach is that no serverside configuration is required. All urls point at the same resource (e.g. the route), which you can make your index.html file.
You can change this mode to history. The history mode uses the history api of the browser. It will only work in recent browsers, but support should not be an issue at this point. It will also require server side configuration in that you need to internally rewrite your router urls to the same file. If you would not do that, refreshing the page will show a 404 page instead of the page you want to see.
vue-router default mode is hash mode, that is why you see a # on your URL. It uses the URL hash to simulate a full URL without reloading the page if it changes.
To get rid of the hash, we can use vue-router history mode. Change the mode like so:
const router = new VueRouter({
mode: 'history',
routes: [...]
})
This leverages the History API.
If you want to use the history mode, you'll need to change your server configuration. Vue Router docs has some examples here.
The vue router defaults to hash mode. For your url to go to http://localhost:8080/test you need to go into history mode. This is done because by default web servers are not setup to redirect all requests to one html file. hash mode is used to per the docs:
The default mode for vue-router is hash mode - it uses the URL hash to simulate a full URL so that the page won't be reloaded when the URL changes.
Change your router to this to get history mode. But you will need to configure NGINX or Apache2 to redirect all requests to your vue code
const router = new VueRouter({
mode: 'history', // Add this to your router
routes: [...]
})

express server for serving Vue.js html file

I wrote a Vue application using the CLI. I’ve run the build command and got the dist folder with html file and the associated js/css file etc. Now I want to host the app on heroku with node/express sever, what I’ve written only half works.
For the record I’m using the vue router to render different components at different routes.
const routes = [
{path: "/", redirect: "/home"},
{path: "/home", component: body},
{path: "/home/new", component: create},
{path: "/home/entry/:id", component: blog},
{path: "/register", component: register},
{path: "/logout", component: logout},
{path: "/home/user/:userprofile", component: userprofile}
]
My vue application calls a separate backend API for all its data so the express server I’m requesting is only to server the html file across all routes.
This is what I have found from google:
var express = require('express');
var path = require('path');
var serveStatic = require('serve-static');
var port = process.env.PORT || 5000;
app = express();
app.use(serveStatic(__dirname + "/dist"));
app.listen(port);
It works when I’m going to “/” route but when I go to “/home” or similar it returns an error “cannot GET /home” or similar.
Can someone write me a short and simple express sever app for deploying vue on Heroku please?
Most likely you are missing configuration on your web server to redirect all requests to "/". VueJs router takes responsibility after that but it doesn't receive requests unless you explicitly configure your web server to do so.
Here is a Vue Router documentation page with short code snippets for different web servers that you will need to add to your web server configuration.

VueJs 2: Unable to render view when using history mode and route params

I am trying to set up SPA routes using history mode as follows:
{
mode: 'history',
routes: [
{
path: '/',
component: Home
},
{
path: '/articles',
component: ArticleList,
children: [
{
path: ':title',
component: ArticleView
}
]
}
]
}
As I am using the history mode routing on vue and on express application I've set up "express-history-api-fallback" as the last middleware in the pipeline:
const app = express();
const root = path.join(__dirname, '../client/dist');
app.use(express.static(root));
/* other middlewares */
app.use(fallback('index.html', {root: root}));
At the moment of a page reload, everything works fine. I.e. loading a url http://application/articles, opens correctly the view, BUT when I try to access the view that takes in a parameter, no matter what, the view does not get loaded and two requests are made to the express.
I.E. a request to http://application/articles/test will resolve into two requests. One to http://application/articles/test and another one to http://application/articles/app.[calculated-hash].js
As far as I understand, the first request fetches the index.html the other request fetches the bundled js script.
Also, on the express app, all routes to api start with 'api' prefix.
Question:
What is wrong with my setup/code using history mode and route params because no routes with parameters are loaded when trying to access them when entering url manually or hitting refresh?
Update:
Using connect-history-api-fallback produces the same results
The problem was with the script tag the webpack injects into the index.html
<script type="text/javascript" src="app.06503cbc260646a996d9.js"></script>
The src attribute value was missing a '/' prefix thus the resolution of files failed.
So to make it work, I've linked the src file like this:
<script type="text/javascript" src="/app.06503cbc260646a996d9.js"></script>
As I am using the webpack to bundle js files, on the webpack config I've added output.publicPath '/'
More info: connect-history-api-fallback bugtracker