How to setup `vite-plugin-pages`, cannot find module `~pages` - vue.js

I'm trying to set up file system based routing for a Vue 3 application using Vite with the help of vite-plugin-pages.
I created the project using yarn create vite with vue-ts as the options and added the plugin via yarn add vite-plugin-pages --dev, yarn add vue-router.
Following the readme on the github, I have added the following to my vite.config.ts:
import Pages from 'vite-plugin-pages'
export default {
plugins: [
// ...
Pages(),
],
}
However, at the next step, in main.ts:
import { createRouter } from 'vue-router'
import routes from '~pages'
const router = createRouter({
// ...
routes,
})
I cannot seem to import from ~pages. I cannot find the module. vue-router itself is working fine, as I can create a router fine, declaring the routes myself. In a vite template, they seem to be using import routes from 'virtual:generated-pages' instead and I have no idea how either works.
So, the question is, how would I go about generating the dynamic routes and as a whole, set up the usage of vite-plugin-pages?

You can try like this:
import Pages from "vite-plugin-pages"
export default defineConfig({
plugins: [
Pages({
pagesDir: [
{dir: 'src/pages', baseRoute: ''},
],
extensions: ['vue'],
syncIndex: true,
replaceSquareBrackets: true,
extendRoute(route) {
if (route.name === 'about')
route.props = route => ({query: route.query.q})
if (route.name === 'components') {
return {
...route,
beforeEnter: (route) => {
// eslint-disable-next-line no-console
// console.log(route)
},
}
}
},
}),
],
});
Then in main.js
import { createRouter, createWebHistory } from 'vue-router';
import generatedRoutes from 'virtual:generated-pages';
const router = createRouter({
history: createWebHistory(),
routes: generatedRoutes,
});

You can also declare the reference in any of your type declarations.
/// <reference types="vite-plugin-pages/client" />

// tsconfig.json
"compilerOptions": {
...
"types": ["vite-plugin-pages/client"]
}

Related

How to use Environment Variables inside Vue3+Vite component library?

I have created a component as part of my component library that I am building with Vue3 and Vite. Everything works well, except when I try to use environment variables. I want the app that consumes this component library to be able to provide the component with environment specific data.
I have played around and found that if I have a .env file as part of the component library project, I am able to access those variables, but I want to be able to provide that during runtime and not during build time.
Here is my vite.config.ts
import { defineConfig } from "vite";
import { resolve } from "path";
import vue from "#vitejs/plugin-vue";
import dts from "vite-plugin-dts";
export default ({ mode }) => {
return defineConfig({
optimizeDeps: {
exclude: ["vue-demi"],
},
plugins: [
vue(),
dts({
insertTypesEntry: true,
}),
],
server: {
open: true,
},
build: {
lib: {
entry: resolve(__dirname, "src/lib.ts"),
name: "complib",
fileName: "complib",
},
rollupOptions: {
external: ["vue"],
output: {
globals: {
vue: "Vue",
},
exports: "named",
},
},
},
});
};
The entry looks like:
import { App, install } from "vue-demi";
import TestComp from "./components/TestComp.vue";
import "./tailwind.css";
install();
export default {
install: (app: App) => {
app.component("TestComp", TestComp);
},
};
export { Header };
And here is a minimal component TestComp.vue:
<script setup lang="ts">
import { onMounted } from "vue";
onMounted(() => {
console.log(import.meta.env.VITE_TEST_VAR);
});
</script>
<template>
<span>Test Comp</span>
</template>

Uncaught SyntaxError: The requested module '/node_modules/.vite/vue.js?v=535663ae' does not provide an export named 'default'

I'm using a js framework known as griptape(used for blockchain). I'm getting this error when trying to use the vue router.
import Vue from "vue"; //Error **does not provide an export named 'default'**
import VueRouter from "vue-router";
import Home from "../views/Home.vue";
Vue.use(VueRouter);
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"),
},
];
const router = new VueRouter({
routes,
});
export default router;
while my vue.d.ts file looks like this
import { CompilerOptions } from '#vue/compiler-dom';
import { RenderFunction } from '#vue/runtime-dom';
export declare function compile(template: string | HTMLElement, options?: CompilerOptions): RenderFunction;
export * from "#vue/runtime-dom";
export { }
router.d.ts file look like this
I think you are using Vue 3. You should check your vue-router version. If you just run npm i vue-router now, the version should be "^3.5.3". Try to use npm i vue-router#next to install newer version.
Then export router like this:
import {createRouter, createWebHistory} from 'vue-router'
const routes = [
{
path:'/',
name:"Home",
component:()=>import('./pages/Home.vue')
}
,
{
path:'/about',
name:"About",
component:()=>import('./pages/About.vue')
}
]
const router = createRouter({
history:createWebHistory(),
routes
})
export default router
You technically didn't ask a question I will try to explain the error. Your error states what you try to do, importing a default export from the module 'vue' which doesn't exist.
// some ts file
import Vue from "vue";
// the module
export default {}
If there should be a named export called 'Vue' you should write it as follows: import { Vue } from 'vue'
references:
https://www.typescriptlang.org/docs/handbook/modules.html#default-exports

How to add router with query param to router list?

