Project setup
The project is laravel 10 setup with sail and thus using vite.
Also bootstrap 5 and bootstrap icons is added through npm.
What I want to achieve
I am using blade components and I want each component to have its own scss file for styling.
I want the styling to be only loaded when using the component.
What I want to know
Is it possible to use seperate scss files in my laravel project?
How do I tell laravel which scss file is for which blade file?
If its not possible to use scss files how can I achieve my goal with css files?
Where would I put the scss/css files in my project?
I read that when using vite you can put them in the resource folder and otherwise they should be in the public folder.
What I have now
If I am missing files that are necessary for an answer please inform me.
I want this question to be understandable and usable for other users so thats why I try to include as little as possible of my own files.
My vite config:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import path from 'path';
export default defineConfig({
plugins: [
laravel({
input: ['resources/scss/app.scss', 'resources/js/app.js'],
refresh: true,
}),
],
resolve: {
alias: {
'~bootstrap': path.resolve(__dirname, 'node_modules/bootstrap'),
'~bootstrap-icons': path.resolve(__dirname, 'node_modules/bootstrap-icons'),
}
}
});
My package json:
{
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build"
},
"devDependencies": {
"axios": "^1.1.2",
"laravel-vite-plugin": "^0.7.5",
"sass": "^1.62.1",
"vite": "^4.0.0"
},
"dependencies": {
"@popperjs/core": "^2.11.7",
"bootstrap": "^5.2.3",
"bootstrap-icons": "^1.10.5"
}
}
My folder structure:
public/
└── build
resources/
├── js/
│ ├── app.js
│ └── bootstrap.js
├── scss/
│ ├── components/
│ │ └── form/
│ │ └── text-input.scss
│ └── app.scss
└── views/
├── auth/
│ └── login.blade.php
├── components/
│ └── form/
│ └── text-input.blade.php
└── layouts/
└── authentication.blade.php
What I have tried
I have tried to put the scss files in resources and public folder and reference them with @pushonce(‘mystack) in my blade view.
This is without success since the scss stays empty.
When adding my scss file to the app.js as import it is loaded but with a generic build name and loaded on every single page of the application, which im trying to avoid.
3
Answers
Answer
I have found out that styling to be only loaded when using the component. Is not possible with Vite, but it is possible in laravel mix.
Solution
For the solution we will migrate to laravel mix and change a little of the setup.
Migrate from vite to laravel mix
Follow the steps from here: https://github.com/laravel/vite-plugin/blob/main/UPGRADE.md#migrating-from-vite-to-laravel-mix
Npm packages
These packages have to be installed as dev dependencies:
sail npm install sass sass-loader glob resolve-url-loader --save-dev
We need these packages to compile the scss files and add them automaticly to laravel mix.
If you also want the public directory to be cleaned each time when build add:
npm install rimraf --save-dev
.Update the webpackconfig
Change the extension from
webpack.mix.js
towebpack.mix.cjs
if using ES module.Add this inside the
webpack.mix.cjs
file:This will add javascript and scss files in your resources directory automaticly to laravel mix so its compiled to the public folder. It also keeps the same directory structure. When adding new files be sure to use
npm run dev
so they are compiled and watched by laravel mix.Usage
You now can use @push('styles') or @pushonce('styles') inside your blade files to load the styles/js only when the blade view is used.
Example
Have in your root file (Layout):
Now in the blade view you're using:
I use pushOnce since I sometimes reuse components multiple times on a page and only want the styling and javascript to be loaded once.
Npm webpack
Be sure to run webpack when using laravel with
npm run dev
ornpm run watch
. When adding new files you should rerun the command again.Pay attention for this
For this you write the styling in your .scss files in the
resource/scss/**
directory but when referencing it in the blade view you use thepublic/css
directory with the .css extension.You can use Laravel mix if you only want to use them inside Blade components and refer the scss to css converted file for each scss file in each Blade components
https://laravel.com/docs/10.x/mix
https://laravel-mix.com/
What you’re trying to achieve is easy to do with
@push
and@stack
directives. The following assumes an older "Template Inheritance" style, but I’ve tested it to work with component approach as well, as long as you use the@stack
directive in the layout.In your layout:
In your view file (auth/login.blade):
In your "component" file:
The result is the rendered markup that includes the styles from both: your view file and any "components" down the line.