Subscribe on changes!

Export "setComponent" in @vue/runtime-core

avatar
Sep 16th 2021

What problem does this feature solve?

Vue's reactivity APIs are powerful and DX friendly, but also fairly framework agnostic (as far as I can tell). Likewise, Vue's composition API is powerful and DX friendly but is more integrated with Vue's component system.

While @vue/reactivity seems to work OOTB with other UI libraries, such as React, the composition API doesn't share those same benefits today due to its required integration into component lifecycles to work as-intended

As a result, there has been work trying to get the composition API working in other environments:

https://github.com/antfu/reactivue https://github.com/oceanbit/ngx-vue

However, both of these examples were implemented prior to the useEffect RFC was added in Vue 3.2. Because of this, both packages have had to entirely re-implement the composition system to add lifecycle methods and cleanup - mostly by the means of copying + pasting the code from vue-next and adding some minor changes.

https://github.com/antfu/reactivue/blob/master/packages/reactivue/src/watch.ts

This has led to duplicative code between the two projects that are hard to keep up with how quickly Vue is able to address bugs and add features to the Composition API

Luckily, because useEffect introduces the concept of being able to stop an effect and run them external to a Vue component - there's massive potential to remove this duplicative code for composition APIs such as watch and watchEffect:

https://github.com/oceanbit/vue-in-express-poc/blob/simple-demo/index.js

However, there's still a problem in terms of lifecycle hooks. Ideally, we could simply utilize @vue/runtime-core's code for management of assigning hooks to a "component" instance and libraries such as reactivue could simply call those hooks and cleanup as-needed.

While a bit hacked together, I was able to get this working (with one asterisk that I'll touch on in a moment) in an Express server example:

https://github.com/oceanbit/vue-in-express-poc/blob/main/index.js

The only problem is that in order to get this working, I had to utilize a function that's not accessible from the dist build: setCurrentInstance

https://github.com/oceanbit/vue-in-express-poc/

What does the proposed API look like?

Ideally, we could have setCurrentInstance exported from the dist build.

This API is exported within the component.ts file, but is not exported in the index.ts file (and therefore not shown within dist or elsewhere)

https://github.com/vuejs/vue-next/blob/master/packages/runtime-core/src/component.ts#L544

It's entirely understandable why this is - this is a sensitive API that, without proper understanding of internals, could do great damage. However, similar problems have been solved with namespacing sensitive functions, such as ssrUtils:

https://github.com/vuejs/vue-next/blob/master/packages/runtime-core/src/index.ts#L305-L312

Potentially we could do the same with setCurrentInstance?

There's very likely context in the codebase I'm not aware of with this request. If, after discussion, we decide on a different path to make the same end-goal (of implementing the composition API externally to Vue) is made and larger code changes are required, I'd be happy to contribute whatever I can.

avatar
Sep 16th 2021

TLDR, expose setCurrentInstance as public api in runtime

avatar
Oct 5th 2021

I would be happy to make a PR to add this export in runtime. Is this something I could potentially add?

If so, should it be under a namespace? What should it be?