Vuejs 3 - what's the alternative of require.context in vitejs - vue.js

I'm looking for way to make the same logic of require.context of webpack in vitejs, I've found this plugin named vite-plugin-import-context, I tried it out but there's something that I didn't understand which is import dynamicImport from '../src/index' in the basic usage :
import { UserConfigExport } from 'vite';
import vue from '#vitejs/plugin-vue';
import dynamicImport from '../src/index';// <-- this is not described
export default (): UserConfigExport => {
return {
plugins: [vue(), dynamicImport(/*options*/)],
};
};

require should never be used in source code when using Vite. It's ESM only.
For Vite v2, import.meta.globEager can be used.
For Vite >v2, import.meta.globEager is deprecated. Use import.meta.glob('*', { eager: true }) instead.

import.meta.glob() is webpack alternative of require.context() . It has been added in vite since v2.3.4 .
Here is a link to the doc https://vitejs.dev/guide/features.html#glob-import

Yep, that example is directly taken from examples folder in the repo so it works only in that repo.
If you install the plugin via npm or yarn, the line should look like import dynamicImport from 'vite-plugin-import-context'

Here is how I import all the plugins/modules:
main.ts
import { createApp } from 'vue';
import App from './App.vue';
const app = createApp(App);
// styles here
import '#/assets/styles/tailwind.css';
import '#/assets/styles/main.scss';
// install all modules under `modules/`
Object.values(
import.meta.glob<{ install: (ctx: any) => void }>('/src/modules/*.ts', { eager: true })
).forEach((module) => module.install?.(app));
app.mount('#app');
and here is how I keep things ready in my modules folder to export:
modules/pinia.ts
import { createPinia } from 'pinia';
export const install = (app: any) => {
app.use(createPinia());
};
modules/router.ts
import type { RouteRecordRaw } from 'vue-router';
import { createRouter, createWebHashHistory } from 'vue-router';
import generatedRoutes from '~pages';
import { setupLayouts } from 'virtual:generated-layouts';
const routes: RouteRecordRaw[] = setupLayouts(generatedRoutes);
const router = createRouter({
history: createWebHashHistory(),
routes,
});
export const install = (app: any) => {
app.use(router);
};

Related

Remove default font in quasar without quasar config

I have successfully added my font to my Quasar project. Only this is not visible because the old font still overwrites it. I've read the documentation(https://quasar.dev/style/typography#default-font) about removing Roboto font but this only applies to quasar.config file which I don't have. Only vite.config.js And I can't get the font removed there. So my question is how can I delete a simple font in the right way.
This is my main.js at the moment.
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from "./router"; //router
import { createPinia } from "pinia"; //state managment
import { Quasar } from 'quasar'
import iconSet from 'quasar/icon-set/svg-line-awesome'
import '#quasar/extras/line-awesome/line-awesome.css'
import 'quasar/dist/quasar.css'
import { i18n } from './lang/i18n' //lang
createApp(App).use(i18n).use(createPinia()).use(router).use(Quasar,{plugins: {},lang: quasarLang, iconSet: iconSet, extras: []}).mount("#app");
According to documentation, you can supply Quasar options to Vite config. Like so:
// FILE: vite.config.js
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
import { quasar, transformAssetUrls } from '#quasar/vite-plugin'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue({
template: { transformAssetUrls }
}),
quasar({
sassVariables: 'src/quasar-variables.sass',
extras: [
'roboto-font'
]
})
]
})

How to use Axios globally using composition API

I'm having trouble getting Axios to work using the composition API. The following is what I've done, but I'm unsure how to access Axios within setup(). I'm aware that the "this" keyword is no longer available in the composition API.
Created an axio.js file in /plugins:
import axios from 'axios'
export default {
install: (app, options) => {
app.config.globalProperties.axios = axios.create({
baseURL: options.baseUrl,
withCredentials: true,
headers: {
Authorization: options.token ? `Bearer ${options.token}` : '',
}
})
}
}
Added it to plugins/index.js
import { loadFonts } from './webfontloader'
import vuetify from './vuetify'
import pinia from '../store'
import router from '../router'
import axios from './axios'
export function registerPlugins (app) {
loadFonts()
app
.use(vuetify)
.use(pinia)
.use(router)
.use(axios, { baseUrl: import.meta.env.VITE_AXIOS_BASE_URL })
}
Then the main.js file registers all plugins:
import App from './App.vue'
// Composables
import { createApp } from 'vue'
// Plugins
import { registerPlugins } from '#/plugins'
const app = createApp(App)
registerPlugins(app)
app.mount('#app')

Error: vue-composition-api No vue dependency found

