Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I fail a Vue.js build on unregistered components?

Consider the following component template...

<template>
  <Unknown></Unknown>
</template>

...where Unknown may or may not be a globally registered component. At runtime, I'll encounter this informative error:

[Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.

[...]

However, for my use case, I'd like to enforce that no such occurrences such as this happen at build time. Currently, vue-cli-service build performs a successful build in this scenario, and then reveals the error at runtime (useless at this point).

I'm curious if there is a way to introspectively capture this potential problem and force a build failure. I was hoping to discover a --strict flag (or the like) that disallows situations such as this.

I've even experimented with the template-compiler and the component-compiler to see if I could catch it on a manual inspection, and shockingly no errors were reported.

Any ideas?


Here is my mentioned experiment in more detail using the even lower level component-compiler-utils. This should be portable to observe the same results. Notice how both error reporting fields are empty!

"dependencies": {
  "@vue/component-compiler-utils": "3.0.0",
  "vue-template-compiler": "2.6.10"
}
[...]
const ccu = require('@vue/component-compiler-utils');
const vtc = require('vue-template-compiler');

const file = `
<template>
  <div class="component">
    <Unknown></Unknown>
  </div>
</template>

<script>
  export default {
    name: 'Component',
    data: function () {
      return {}
    },
  }
</script>

<style scoped lang="scss">
  .component {
    width: 100px;
    height: 100px;
  }
</style>
`;

const parsed = ccu.parse({
  compiler: vtc,
  source: file,
  needMap: false
});

const compiled = ccu.compileTemplate({
  compiler: vtc,
  source: parsed.template.content,
});

console.log('parsed | errors', parsed.errors);     // [] empty!
console.log('compiled | tips', compiled.tips);     // [] empty!
console.log('compiled | errors', compiled.errors); // [] empty!
like image 803
scniro Avatar asked Aug 22 '19 18:08

scniro


2 Answers

I'm sorry to say that I think the answer is that this is not possible. Please review the Component Registration section of the documentation for the background information related to my explanation.

Since:

  1. Components can be registered dynamically (Vue.component('MyComponent', { /* ... */ }) at any time during the lifetime of a Vue application.
  2. Components can be added by plugins and even asynchronously after initialization.
  3. Components can be used dynamically.
  4. Component names are simple strings as opposed to some form of enum or equivalent "fixed" registry of allowed names in the application.

There is no general way for a code analyzer to achieve what you ask. Considering the above, I'm not surprised that none of the options you tried report errors. Indeed the opposite would be surprising because it would not work with components registered by plugins. Really, there is no other way to know before run-time if a named component is available or not.

That said, I tried writing a unit test that instantiates a component that uses an unknown component. I get the same "Unknown custom element..." warning in the console, but since nothing is thrown, the test does not fail! Bummer... I took a peek at the source code for that warning and unfortunately nothing is registered anywhere to record the missing component.

Another option is to do that unit test that mounts the component and then check via vm.$refs or DOM elements whether the desired component was actually rendered. It seems like a big hassle though and a lot of maintenance.

But, I think I found a nice hook to get the warning! Check out Vue.config.warnHandler. You can add a warnHandler in the test that mounts the component and checks that no warnings about missing elements are emitted.

like image 197
bernie Avatar answered Oct 19 '22 22:10

bernie


You can try pre-rendering couple of routes and check for errors on those pages. Probably you can't be 100% sure but at least you can cover most important pages.

This plugin might come handy to do that: https://www.npmjs.com/package/vue-cli-plugin-prerender-spa

like image 26
Doğancan Arabacı Avatar answered Oct 19 '22 23:10

Doğancan Arabacı