Closed hdodov closed 5 years ago
At least half an answer: You can get the Vue instance at window.panel.app
Yep, but only during my plugin's initialization. In my store.js at import time, for example, that property doesn't exist yet because the panel app doesn't exist yet.
I've found a hack to get it to work. I described it here. It would be awesome if you could schedule this fix in Kirby's next update. Two simple references to Vue and Vuex in window.panel
is all that is needed. They have to be present before the panel app is created, though.
Let's see - they still might not available during initialization of your plugin as the plugins are initialized before the panel/app.
Yep, but the panel app still has to import/require them, right? My idea is to immediately save a reference to those objects in the window
. In the panel's app.js:
import Vue from 'vue'
import Vuex from 'vuex'
window.panel = {
vue: Vue,
vuex: Vuex
}
// continue...
// initialize plugins
// initialize panel app
More specifically, this file.
Check out the commit in my fork. I believe that's all we need. I currently don't have the time to set up a dev environment and create a proper PR. But I believe that's all we need.
We need to test this thoroughly. My understanding so far has been that the plugins are initialized before anything else.
Yeah, but the initialization of anything else has nothing to do with the references to Vue and Vuex. They are just references. You don't need to initialize references. In my case, I needed a reference to Vuex because it has the Vuex.Store
constructor, and it doesn't depend on the initialization of anything Kirby-related. When my plugin uses panel.Vuex.Store
, the panel would be at the right part of its initialization process. panel.Vuex
is just a reference to the Vuex in the Kirby vendor bundle so that I can use that Vuex instead of importing my own.
It should be tested, no doubt, but in my mind, it should work.
Reply to: https://github.com/getkirby/kirby/pull/1576#issuecomment-473659818
I see now. I thought that the panel.plugin()
definition was somewhere in the main.js entry point where Vue and Vuex are.
The created()
extension would be useful, I think, but it might not solve this exact problem cleanly. You'll likely need the reference to Vuex when the plugin's index.js is executed, not when the plugin is initialized.
For example, in my plugin, I have store.js
:
export default new Vuex.Store({
...
})
in my App.vue
:
import store from './store'
export default {
store,
...
}
and in my index.js
:
import App from './App.vue'
panel.plugin({
component: App
...
})
When my index.js runs, it would import App.vue, which imports store.js, which then immediately exports a new Vuex store. This is where I'd need the reference to Vuex. I think it's long before the created()
hook you've implemented.
One solution I can think of is to expose Vuex in the vendors.js chunk since it's loaded before the plugins. I think that's possible with webpack? What I mean by that is to have all vendor code in that chunk with the addition of:
import Vue from 'vue'
import Vuex from 'vuex'
window.panel.Vue = Vue
window.panel.Vuex = Vuex
It still makes sense logically - app.js chunk would contain app related code, vendors.js would still contain vendor related code.
Actually, it might be good to expose all other dependencies of the panel as well. I can see that it also uses Vue Router, Sortable, autosize... what if a plugin needs those? It would be redundant to import your own versions of these dependencies if they're already there. On the other hand, if you do need a different release of these dependencies, you could still import whatever version you wish. But it would be great to have the flexibility to use the panel's dependencies. Aside from having a smaller bundle size, the panel and the plugin would also share the same state of their dependencies, which in my case with Vue and Vuex, is very important.
I could see the created()
hook helpful, but a perfect solution to the current problem would be to somehow expose the panel's dependencies in window
.
Edit: I also posted a question on StackOverflow.
I think the correct way to expose these objects would be expose-loader. Please, add this feature to Kirby in the next release. It opens a lot of possibilities.
The created
extension was merged on our features branch and will be in 3.2 https://github.com/getkirby/kirby/pull/1589#event-2330247254
I think your use case can be perfectly solved via e.g.
panel.plugin("distantnative/test", {
created: function (app) {
app.$store.registerModule("hello", {
namespaced: true,
actions: {
world(context) {
console.log("hi!");
}
}
});
}
});
I'm creating a plugin for K3 that uses Vuex. I have problems with it, though. You can find more in my forum post but to summarize - I believe the problem lies in my usage of a separate Vue and Vuex instance and not the same instances that the panel app uses.
I am forced to use separate instances because there's no apparent way I can call
Vuex.Store()
on the Kirby Vuex object. Right now, I import it from my plugin's node_modules, which is bad because the panel ends up with two different Vue and Vuex objects. If another similar plugin is loaded, there will be three and so on...My proposal is to expose the Vue and Vuex objects that Kirby uses so plugins can access them:
in Kirby's app.js:
or perhaps something like:
So if I need a Vuex store in my plugin, I would simply use: