Improve WebStorm (and potentially other tools) support
See original GitHub issueSome Background
I have only recently jumped into the vue.js world and the first thing that I noticed, coming from angular, was the effort required to get my tools working. This boils down to how versatile vue is when it comes to declaring components, plugins, etc. Basically, As long as you call Vue.component(...)
, you’re golden. They don’t tell you how you should call it; only that you have to.
When I tried to add bootstrap-vue to my project, I quickly noticed that WebStorm would complain about unknown components, which means no auto-completion and warnings everywhere. I tried switching to the plugin import method, which I wanted to use from the start so that I don’t import everything for no reason… Same thing! Still no tooling support.
I dug down into WebStorm issues and I finally understood how they detect components… They added one additional assumption, based on most vue examples, to how the Vue.component
function should be called: the arguments passed to the call must be known statically. This makes a lot of sense when you think about it. How can a tool know about which component is registered if it can’t guess its name and source object just by looking at the code?
The Problem
Now to the heart of this issue. This project uses a utility method named registerComponents
which get passed a map of components to register. I do not know if it provides other gains than avoiding calling Vue.component
over and over again, but I do know that this call is always going to cause trouble for tools that needs to know which component is registered.
Because of this function, it is impossible for tools to know what will be passed to vue unless they actually run the code, which is prohibitively slow when we’re talking about auto-completion in a constantly changing code-base.
The Workaround
It is possible to get these tools to work by either fake registering components in a file that isn’t even imported, like vuetify is doing, or by writing this file by hand, like some people suggested in the WebStorm support forums. This solution implies either generating code in my project for one of my dependencies or typing a lot of code by hand… not very great.
An other solution is to manually register every component in my project by following your “importing individual components” instructions. In this case, I open myself to a lot of pitfalls when it comes library updates and potentially other dependencies that needs to be loaded in the right order…
Either way, I feel that these solutions are really painful to manage and should ultimately really be handled by the vue plugin system. Why have a plugin system if adding tooling to your project makes it useless?
My Take On This
Please take everything I am going to write in this section with a grain of salt. I have less than 4 hours of experience using this library, and less than 40 hours in the vue.js world. I might be completely wrong with this.
I think that to ensure that tools that needs to know about your components, like WebStorm, works to their best of their capability, this library needs to publish statically parsable plugins. This could be done through code generation, or by simply inlining/unrolling the registerComponents method calls by hands.
In other words, I think that your plugins should look like this:
// imports...
var VuePlugin = {
install: function install(Vue) {
Vue.component('bContainer', bContainer);
Vue.component('bRow', bRow);
Vue.component('bCol', bCol);
Vue.component('bFormRow', bFormRow);
}
};
vueUse(VuePlugin);
export default VuePlugin;
Notice that you can still pass in vue as a parameter. No need to import it. These tools are really not that sophisticated… they just need you to call Vue.component
, they don’t even care if its a real Vue
instance.
Conclusion
I understand that changing this kind of thing can be breaking or time consuming and I don’t expect a fix for this problem soon. I am more trying to start a discussion about how plugins should be packaged. I am also curious as to what is the reason behind the plugin pattern that bootstrap-vue uses.
Any reason why my example wouldn’t work? In the mean time, what is your recommendation on the best approach to use your library: Should I stick to plugins or prefer single component imports?
Issue Analytics
- State:
- Created 5 years ago
- Reactions:1
- Comments:6 (2 by maintainers)
Top GitHub Comments
This is still an issue in IntelliJ even after the latest update.
@kawazoe JetBrains is aware of this problem and they are trying to improve that. Source
I tested it in PhpStorm and autocomplete etc. doesn’t work there either. Vuetify or Buefy work fine out of the box. The way Vuetify is registering the components is also dynamic (webpack require.context): https://github.com/vuetifyjs/vuetifyjs.com/blob/dev/src/components/index.js#L17
@mosinve I did some quick tests with BootstrapVue, Vuetify and Buefy. I registered a test component inside each library’s
install
function insrc/index.js
orsrc/index.ts
respectively e.g.:After restarting WebStorm/PhpStorm and invalidating the cache, autocomplete picked up the test component for Vuetify and Buefy. Then I added the test component to every
.js
file defined as an entry point in thepackage.json
but the results were the same.