Vue-router: No route works after build - vue.js

I created a project with Vite, Pinia and Vue-router. Everything works perfectly in development, but when I access the build, only the main path works. All other redirects return 404:
"Failed to load resource: the server responded with a status of 404 ()"
"crbug/1173575, non-JS module files deprecated.
(anonymous) # VM10:6789"
Any idea what could be happening?
*** Main.js ***
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
// Font Awesome
import { library } from '#fortawesome/fontawesome-svg-core'
import { fas } from '#fortawesome/free-solid-svg-icons'
import { far } from '#fortawesome/free-regular-svg-icons'
import { fab } from '#fortawesome/free-brands-svg-icons'
import { FontAwesomeIcon } from '#fortawesome/vue-fontawesome'
//Router
import router from './router'
//Pinia
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
library.add(fas, far, fab);
const pinia = createPinia();
pinia.use(piniaPluginPersistedstate);
createApp(App)
.use(pinia)
.use(router)
.component('fa', FontAwesomeIcon)
.mount('#app')
*** App.vue ***
<script setup>
import { RouterView } from "vue-router";
</script>
<template>
<RouterView />
</template>
*** router/index.js ***
import { createRouter, createWebHistory } from 'vue-router'
import { useAuthStore } from '../stores/AuthStore';
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: "/katriumweb/login",
name: "login",
component: () => import("#/views/Login.vue")
},
{
path: "/katriumweb/playground",
name: "playground",
component: () => import("#/views/Playground.vue")
},
{
path: "/katriumweb/",
name: "home",
component: () => import("#/views/Home.vue"),
meta: {
authRequired: true
}
},
{
path: "/katriumweb/vehicleupdate",
name: "vehicleupdate",
component: () => import("#/views//workflows/VehicleUpdate.vue"),
meta: {
authRequired: true
}
}
],
});
router.beforeEach(async (to, from, next) => {
const authStore = useAuthStore();
let token = authStore.user? authStore.user.TOKEN : false;
const checkToken = await fetch("*******", {
method: "GET",
headers: {
"Token": `${token}`
}
})
if (to.meta.authRequired) {
if (!checkToken.ok || !token) {
localStorage.clear();
next("/katriumweb/login");
} else {
next();
}
} else {
next();
}
})
export default router;
*** vite.config.js ***
import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";
import vue from "#vitejs/plugin-vue";
// https://vitejs.dev/config/
export default defineConfig({
base: "/katriumweb/",
plugins: [vue()],
resolve: {
alias: {
"#": fileURLToPath(new URL("./src", import.meta.url)),
},
},
});

Since the app itself only has an index.html file and everything else is done via javascript, when you navigate to /mypage it tries to grab another html file.
The Vue Router createWebHistory works this way. A simple fix is to use createWebHashHistory, which uses a hash in order to create the routing.
Otherwise, more solutions are available on the documentation (eg. Netlify supports a redirect property to handle this).
The docs: https://router.vuejs.org/guide/essentials/history-mode.html

Related

Why not render vue router items in production?

Production build looses something.
I have Vue 3.2.33 project; vite: 2.9.5
When running dev-server all the template renders fine:
App.vue:
<template>
<div id="menu">
<nav class="navbar">
<router-link class="navbar__link" to="/">{{ state.reg }}</router-link>
<router-link class="navbar__link" to="/Information">{{
state.info
}}</router-link>
<router-link class="navbar__link" to="/Subscribers">{{
state.subs
}}</router-link>
</nav>
<LocaleSwitcher />
</div>
<router-view></router-view>
</template>
router config file
import { createRouter, createWebHistory } from "vue-router";
import Information from "#/views/Information.vue";
import Search from "#/views/Search.vue";
import Subscribers from "#/views/Subscribers.vue";
import { useStore } from '#/stores/store'
const routes = [
{
path: "/",
name: "Search",
component: Search,
},
{
path: "/information",
name: "Information",
component: Information,
},
{
path: "/subscribers",
name: "Subscribers",
component: Subscribers,
},
];
const router = createRouter({
history: createWebHistory(),
routes
});
router.beforeEach((to) => {
const store = useStore()
if (!store.hasGroup && to.path !== '/') {
return '/'
}
})
export default router;
vite.config.ts
import { fileURLToPath, URL } from "url";
import vueI18n from "#intlify/vite-plugin-vue-i18n";
import { defineConfig } from "vite";
import vue from "#vitejs/plugin-vue";
import path from "path";
export default defineConfig({
plugins: [
vue(),
vueI18n({
include: path.resolve(__dirname, "./src/locales/**"),
}),
],
resolve: {
alias: {
"#": fileURLToPath(new URL("./src", import.meta.url)),
},
}
});
but if I run build for production and run preview server, none of router components(router-link and router-view) render. Reading vite and vue-router documentation does not clarify anything yet. I would be grateful for any help, given that I am often just inattentive

