Laravel-mix: Tailwindcss2 @apply directive doesn't work inside vue component

Created on 16 Jan 2021  Â·  16Comments  Â·  Source: JeffreyWay/laravel-mix

  • Laravel Mix Version: "^6.0.6"
  • Node Version: 14.4.0
  • NPM Version: 6.14.5
  • OS: windows

I create a laravel application with jetstream and inertia-vue stack for my new project problem is Tailwindcs version 2 using postCss and it doesn't support @apply directive inside vue components but inside .css file it works fine I don't want that because that css file will load my every page I just want short inline utility classes with @apply directive but I can't, How Can I achieve that.?

inside my vue template

<template>
 <div class="mt-4">
  <label for="hello">Hello</label>
  <input id="hello" class="input"/>
 </div>
</templete>

<style scoped>
    .input {
        @apply bg-gray-200 border h-10
    }
</style>

output inside browser like this

Capture

webpack.mix.js

const mix = require('laravel-mix');

mix.js('resources/js/app.js', 'public/js').vue()
    .postCss('resources/css/app.css', 'public/css', [
        require('postcss-import'),
        require('tailwindcss'),
        require('autoprefixer'),
    ])
    .webpackConfig(require('./webpack.config'));

if (mix.inProduction()) {
    mix.version();
}

webpack.config.js

const path = require('path');

module.exports = {
    resolve: {
        alias: {
            '@': path.resolve('resources/js'),
        },
    },
};

tailwind version : "^2.0.1",

laravel version : 8.x,

jetstream version : 2.x,

inertiajs version: "^0.8.2"

Most helpful comment

Yeah this is something we need to look at. At the moment you have to specify the postCSS plugins globally for it to affect anything other than the specific css/sass/less/etc… file/tree you've given via mix.postCss / et al:

mix.options({
    postCss: [require("tailwindcss")("./tailwind.config.js")]
})

Note that you can set these plugins globally in your mix file like above and do not need to specify plugins via mix.postCss. You also have the option of using a postcss config file which we will honor as well.

@JeffreyWay What are your thoughts on this? Should we leave this as is or do you think it'd be reasonable to populate the PostCSS plugins globally from a single mix.postCss call. I'm on the fence about it.

All 16 comments

Have you tried below?

<style lang="postcss" scoped>
    .input {
        @apply bg-gray-200 border h-10
    }
</style>

I can't get @apply to work in my scoped styles either.

I got it working after installing laravel-mix-tailwind and using it this way in my webpack.config.js

require('laravel-mix-tailwind')

mix.postCss('resources/css/app.css', 'public/css', [
    require('tailwindcss')('./tailwind.config.js')
]).tailwind()

