How to use an npm package component with Vite + Vue? - vue.js

What would be the steps to add a component to Vite with Vue, as an npm package?
I assumed these:
npm install example
open src/App.vue and add import Example from 'example'
in App.vue, in <template>, add <Example />
Is that correct?
I am trying to install and use vue-select like so, but it's not working:

The process you described is correct, but you must also register the component before you can use it (within components: { ... }).
Since you mentioned you're using vue-select, I will use that as an example.
Step #0 - Install
As you've already done, ensure your project is initialized (npm init), then run yarn add vue-select / npm i vue-select.
Step #1 - Initialize
In your main.js, import and register with:
import VSelect from 'vue-select';
Vue.component('v-select', VSelect);
/* rest of your Vue initialization here */
Step #2 - Use Component
<v-select :options="[{label: 'Canada', code: 'ca'}]"></v-select>
You'll also need to import the stylesheet in your CSS, with:
#import 'vue-select/src/scss/vue-select.scss';
Real Example
If you want to see a full example, I am using this package in one of my projects, I'm registering the component in my main.js and using it ThemeSelector.vue.
Also, if your project is large and/ or you're only using this component in one place, then a better approach would be to import it into the component that's using it. This is done in a similar way, but you must also register it under components: { ... } for it to be accessible within your <template>.

Your screenshot shows you're importing vSelect in a <script> block, and expecting it to be automatically registered for the component's template. That would only work in a <script setup> block.
However, your GitHub repo (which seems to be different from the screenshot you posted) reveals other issues in your code:
You're using Vue 2 code to globally register the v-select component in your Vue 3 app. In Vue 3, global component registration is done from the application instance (i.e., returned from createApp()).
// main.js
import VSelect from 'vue-select';
// Vue.component('v-select', VSelect); ❌ Vue 2 code
import { createApp } from 'vue'
import App from './App.vue'
createApp(App)
.component('v-select', VSelect) ✅
.mount('#app')
You're using #import (CSS syntax) to import your SCSS file in the <script> block. Either move the CSS into a <style lang="scss"> block; or remove the # prefix, which would create a valid import for <script>.
<script setup>
// #import 'vue-select/src/scss/vue-select.scss'; ❌ The # prefix is invalid in <script>
import 'vue-select/src/scss/vue-select.scss'; ✅
</script>
<!-- OR -->
<style lang="scss">
#import 'vue-select/src/scss/vue-select.scss';
</style>
Your project is missing sass, which is required to process SCSS files. You can install it as a dev dependency with:
$ npm i -D sass
Here's a demo with the fixes pointed out above.

Related

Enable Typescript in SFC: Laravel 9 + vite + vue-loader

I wanted to create a project using this github repo as a base:
https://github.com/suresh-ramani/laravel-vue3-vite
The repo essentially enables a Laravel 9 full stack server-side rendered application to use vue3 within the blade template files. You can mount a vue3 app inside the blade files and import SFC (Single-File Components) ending in .vue to construct the application.
I want to enable Typescript INSIDE THE .VUE FILES. I am already aware of how to use vite to compile a basic .ts file.
I figured out the answer to my own question. To help others I'll take you through the steps. It's way easier than I thought it was going to be.
Step 1: Install TypeScript
System command: npm install typescript
Or
Laravel Sail Command: ./vendor/bin/sail npm install typescript
Step 2: Add lang attribute to your vue files
Add lang="ts" to your <script> tag
<template>
This is a test
</template>
<script lang="ts">
export default {
name: "App",
mounted() {
const message: string = "Testing 1 2 3"
console.log(message)
}
}
</script>
<style scoped>
</style>

Vue is not defined in a standalone web component

