Is there a way to import a folder structure in Vite - vue.js

I have a bunch of sub-folders plus a few .vue components in the src/pages folder. With webpack I was able to get a list of the page paths and name with code like this:
export default require
.context("../pages", true, /^\.\/.*\.vue$/)
.keys()
.map(page => page.slice(2).replace(".vue", ""))
.filter(page => page !== "Index")
.map(page => ({
file: page,
title: createTitle(page),
path: slugify(kebabCase(page))
}));
Vite doesn't seem to support this. I tried const pages = import.meta.glob('../pages/*.vue') but this only works for files, not files inside sub-folders.
Any idea how I can achieve this with Vite?

I found a way. It's not perfect but not terrible either:
const pages = import.meta.glob('../pages/*.vue')
const folders = import.meta.glob('../pages/*/*.vue')
const both = {...pages, ...folders}
export default both
This is a refinement:
const pages = import.meta.glob('../pages/**/*.vue')
export default pages

I think you're looking for something like vite-plugin-pages :
installation :
npm install -D vite-plugin-pages
which requires vue-router to be installed :
npm install vue-router
Add to your vite.config.js:
import Pages from 'vite-plugin-pages'
export default {
plugins: [
// ...
Pages(),
],
}
Router config :
import { createRouter } from 'vue-router'
import routes from '~pages'
const router = createRouter({
// ...
routes,
})
There're also other plugin like unplugin-vue-components to resolve components and vite-plugin-vue-layouts to resolve layouts

Related

Error to deploy my Vue3 app to Github Pages

I have uploaded my project with Vue3 to Github pages (check my repository), the branch is assigned to gh-pages and I have also uploaded the /dist folder, generated with the:
npm run build command.
I also modified the vue.config.js file with this data from my repository:
const { defineConfig } = require('#vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
publicPath: process.env.NODE_ENV === "production" ? "/pokevue/" : "/"
})
I have two questions:
The first is why isn't Vue working/loading in my web, if I followed the instructions in this guide correctly.
The second one is why this route does not show the "home" (it is broken, of course):
https://amoralesdesign.github.io/pokevue/
But when you click on the Pokémon logo it does redirect to my real Home, although if you reload the page it gives a 404.
You need to config your base router points to your github page path:
const router = createRouter({
history: createWebHistory(process.env.NODE_ENV === 'production' ? '/pokevue/' : '/'),
routes
})
The reason when you click on the logo your home page is showing is that in that case, the vue router will match your URL with the home page route.

How to fix the asset file path in my Vue (Vite) application build?

I recently completed a small project in Vue, but when I uploaded it to my server, I am just seeing a blank screen. From my research, I discovered it was likely an issue relating to the asset path as I had it in a sub-directory (https://digitalspaces.dev/portfolio/wil/). After some time trying to fix it by editing the vite.config.js file, I gave up and decided to host it in a subdomain (https://wil.digitalspaces.dev/) instead, where it is now.
The problem is, the index.html now thinks the assets files are at https://digitalspaces.dev/portfolio/wil/assets/, which is true I suppose, but they don't seem to be working from there (nor should they be). Frustratingly, when the build is in https://digitalspaces.dev/assets/, the assets directory is https://digitalspaces.dev/assets/, so it's broken no matter where I have it.
I based my project on the Vue.js quick start guide using vite.
My complete repo is on GitHub, and this is the vite.config.js file:
import { fileURLToPath, URL } from 'url'
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
import vueJsx from '#vitejs/plugin-vue-jsx'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(), vueJsx()],
resolve: {
alias: {
'#': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
Thanks to anyone who is able to help.
The subdirectory on your site is /portfolio/wii/, so you should configure the base URL to match:
// vite.config.js
import { defineConfig } from 'vite'
export default defineConfig({
⋮
base: '/portfolio/wii/'
})

Using Stencil components with Ionic Vue

In the Stencil docs section on framework integration with Vue it states the following:
In order to use the custom element library within the Vue app, the
application must be modified to define the custom elements and to
inform the Vue compiler which elements to ignore during compilation.
According to the same page this can be achieved by modifying the config of your Vue instance like this:
Vue.config.ignoredElements = [/test-\w*/];
This relates to Vue 2 however. With Vue 3 (which Ionic Vue uses) you have to use isCustomElement as stated here.
Regretably, I can’t for the life of me get Vue and Stencil to play nice. I have tried setting the config like this:
app.config.compilerOptions.isCustomElement = tag => /gc-\w*/.test(tag)
This causes Vue throw the following warning in the console:
[Vue warn]: The `compilerOptions` config option is only respected when using a build of Vue.js that includes the runtime compiler (aka "full build"). Since you are using the runtime-only build, `compilerOptions` must be passed to `#vue/compiler-dom` in the build setup instead.
- For vue-loader: pass it via vue-loader's `compilerOptions` loader option.
- For vue-cli: see https://cli.vuejs.org/guide/webpack.html#modifying-options-of-a-loader
- For vite: pass it via #vitejs/plugin-vue options. See https://github.com/vitejs/vite/tree/main/p
However, I have no idea how to implement any of the above suggestions using Ionic Vue. I have been messing around with chainWebpack in config.vue.js but without success so far.
Any help would be greatly appreciated.
I'm not an expert in Vue but here's how I did it:
Add the following to your ./vue.config.js (or create it if it doesn't exist):
/**
* #type {import('#vue/cli-service').ProjectOptions}
*/
module.exports = {
// ignore Stencil web components
chainWebpack: config => {
config.module
.rule('vue')
.use('vue-loader')
.tap(options => {
options.compilerOptions = {
...options.compilerOptions,
isCustomElement: tag => tag.startsWith('test-')
}
return options
})
},
}
This will instruct Vue to ignore the test-* components. Source: https://v3.vuejs.org/guide/web-components.html#skipping-component-resolution
Next, load the components in ./src/main.ts.
Import the Stencil project:
import { applyPolyfills, defineCustomElements } from 'test-components/loader';
Then replace createApp(App).use(router).mount('#app') with:
const app = createApp(App).use(router);
// Bind the custom elements to the window object
applyPolyfills().then(() => {
defineCustomElements();
});
app.mount('#app')
Source: https://stenciljs.com/docs/vue
Also, if anyone is using vite2+, just edit the vite.config.js accordingly:
import { fileURLToPath, URL } from 'url'
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue({
template: {
compilerOptions: {
isCustomElement: tag => tag.startsWith('test-') // ✅ Here
}
}
}) ],
resolve: {
alias: {
'#': fileURLToPath(new URL('./src', import.meta.url))
}
}
})

