0👍
For people struggling with this, here is a solution:
https://vuejs.org/api/application.html#app-config-warnhandler
You can use this handler to notify when a missing component is rendered. Warnings only work during development, so this config is ignored in production mode. In my case, since I use quasar, I made a plugin in src/boot
, which receives the Vuejs app object, and added the following code:
app.config.warnHandler = (msg: string, instance: ComponentPublicInstance | null, trace: string): void => {
if (msg.includes('Failed to resolve component')) {
alert(`⚠️ ${msg}\nNothing will be rendered at its place.\n${trace}`)
}
}
I don’t know how to place something in the DOM instead of the object, but an alert is good enough. Saved plenty of lives since then 😉
1👍
It’s quite easy to solve this with a rollup plugin.
The plugin could be written right inside vite.config.js. Or move it to a separate module.
Here you use the rollup hook resolveId
. The Vite/Rollup calls this hook when it cannot resolve an import.
Than use the load
hook to provide a fake component that would issue the error into the console and display it on the page:
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
{
resolveId(id) {
if (id.endsWith('.vue')) {
return 'MissingPlaceholder.vue?id=' + id;
}
},
load(id) {
if (id.includes('MissingPlaceholder.vue')) {
const missing = id.match(/(?<=\?id=).+$/)[0];
return `
<script setup>
console.error('Component "${missing}" is missing!');
</script>
<template>
<div style="background:yellow;color:red">Component "${missing}" is missing!</div>
</template>
`;
}
}
}
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
App.vue
<script setup>
import HelloWorld from './components/HelloWorld.vue'
import TheWelcome from './components/TheWelcome.vue'
import MissingComponent from './components/MissingComponent.vue'
const src = 'x" onerror="alert(\'busted\')"';
</script>
<template>
<header>
<img alt="Vue logo" class="logo" :src="src" width="125" height="125" />
<div class="wrapper">
<HelloWorld msg="You did it!" />
<MissingComponent />
</div>
</header>
<main>
<TheWelcome />
</main>
</template>