Using vuex store with npm-link in vue-cli 3 project loses $store - vue.js

I think this is a config issue related to keeping store in an npm-linked folder.
I made a vue-cli 3 project and got the “counter” example running (from https://github.com/vuejs/vuex/tree/dev/examples/counter)
Works: When I move the store.js to an installed node_modules package (and update its import url) it continues to work.
Breaks: When I move the store.js to an npm linked node_modules package it compiles and dev tools finds the store, but I get a blank screen and console error: Property or method “$store” is not defined on the instance but referenced during render
It also works properly with a linked package if I build the minimized js (npm run build). Is there a config setting I'm missing?

The problem turned out to be that the linked packages had its own node_modules folder. I think that may have resulted in webpack creating 2 instances of Vue and attaching the linked package to the 2nd instance.
Deleting the depended upon package's node modules and letting webpack / vue-cli run at the root level resolved my problem.

I realize this question is ridiculously old, but I ran into this exact issue. As deleting node_modules isn't a valid solution, here's what actually worked.
In the library you're importing into your main app, edit your package.json file.
You want to move Vue to be a peer dependency.
"dependencies": {
"vue": "^3.0.0" // move this
},
Move "vue" here.
"peerDependents": {
"vue": "^3.0.0"
},
This will cause your library to use the instance of Vue utilized by your main vue app. As the accepted answer states, this issue is indeed caused by each package loading its own Vue instance. The issue happens because reactivity is bound to the Vue instance. As each library gets its own instance, this creates a situation where reactivity isn't properly tracked between the instances.
I found the solution to this in the Vuejs git repo at https://github.com/vuejs/vue-cli/issues/4271

Related

vue-cli-service won't serve if using yarn link'ed package

I've got a private npm package hosted on GitHub. The package is essentially a Vue component and I build it with vue-cli-service build --target lib --name init-map src/main.ts. Here's the main.ts's contents:
import InitMap from "./components/InitMap.vue";
export { InitMap };
I use the package inside my other project, and I develop them both simultaneously. Therefore, I want to link the package: yarn link (inside the package directory), then yarn link #smellyshovel/init-map inside the consuming-project directory.
The problem is that when I run "yarn serve" (i.e. vue-cli-service serve) inside the main project, it freezes on 69%...
... and seems to stay like that forever.
Axios doesn't seem to be a problem to me (even though the message), since 1) everything is working fine without the linked package, 2) it shows a different message sometimes (something bootstrap-vue-related on 58%) though I only saw this other message like once (and not sure what exactly caused the difference).
What am I doing wrong? Why does the serve freezes when using a linked package as a dependency? How do I solve this?
Please, name me any other stuff you would like me to show since I'm not sure what exactly could be related to the issue and therefore haven't included any details that might be of interest.
OK, the problem indeed seems to be related to resolving symlinks, and the solution would be to simply prevent webpack from resolving these symlinks: https://github.com/vuejs/vue-cli/issues/1494#issuecomment-498144990
configureWebpack: {
resolve: {
symlinks: false,
},
}

Using yalc with Vue results in unknown element

I am using a third party component (vue-image-lightbox) which currently has a bug. I cloned the repo and made the change and want to deploy it with my app to see if it fixes the issue. To do this I installed yalc.
In the component project (vue-image-lightbox) I ran
npm run build
yalc publish
My understanding is that this places my vue-image-lightbox into the yalc store.
Next, I went to my dependent project and ran
npm uninstall vue-image-lightbox (remove the existing component)
yalc add vue-image-lightbox. This creates
a) .yalc directory with the deployed component
b) adds entry to package.json : "vue-image-lightbox": "file:.yalc/vue-image-lightbox",
run npm install to pick up any dependencies
After this I ran my app and went to the component that uses vue-image-lightbox. In the console I not get the warning
"[Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option."
All of the registration code works without issue with the git installed component. I don't understand why I see this when I try to use yalc.
The component is registered locally with
import LightBox from 'vue-image-lightbox'
components: { LightBox }
I would love to know what is different about the yalc installed component that is causing this issue. Is there a better way to test out patches on third party components other than yalc?
Thanks!

How to turn multiple vue components into one single npm package?

I was told by the project manager at the company I work for to take all the global components of a vue project we're working on and turning them into a single npm package that anyone working on the project can import and start using. essentially I have to take the global components and turn them into a component library like vuetify which is installed using npm and than imported from node modules directory.
I was wondering if you guys could point me in the right direction on how to achieve this. thanks in advance.
So, regardless of the implementation, the main thing you need is following this guide on how to create an npm package
https://docs.npmjs.com/creating-and-publishing-private-packages
Then
You create an src folder.
In the src, you will create a folder named "components" with all your -duh- components.
In the src folder, you will also create an index.js file, from there you will export your components.
export { default as VDataTable } from './components/VDataTable.vue'
// ...etc
Option1
If you use a bundler for your projects, and you know by a fact that all your codebases will use a bundler, you can simply create a folder with a package.json.
In your package.json then you will
"module": "src/index.js",
"main": "src/index.js"
In this scenario, you are letting your main project bundler (which is using the package) transpile all the packages for you, (babel, single file components)
Option 2
In case you have absolutely no clue of the nature of the projects which can use your library you will need a bundler for your components.
An example can be Rollup.
I suggest these 2 guides.
https://rollupjs.org/
https://rollup-plugin-vue.vuejs.org/
Long story short, Rollup will transpile for you the files you requested (js and css), and you will have to make them available from your package.json
"module": "src/dist/library.esm.js",
"main": "src/library.common.js"
And then you can release your package. Possibly privately or you might get fired :P