Lazy Loading Components not working with Vue Router

When trying to lazy load components in my routes.js file, my CSS is not compiled.
When using an import statement at the top of the file, everything works as expected. There are no console errors or compile errors. I'm using Vue.js, Vue-Router, Laravel, and Laravel-Mix (all latest versions)
//Working (CSS is present)
import Home from '../../components/admin/Home';
//Not Working (No CSS is present)
function loadView(view) {
return () => import(/* webpackChunkName: "view-[request]" */ `../../components/admin/${view}.vue`)
}
//How I'm initializing the component
let routes = [
{
path: '/',
name: 'home',
component: loadView('Home'),
meta: {
requiresAuth: true
}
}]
//Laravel Mix Config
const mix = require('laravel-mix');
const webpack = require('webpack');
mix.js('resources/js/apps/registration/app.js', 'public/js/apps/registration/app.js')
.js('resources/js/apps/admin/app.js', 'public/js/apps/admin/app.js')
.js('resources/js/material-dashboard.js', 'public/js/material-dashboard.js')
.js('resources/js/material-dashboard-extras.js', 'public/js/material-dashboard-extras.js')
.sass('resources/sass/app.scss', 'public/css');
mix.webpackConfig({
plugins: [
/**
* Bug with moment.js library causing ./locale not to be found
* https://github.com/moment/moment/issues/2979
* Created an empty module running npm install --save empty-module and then doing the below
*/
new webpack.ContextReplacementPlugin(/\.\/locale$/, 'empty-module', false, /js$/),
/**
* Global objects are not getting recognized via require
* Set them up here
* global_name: path or module
*/
new webpack.ProvidePlugin({
/**
* There was an error with Popper not being defined due to Popper being included in Bootstrap
* https://github.com/FezVrasta/bootstrap-material-design/issues/1296
*/
'Popper': 'popper.js/dist/umd/popper'
})
]
});
Attached are screenshots of what I mean by CSS not being applied
How page looks with import
How page looks when trying to lazy load components in routes.js
You are not supposed to import the webpack chunk name, instead just reference the approriate path to the component like so:
//Not Working (No CSS is present)
function loadView(view) {
return () => import( `../../components/admin/${view}.vue`)
}
NB: not tested, hope it helps :)

How to use BugSnag inside of a nuxt.js app?

BugSnag provides a very useful and initially free product for tracking errors in your vue app. The problem is that there is no documentation for using this in a nuxt app. A plugin would be the best place to utilize it in the app.
Trying to resolve this was killing me for a while but I was able to find help from Patryk Padus from the comments on this post.
For anyone trying to make this happen, do the following:
1.Place the following code inside of a plugin located in the /plugins folder of your application root:
#/plugins/bugsnag.js
import Vue from 'vue'
import bugsnag from '#bugsnag/js'
import bugsnagVue from '#bugsnag/plugin-vue'
const bugsnagClient = bugsnag({
apiKey: 'YOUR-KEY',
notifyReleaseStages: [ 'production', 'staging' ]
})
bugsnagClient.use(bugsnagVue, Vue);
export default (ctx, inject) => {
inject('bugsnag', bugsnagClient)
}
2.Inside of the nuxt.config add the following to your plugins section:
plugins: [
'#/plugins/bugsnag.js',
],
3.Inside of your vue layout reference the bugsnag object using the $bugsnag object:
this.$bugsnag.notify(new Error('Nuxt Test error'))
If you're reading this in January 2021 and using Nuxt v2.x.x and above, the above answer might not work for you.
Here's what I did instead:
import Vue from 'vue'
import bugsnag from '#bugsnag/js'
import BugsnagVue from '#bugsnag/plugin-vue'
const bugsnagClient = bugsnag.start({
apiKey: process.env.BUGSNAG_KEY,
plugins: [new BugsnagVue()], // this is important
})
Vue.use(bugsnagClient) // // this is also important
export default (ctx, inject) => {
inject('bugsnag', bugsnagClient)
}
Tip: Install the #nuxt/dotenv module to be able to use process.env in your plugin.
References:
Bugsnag Vue installation reference