I want to add a route with query params.
If the url is blog, then navigate to index page.
If the url includes the author query param, replace a component on the page with the BlogAuthorPage component.
router: {
extendsRoutes(routes, resolve) {
routes.push({
name: 'author-page-detail',
path: '/blog?author=*',
component: resolve(__dirname, 'pages/blog/author-page.vue')
})
}
}
This should not be done in nuxt.config.js's router key but rather in your blog.vue page directly with a component router guard.
The code below should be enough to check if the route does have a author query params and redirect to the blog/author-page page.
<script>
export default {
beforeRouteEnter(to, from, next) {
next((vm) => {
if (vm.$route.query?.author) next({ name: 'blog-author-page' })
else next()
})
},
}
</script>
I use "#nuxtjs/router": "^1.6.1",
nuxt.config.js
/*
** #nuxtjs/router module config
*/
routerModule: {
keepDefaultRouter: true,
parsePages: true
}
router.js
import Vue from 'vue'
import Router from 'vue-router'
import BlogIndexPage from '~/pages/blog/index'
import BlogAuthorPage from '~/pages/blog/author-page';
Vue.use(Router);
export function createRouter(ssrContext, createDefaultRouter, routerOptions, config) {
const options = routerOptions ? routerOptions : createDefaultRouter(ssrContext, config).options
return new Router({
...options,
routes: [
...options.routes,
{
path: '/blog',
component: ssrContext.req.url.includes('/blog?author') ? BlogAuthorPage : BlogIndexPage
}
]
})
}

Problems with the work of preloader vue.js

I'm trying to make showing preloader when i go from one component to another. I use this preloader. I create file loader.js and write there:
import Vue from 'vue';
import Loading from 'vue-loading-overlay';
import 'vue-loading-overlay/dist/vue-loading.css';
Vue.use(Loading);
let loader = Vue.$loading.show({
loader: 'dots',
color: '#5D00FF',
zIndex: 999,
});
function loaderStart() {
loader;
}
function loaderEnd() {
loader.hide();
}
export default {loaderStart, loaderEnd}
loader,js i import to the index.js and there i write when i want to call loader start but it does not starting(withoun if in beforeResolve preloader is working). Here is index.js:
import Vue from 'vue'
import Router from 'vue-router'
import Authorization from '#/components/Authorization'
import Main from '#/components/Main'
import loader from './loader'
Vue.use(Router)
const router = new Router({
routes: [
{
path: '/',
name: 'Main',
component: Main,
},
{
path: '/authorization',
name: 'Authorization',
component: Authorization
}
]
})
router.beforeResolve((to, from, next) => {
if(to.path) {
loader.loaderStart()
}
next()
});
router.afterEach((to, from) => {
loader.loaderEnd()
});
export default router;
Please, help me find the problem
Your current loader will appear just once because you called show method once as well. You need to invoke show method every loaderStart call and store the loader:
let loader = null;
function loaderStart() {
// it would be better to extract these values as constants
loader = Vue.$loading.show({
loader: 'dots',
color: '#5D00FF',
zIndex: 999,
});
}
function loaderEnd() {
loader.hide();
}
Probably you have some async components since you added loader to routing logic, so you should use the beforeEach hook instead of the beforeResolve one.
router.beforeEach((to, from, next) => {
loader.loaderStart()
next()
});
router.afterEach((to, from) => {
loader.loaderEnd()
});
Loader API docs (show method)
Vue-router guards
Vue-router navigation flow

Angular2.0 router works for components not modules?

I am trying to modify an existing angular app to fit into the structure of this Starter Project. Anyway, so I have my app module with a submodule (tutorial). Which looks like this:
When landing on the root domain and then navigating with the router links to http://localhost:3000/tutorial/chapter/0, everything works fine. However, if I refresh the page or try to go directly to that link, I get the error:
Unhandled Promise rejection: Template parse errors:
'my-app' is not a known element:
1. If 'my-app' is an Angular component, then verify that it is part of this module.
2. If 'my-app' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '#NgModule.schema' of this component to suppress this message. ("
<body>
[ERROR ->]<my-app>
<div class="valign-wrapper">
<div class="preloader-wrapper active valign"): a#30:4 ; Zone: <root> ; Task: Promise.then ; Value: Error: Template parse errors:(…) Error: Template parse
So I believe this is happening because rather than that url linking to the appcomponent, with the tutorial submodule as a child, it's just linking to the TutorialModule, and then the <my-app></my-app> tags from the index.html aren't recognised. This worked before, so I am not sure what aspect of this new configuration has broken this.
Here is my app.routes.ts:
import { homeComponent } from './components/home/home.component';
import { pluginsComponent } from './components/plugins/plugins.component';
import { Routes, RouterModule } from '#angular/router';
const appRoutes: Routes = [
{ path: '', component: homeComponent },
{ path: 'tutorial', loadChildren: 'tutorial/tutorial.module', pathMatch: 'prefix'},
{ path: 'plugins', component: pluginsComponent }
];
export const appRoutingProviders: any[] = [];
export const routing = RouterModule.forRoot(appRoutes);
and my tutorial.routes.ts:
import { Routes, RouterModule } from '#angular/router';
import { tutorialComponent } from './tutorial.component';
import { chapterComponent } from './chapter/chapter.component';
const tutorialRoutes: Routes = [
{
path: 'tutorial',
component: tutorialComponent,
children: [
{ path: 'chapter/:id', component: chapterComponent },
{ path: '', redirectTo: 'chapter/0', pathMatch: 'full'},
]
}
];
export const tutorialRouting = RouterModule.forChild(tutorialRoutes);
finally in my app.ts where I define the express routes I have:
app.all(/^\/tutorial$/, (req, res) => {
res.redirect('/tutorial/');
});
app.use('/tutorial/', (req, res) => {
res.sendFile(resolve(__dirname, '../public/index.html'));
});
to serve the angular index for the tutorial component.
The whole repo is here
The issue was the index.html file, I had <base href="."> where it should have been <base href="/">. I have a bug report here
#micronyks already said this in the comment but what you need to do a setup your web server to redirect all requests to your index.html page. Then your app will load and navigate to your "deep" link.