-
-
Notifications
You must be signed in to change notification settings - Fork 8.6k
Global API Change #30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Concerning Adoption strategies: The compatibility build won't be able to provide complete compatibility in this regard, since an "old" app would still try and use the global constructor to do mixins etc., right? |
Will we do a separate RFC for provide/inject as a whole or are we planning to keep the |
Will it break the auto-installation feature like <script src="/path/to/vue.js"></script>
<script src="/path/to/vuex.js"></script> If I don't misunderstand we couldn't "install" or "use" a feature before an app created. Does it mean this kind of global installation would be banned? Thanks. |
And currently |
@Jinjiang yes, this is a breaking change and it will break auto installation. If we still allow implicit global installation it would make this change pointless. |
Hm. Would the Plugin API (install function receiving the/a Vue constructor) be the same though? I don't want to break every plugin in the whole ecosystem :( |
@LinusBorg most plugins should be able to remain unchanged, with some exceptions:
|
Couldn't we try and find some middle ground for 3.0 and just deprecate it and then drop this in 4.0? Maybe something like this:
This would ensure backwards compatibility while giving people the possibility of using the new api in their apps if they want to keep the plugins local to their app instance. |
but what is the deal with global plugin install? it only worked while prototyping |
Not sure what you mean. I'm sure there are a ton of production apps out there that use Vue in server-rendered pages and include it from a CDN, along with plugins:
Sure, people have to upgrade their dependency and some code anyways, but the point is that this requires the plugin author to upgrade their plugin's code to work with Vue 2 and 3 differenty, and add documentation about this etc. In short: It's another thing plugin authors have to do to ensure Vue 3 compatiblity, and it's not done by just compiling a new bundle with the new template compiler and correcting a few little things in the code, now they need to update docs as well etc. I think this is one of those things that we should deprecate and not just take away from people, as I generally have a bad feeling about potentially underestimating the amount of churn pain we will be inflicting on people with all of the things we are changing. |
@LinusBorg I think a middle ground (as included in the public RFC) is to provide stubs that emit warnings for these moved methods. For example if a plugin calls |
Summary
Re-design app bootstrapping and global configuration API.
Basic example
Before
After
Motivation
Vue's current global API and configurations permanently mutate global state. This leads to a few problems:
Global configuration makes it easy to accidentally pollute other test cases during testing. Users need to carefully store original global configuration and restore it after each test (e.g. resetting
Vue.config.errorHandler
). Some APIs (e.g.Vue.use
,Vue.mixin
) don't even have a way to revert their effects. This makes tests involving plugins particularly tricky.vue-test-utils
has to implement a special APIcreateLocalVue
to deal with thisThis also makes it difficult to share the same copy of
Vue
between multiple "apps" on the same page, but with different global configurations:Detailed design
Technically, Vue 2 doesn't have the concept of an "app". What we define as an app is simply a root Vue instance created via
new Vue()
. Every root instance created from the sameVue
constructor shares the same global configuration.In this proposal we introduce a new global API,
createApp
:Calling
createApp
with a root component returns an app instance. An app instance provides an app context. The entire component tree formed by the root instance and its descendent components share the same app context, which provides the configurations that were previously "global" in Vue 2.x.Global API Mapping
An app instance exposes a subset of the current global APIs. The rule of thumb is any APIs that globally mutate Vue's behavior are now moved to the app instance. These include:
Vue.config
->app.config
Vue.config.productionTip
Vue.component
->app.component
Vue.directive
->app.directive
Vue.filter
->app.filter
Vue.mixin
->app.mixin
Vue.use
->app.use
Global APIs that are idempotent (i.e. do not globally mutate behavior) are now named exports as proposed in Global API Treeshaking.
Mounting App Instance
The app instance can be mounted with the
mount
method. It works the same as the existingvm.$mount()
component instance method and returns the mounted root component instance:Provide / Inject
An app instance can also provide dependencies that can be injected by any component inside the app:
This is similar to using the
provide
option in a 2.x root instance.Drawbacks
Global APIs are now split between app instance methods and global named imports, instead of a single namespace. However the split makes sense because:
App instance methods are configuration APIs that globally mutate an app's behavior. They are also almost always used together only in the entry file of a project.
Global named imports are idempotent helper methods that are typically imported and used across the entire codebase.
Alternatives
N/A
Adoption strategy
Unresolved questions
Vue.config.productionTip
is left out because it is indeed "global". Maybe it should be moved to a global method?The text was updated successfully, but these errors were encountered: