Vue 404 on refresh in 'production' - vue.js

I say production, but it's running locally in a docker container. My backend is Django.
I'm having a little trouble with my vue app. submitting a form, or refreshing the page results in a 404 error. My data gets posted, but I have to go back to the beginning and navigate back to see my page. My searching led me to believe that using
history: createWebHistory()
might solve my problem, but the result is the same.
My /router/index.js:
...
{
path: '/dashboard/users/:id',
name: 'Users',
component: Users,
meta: {
requireLogin: true
}
},
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requireLogin) && !store.state.isAuthenticated) {
next('/log-in')
} else {
next()
}
})
export default router
Lots of topic seem to involve netify, or apache, of which I'm running neither. Any direction is appreciated.

It sounds like you may be missing a catch-all route in your router configuration. Without seeing your full router configuration, it's hard to say for sure, but something like this might work:
{
path: '*',
component: NotFound
}
This will catch any routes that don't match any of your other routes, and render the NotFound component.

Related

Handling thousands of custom routes from a database in Nuxt.js

I have a Nuxt JS (v3) application with thousands of custom routes, many pointing to the same pages, but at the domain root.
e.g /some-product-name-one, /a-secondary-product-name, /some-category-name, /some-static-page.
So in this case, the slug can be anything at domain root level, which is why i must fetch it from my database to assert which component is to be used.
What i've done is fetch all the routes (about 27.000) from my Database via. an API on build in my app/router.options.ts so it looks like so:
import type { RouterOptions } from '#nuxt/schema'
export default <RouterOptions> {
routes: (_routes) => [
{
name: 'product_some-product-name-one',
path: '/some-product-name-one',
component: () => import('~/pages/product.vue'),
props: {
id: '2421'
}
},
{
name: 'category_some-category-name',
path: '/some-category-name',
component: () => import('~/pages/category.vue'),
props: {
id: '45'
}
},
{...}
]
}
Now, the build time was 10 minutes and the application is extremely slow. Navigating to the website timed out.
How can i fetch routes from my database in Nuxt.js and send the user to the correct component?
Rather than baking all of the routes individually into the router, you might want to use a dynamic route such as _id.vue and handle the varying parameter within the component.

vueJS 3.x: navigate from page after HTML form-submit

Versions:
vueJS: 3.0.0
vuex: 4.0.2
Chrome: Version 94.0.4606.61 (Official Build) (x86_64)
One advantage of SPA frameworks like vueJS is that they offer some efficiencies in network consumption (ie, fewer server hits by delivering UI/UX assets to client in bulk, and hopefully minimizing server requests). But I'm running into a scenario where just the opposite happens: ie, I am required to revisit the server in order to navigate between vueJS components/views. This seems highly contradictory to the SPA ethos, and I'm suspicious something simple must be wrong in my setup. Details follow.
router/index.js:
import { createRouter, createWebHistory } from 'vue-router'
import Home from '#/views/Home.vue'
import Car from '#/views/Car.vue'
import Bike from '#/views/Bike.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '#/views/About.vue')
},
{
path: '/cars/new',
name: 'New Car',
component: Car
},
{
path: '/cars/:id',
name: 'Edit Car',
component: Car,
props: true
},
{
path: '/bikes/new',
name: 'New Bike',
component: Bike
}
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
export default router
Then in Car.vue component, I have a form-submit handler something like this:
handleSubmit(event) {
let form = event.target;
if (form.checkValidity()) {
// Add or update Car.
window.location.href = window.location.origin + process.env['BASE_URL'];
}
this.wasValidated = true
Rather than using window.location.href, I tried to use:
this.$router.push('Home');
But that had no effect. That is, the URL in the browser address bar began as something like http://localhost:8080/myapp/, and remained that way after the router-push.
I also tried pushing to other routes, like About; in that case, the browser address bar properly toggled to http://localhost:8080/myapp/about, but the page content remained the same!
Clearly, this cannot be the right behavior.
Can you suggest how to fix this?
this.$router.push('Home') tries to push 'Home' as a path, but there's no matching path in your router config, nor is there a fallback route (for 404s), so the route simply doesn't change.
If you meant to push the route by name, the $router.push() argument needs to be an object:
this.$router.push({ name: 'Home' })
If you prefer to use a path, the path of Home is actually /:
this.$router.push('/')

Vue: only allow access to page if redirected to programatically

I have a route which shows after a user has completed a payment, say at the /success URL. How would I make that someone can't simply go to example.com/success and see the success screen. Instead, it should only be accessed by running this.$router.go('/success/'); in code.
Thanks
Take a look at Navigation Guards.
You can add a beforeEnter to the route which you can use to check if the user should access the page.
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
You can do this with router navigation guards, in particular in-component guards. By defining the beforeRouteEnter, you can check (for example) the store, to see if data associated with payments is defined.

How to redirect non-dynamic urls with vue-router

We have a vue.js app for an insurance company where every agent has their own dynamically-generated website. Currently, if you visit a gibberish link, it will show the blank agent template. We need urls that don't include an agent's slug to redirect to our "NotFound" component.
Below is our vue-router code if there happens to be an easy fix. Otherwise is it easier to add a computed function to redirect a visitor if, for example, the agent.name == null?
Thanks for any help!
Example of a good url: https://my.piaselect.com/georgebeach
Example of a bad url: https://my.piaselect.com/georgebeach2
Our router:
{
path: "/:id",
component: AgentSite,
name: 'AgentSite',
props: true
},
{
path: '*',
name: 'NotFound',
component: NotFound
}
Building on what #Jacob Goh has said.
You need a way to to now if the agent id is valid or not. Let's assume you have a list of agent id's, you can use a route guard to block the route to invalid ids.
https://router.vuejs.org/en/advanced/navigation-guards.html
I haven't tested this, but you should be able to get the general idea.
const agentIds = ['Bob', 'Michael']
const router = new VueRouter({
routes: [
{
path: '/foo:id',
component: Foo,
beforeEnter: (to, from, next) => {
if (agentIds.includes(to.params.id)) {
// The agent is fine - continue
next();
} else {
// doesn't exist - go back to root or any other page
next({ path: '/' });
}
}
}
]
})
it doesn't work because you don't specify any name in this path :
{
path: "/:id",
component: AgentSite,
name: 'AgentSite',
props: true
},
because of that, this path allow any random chars at the root to return the component AgentSite (but blank because the random chars "param" fit to nothing in the component i guess).
To prevent that, you can specify a name to your path : path: "agent/:id" for example.
Edit : it seems you already had a great solution here...

how to render proper page based on user visit before on initial page load in vuejs

Basically my idea is to load home page , if user visits for first time and if user has already visited display the details of user.
There is no login for this app.Its like anonymous login.
Where to write the function like before Route ? on initial load itself it should go to correct page
I think you can do this with Route Guard beforeEnter method. For more information see https://router.vuejs.org/guide/advanced/navigation-guards.html#per-route-guard.
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// Do your logic here.
}
}
]
})