This question comes from a Kirby CMS issue I am having. Here's a brief summary.
The Kirby panel uses Vue and Vuex and bundles them with Webpack (through Vue CLI). It has two chunks, vendors and app. People could also write plugins for that panel. The JS execution order is as follows:
vendors.js chunk
Plugins' JavaScript bundles (for instance, myplugin.js)
app.js chunk
The question is - how can myplugin.js reference the same Vuex as app.js? As I've described in my issue, there are problems with Vue if I use my own Vue and Vuex in myplugin.js. Since Kirby loads my Vue component in its own Vue instance, that component's store should use a Vuex Store bound to the same Vue instance, otherwise Vue's reactivity breaks.
We can't add the following in app.js:
import Vue from 'vue'
import Vuex from 'vuex'
window.KirbyVue = Vue
window.KirbyVuex = Vuex
because the app.js chunk is executed after myplugin.js. Therefore when imports in myplugin.js are resolved, references to KirbyVuex would not exist yet. So you couldn't do:
new KirbyVuex.Store({
...
})
because KirbyVuex would be undefined.
So apparently, those dependencies should be exposed in the vendors.js chunk. Is there a way that could happen? A plugin might need to use other panel dependencies aside from Vue and Vuex. It would be redundant to include them if they're already there. Also, it might be necessary for the plugin and panel to share the same dependency state, in which case using the same dependency is a requirement (as is my case here with Vuex).
Is there a way for the panel to expose its dependencies to the window object? It already creates window.panel which contains useful data for the plugins. Could it somehow add window.panel.vendors in there? Or perhaps just window.vendors? From there you'd be able to use new vendors.Vuex.Store(...) in the plugin.
Is there a functionality in Webpack that allows dependencies to be exposed to outside code?
Related
How should I structure my Vue CLI project? I am unable to find any proper documentation regarding this.
Basically I have around 10 modules and each module has a js file associated with it.
Currently, I am putting all the pages written in my router.js in views directory and all the components in the components directory. I want to know where should I keep mine js files?
All the js api calls associated with every module
JS files containing all the constants related to every module??
Q1: Usually API calls are stored under a respective store if you are using Vuex. If not you can use define them as mixins and use where necessary. The mixins are the parts of the javascript code that are reused in different components. In a mixin you can put any component’s methods from Vue.js they will be merged with the ones of the component that uses it.
Q2: This can definitely go under mixins.
You can also have a util folder (optional) where it contains the functions that you use in components, such as regex value testing, constants, or filters.
Refer to this boilerplate if your project is mid-scale or large-scale.
create a service folder,create service.js -api call goes here(now all you need is to call it when ever you need it)
you have a store folder with store.js(index.js) inside store folder create modules folder
with you modules. inside store.js create modules:[user,event...]
basically that's it. edit your modules files event.js user.js.
you can add getters,mutations,state,actions. just dont forget export const namespaced = true so it`ll go to the global namespace
I created an api. And for him, I created a one-page interface using vuecli. My plans are to embed it in the projects I need. The question is what needs to be done to export the written application and reuse it where necessary?
The structure of the project is shown in the screenshot.
src/main.js - connect and configure axios
src/App.vue - I describe the main component of the application
(maybe I need to put it in a separate component in the components
folder)
src/components/OneDay.vue is the second component that is mainly
called src/App.vue several times.
src/mixins/dateHandler.js - several functions common to the two
components, which are connected as mixins.
I have not modified any other files. How can I prepare this correctly so that I can connect these components to my other applications using composer? I connect, configure some variables (api address, for example) and display it in the right place on the page - this is how I see it.
You can try to create a web component using VUE CLI 3 to use it later in a different code base. Just make sure your main.js file looks like this
import Vue from 'vue';
import wrap from '#vue/web-component-wrapper';
import VueWebComponent from './components/VueWebComponent';
const CustomElement = wrap(Vue, VueWebComponent);
window.customElements.define('my-custom-element', CustomElement);
and build it using vue-cli-service build with --target wc
You can read more precise instructions there:
https://github.com/vuejs/vue-web-component-wrapper
https://vuejsdevelopers.com/2018/05/21/vue-js-web-component/
I have some reusable React components published to NPM, that I am installing and using within my React application. Is it possible for me to set an alias in my React app, that can be used within these NPM components? For example, I want to allow the use of a folder common, which is within my React App, within the React components. So if I do this in my React components, it should work
import someVal from 'common';
I am bundling these React components with Webpack, and sending down the transpiled, bundled version for use within the React application. I tried setting the alias the regular way within the React app webpack config (by setting resolve.alias), but it does not work. Can this be done? Or am I approaching this incorrectly? Any suggestions would be great, thanks!
Edit: So the React components from NPM are within my node_modules folder, and it is already bundled up via it's own Webpack config. I then run these components through my React application Webpack config as well (I'm whitelisting the folder), in the hopes that the new common alias will be added there. But no luck. I keep getting a
someVal is undefined error.
My common file has the following: Ignore the logic for now (I'm only posting a part of the code)
import _myClass from '../components/MyClass';
const myClass = _myClass; // Other things are done to it
export default myClass;
In my React components Webpack bundle file (after I fixed the default import statement)
/* harmony import */ var common__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! common */ "./src/common/index.js");
...
return common__WEBPACK_IMPORTED_MODULE_25__["default"].myFunction({
...
});
This still seems to be looking for common within the React components package, and not within the React app package that I am trying to use this in.
I need to import a Vue component asynchronously by the full URL opposed to relative URL. The following example taken from the VueJS documentation works just fine for components within the same project
Vue.component(
'app-component-one',
() => import('./component-from-app-one')
)
However, my goal is to import components from a separate project that's deployed on the same server. I was hoping I could use the full URL and do something like...
Vue.component(
'app-component-two',
() => import ('http://sample-domain.com/project-2/components/component-from-app-two.vue')
)
but it results in and error:
This dependency was not found:
* http://sample-domain.com/app-2/components/component-from-app-two.vue in ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0&bustCache!./src/components/SampleComponent.vue
Is importing components by full URL possible? Thanks in advance!
The example you referenced from the Vue website is leveraging the code-splitting functionality from WebPack, so it will NOT work to load files that are not part of the same project.
What you are trying to do is typically called "dynamic/asynchronous ES6 module loading". Not to get too deep in to it.. but the current import blah from X only support static imports. If you care more about the nitty-gritty details of this.. there is a TC39 proposal for dynamic imports in JS
In the mean time... us mortals have to depend on tools like SystemJS which will do exactly what you are asking for.
But like #divine mentioned... you need some type of build-process that generates the stand-alone Vue component. You can use either WebPack or RollUp to export it as a UMD and the use SystemJS to import that component by referencing the full URL (you could even import it from a different domain! assuming that domain supports CORS)
This Meteor template code is the default generated when meteor create myApp is invoked. In main.js the first 3 lines are:
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import './main.html';
But when I comment them out, the app still runs. Reading the docs could not answer my question, Why do we need the import statement if the app still runs without them? Thanks
Earlier versions of Meteor relied heavily on using the global namespace for accessing shared libraries. As of Meteor 1.3, you can now use Meteor's ES2015 module support. This means you can use import/export functionality to expose access to various parts of your codebase, without having to rely on globals. Using imports/exports is now the preferred/recommended way of referencing parts of your application, so meteor create functionality was updated to demonstrate this. As you mentioned, you can remove the import statements above and you will still be able to access Template and ReactiveVar globally (for backwards compatibility). It's important to note however that this might change in the future - Meteor has fully embraced ES2015 module support, and could potentially drop the use of globals completely (well, to the extent possible).
One more thing to note - Meteor 1.3 also introduced new "lazy-loading" functionality, wherein application code stored under an /imports directory will no longer by eagerly loaded when the application starts up. Code stored under an /imports directory will only be loaded if it's referenced by an import statement somewhere else in your codebase. See Special directories for more info.