css changed after nuxt generate - vue.js

I'm using Nuxt with Vuetify.
I created a class and assigned it some padding.
The class is defined in a unscoped <style> in layouts/default.vue.
when I'm on development mode (npm run dev) everything looks great as I aimed for.
the class is on container element so the final html looks like
<div class="container container--fluid my-class">
the devtools look like that when I'm on dev mode:
so my-class is applied. But once I build the project (npm run generate) my-class is overridden by the container class rules:
I guess it is happening because of the order in which the classes combined into a single css but not sure it behaves differently for dev and built projects.
How can I fix it?

After some more digging it seems to be a known issue with nuxt.
It happens when declaring styles in non-scoped style tag, and using it somewhere else.
I followed these steps: https://stackoverflow.com/a/60925793/9103301
which is basically integrating Vuetify into nuxt manually and not with #nuxt/vuetify.
then I could control over the order the css is loaded in nuxt.config.js - first vuetify and then my styling (which I moved from the layout the a css file).
a more basic vuetify plugin that worked for me:
import Vue from "vue"
import Vuetify from "vuetify"
version "^2.1.1" ,
Vue.use(Vuetify)
export default (ctx) => {
const vuetify = new Vuetify({
theme: {
dark: false, // From 2.0 You have to select the theme dark or light here
},
})
ctx.app.vuetify = vuetify
ctx.$vuetify = vuetify.framework
}
You'll have to install icons as well, vuetify default is mdi which is installed with npm install #mdi/font -D

managed to fix this by disabling tree shaking for vuetify. Change the following in nuxt.config.js:
buildModules: [
["#nuxtjs/vuetify", { treeShake: false }],
],

Related

How to bundle tailwind css inside a Vue Component Package

In one of my projects, I build a nice vue3 component that could be useful to several other projects. So I decided to publish it as an NPM package and share it with everyone.
I wrote the isolate component, build it and publish BUT I use Tailwind css to make the style.
When I publish and install the component everything is working BUT without the beauty of the css part.
I tried several configurations and alternative tools to generate the package that automatically add the tailwind as an inner dependency to my package.
Does someone have experience with this? how can build/bundle my component by adding the tailwind CSS instructions into it?
You're almost there
Since you've got your component working, the majority of the part has been done.
For configuring the styling of the component you need to identify the Tailwind CSS classes being used by your Vue component package and retain them in the final CSS that is generated by the Tailwind engine in your project.
Follow below steps in the project where you want to use your tailwind vue component package.
For Tailwind CSS V3
// tailwind.config.js
module.exports = [
//...
content: [
"./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}",
"./node_modules/package-name/**/*.{vue,js,ts,jsx,tsx}" // Add this line
// Replace "package-name" with the name of the dependency package
],
//...
]
For Tailwind CSS V2
// tailwind.config.js
module.exports = [
//...
purge: {
//...
content: [
"./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}",
"./node_modules/package-name/**/*.{vue,js,ts,jsx,tsx}" // Add this line
// Replace "package-name" with the name of the dependency package
],
//...
//...
}
]
The content property in the tailwind.config.js file defines file path pattern that the tailwind engine should look into, for generating the final CSS file.
For Pro users
You may also try to automate the above setup by writing an install script for your npm package to add this configuration to the tailwind.config.js file
References
Tailwind Docs - 3rd party integration
It's a bit difficult for someone to answer your question as you've not really shared the source code, but thankfully (and a bit incorrectly), you've published the src directory to npm.
The core issue here is that when you're building a component library, you are running npm run build:npm which translates to vue-cli-service build --target lib --name getjvNumPad src/index.js.
The index.js reads as follows:
import component from './components/numeric-pad.vue'
// Declare install function executed by Vue.use()
export function install (Vue) {
if (install.installed) return
install.installed = true
Vue.component('getjv-num-pad', component)
}
// Create module definition for Vue.use()
const plugin = {
install
}
// Auto-install when vue is found (eg. in browser via <script> tag)
let GlobalVue = null
if (typeof window !== 'undefined') {
GlobalVue = window.Vue
} else if (typeof global !== 'undefined') {
GlobalVue = global.Vue
}
if (GlobalVue) {
GlobalVue.use(plugin)
}
// To allow use as module (npm/webpack/etc.) export component
export default component
There is no mention of importing any CSS, hence no CSS included in the built version.
The simplest solution would be to include the index.css import in your index.js or the src/components/numeric-pad.vue file under the <style> section.
Lastly, I'm a bit rusty on how components are built, but you might find that Vue outputs the CSS as a separate file. In that case, you would also need to update your package.json to include an exports field.

Vue: icons are not displayed when css.extract: false