vue-cli-service: SyntaxError: Unexpected token '...'. Expected a property name

I'm working on putting together a small app using vue, and I specifically need it to run on a device that does not support ES6. I'm using vue-cli-service build to build, and when trying to open this page on my ES5 device, I'm seeing this error SyntaxError: Unexpected token '...'. Expected a property name.
I have installed babel, and added this to my .babelrc: { "presets": ["#babel/preset-env"] }
I'm not really sure what else to try, I haven't been able to find anything that specifically addresses this. Even the vue-cli-service documentation suggests ways to support polyfill for ES5, but I don't think this is the same thing.
I had this problem with Vuetify and Safari 11.1
I guessed I needed to transpile the ES6 version of Vuetify for older browsers. The solution was difficult to search for, as most of the suggestions were about modifying webpack or babel configuration, which I find obscured inside Vue CLI.
I eventually uncovered the solution myself by rebuilding my project from scratch via Vue CLI, and the installer magically added a transpilation option for Vuetify which I was missing - I think because I had previously upgraded Vuetify across the ES5 to ES6 versions, and perhaps their upgrade script doesn't perform this step.
vue.config.js
module.exports = {
"transpileDependencies": [
"vuetify"
],}
this is the equivalent of webpack
build: {
transpile: ['vuetify']
}
Restart the build and reload.
Of course you will need to find which of your packages it is - this is just an example. I just dug around in the error stack until finding something which belonged to Vuetify.

Creating a single Vue component inside a larger project

I have a PHP project that uses Kirby CMS. I also use Gulp for building my assets. Now, I need to add a calculator on the homepage that is complex enough to justify the usage of Vue. How would I incorporate Vue in my project without introducing a ton of new tooling? All I want is a simple Single File Component basically. I have:
<div id="calculator"></div>
and I want the component to be rendered there. Nothing more.
After some consideration, I came up with the following options but found issues with each of them:
Use the Vue CLI for instant prototyping. That's the closest solution for my use case, but I can't easily develop the component. If I use vue serve, I get to see the component isolated in a new page. The issue lies in the fact the component isn't a part of my project's page. It's not affected by its stylesheets, layout, and other scripts. I can't know if it'll work properly once I build it and view it in my project. Running vue build on each change would be pretty painful and time consuming. Sadly, vue watch isn't a thing, which leads me to:
Creating a project and using Vue CLI Service. If I create a project, I'd be able to run vue-cli-service build --watch and have my component automatically refresh on each change of its source file. While developing the component, I simply make a change, wait for it to compile, and refresh my project in the browser to see the modified component in action. While that would work, it introduces a bunch of node_modules inside my project, along with a package.json. I feel that's too much for just a single component. It would pollute the project more than I'd like:
assets/
js/
build/
calculator/
dist/
node_modules/ # modules here
public/ # I don't need that
package.json # package here
package-lock.json
App.vue
scripts/
main.js
content/
site/
node_modules/ # modules here as well
panel/
package.json # package here as well
package-lock.json
index.php
I would basically have a project within a project.
Use vueify to compile the component with Browserify and Gulp (which I already use). While this appears OK, vueify is deprecated and not supported. Besides, I'd have to add a bunch of stuff to my gulpfile.js in order to use Babel + ESLint for the component.
How do I set up Vue in such a way that I'm able to develop a very simple component as a part of a larger project with as little friction as possible?
If anyone has dealt with a similar problem, how did they solve it?
I ended up using the second approach I mentioned in my question with one small twist - I initialized the Vue project in my main project. I merged them.
I opened the parent folder of my project in a terminal.
I ran vue create my-project where my-project was the actual folder name of my project. The CLI asked if it should overwrite the project or merge it. I chose merge.
After the project was created, my old package.json was overwritten and only had the Vue dependencies listed in it.
I reverted my old package.json and installed these packages: #vue/cli-plugin-babel, #vue/cli-service, vue-template-compiler, and vue.
I added the following npm script in my package.json:
"scripts": {
"calculator": "vue-cli-service build assets/js/calculator/main.js --watch --dest assets/js/calculator/build"
}
Result
My project's folder structure remained the same, except for a few new packages in node_modules. I put my component files in assets/js/calculator/. There, I have main.js which is the main component script, and build which is a folder containing the processed component.
I have:
<div id="calculator"></div>
in my page, and:
<script src="/assets/js/calculator/build/app.js"></script>
in the footer. When I open the page, the component is rendered correctly.
To modify the component, I simply run npm run calculator in a terminal, which spins up the CLI service. It monitors the main.js file and builds the component on each change. Once the build is complete (which happens in under a second), I refresh the page and the updated component is there.
Conclusion
I believe that's the smoothest way to handle this use case. It didn't bloat the project, all dependencies were listed, and the development experience is great. The part where my package.json got overwritten was a bit concerning, but other than that - it worked perfectly. If there's a better way to do this, please leave an answer!
This is probably not the answer you're looking for but if I were you I'd look into inline templates and x-templates as they seem well suited to your use case.
Also have a look at this blog post. It offers a nice write up about the different template authoring methods in Vue and their pros/cons.