Vue router 3 not rendering nested routes

I'm trying to render my nested routes in Vue 3 using Vue Router 4.
routes/index.ts
import { createRouter, createWebHistory } from "vue-router";
import {NavbarLayout} from "#/layouts/NavbarLayout";
import AuthRoutes from "#/router/children/AuthRoutes";
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: "/",
component: NavbarLayout,
// children: AuthRoutes,
},
],
});
export default router;
App.ts
import { defineComponent, h } from "vue";
import { VApp, VMain } from "vuetify/components";
export const App = defineComponent({
name: "App",
setup() {
return function render() {
// "Hello" is printed to the screen
return h(VApp, h(VMain, () => ["Hello", h("router-view")]));
};
},
});
NavbarLayout.ts
import { defineComponent, h } from "vue";
import { VContainer } from "vuetify/components";
import { useRoute } from "vue-router";
export const NavbarLayout = defineComponent({
name: "NavbarLayout",
setup() {
const route = useRoute();
// The alert pop up is not shown as well
alert("it should trigger this alert");
return function render() {
// "sub router" is not printed to the screen
return h(VContainer, () => ["sub router", h("router-view", { key: route.path })]);
};
},
});
The HTML being rendered
I have tried several combinations but so far nothing seems to work. Anyone has a clue on why the nested route is not being rendered?

Using vuex PersistedState with vuex modules

I want to use PersistedState https://github.com/robinvdvleuten/vuex-persistedstate with vuex but i can't get to setup correctly.
I have this module inside the store directory
export const auth = {
namespaced: true,
state: {
},
getters: {
countLinks: state => {
return state.links.length
}
},
mutations: {
SET_LINKS: (state, links) => {
state.links = links;
},
//Synchronous
ADD_LINK: (state, link) => {
state.links.push(link)
},
REMOVE_LINK: (state, link) => {
state.links.splice(link, 1)
},
REMOVE_ALL: (state) => {
state.links = []
}
},
actions: {
//Asynchronous
removeLink: (context, link) => {
context.commit("REMOVE_LINK", link)
},
removeAll ({commit}) {
return new Promise((resolve) => {
setTimeout(() => {
commit('REMOVE_ALL')
resolve()
}, 1500)
})
}
}
}
I have named this àuth.js
This is my index.js file also inside store directory
import { createStore } from 'vuex'
import createPersistedState from "vuex-persistedstate"
import { auth } from './auth'
const dataState = createPersistedState({
paths: ['data']
})
const store = createStore({
modules: {
auth
},
plugins: [dataState]
})
I have a total of 7 modules i would like to load and use in various places in my application. To kick things off i just want to load auth module and use it in my home.vue page
This is the script section of my home.vue
import Footer from '#/components/Footer.vue'
import Header from '#/components/Header.vue'
import { mapGetters} from 'vuex'
import store from '../store';
export default {
name: 'Home',
components: {
Footer,Header
},
mounted () {
var links = ['http://google.com','http://coursetro.com','http://youtube.com'];
store.commit('SET_LINKS', links);
},
computed: {
...mapGetters([
'countLinks'
]),
}
}
This is my main.js file
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import i18n from './i18n'
import FlagIcon from 'vue-flag-icon'
import {store} from './store';
createApp(App).use(i18n).use(FlagIcon).use(store).use(router).mount('#app')
When i npm run serve, i get the error
10:7 error 'store' is assigned a value but never used
no-unused-vars
How should i correct this to be able to use auth.js module anywhere in my application?

Dependency not found - Vue Js