When building a Vue library (component), according to Vue docs, you can set css.extract: false in vue.config.js to avoid the users having to import the CSS manually when they import the library into an app:
vue.config.js
module.exports = {
css: {
extract: false
}
}
However, when you do that, the icons are not displayed in the production build.
In this case I'm using #mdi/font and weather-icons. Neither of them load:
To reproduce
You can reproduce this with this Vue library (component):
Create new Vue project with vue create test
Clone the repo and put in the same directory as the Vue test project
In vue-open-weather-widget set css.extract: false in vue.config.js;
And comment out CSS import:
import 'vue-open-weather-widget/dist/vue-open-weather-widget.css'
Build vue-open-weather-widget with yarn build
Import it into the test Vue app with yarn add "../vue-open-weather-widget";
Serve the test app yarn serve
I have looked at your lib (nice component BTW). I created a build with css: { extract: false } and first looked at the behavior when importing vue-open-weather-widget.umd.js directly into an HTML file. And that worked without any problems.
The thing is that the fonts remain external in the dist after the build. And it seems that there is a problem to find the fonts when your component is loaded in a Webpack project (in our case Vue CLI project). I don't know why the fonts are not referenced correctly. But I have found another, and possibly a better solution.
As it is stated in the MDI docs, the use of the web fonts can negatively affect the page performance. When importing only one icon, all of them are imported, which in turn increases the bundle size. In such a small component this is more than suboptimal, especially for the component users. Therefore here is the alternative solution, also suggested by MDI:
Use #mdi/js instead of #mdi/font
Remove all #mdi/font references in your code and install deps:
npm install #mdi/js #jamescoyle/vue-icon
Replace all icons with SVG(e.g. in MainView.vue). Note that on this way only icons are included in the bundle that are used in your components:
...
<span #click="state.settings.view = 'settings'">
<svg-icon type="mdi" :path="mdiCogOutline"></svg-icon>
</span>
...
import SvgIcon from '#jamescoyle/vue-icon'
import { mdiCogOutline } from '#mdi/js'
...
components: {
SvgIcon
},
data () {
return {
mdiCogOutline: mdiCogOutline
}
},
Adjust vue.config.js:
module.exports = {
css: {
extract: false
}
}
Build component:
# i would also include --formats umd-min
vue-cli-service build --target lib --formats umd-min --name vue-open-weather-widget src/main.js
Now your dist contains only 192.68 KiB vue-open-weather-widget.umd.min.js and the component is ready to use over CDN or in a Vue CLI Project, without importing any CSS or fonts. I have tested both cases. Here is how it looks like:
Hope it helps you! Feel free to ask if you have further questions.

Nuxt + Vuetify + VueDraggable - draggable tag prop, v-row, works in dev server but not after building/running for production

I'm building a Nuxt app with Vuetify buildModule setup and want to make a number of v-cols sortable via VueDraggable (in my case, I built and added a super small Nuxt plugin which binds a global draggable component from the default export from VueDraggable). The v-cols should be wrapped with a v-row, so I'm using the draggable component with tag="v-row". This works well when running the dev server (nuxt-ts in my case since I'm using Nuxt with typescript support), but fails when building and running in production mode.
To illustrate the issue, here is some info on what's happening. My source is as follows (i.e. I use Pug):
In development mode, my v-row is rendered correctly in the DOM from Vuetify:
But when building and running in production mode, the draggable component literally renders v-row as the DOM tag instead of it going through rendering/parsing via Vuetify:
Does anyone have any idea on how to identify the root cause and how to resolve it here? I can likely hack my way around this problem for now, but want to know if this is a Nuxt bug or if anyone has solved this in any other way.
Just came across this issue, it turns out you need to register the VRow component globally:
import { VRow } from 'vuetify/lib';
Vue.component("v-row", VRow)
in your main.js
If the problem is caused by the vueDraggble registration try following:
Create <project-root>/plugins/draggable.ts
import draggable from 'vuedraggable';
import Vue from 'vue';
Vue.component('draggable', Draggable);
And remove
import draggable from 'vuedraggable'
from your .vue files.
and in your nuxt.config.js add
export default {
// ...
plugins: [
{ src: '~/plugins/draggable.ts', mode: 'client' }
]
//...
}

Loading vuetify in a package that i use in a vuetify project

What is the correct way of loading vuetify into a package that i use in a vuetify project?
When serving projects it all seems to work fine but when i build the project i've got some issues with the css/sass
things i've tried:
With vuetify loader: the css is loaded twice so i can't overwrite sass variables
Without vuetify loader: the package doesn't have the vuetify css, so it looks horrible
Without vuetify loader with vuetify.min.css: the css is loaded twice so i can't overwrite sass variables, and the loaded css is all the css so it's huge
My package is called vuetify-resource, and this is the source code of the index.js (without the vuetify loader) At this point everything works on npm run serve But when i build the package doesn't have "access" to the vuetify css.
import Vue from 'vue';
import Vuetify from 'vuetify';
import VuetifyResourceComponent from './VuetifyResource.vue';
Vue.use(Vuetify);
const VuetifyResource = {
install(Vue, options) {
Vue.component('vuetify-resource', VuetifyResourceComponent);
},
};
export default VuetifyResource;
To solve my issue i had to do a couple of things.
Make peer dependencies of vuetify and vue
add vuetify to the webpack externals, so when someone uses the package, the package uses that projects vuetify
not longer import vue and vuetify in the index.js it's not needed, the project that uses the package imports that
import the specific components that you use in every .vue file
for example:
Vue.config.js
module.exports = {
configureWebpack: {
externals: {'vuetify/lib': 'vuetify/lib'},
},
};
index.js
import VuetifyResourceComponent from './VuetifyResource.vue';
const VuetifyResource = {
install(Vue, options) {
Vue.component('vuetify-resource', VuetifyResourceComponent);
},
};
export default VuetifyResource;
part of the component.vue
import { VDataTable } from 'vuetify/lib';
export default {
name: 'vuetify-resource',
components: {
VDataTable
},
Step 4 in Ricardo's answer is not needed if you use vuetify-loader, it will do the job for you.
And I would modify step 2 to also exclude Vuetify's styles/css from your bundle. If you don't exclude them you can run into styling issues when the Vuetify version differ between your library and your application.
Use a regular expression in vue.config.js like this: configureWebpack: { externals: /^vuetify\// }. That way, only your own styles are included in the library bundle.

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
}
// ...
}