Laravel Mix for Kirby

Hey @jimbobrjames, Thanks for the reply. Here’s an example of what I mean:

Say I have a /src/sass/templates folder containing files like…

  • home.sass
  • about.sass
  • projects.sass
  • etc…

and I want each file processed individually and output to the /assets/css/templates folder. I want the resulting files to be…

  • home.css
  • about.css
  • projects.css
  • etc…

The templates folder is the primary place I use this because I like using Kirby’s @auto feature. Basically any file I put into /src/sass/templates I always want output to the same file name with a .css extension.

So I’m asking if it’s possible to pass Laravel Mix a folder and have it process all of the files within and output them to some other folder

Oh yes, i see. Personally i dont do it like that, i use imports into scss and requires / imports in the main script file to keep my code modular but end up with a single concatainated file.

That said, there does seem to be a work around. Since mix is actually a fancy pants wrapper around webpack, you can actually load webpack plugins into it. There is one for glob loading which means you can work around it like this…

mix.webpackConfig({
  module: {
    rules: [
      {
        test: /\.scss/,
        loader: 'import-glob-loader'
      }
    ]
  }
});

Heres were i got this info from. But i have a feeling that means globbing inside an import statement, rather then in the mix config. Have a google around if it doesnt work out for you, i’m sure theres probably another webpack plugin out there.

1 Like

Hi @HYR

From the Laravel-Mix page:

Multiple Builds

Should you need to compile more than one root file, you may call mix.sass() (or any of the preprocessor variants) as many as times as is needed. For each call, webpack will output a new file with the relevant contents.

mix.sass('src/app.scss', 'dist/') // creates 'dist/app.css'
   .sass('src/forum.scss', 'dist/'); // creates 'dist/forum.css'

https://laravel-mix.com/docs/4.0/css-preprocessors#multiple-builds

But like this… you have to add each entry manually to the webpack.mix.js.

Saludos, Funkybrotha

Sure, you can totally do that but i think @HYR was wanting to glob it so it didnt matter how many he had (every site is different after all), he could wild card it with a * rather having to write the names in.

Personally I only use this for the rare occasion i need an art directed post. There were once performance benefits to splitting the style sheet per page but if your server is capable of HTTP/2 with push enabled, there is really no need to because all the assets get pulled concurrently rather then consecutively.

Hi @RobertC

Thanx a lot for your work! Now it works.

How can I remove the double slashes between assets//css and assets//js?

<link href="//localhost:3000/assets//css/app.min.css?id=6224ecd8a27c8166ad75" rel="stylesheet">
<script src="//localhost:3000/assets//js/app.min.js?id=d5af252260873add5cc2"></script>

My webpack.mix.js

// Laravel-Mix
// ======================================================================
let mix = require('laravel-mix');

// BrowserSync
// ======================================================================
mix.browserSync({
  proxy: 'kirby-3-laravel-mix:8888',
  files: [
    "../kirby/assets/js/**/*.js",
    "../kirby/assets/css/**/*.css",
    "../kirby/site/templates/*.php",
    "../kirby/site/snippets/**/*.php",
    "../kirby/content/**/*.txt"
  ],
  notify: false
});

// Javascript
// ======================================================================
mix.js('src/js/app.js', '../kirby/assets/js/app.js');

// SASS
// ======================================================================
mix.sass('src/sass/app.scss', '../kirby/assets/css/app.css');

// Version
// ======================================================================
mix.version();

// Minify
// ======================================================================
mix.minify(['../kirby/assets/js/app.js', '../kirby/assets/css/app.css']);

// Public Path
// ======================================================================
mix.setPublicPath('../kirby/assets/');

// Copy Files
// ======================================================================
mix.copyDirectory('src/fonts', '../kirby/assets/fonts');
mix.copyDirectory('src/images', '../kirby/assets/images');

// Mix Options
// ======================================================================
mix.options({
  processCssUrls: false,
});

