Vue CLI plugin CSS preprocessor (sass) transpile in parent - vue.js

We have a pretty standard Vue CLI environment. It currently ingests a vue plugin we created via the install method. The plugin is also a Vue CLI environment and lives as a git submodule in the repo.
Currently the parent uses sass and sass-loader packages to transpile. It's configured in the vue.config.js settings, like so:
module.exports = {
// Other properties and settings removed to simplify
css: {
loaderOptions: {
sass: {
data: `
#import "#/styles/global.scss";
`
}
}
}
The global.scss just houses all our style includes.
The plugin is set up in a similar way, but none of the code is getting ingested into the parent. Which totally makes sense, as there is nothing importing/building the plugins style files. Anyone know how to import and transpile plugin sass style sheets? Thank you!

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.

Import scss module in Nuxt application

I want to import a SCSS file in my Nuxt project.
For this I tried to follow the documentation where I simply add the path with filename in css file as:
nuxt.config.js
css: ['#/scss/_introPage.scss]
But it gives error as
Cannot find module '../scss/_introPage.scss'
My folder structure:
> components
> pages
> scss > _introPage.scss
> static
> store
> test
> nuxt.config.js
> package.json
How can I include the SCSS file and apply the global CSS into my project?
If anyone needs any further information please let me know.
Thank you everyone for your input.
I had to install sass, sass-loader#10 and fibers for it to work.
nom install --save-dev sass sass-loader#10 fibers
Nuxt.js provides a good way to share global CSS files with a css option in nuxt.config.js
example:
// nuxt.config.js
export default {
// other options
css: [
// Load a Node.js module directly (here it's a Sass file)
'bulma',
// CSS file in the project
'#/assets/css/main.css',
// SCSS file in the project
'#/assets/css/main.scss'
],
// other options
}
in your case, you need to add sass and sass-loader to load sass, scss, less &... files in your projects.
SASS: yarn add sass-loader sass
LESS: yarn add less-loader less
Stylus: yarn add stylus-loader stylus
to share your global style files(scss, sass, & ... ) and other good features
you can use Nuxt Style Resources.
Share variables, mixins, functions across all style files (no #import
needed)
Add #nuxtjs/style-resources dependency using yarn or npm to your project with on of these commands:
yarn add -D #nuxtjs/style-resources or npm install --save-dev #nuxtjs/style-resources
and then you can add '#nuxtjs/style-resources' in buildModules option in nuxt.config.js file import your global scss files like this:
// nuxt.config.js
export default {
// other options
buildModules: [
'#nuxtjs/style-resources',
],
styleResources: {
// your settings here
scss: ['#/assets/scss/_introPage.scss'],
sass: [],
less: [],
stylus: [],
hoistUseStatements: true // Hoists the "#use" imports. Applies only
to "sass", "scss" and "less". Default: false.
}
// other options
}
for more information see this link https://www.npmjs.com/package/#nuxtjs/style-resources

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.

Overriding Vuetify variables

I'm using Vuetify in my project, and I want to use a variable file to override the styles generated by Vuetify.
I'm loading the components and their corresponding styles using the a-la-carte method, so I'm NOT importing the Vuetify SASS file using this:
#import '~vuetify/src/styles/styles.sass'
// Not using this method because I don't want to generate styles that are not being used by
// vuetify components I'm not using
Also, my project is using *.scss, not *.sass.
I'm also injecting a global SCSS file containing mixins and other variables in my vue.config.js:
css: {
sourceMap: productionSourceMap,
loaderOptions: {
scss: {
prependData: `#import '#/scss/_common.scss';`
}
}
},
I included a Vuetify variable, $border-radius-root, in that common.scss file, but it doesn't seem to have any effect.
Any idea how to do what I want without having to write entirely new CSS rules to override Vuetify's generated stylesheet? Basically I want to change the units that Vuetify uses using their own stylesheet generator.
Actually the solution is, and I'm dumb for not thinking of this before, to add another loader to vue.config.js:
css: {
sourceMap: productionSourceMap,
loaderOptions: {
scss: {
prependData: `#import '#/scss/_common.scss';`
},
sass: {
prependData: `#import '#/sass/_vuetify-variables.sass';`
}
}
},
Since vuetify is using sass as the css pre-processor, it needs sass-loader to handle the variable overrides and apply it to the framework.
If you are using Nuxt:
you can add customVariable path in your nuxt.config.js file, in vuetify object
Note you have to enable treeShake. This option is required for custom SASS variables to work
example:
vuetify: {
// usually file should be in assets folder
customVariables: ['~/path/to/variables.scss'],
treeShake: true,
}
If you are using Vue CLI:
Create a folder with name: sass, scss, or styles
Create new file inside this folder and name it: variables.scss or variables.sass
vuetify-loader will automatically bootstrap your variables into Vue CLI’s compilation process, overwriting the framework defaults.
From Vuetify docs:
If you have not installed Vuetify, check out the quick-start guide. Once installed, create a folder called sass, scss or styles in your src directory with a file named variables.scss or variables.sass. The vuetify-loader will automatically bootstrap your variables into Vue CLI's compilation process, overwriting the framework defaults.
So, the vuetify-loader automatically loads #/scss/variables.scss in a Vue CLI project, so you could set $border-radius-root in that file, and it will overrride the framework default.

Stencil and Sass file

I am trying to port a React component to Stencil.
The component .scss file has an #import for another A.scss file. That A.scss file #import the bootstrap-sass/assets/stylesheet/bootstrap/_variables and #import another B.scss file.
Can Stencil handle that or do I need to merge everything in one file?
You can import other Sass files; you don't need to merge everything to one single file.
You can keep using Sass as you are using it with React. Just keep in mind that to be able to use Sass with Stencil, you have to install the Sass plugin and add the plugin to the plugins array in your stencil.config.js file.
For more information, check the Sass documentation on the Stencil website.
In your stencil.config.ts (or stencil.config.js) file:
export const config: Config = {
plugins: [
sass({
includePaths: [path.resolve(__dirname, 'path/to/styles')]
})
]
};
Yes, it can handle Sass files and their imports.
Install package stencil/sass:
npm i #stencil/sass -D
In your stencil.config.ts file:
import { Config } from "#stencil/core";
import { sass } from "#stencil/sass";
export const config: Config = {
// ... You configuration
plugins: [
sass({
includePaths: ["./node_modules/"],
}),
],
};
In the above example, we're telling the Stencil compiler to compile Sass files. The includePaths array tells the compiler the directories/files it should look into for the Sass files.
In order to use #import from a Node.js package, all you need is:
#import "~bootstrap-sass/assets/stylesheet/bootstrap/_variables";
Note: The ~ operator here is necessary when not importing using relative paths(./style.scss, ../../style.scss, etc.)
If you are importing the b.scss file using relative paths (./b.scss, ../b.scss, etc.), you won't need to add anything else to Sass plugin configuration.
I never tried multiple imports, but I can't see why this wouldn't work.
To get Stencil working with .scss, you should install this plugin, as described here.
npm install #stencil/sass --save-dev
Then add this property to config in file stencil.config.ts.
plugins: [
sass()
]