I have recently added axios to a file called services.js so it's better organised. This file is on my root folder.
#/services.js
import axios from "axios";
const axiosInstance = axios.create({
baseURL: " server url here",
});
export const api = {
get(endpoint) {
return axiosInstance.get(endpoint);
},
post(endpoint, body) {
return axiosInstance.post(endpoint, body);
},
};
Then I have a component called Post.vue in my view folder:
<template>
<section>
<div>
<ul></ul>
</div>
</section>
</template>
<script>
import { api } from "#/services.js";
export default {
name: "Post",
props: ["id"],
data() {
return {
post: null,
};
},
methods: {
getPost() {
api.get(`/post/${this.id}`).then(response => {
this.post = response.data;
console.log(this.post);
});
},
},
created() {
this.getPost();
},
};
</script>
<style></style>
I also have a router.ts file with all my routes:
import Vue from "vue";
import VueRouter, { RouteConfig } from "vue-router";
import Home from "../views/Home.vue";
import Podcasts from "../views/Podcasts.vue";
import Post from "../views/Post.vue";
Vue.use(VueRouter);
const router = new VueRouter({
routes: [
{
path: "/",
name: "home",
component: Home,
},
{
path: "/podcasts",
name: "podcasts",
component: Podcasts,
},
{
path: "/post/:id",
name: "post",
component: Post,
props: true,
},
],
});
export default router;
It's giving me a dependency error like #/services.js did not exist.
Unsure what's wrong at this stage.
Thanks a lot in advance for helping out
In a standard Vue CLI project, the # symbol resolves to /src
If your file is in the root of your project try
import { api } from '#/../services'
But personally, I'd move it into src
You can check the Webpack configuration using
vue inspect
Look for the resolve.alias rules.
Check your webpack configuration, depends on the version of webpack you have, there should be an alias # like this:
const path = require('path');
module.exports = {
//...
resolve: {
alias: {
"#": path.resolve(__dirname) // check the path here
}
}
};
Or if you are using vue.config.js
configureWebpack: {
name: name,
resolve: {
alias: {
'#': path.resolve(__dirname)// check the path here
}
}
},
Make sure the path is correctly set up. You mentioned you have another project working fine, which makes it a good reference.

Camera mobile used for progressive web app

I realize a progressive application web app under view and I have a problem for the use of the mobile camera. I have a blank page. Here is my file seen for the camera:
<template>
<div class="container" id="app">
<router-link class="waves-effect waves-light btn" to="/livreur" #click.native="hideMenu"><i class="material-icons">arrow_back</i>
</router-link>
<div class="camera-modal">
<video ref="video" class="camera-stream"/>
</div>
</div>
</template>
<script>
var constraints = {
audio: false,
video: {
facingMode: {exact: 'environment'}
}
}
export default {
mounted () {
navigator.mediaDevices.getUserMedia(constraints)
.then(function (mediaStream) {
var video = document.querySelector('video')
video.srcObject = mediaStream
video.onloadedmetadata = function (e) {
video.play()
}
})
.catch(function (err) {
console.log(err.name + ': ' + err.message)
})
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>
</style>
My file main.js:
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'
import Axios from 'axios'
import VueSignature from 'vue-signature-pad'
Vue.prototype.$http = Axios
const token = localStorage.getItem('user-token')
if (token) {
Vue.prototype.$http.defaults.headers.common['Authorization'] = token
}
Vue.use(VueSignature)
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
My router.js file:
import Vue from 'vue'
import Router from 'vue-router'
import store from './store.js'
import Home from '#/components/Home'
import Delivered from '#/components/Delivered'
import Absent from '#/components/Absent'
import Refused from '#/components/Refused'
import Livreur from '#/components/preprations/Livreur'
import Prepa from '#/components/preprations/Prepa'
import Scan from '#/components/preprations/Scan'
import Login from '#/components/Login'
Vue.use(Router)
let router = new Router({
routes: [
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/delivered',
name: 'delivered',
component: Delivered
},
{
path: '/absent',
name: 'absent',
component: Absent
},
{
path: '/refused',
name: 'refused',
component: Refused
},
{
path: '/livreur',
name: 'livreur',
component: Livreur
},
{
path: '/prepa',
name: 'prepa',
component: Prepa
},
{
path: '/scan',
name: 'Scan',
component: Scan
}
]
})
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
if (store.getters.isLoggedIn) {
next()
return
}
next('/login')
} else {
next()
}
})
export default router
I tried to change the constraints but nothing helps, I try the default values ​​but it does not work.
I do not see where it's blocking at all. Thank you for your help.