Nwidart Laravel Modules managing resources with webpack and mix.

Viewed 3048

I'm using nwidart's laravel modules to create separate modules for a laravel application, each module has code contained for that module. Currently I'm trying to put the css files relevant to each module into a separate app.scss and then use webpack to move the .scss into the public directory.

I have managed to achieve this by including separate webpack.mix files for each module that moves the css to the main public directory. My problem however is that to achieve this I have to run the command npm run dev in the root of each module folder every-time I want to update the css. Is there an easier way to run all the module webpack.mix.js files in an application or will I have to manually do it each time?

Here is the module package I'm using https://github.com/nWidart/laravel-modules

Also here is an example of how the directories look

--app

----Modules

------Blog -> webpack.mix.js

--------Resources

-----------Assets

-------------Sass -> app.scss

Also here is a copy of webpack.mix.js for the blog module

const { mix } = require('laravel-mix');
require('laravel-mix-merge-manifest');

mix.setPublicPath('../../public').mergeManifest();

mix.sass( __dirname + '/Resources/assets/sass/app.scss', 'css/blog.css');

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

I had this problem with the nwidart module. To solve this problem in main weppack.mix.js write this code:

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

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

mix.js('resources/js/app.js', 'public/js')
   .sass('resources/sass/app.scss', 'public/css');

const moduleFolder = './Modules';

const dirs = p => fs.readdirSync(p).filter(f => fs.statSync(path.resolve(p,f)).isDirectory())

let modules = dirs(moduleFolder);

cssArray = [];
cssArray.push('public/css/app.css');

modules.forEach(function(m){
  let js = path.resolve(moduleFolder,m,'Resources','assets','js', 'app.js');
  mix.js(js,'public/js');
  let scss = path.resolve(moduleFolder,m,'Resources','assets','sass', 'app.scss');
  mix.sass(scss,'public/css/'+m+'.css');
  cssArray.push('public/css/'+m+'.css');
});

mix.styles(cssArray, 'public/css/all.css');

I Been searching this, but can't belive no documented solution exist yet in 2020. so, here is my solution but i don't think is the correct one, but helps, and is a lot easier than the previous.

After create your module with:

artisan module:make Bla

You have for example (Bla is the name of your module):

./Modules/Bla/webpack.mix.js
./Modules/Bla/Resources/assets/js/bla.js
./Modules/Bla/Resources/assets/scss/bla.scss
./Modules/Bla/Resources/assets/images/module-icon-example-1.png
./Modules/Bla/Resources/assets/images/module-icon-example-2.png

And the main webpack

./webpack.mix.js
./resources/js/app.js
./resources/sass/app.scss
./resources/img/main-icon-example-1.png

SOLUTION:

You need to modify ./resources/js/app.js addiding this line

...
require('./bootstrap');
...
require('../../Modules/Bla/Resources/assets/js/bla');

You need to modify too ./resources/sass/app.scss addiding this line

// Variables
@import 'variables';
// Bootstrap
@import '~bootstrap/scss/bootstrap';
// PersonalizedModule
@import './../../Modules/Bla/Resources/assets/sass/bla';

And for the images you need to modify ./webpack.mix.js add this lines. specially copyDirectory or copy, both use different aproaches.

mix.react('resources/js/app.js', 'public/js')
    .sass('resources/sass/app.scss', 'public/css')
    .copyDirectory('resources/img', 'public/img')
    .copyDirectory('Modules/Bla/Resources/assets/img', 'public/img');

run:

>npm run development -- --watch

or

>npm run production

At this point you have public/app.js public/app.css with all code in your modules and a directory public/img of all your images.

cons: resultant app.js file is BIG ( can it be fixed? )

i think the best way is to run cascade all webpack.mix.js but i not find a easy way to do it yet.

Related