Using Bootstrap 4 with NuxtJS - vue.js

I'm trying to associate bootstrap 4 (bootstrap-vue) with Nuxt.
I have difficulties using mixins and variables in pages or components, although I added style-resources-module.
Here is an extract of nuxt.config.js:
/*
** Global CSS
*/
css: ["~/scss/vars.scss"],
/*
** Plugins to load before mounting the App
*/
plugins: [],
/*
/*
** Nuxt.js modules
*/
modules: [
// Doc: https://bootstrap-vue.js.org/docs/
"bootstrap-vue/nuxt",
// Doc: https://github.com/nuxt-community/style-resources-module
"#nuxtjs/style-resources"
],
/*
** Disabling Bootstrap Compiled CSS
*/
bootstrapVue: {
bootstrapCSS: false,
bootstrapVueCSS: false
},
/*
** Style resources
*/
styleResources: {
scss: [
"./scss/*.scss",
"~bootstrap/scss/bootstrap.scss",
"~bootstrap-vue/src/index.scss"
]
},
./scss/vars.scss sets variables, and also overrides Bootstrap's
(e.g. $orange: #DD7F58;
Here is an extract of one of the components:
<style lang="scss" scoped>
.myClass{
display: none;
#include media-breakpoint-up(md) {
display: block;
}
}
</style>
Compilation throws the following error: _No mixin named media-breakpoint-up_.

Here is a setup that works, if ever you meet the same issue:
nuxt.config.js:
/*
** Nuxt.js modules
*/
modules: [
// Doc: https://bootstrap-vue.js.org/docs/
"bootstrap-vue/nuxt",
// Doc: https://github.com/nuxt-community/style-resources-module
"#nuxtjs/style-resources"
],
/*
** Disabling Bootstrap Compiled CSS
*/
bootstrapVue: {
bootstrapCSS: false,
bootstrapVueCSS: false
},
/*
** Style resources
*/
styleResources: {
scss: "./scss/*.scss"
},
./scss/custom.scss:
// Variable overrides
$orange: #DD7F58;
// Bootstrap and BootstrapVue SCSS files
#import '~bootstrap/scss/bootstrap.scss';
#import '~bootstrap-vue/src/index.scss';
// General style overrides and custom classes
body {
margin: 0;
}

I use the following code inside nuxt.config.js:
modules: [
'bootstrap-vue/nuxt',
'#nuxtjs/style-resources',
],
bootstrapVue: {
bootstrapCSS: false,
bootstrapVueCSS: false
},
styleResources: {
scss: [
'bootstrap/scss/_functions.scss',
'bootstrap/scss/_variables.scss',
'bootstrap/scss/_mixins.scss',
'bootstrap-vue/src/_variables.scss',
'~/assets/css/_variables.scss', // my custom variable overrides
],
},

For Bootstrap v5, I used
https://www.npmjs.com/package/#nuxtjs/style-resources
nuxt.config.js
css: [
'#/assets/scss/main.scss',
],
styleResources: {
scss: [
'~/node_modules/bootstrap/scss/_functions.scss',
'~/node_modules/bootstrap/scss/_variables.scss',
'~/node_modules/bootstrap/scss/_mixins.scss',
'~/node_modules/bootstrap/scss/_containers.scss',
'~/node_modules/bootstrap/scss/_grid.scss'
]
},
modules: [
'#nuxtjs/style-resources',
],
Component
<style scoped lang="scss">
.header {
#include make-container();
}
</style>

Related

Sass global variables and mixins not working

I've set up a project using Vue 3.2.33 and Vite 2.9.5
When I try to access any global variable or mixin from within any vue component, I get an undefined error. This problem doesn't occur in scss files.
The import itself seems working correctly because any css rules in it are working.
vite.config.ts:
import { fileURLToPath, URL } from 'url';
import { defineConfig } from 'vite';
import vue from '#vitejs/plugin-vue';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'#': fileURLToPath(new URL('./src', import.meta.url)),
},
},
css: {
preprocessorOptions: {
scss: {
additionalData: '#use "#/styles/variables";',
},
},
},
});
src/styles/_variables.scss:
// breakpoints
$breakpoints: (
"sm": 576px,
"md": 768px,
"lg": 992px,
"xl": 1200px,
"xxl": 1400px,
);
#mixin test {
border: 3px solid red;
}
Example use:
<style scoped lang="scss">
#use 'sass:map';
.container {
max-width: 100%;
width: 100%;
margin: 0 auto;
#include test; // <- undefined
&--fluid {
max-width: 100%;
width: 100%;
}
}
$widths: (
'sm': 540px,
'md': 720px,
'lg': 960px,
'xl': 1140px,
'xxl': 1320px,
);
#each $breakpoint, $width in $widths {
#media (min-width: map.get($breakpoints, $breakpoint)) { // <- $breakpoints undefined
.container {
max-width: $width;
}
}
}
</style>
use
#import
in your vite config instead of
#use
vite.config.ts:
export default defineConfig({
plugins: [vue()],
css: {
preprocessorOptions: {
scss: {
additionalData: '#import "./src/styles/variables.scss";',
},
},
},
});
keep in mind that you cannot import the same file variables.scss again in your main.ts file otherwise, you will get this error
[sass] This file is already being loaded.
by the way, you can also import the scss file in every single component manually as you mentioned but that would be really tedious so using a global import in preprocessorOptions in vite.config.ts is a much better option for files used globally like a variables.scss file.
I've managed to "fix" the issue. Turns out, when I replace all #use rules for file imports, the sass code is imported correctly and works. But this produces a new problem as the #import rules cannot be placed before #use, so I had to remove the additionalData key from config and include the imports manually.

