@apply doesn't work with Laravel Mix
HapLifeMan opened this issue · 12 comments
Hey,
Everything works fine until I decided to use components as it's said in the documentation.
Compiling failed :
ERROR Failed to compile with 2 errors 12:41:50 PM
error in ./resources/assets/sass/app.css
Module build failed: ModuleBuildError: Module build failed: Syntax Error
(2:3) No .text-white class found.
1 | .btn {
> 2 | @apply .text-white;
| ^
3 | }
4 |
at runLoaders (/Users/thomas/Sites/cdsud/www/node_modules/webpack/lib/NormalModule.js:195:19)
at /Users/thomas/Sites/cdsud/www/node_modules/loader-runner/lib/LoaderRunner.js:364:11
at /Users/thomas/Sites/cdsud/www/node_modules/loader-runner/lib/LoaderRunner.js:230:18
at context.callback (/Users/thomas/Sites/cdsud/www/node_modules/loader-runner/lib/LoaderRunner.js:111:13)
at Promise.resolve.then.then.catch (/Users/thomas/Sites/cdsud/www/node_modules/postcss-loader/lib/index.js:185:44)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
@ multi ./node_modules/laravel-mix/src/builder/mock-entry.js ./resources/assets/sass/app.css
error in ./resources/assets/sass/app.css
Module build failed: ModuleBuildError: Module build failed: Syntax Error
(2:3) No .text-white class found.
1 | .btn {
> 2 | @apply .text-white;
| ^
3 | }
4 |
at runLoaders (/Users/thomas/Sites/cdsud/www/node_modules/webpack/lib/NormalModule.js:195:19)
at /Users/thomas/Sites/cdsud/www/node_modules/loader-runner/lib/LoaderRunner.js:364:11
at /Users/thomas/Sites/cdsud/www/node_modules/loader-runner/lib/LoaderRunner.js:230:18
at context.callback (/Users/thomas/Sites/cdsud/www/node_modules/loader-runner/lib/LoaderRunner.js:111:13)
at Promise.resolve.then.then.catch (/Users/thomas/Sites/cdsud/www/node_modules/postcss-loader/lib/index.js:185:44)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
My wepback.mix.js
:
let mix = require('laravel-mix');
let tailwind = require('tailwindcss');
mix.postCss('./resources/assets/sass/app.css', './public/css/main.css', [tailwind('./tailwind.js')]).disableNotifications();
... and app.css
:
@tailwind preflight;
@import "./components/buttons.css";
@tailwind utilities;
@import './main.css';
@import './admin.css';
What's wrong? :/
Can you share a public repo that reproduces this? I would expect a different error since @import
doesn't inline imports in normal CSS and is also required to be the first statement in a file.
Are you using CSS here or Sass?
Here's the repo: https://github.com/HapLifeMan/apply-css-not-working and I'm using CSS!
Ah ok I've reproduced this now.
The issue is that @import
doesn't work the same way in normal CSS as it does in Sass or Less. Mix seems to be trying to process your buttons.css
file with Tailwind independently, and it can't find any of the other classes because they aren't in the same file.
There's a couple ways to work around this:
-
Use Less just for it's import functionality. Your mix file would look like this then:
mix.less('./resources/assets/less/app.less', './public/css/main.css') .options({ postCss: [ tailwind('./tailwind.js')]}) .disableNotifications()
You can even keep your other files as plain CSS files and import them like this:
@tailwind preflight; @import (inline) "./components/buttons.css"; @tailwind utilities; @import (inline) './main.css'; @import (inline) './admin.css';
-
Use the postcss-import plugin to inline your imports. I would probably lean towards this option if you want to stay away from existing preprocessors and just use Tailwind with raw CSS.
There's one gotcha with this plugin which is that it's very strict about the CSS spec and the CSS spec says that
@import
rules have to come first in a file, which means you can't have@tailwind preflight
come before an@import
rule.The way to get around that is to move your Tailwind calls to their own files, and make your main CSS file just imports:
@import "./tailwind-preflight.css"; @import "./components/buttons.css"; @import "./tailwind-utilities.css"; @import "./main.css"; @import "./admin.css";
tailwind-preflight.css
would just look like this:@tailwind preflight;
...and
tailwind-utilities.css
would just look like this:@tailwind utilities;
To use the import plugin, add it to the beginning of your PostCSS plugin chain:
let mix = require('laravel-mix'); let tailwind = require('tailwindcss'); let postcssImport = require('postcss-import'); mix.less('./resources/assets/css/app.css', './public/css/main.css', [ postcssImport(), tailwind('./tailwind.js'), ]) .disableNotifications();
Let me know if that fixes your issue! We'll definitely have to add some more documentation about this.
Bug fixed! Thank you
I can now move on serious stuff
I have quite large webpack.mix.js - for anyone that finds this issue, it might be helpful to know:
If you have any weird problems (like your css file being literally copied and not processed) you should put that last snippet (excluding the first line) somewhere at the end of the webpack.mix.js. This did the trick for me.
Hey @adamwathan, just noticed I think you have a minor mistake in your tip for postcss-import.
You have tailwind-utilities.css
as having @tailwind preflight; when it should be @tailwind utilities; right?
Good catch, fixed!
@adamwathan I've tried using your postcss-import method but am still getting the same issue about "missing '}'" when trying to build using @apply.
webpack.mix.js
let mix = require('laravel-mix');
let tailwindcss = require( 'tailwindcss' );
let dirs = {
src: {
js: 'src/js/',
scss: 'src/scss/'
},
dist: {
js: 'web/js/',
css: 'web/css/'
}
}
mix.js( dirs.src.js + 'main.js', dirs.dist.js )
.sass( dirs.src.scss + 'tailwind.scss', dirs.dist.css ).options({
postCss: [ tailwindcss('tailwind.config.js') ]
})
.sass( dirs.src.scss + 'style.scss', dirs.dist.css, [
portcssImport(),
tailwind()
])
tailwind.scss
@tailwind base;
@tailwind components;
@tailwind utilities;
body{
/* This comment solves Mix's issue with needing an SCSS file with at least one non-empty ruleset */
}
style.scss
html{
font-size: 20px;
}
body{
padding:
env( safe-area-inset-top, 0 )
env( safe-area-inset-right, 0 )
env( safe-area-inset-bottom, 0 )
env( safe-area-inset-left, 0 );
font-weight: 200;
}
.plate{
@apply bg-gray-900 text-white p-4;
}
To confirm, if I remove the @apply declaration then everything works fine...
Can you create a public GitHub repo that reproduces the issue? I can play with it and figure it out much faster that way than having to recreate it all from scratch myself.
I tried creating a public GitLab repo but couldn't push to it for some reason... so I've attached a zip here. I removed all sensitive info, node modules and composer packages. It's a Craft CMS site
@adamwathan have you found what the problem with @jcush problem, please? I'm facing the same problem here.
@thamerbelfkihthamer I haven't tried this yet, but just re-reading the issue I think in the meantime while we let @adamwathan dig into it it could be an idea to create a separate stylesheet for utilities created by applying tailwind classes, then less
that one and sass
the others. So you'd do all your @apply
calls in one sheet, which would use less
, then put the rest of your styles in sass
.
In the nicest way possible without any offence meant to Tailwind or Adam (big Refactoring UI fan here) I'm currently customising Bootstrap 4 for theming instead. I just have more experience with it personally and wanted to crack on with the project.