My mix-manifest.json

{
    "/js/app.js": "/js/app.js?id=d5af252260873add5cc2",
    "/css/app.css": "/css/app.css?id=6224ecd8a27c8166ad75",
    "/js/app.min.js": "/js/app.min.js?id=d5af252260873add5cc2",
    "/css/app.min.css": "/css/app.min.css?id=6224ecd8a27c8166ad75"
}

My includes:

<?php echo mix('/css/app.min.css') ?>
<?php echo mix('/js/app.min.js') ?>

Saludos, Funkybrotha

ps.
…a little typo in your index.php - file at line 32 :wink:
// Get the correct $$assetsDirectory

1 Like

I have the same problem with the double dash :eyes: I’ve tried to modify diverently.laravel-mix-kirby.manifestPath and diverently.laravel-mix-kirby.assetsDirectory but nothing worked for me.

@funkybrotha @thkm When you update the plugin it should be fixed now.

composer update diverently/laravel-mix-kirby

1 Like

Great, Thanks :+1:

I agree with @jimbobrjames on spliting CSS per templates. I’d only use it if each template requires a good amount of CSS. Keeping it all in one file usually yields a smaller file size when your server GZIPs it.

Anyway, here’s a clean way you can achieve that with Laravel Mix:

const mix = require('laravel-mix')
const glob = require('glob-all')

mix.js('src/js/app.js', 'assets/js')
   .sass('src/sass/app.scss', 'assets/css')

glob.sync(['./src/sass/templates/*.scss'])
    .forEach(template => mix.sass(template, 'assets/css/templates'))

Make sure you install glob-all with NPM or Yarn before.

2 Likes

Thanks @pedroborges that’s useful!

You can get the css even smaller still if you get Kirby to help you out with UnCss which will remove unused rules. Great if youve used something Bootstrap or Foundation.

With postcss-uncss installed, add this to your mix options…

mix.options({
  processCssUrls: false,
  postCss: [
    require('postcss-uncss')({
      html: JSON.parse(require('fs').readFileSync('./uncss.json', 'utf-8')),
      ignore: [/.(uniform|uniform-succesful|more|classes|to|keep)/]
    }),
  ],
})

And this route to your Kirby config…

// Routes
'routes' => [
  [
    'pattern' => 'uncss.json',
    'action'  => function () {
      header('Content-type: application/json; charset=utf-8');
        $pages = site()->index();
        $root = site()->find('home');
        $json = array();
        $json[] = (string)$root->url();

        foreach ($pages as $page) {
            $json[] = (string)$page->url();
        }
        return json_encode($json);
    }
  ]
]

Then hit that route with curl to get the json on disk…

curl http://yourtestsite.test/uncss.json > uncss.json

Next time you run mix in production, it will use your sites pages to strip unused rules from it :slight_smile:

It does not use javascript, so you may need to add any javascript generated classes to the ignore list or they will get removed. It’s clever enough to find strings in classes, so for Tiny Slider for example, just adding tns to the ignore is enough, you do not need all the classes Tiny sliders stylesheet.

2 Likes

hi @RobertC

Vielen Dank! Super - Arbeit!!! :wink:

Now the URL looks good too…

Have a nice weekend.

Saludos, Funkybrotha

jimbobrjames thanx
for letting me know about laravel mix!

1 Like

@RobertC I created a pull request for handling array values and auto templates (@auto): https://github.com/Diverently/laravel-mix-kirby/pull/4

It’ll look like this:

<html>
<head>
    <!-- ... -->
    <?php echo mix('/main.css') ?>
    <?php echo mix([
      '/additional.css',
      '@autocss'
    ]) ?>
</head>
<body>
    <!-- ... -->
    <?php echo mix('/main.js') ?>
    <?php echo mix([
      '/additional.js',
      '@autojs'
    ]) ?>
</body>
</html>
3 Likes