I am building a standalone Vue component and using it in another Vue project.
Build component:
vue build --target wc --inline-vue --name user-menu user-menu.vue
It's a simple component so far without functionality, just markup.
Then, in the main project in package.json:
"devDependencies": {
"user-menu": "git+https://........user-menu.git",
Then, in the main.js:
import Vue from "vue";
import UserMenu from "user-menu"
....
Vue.use(UserMenu);
const app = new Vue(config).$mount("#root");
window.app = app;
Vue.use(UserMenu);
And it says:
user-menu.js?e2ea:1446 Uncaught ReferenceError: Vue is not defined
on a row
module.exports = Vue;
But the Vue CLI 3 documentation says that:
In web component mode, Vue is externalized. This means the bundle will
not bundle Vue even if your code imports Vue. The bundle will assume
Vue is available on the host page as a global variable.
Any idea how to fix that?
Finally I came to the following solution: the component should not be built at all. Source files are enought to be imported like this:
import UserMenu from "user-menu/user-menu";
Pay attention that the path should point at the imported vue file, not just to the folder. But the extension "vue" must be skipped.
The final application will build it all together.

Unknown custom element error in Vue.js project

I started creating a project in vue.js based on this one:
https://github.com/creativetimofficial/vuetify-material-dashboard
When trying to integrate TableList.vue component, I get an error:
Unknown custom element: <material-card> - did you register the component correctly?
Vue.js project was created using webstorm. I copied over styles folder and enabled watcher to compile scss files into css. I run project using npm serve command in WebStorm.
My App.vue looks a little different like this:
<template>
<v-app>
<TheBar />
<TheNavigationDrawer />
<TheView />
</v-app>
</template>
<script>
import TheBar from '#/components/core/TheBar.vue'
import TheNavigationDrawer from "#/components/core/TheNavigationDrawer";
import TheView from '#/components/core/TheView.vue'
export default {
name: 'app',
components: {
TheBar,
TheNavigationDrawer,
TheView
},
data: () => ({
}),
};
</script>
<style lang="scss">
#import './styles/index.scss';
</style>
As you can see I am importing the full file, which in turn imports _cards.scss file which should have definition of material-card component. Is this how it works?
I tried registering component manually by adding material-card to components property but it fails to parse kebab-case properly because of '-' sign.
What also intrigues me is that the original creator NEVER registers material-card component so how the hell does his TableList.vue component know it?
I also found this guide - https://medium.com/#mahesh.ks/using-sass-scss-in-vue-js-2-d472af0facf9. However I don't see a webpack.config.js file anywhere, where is this?
Any help is greatly appreciated. :D
There are multiple ways of importing components into your Vue instance. For the case of the project you're working from, the vuetify library is imported at the root instance which allows all components to be available globally. This means you don't need to import the desired components within specific .vue files.
It's likely that you haven't installed all of the dependencies correctly. Or you have not properly imported these dependencies within main.js. Check that these dependecies (found in package.json) have been installed by running npm list.

bootstrap-vue's `b-tabs` renders differently depending on the Vue build that I import

I'm using bootstrap-vue and I've noticed b-tabs renders differently depending on the Vue build that I import:
If I import vue it renders correctly:
https://codesandbox.io/s/vue-template-77mzg
But if I import vue/dist/vue.common or vue/dist/vue It renders wrongly:
https://codesandbox.io/s/vue-template-y0t15
Also, it doesn't happen with other components, like b-navbar-nav. They render correctly regardless of the vue build I import.
I'd like to understand why does it happen, since I need to import a vue version that includes the compiler because some components need it.
Thanks!
When importing a specific variant of Vue (i.e. commonjs vs ES), you need to set up an alias in webpack to ensure that BootstrapVue (and other dependants such as PortalVue) use the same build of Vue (as BootstrapVue also imports from vue).
See the docs on setting up aliases (so you can just import Vue from 'vue'):
https://bootstrap-vue.js.org/docs#aliasing-vue-import
i.e. for Webpack config
module.exports = {
// ...
resolve: {
alias: {
'vue$': 'vue/dist/vue.common.js'
}
}
}

Vuetify Styles not visible

I am a beginner in the world of Vue, so please bear with my foolish question(s).
I have a boilerplate code for a Vue project which I cloned from:
Vue Enterprise Boilerplate
I wanted to use Vuetify components, so I followed the following steps:
1. Cloned the vue-enterprise-boilerplate
2. npm install vuetify --save
3. In my main.js I added the vuetify dependency like:
import Vuetify from 'vuetify';
import 'vuetify/dist/vuetify.min.css';
Vue.use(Vuetify);
4. I am using Vue CLI 3 (which comes with the boilerplate), also I have installed the CCS Loader.
5. Now in my app.vue, I have a simple button like:
<v-app>
<v-btn color="primary">Test</v-btn>
</v-app>
But when I run the app, I only see the outline of the button, but the styles are missing. Here is a screenshot below:
Also here is the dev-tools snapshot:
As you can see, the vuetify.min.css is being referenced, I am unable to debug why this is not behaving as per the Vuetify guides.
What steps am I missing?
What fixed the issue for me was the adding of class .v-application at the top most html tag (or the first one after template tag). Usually if I add <v-app> it all works but for some reason using vuitify 2.0.4 this didn't worked (may be because I'm not using vue-cli and webpack but parcel.js).
So adding this class solved the same issue for me.
EDIT
Actually I just found why v-app was ignored. Since I'm using vuetify 2.0.4. without vue-cli and webpack I need to include the vuetify components by my self like so:
import Vue from 'vue'
import Vuetify, {
VCard,
VImg,
VCardTitle,
VBtn,
VCardActions,
VCardText,
VProgressCircular,
VSpacer,
VDialog,
VDivider,
VAlert,
VApp,
} from 'vuetify/lib'
Vue.use(Vuetify, {
components: {
VCard,
VImg,
VCardTitle,
VBtn,
VCardActions,
VCardText,
VProgressCircular,
VSpacer,
VDialog,
VDivider,
VAlert,
VApp,
},
})
import 'material-design-icons-iconfont/dist/material-design-icons.css';
export default new Vuetify({})
Which is then imported in the vue app like this:
import Vue from "vue";
import vuetify from './src/vuetify'
import VocabularyApp from "./src/App.vue";
new Vue({
vuetify,
render: h => h(VocabularyApp)
}).$mount('#app-tutor');
So v-app wasn't working as I didn't included it in the list of components that I need for my app to work. More you can find here.
Welcome to the vuetiful world of vue.
You are looking into the shadow dom, please inspect the button element not the div element inside button element. The parent button element of the div will have classes like .primary .error based on the prop you give.
See the screenshot:
I hope this helps.
In my case I used stylus and had the css.requireModuleExtension = false option in vue.config.js. Styles just didn't load. Switching it to the true or removing this option did the trick.
// vue.congif.js
module.exports = {
// ...
css: {
// ...
requireModuleExtension: true
}
// ...
}