Style example in my vue file (notice the absence of the lang attribute:

<style>
.lookie {
    @apply bg-pink-100 text-pink-600 rounded-full border border-pink-400 mb-8;
}
</style>

Yeah this is something we need to look at. At the moment you have to specify the postCSS plugins globally for it to affect anything other than the specific css/sass/less/etc… file/tree you've given via mix.postCss / et al:

mix.options({
    postCss: [require("tailwindcss")("./tailwind.config.js")]
})

Note that you can set these plugins globally in your mix file like above and do not need to specify plugins via mix.postCss. You also have the option of using a postcss config file which we will honor as well.

@JeffreyWay What are your thoughts on this? Should we leave this as is or do you think it'd be reasonable to populate the PostCSS plugins globally from a single mix.postCss call. I'm on the fence about it.

I got it working after installing laravel-mix-tailwind and using it this way in my webpack.config.js

require('laravel-mix-tailwind')

mix.postCss('resources/css/app.css', 'public/css', [
    require('tailwindcss')('./tailwind.config.js')
]).tailwind()

Style example in my vue file (notice the absence of the lang attribute:

<style>
.lookie {
    @apply bg-pink-100 text-pink-600 rounded-full border border-pink-400 mb-8;
}
</style>

Couldn't get this to install. Looks like laravel-mix-tailwind doesn't support Laravel Mix 6 yet?

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! Found: [email protected]
npm ERR! node_modules/laravel-mix
npm ERR!   dev laravel-mix@"^6.0.6" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! dev laravel-mix-tailwind@"*" from the root project
npm ERR!
npm ERR! Conflicting peer dependency: [email protected]
npm ERR! node_modules/laravel-mix
npm ERR!   peer laravel-mix@"^2.1.7" from [email protected]
npm ERR!   node_modules/laravel-mix-tailwind
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
npm ERR! See /Users/myuseraccount/.npm/eresolve-report.txt for a full report.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/myuseraccount/.npm/_logs/2021-01-18T15_50_22_169Z-debug.log

I got it working after installing laravel-mix-tailwind and using it this way in my webpack.config.js

require('laravel-mix-tailwind')

mix.postCss('resources/css/app.css', 'public/css', [
    require('tailwindcss')('./tailwind.config.js')
]).tailwind()

Style example in my vue file (notice the absence of the lang attribute:

<style>
.lookie {
    @apply bg-pink-100 text-pink-600 rounded-full border border-pink-400 mb-8;
}
</style>

Couldn't get this to install. Looks like laravel-mix-tailwind doesn't support Laravel Mix 6 yet?

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! Found: [email protected]
npm ERR! node_modules/laravel-mix
npm ERR!   dev laravel-mix@"^6.0.6" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! dev laravel-mix-tailwind@"*" from the root project
npm ERR!
npm ERR! Conflicting peer dependency: [email protected]
npm ERR! node_modules/laravel-mix
npm ERR!   peer laravel-mix@"^2.1.7" from [email protected]
npm ERR!   node_modules/laravel-mix-tailwind
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
npm ERR! See /Users/myuseraccount/.npm/eresolve-report.txt for a full report.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/myuseraccount/.npm/_logs/2021-01-18T15_50_22_169Z-debug.log

Hm, that's strange. I'm using yarn, maybe that's why. I installed laravel-mix-tailwind before laravel-mix

So now I have the use case of using postcss in a vue component like below:

<style lang="postcss">
.test {
    @apply bg-red-400; /*Not working */
}

.postcss-test {
    .working {
       background: red; /* Not working */
   }
}

I've also added this to my webpack config:

        rules: [
            {
                test: /\.postcss$/,
                use: [
                    'vue-style-loader',
                    'css-loader',
                    {
                        loader: 'postcss-loader'
                    }
                ]
            }
        ]

So basically I have to choose between tailwind or postcss, which is weird. I though @apply was parsed with postcss anyways?

If wanna use postcss and you wanna use @apply directive to work inside vue components then just install this plugin and inside your webpack.mix.js configure like this, don't need to do anything

for postcss

const mix = require('laravel-mix');
require('laravel-mix-tailwind')

mix.js('resources/js/app.js', 'public/js').vue()
    .postCss('resources/css/app.css', 'public/css', [
        require('postcss-import'),
        require('tailwindcss')('./tailwind.config.js'),
        require('autoprefixer'),
    ])
    .webpackConfig(require('./webpack.config'))
    .tailwind();

if (mix.inProduction()) {
    mix.version();
}

if you wanna use a preprocessor like sass etc.. then you don't need to install this plugin, and then uninstall postcss, postcss-import, autoprefixer from package.json and install resolve-url-loader, sass, sass-loader and your webpack.mix.js will look like this

npm uninstall postcss postcss-import autoprefixer then npm install --save-dev resolve-url-loader sass sass-loader

for preprocessor

const mix = require('laravel-mix');
const tailwindcss = require('tailwindcss');

mix.js('resources/js/app.js', 'public/js').vue()
    .sass('resources/sass/app.scss', 'public/css')
    .options({
        processCssUrls: false,
        postCss: [ tailwindcss('./tailwind.config.js') ],
    })
    .webpackConfig(require('./webpack.config'));

if (mix.inProduction()) {
    mix.version();
}

Hope guys this will help

@ShekhSaifuddin007 Are you able to install laravel-mix-tailwind on a Laravel 8 project? I'm getting a conflicting peer dependency when I try (posted above).

This seems to be the culprit.

https://github.com/JeffreyWay/laravel-mix-tailwind/blob/master/package.json on line 25

"peerDependencies": {
    "laravel-mix": "^2.1.7"
}

I submitted this as an issue to that repo: https://github.com/JeffreyWay/laravel-mix-tailwind/issues/30

The solution on the fresh install is as simple as putting a bare config file on the root of the project. Source.

// postcss.config.js
module.exports = {
    plugins: {
        tailwindcss: {},
        autoprefixer: {},
    },
}

@anotherglitchinthematrix Created ./postcss.config.js with the contents below... didn't make a difference. Same error.

module.exports = {
    plugins: {
        tailwindcss: {},
        autoprefixer: {},
    }
}

@ShekhSaifuddin007 Are you able to install laravel-mix-tailwind on a Laravel 8 project? I'm getting a conflicting peer dependency when I try (posted above).

This seems to be the culprit.

https://github.com/JeffreyWay/laravel-mix-tailwind/blob/master/package.json on line 25

"peerDependencies": {
    "laravel-mix": "^2.1.7"
}

I submitted this as an issue to that repo: JeffreyWay/laravel-mix-tailwind#30

This has been resolved with the latest patch version of laravel-mix-tailwind.

@see
https://github.com/JeffreyWay/laravel-mix-tailwind/issues/30#issuecomment-767678728

@fylzero I think probably need to update your laravel-mix

So to sum up my experience:

  • can't use lang="postcss" in style (webpack throws errors then) and therefore get linter errors when using long @apply with many classes
  • browserSync don't reflect changes in vue component styles (yes, it recompiles "something" but no changes in the page)

I really expected that .vue().tailwind() will solve the issue...

I believe this may have been fixed in v6.0.16 which has upgraded the dependency "vue-style-loader": "^4.1.3".

I believe this may have been fixed in v6.0.16 which has upgraded the dependency "vue-style-loader": "^4.1.3".

It's not fixed.

A workaround that can temporarily solve this problem without using laravel-mix-tailwind:

In webpack.mix.js:

const mix = require('laravel-mix')

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel applications. By default, we are compiling the CSS
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.ts('resources/js/app.ts', 'public/js').vue()
  .postCss('resources/css/app.css', 'public/css')
  .webpackConfig(require('./webpack.config'))
  .sourceMaps()

if (mix.inProduction()) {
  mix.version()
}

In webpack.config.js:

const path = require('path')

module.exports = {
  resolve: {
    alias: {
      '@': path.resolve('resources/js')
    }
  },
  module: {
    rules: [
      {
        test: /\.(postcss)$/,
        use: [
          'vue-style-loader',
          { loader: 'css-loader', options: { importLoaders: 1 } },
          'postcss-loader'
        ]
      }
    ]
  }
}

In postcss.config.js:

module.exports = {
  plugins: [
    require('postcss-import'),
    require('tailwindcss')('./tailwind.config.js'),
    require('autoprefixer')
  ]
}

Now I can use:

<style lang="postcss">
.input-form {
  @apply block w-full mt-1 border-gray-300 rounded-md shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50;
}
</style>
Was this page helpful?
0 / 5 - 0 ratings

Related issues

pixieaka picture pixieaka  Â·  3Comments

Bomavi picture Bomavi  Â·  3Comments

wendt88 picture wendt88  Â·  3Comments

rlewkowicz picture rlewkowicz  Â·  3Comments

nezaboravi picture nezaboravi  Â·  3Comments