Vite - Separate chunk for fonts

I am building a library that contains components and some shared CSS, like a design system.
The problem is that it is not separating the fonts in different chunks, instead, it is inlining them in the font as base 64, so the CSS file gets huge!
// vite.config.ts
import { defineConfig } from 'vite';
import vue from '#vitejs/plugin-vue';
import { resolve } from 'path';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
build: {
lib: {
entry: resolve(__dirname, 'src/index.ts'),
name: 'design-system',
},
rollupOptions: {
external: ['vue'],
output: {
globals: {
vue: 'Vue',
},
},
},
},
resolve: {
alias: [
{ find: '#', replacement: '/src' },
],
},
});
I already tried to place it in root/public, but it didn't work.
I have a file _fonts.css which import fonts like so
#font-face {
font-family: Inter;
src: url('/public/fonts/Inter-Regular.ttf') format('truetype');
font-weight: 400;
}
And then I have a main.scss that imports it
// main.scss
#import 'normalize';
#import 'themes';
#import 'fonts';
Any idea on how to split it?
I was able to accomplish this in a library we're working on by placing the fonts in the special public directory (see: https://vitejs.dev/guide/assets.html#the-public-directory).
Long story short placing assets in there makes Vite copy them over without any actual transformation and/or renaming.
First of all place your font files in public/fonts/.
Then add the following to vite.config.ts:
{
root: './',
publicDir: 'public',
}
This was necessary although it should be a default setting.
Then my font declaration looks like this:
#font-face {
font-family: MyFont;
src: url('./fonts/myfont.woff2');
font-weight: 200;
}
But - this is for the library mode. In case you're building an app just start the font URL path with / instead of ./.

How do I use `localIdentName` with vue-cli

I'm trying to randomize/minify generated class names.
Currently I'm using a fairly vanilla vue-cli project, and I'm also using Tailwind css which I hope doesn't complicate anything.
Currently this is how far I got in my vue.config.js by reading vue-loader docs, this, and this, however this only works half way... my CSS minifies perfectly, however my vue component classes dont' change, so its like it's not parsing *.vue files.
I thought this could be because I notice it mentioning using <style scoped> but with Tailwind you don't need style tags in your components. Quite literally 100% of the css is contained in my src/assets/styles/main.pcss file, which consists of a few #import statements and that's it.
module.exports = {
css: {
requireModuleExtension: false,
loaderOptions: {
css: {
modules: {
localIdentName: '[hash:6]',
},
},
},
},
chainWebpack: config => {
// disable eslint temporarily
config.module.rules.delete('eslint');
},
};
And my tailwind config:
module.exports = {
future: {
purgeLayersByDefault: true,
removeDeprecatedGapUtilities: true,
},
plugins: [],
purge: [
'./src/**/*.html',
'./src/**/*.vue',
],
theme: {},
};

sass-loader can't resolve #use rule

I'm working on a vuejs app and I'm trying to import my variables files using the #use rule within prependData in sass-loader, but it seems not working properly. Using #use import does not work and I receive erros about variables. But using #import everything goes fine. Am I doing something wrong or getting the wrong concept about #use rule?
Using #import in prependData works:
css: {
loaderOptions: {
sass: {
implementation: require('sass'),
sassOptions: {
indentedSyntax: true
},
// prependData: `#use '~abstracts/variables'` //this does not work
prependData: `#import '~abstracts/variables'` //this works
}
}
}
Using #use does not work:
Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
SassError: Undefined variable.
╷
15 │ color: $chuck
│ ^^^^^^
╵
My package.json:
"sass": "^1.26.3",
"sass-loader": "^8.0.2"
My component:
<style lang="sass">
.title
color: $chuck
</style>
My variables.sass file:
$chuck: #BADA55
TIA
I just figured out what I was missing.
Just add as *:
css: {
loaderOptions: {
sass: {
implementation: require('sass'),
sassOptions: {
indentedSyntax: true
},
prependData: `#use '~abstracts/variables' as *`
}
}
}
I'm just getting used to this new way of using sass.

Can't load global scss variables in Vue SFCs

I tried to follow this tutorial to get access to a global file called variables.scss in all SFC files:
https://vueschool.io/articles/vuejs-tutorials/globally-load-sass-into-your-vue-js-applications/
My project uses vue cli 3, so I added the following property to vue.config.js:
{
css: {
loaderOptions: {
sass: {
data: `#import "src/assets/scss/variables.scss";`
}
}
},
}
the variables.scss file looks like this:
// variables.scss
$purple: #5D2D8B;
My component style looks like this:
<!-- Datepicker.vue -->
<style lang="scss" scoped>
.picker {
color: $purple!important;
}
</style>
But I got this error when trying to use the $purple variable
color: $purple!important;
^
Undefined variable: "$purple"
I've also tried to add style-resources-loader vue-cli plugin, but got the same error.
(added this when tried to use it):
{
pluginOptions: {
'style-resources-loader': {
preProcessor: 'scss',
patterns: [
path.resolve(__dirname, 'src/assets/scss/variables.scss')
]
}
}
}
It seems that on .vue files the #import statement is not applied, but in .scss files it is.
Anyone has an idea what is that about?