I am having an issue with vue-composition-api.
I have included it in my main.ts as an include like this:
import "./registerServiceWorker";
import Vue from "vue";
import "./_core/plugins/composition-api";
import "./_core/plugins/global";
import "./_core/plugins/cloudinary";
import "./_core/plugins/gtm";
import { provide } from "#vue/composition-api";
import { ApolloClients } from "#vue/apollo-composable";
import vuetify from "./_core/plugins/veutify";
import contentfulClient from "./_core/plugins/vue-apollo-contentful";
import apiClient from "./_core/plugins/vue-apollo-api";
import VAnimateCss from "v-animate-css";
import App from "./app.component.vue";
import router from "./router";
import store from "./store";
Vue.config.productionTip = false;
import Meta from "vue-meta";
Vue.filter("formatPrice", function (value: string | number) {
if (typeof value !== "number") {
return value;
}
const formatter = new Intl.NumberFormat("en-GB", {
style: "currency",
currency: "GBP",
minimumFractionDigits: 2,
});
return formatter.format(value);
});
import "./scss/_core.scss";
Vue.filter("time", function (value) {
const date = new Date(value);
const options = {
timeZoneName: "short",
hour: "2-digit",
minute: "2-digit",
};
// eslint-disable-next-line
return date.toLocaleTimeString("en-GB", <any>options);
});
Vue.use(Meta, {
keyName: "head",
});
Vue.use(VAnimateCss);
new Vue({
router,
store,
vuetify,
setup() {
provide(ApolloClients, {
default: apiClient,
apiClient,
contentfulClient,
});
},
render: (h) => h(App),
}).$mount("#app");
compoistion-api.ts looks like this:
import Vue from "vue";
import vueCompositionApi from "#vue/composition-api";
Vue.use(vueCompositionApi);
This compiles, but in my application I see this error:
When digging deeper, I can see that it's complainling about my graph-query.ts script, which is imported in my get-metadata.ts script and in-turn is imported in app.component.ts.
I thought the main.ts file is imported first, so it should use composition-api before the app is mounted? Am I missing something here?
Let me know if you need more information
For anyone stumbling upon this: it might be because the composition API plugin is not initialized before using the API.
From a related github issue:
I had the same issue, it's because you are declaring any reactive elements (ref() / reactive()) before the plugin is installed in your Vue instance.
You can fixing by calling Vue.use(VueCompositionAPI) before importing any of your components/store

Failed to resolve component: amplify-s3-image , but it actually works

I get this warning in my Chrome Console:
runtime-core.esm-bundler.js?d2dd:38 [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.
and then this warning:
[Vue warn]: Failed to resolve component: amplify-s3-image
If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.
But the component actually works, since it shows the image from S3 how it's supposed to.
This is what my main.js looks like:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import Amplify from "aws-amplify";
import AmplifyVue from '#aws-amplify/ui-vue';
import store from './store'
import awsconfig from './aws-exports';
import aws_exports from './aws-exports';
import { applyPolyfills, defineCustomElements } from '#aws-amplify/ui-components/loader';
Amplify.configure(awsconfig);
//Amplify.configure(aws_exports);
applyPolyfills().then(() => {
defineCustomElements(window);
});
const app = createApp(App).use(router).use(store).use(AmplifyVue)
app.config.compilerOptions.isCustomElement = tag => tag.startsWith('amplify-');
app.mount('#app');
and this is in my vue.config.js:
const { defineConfig } = require('#vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true
},
)
module.exports = {
chainWebpack: config => {
config
.plugin('html')
.tap(args => {
args[0].title = "Opensquare";
return args;
},options => {
options['compilerOptions'] = {
...options.compilerOptions || {},
isCustomElement: tag => tag.startsWith('amplify-')
}
return options;
})
}
}
What am I doing wrong? It's not blocking, since the component actually works, but reading the Console with this WARN popping up is a nightmare.

Vue-test-utils loading dependencies - Vue3

I'm developing some tests for single file components in VueJs. These components use font-awesome.
This is my App, as you can see I have fontawesome available for all child components.
import { createApp } from 'vue';
import App from './App.vue';
import "bootstrap/dist/css/bootstrap.min.css";
import "bootstrap";
import { FontAwesomeIcon } from '#fortawesome/vue-fontawesome';
import { fas } from "#fortawesome/free-solid-svg-icons";
import { library } from '#fortawesome/fontawesome-svg-core';
library.add(fas);
createApp(App)
.component("font-awesome-icon", FontAwesomeIcon)
.mount('#app');
Here's a test
import { mount } from '#vue/test-utils'
import ListComponent from '#/components/ListComponent.vue'
import { FontAwesomeIcon } from '#fortawesome/vue-fontawesome';
let someData = [{
name: 'Some person name',
key: '2222222',
moreInfo: [
{title: 'aa'},
{title: 'bb'},
]
},
{
name: 'Some other person name',
key: '12321123,
moreInfo: [
{title: 'cc'},
{title: 'x'},
]
},
}];
let wrapper = mount(ListComponent, {
propsData: {
someData
},
stubs: {
'font-awesome-icon': FontAwesomeIcon
}
});
describe('ListadoImputados.vue', () => {.... tests ....});
Test details are not important, I don't know how to add / include font-awesome-icon in the context so i can avoid getting the following warnings
console.warn node_modules/#vue/runtime-core/dist/runtime-core.cjs.js:40
[Vue warn]: Failed to resolve component: font-awesome-icon
I tried adding this dependency as a mock and stub but no luck. Also importing Fontawesome at the top of the file does not work, the warning is still showing. I was thinking maybe in creating a vue app in the test file and inject the component like this
createApp(App)
.component("font-awesome-icon", FontAwesomeIcon)
.mount('#app');
but I'm copying and pasting code and I'm not sure this is the right way.
Is there a way to add this dependencies to my test context?
I'm using Vue 3, vue-test-utils + jest
In Vue Test Utils v2 (for Vue 3), the stubs mounting option is moved into global.stubs. Also note that a stub does nothing by definition, so stubbing the component only requires providing the component name.
Your mounting options should look like this:
const wrapper = mount(ListComponent, {
global: {
stubs: ['FontAwesomeIcon']
}
})
If for some reason you need the actual component, you could technically provide the component definition as a "stub", but you'd also need to initialize the icons for it as you would in the app's startup:
// assume only `faUserSecret` icon used in `ListComponent`
import { library } from '#fortawesome/fontawesome-svg-core'
import { faUserSecret } from '#fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '#fortawesome/vue-fontawesome'
library.add(faUserSecret)
//...
const wrapper = mount(ListComponent, {
global: {
stubs: { FontAwesomeIcon }
}
})