Git Product home page Git Product logo

laravel-mix-glob's Introduction

laravel-mix-glob

laravel-mix-glob banner


The globs laravel-mix extension.

Boost your productivity by globs usage with an extensive and concise api. And dynamic. Configure once and forget about adding the files each time.

This extension add support for globs usage with an extensive concise api. For a more natural boosted productivity and dynamic.

V2 is out. A full re-write. And this document is for it.

Here is the v1 documentation.

If you used v1. It's advised to migrate toward v2. As it have a more concise api. And more solid flexible system. Plus more fixes or new features. V1 is no more maintained.

Other extensions to check:

What's new in v2

  • Full re-write using typescript and modularity (cleaner code).
  • A whole new more natural and flexible design that bring less coupling and an it would works with all scenario and new things. Robust against change or working with other extensions.
  • Less confusing system.
  • Restart and watching system re-done and improved for better efficiency.
  • Better support for restart with fast-glob object format. A remapping to chokidar was implemented.
  • Interrupt system improved and fixes.
  • Better logging.
  • Automated tests: units and end to end.
  • Simplified documentation.

Remember to star ⭐✨✨✨ after you give it a try. (=> let me star ✨✨✨)

Install

npm i laravel-mix-glob --save-dev

or

npm i laravel-mix-glob@latest --save-dev

to update to v2 if you are already on v1.

Starting example

In place of the bellow with repetition and no dynamic

mix.postCss('src/styles/file.css', 'dist/styles/file.css', [
    require('precss')() // your PostCss plugins
]);
mix.postCss('src/styles/file2.css', 'dist/styles/file2.css', [
    require('precss')() // your PostCss plugins
]);
// ....

you do:

mix.postCss(
  glb.src('./src/styles/**/*.css'),
  glb.out({
    baseMap: './src', // base is ./src
    outMap: './dist', // src/styles/file.css => dist/styles/file.css
  }),
  [
    require('precss')() // your PostCss plugins
  ]
);

The argument that is no glob type and no glb.out type. Would remain the same and through all the possibilities.

And you got the idea. You use globs through such helpers. By using the same old mix api. And same way of chaining.

We can use a specifier (c, compile, ...), to give ourselves the ability to select easily and set easily what to compile and what not.

mix.postCss(
  glb.src('./src/styles/**/*.c.css'), // Adding a specifier. Only to make diff between what need to be compiled and what doesn't
  glb.out({
    baseMap: './src',
    outMap: './dist',
    specifier: 'c', // specifier will be removed. Optional. Allow you to have a specifier so you differentiate what need to be compiled and what doesn't. Just for selection.
  }), // src/styles/file.c.css => dist/styles/file.css
  [
    require('precss')() // your PostCss plugins
  ]
);

To clear up what the specifier is see the following illustration, otherwise check specifier section in glb.out() and OutManager for a full explanation.

resources

And the output will be

output

Know that this extension provides different ways to use globs through different helpers. The main one is glb.src(), glb.out() for src, out calls (most of the time, that's what you would be using). The other one is glb.args() to have more dynamic around setting up the args (more advanced usage. You may never need that.). And glb.arg() is just like glb.src() but for args that are not src,out based. There is other helpers. All are in the reference below. After the next example section. You'll get details about each. Skim only through the list of examples below.

Here we go with more examples.

✨ For full understanding check How it works and the full reference starting by glb.src() & glb.out() & glb.arg().

Javascript

const mix = require('laravel-mix');
const { glb } = require('laravel-mix-glob'); // Make it always the last extension
const path = require('path');

/**
 * ///////// no globs ////////
 */
mix.js('./src/noGlobs/some.js', './dist/noGlobs/some.js');

/**
 * ////////// src out arg ///////////
 */

/**
 * src out
 * ----------
 */

/**
 * with specifier
 */
mix.js(
  glb.src('./src/relative/doneWithSrcOut/specifier/**/*.compile.js'), 
  glb.out({
    baseMap: './src',
    outMap: './dist',
    specifier: 'compile',
  })
);

/**
 * without specifier
 */
{
  // you can have one config and re-use it
  const glbOut = glb.out({
    baseMap: './src',
    outMap: './dist',
  });

  // relative path
  mix.js(glb.src('./src/relative/doneWithSrcOut/noSpecifier/**/*.js'), glbOut);

  // absolute path
  mix.js(
    glb.src(
      path.resolve(
        __dirname,
        './src/absolute/doneWithSrcOut/noSpecifier/**/*.js',
      ),
    ),
    glbOut,
  );
}

/**
 * ////////// react ////////////////
 */

mix
  .js(
    glb.src('./src/reactNoArgs/specifier/**/*.c.jsx'),
    glb.out({
      baseMap: './src',
      outMap: './dist',
      specifier: 'c',
    }),
  )
  .react();

Typescript

mix.ts(
  glb.src('./src/relative/doneWithSrcOut/specifier/**/*.c.ts'),
  glb.out({
    baseMap: './src',
    outMap: './dist',
    specifier: 'c',
  })
);

/**
 * ////////// react tsx ////////////////
 */
mix
  .ts(
    glb.src('./src/reactNoArgs/specifier/**/*.c.tsx'),
    glb.out({
      baseMap: './src',
      outMap: './dist',
      specifier: 'c',
    }),
  )
  .react();
mix
  .ts(
    glb.src([
      './src/relative/doneWithSrcOut/specifier/**/*.c.ts',
      './src/reactNoArgs/specifier/**/*.c.tsx', // string[] multiple globs patterns 
    ]),
    glb.out({
      baseMap: './src',
      outMap: './dist',
      specifier: 'c',
    }),
  )
  .react();

Styling

// no globs
mix.sass('./src/styles/noGlobs/style.scss', './dist/styles/noGlobs/')
// with src out
    .sass(
        glb.src('./src/styles/doneWithSrcOut/specifier/**/*.c.scss'),
        glb.out({
          baseMap: './src',   
          outMap: './dist',
          specifier: 'c',
        }),
    );

Example of glb.args()

Know that most of the time, you would need to use glb.src(), glb.out() instead.

  • This is only for advanced need.
/**
 * ////////// args helper ///////////
 * Dynamically return all args
 * Helpful for conditionally picking up of arguments
 */

/**
 * With specifier
 */

mix.js(
  glb.args('./src/relative/doneWithArgs/specifier/**/*.c.js', (src) => {
    let out = path.resolve(
      path.resolve(__dirname, './dist'),
      path.relative(path.resolve(__dirname, './src'), src),
    ); // handling the output re-basing
    out = glb.replaceExtension(out, '.js'); // <<<<==== helpers
    out = glb.removeSpecifier(out, 'c'); // <<<<====
    
    return [src, out]; // <<<====== returning args
  })
);


/**
 * Without specifier
 */
mix.js(
  glb.args('./src/relative/doneWithArgs/noSpecifier/**/*.js', (src) => {
    let out = path.resolve(
      path.resolve(__dirname, './dist'),
      path.relative(path.resolve(__dirname, './src'), src),
    );
    out = glb.replaceExtension(out, '.js');
    return [src, out];
  })
);

/**
 * ✨✨ Args with glb.mapOutput(), A better helper 🔥🔥
 */

/**
 * With specifier
 */
mix.js(
  glb.args(
    './src/relative/doneWithArgsAndGlbMapOutput/specifier/**/*.c.js',
    (src) => {
      /**
       * Can conditionally set the args and with the helpers that resolve things for u
       */
      const out = glb.mapOutput({
        src,
        outConfig: glb.out({
          baseMap: './src',
          outMap: './dist',
          extensionMap: '.js',
          specifier: 'c',
        }),
      });
      return [src, out];
    },
  ),
);

/**
 * without specifier
 */
mix.js(
  glb.args(
    './src/relative/doneWithArgsAndGlbMapOutput/noSpecifier/**/*.js',
    (src) => {
      /**
       * Can conditionally set the args
       */
      const out = (outMap) => {
        glb.mapOutput({
          src,
          outConfig: glb.out({
            baseMap: './src',
            outMap,
            extensionMap: '.js',
          }),
        });
      };

      if (src.includes('special')) {
        return [src, out('./specialDist')];
      }
      return [src, out('./defaultDist')];
    },
  ),
);

How it works

Same functions as before and you use the glob helpers.

You have different helpers. And you go the same as without globs. But now with the new version of the extension, you use the helpers for the arguments to create Glob objects. The extension will automatically detect and handle the calls accordingly. Processing the globs and the cartesian products (The product of the different possibilities in case of more then just one glob argument).

This new design will allow natural flexibility, and to basically use the glob equivalent to anything u used to do manually before. And with all ease. And that allow the extension to be more independent of laravel-mix updates.

Glob and out types and normal types

The glob type arguments and the glb.out type will be treated with resolution. And the normal argument will be treated as is in every possibility after resolution.

In the example bellow:

mix.postCss('src/file.css', 'dist/file.css', [
    require('precss')() // your PostCss plugins
]);
mix.postCss('src/file2.css', 'dist/file2.css', [
    require('precss')() // your PostCss plugins
]);

With globs as already shown in section above, we will do:

mix.postCss(
  glb.src('./src/styles/**/*.c.css'), // <<<-- glob type argument (here a src type that works with out type)
  glb.out({  // <<<-- out type argument
    baseMap: './src',
    outMap: './dist',
    specifier: 'c',
  }),
  [  // <<<<< ---- normal argument type
    require('precss')() // your PostCss plugins
  ]
);

after the glob is resolved. Let's say:

`./src/styles/file1.c.css`
`./src/styles/file2.c.css`
`./src/styles/another/file1.c.css`

We have 3 cases here:

for every one of the file the out is resolved:

making:

[`./src/styles/file1.c.css`, `./dist/styles/file1.css`]
[`./src/styles/file2.c.css`, `./dist/styles/file2.css`]
[`./src/styles/another/file1.c.css`, `./dist/styles/another/file1.css`]

And the 3d argument is a normal one. No more resolution. The call will go with the following arguments:

// calls mix.postCss(...args)

// call 1
[
  `./src/styles/file1.c.css`, // glob
  `./dist/styles/file1.css`, // out resolution
  [require('precss')()] // no resolution (pass it as is) through all cases
]

// call 2
[
  `./src/styles/file2.c.css`,
  `./dist/styles/file2.css`,
  [require('precss')()]
]

// call 3
[
  `./src/styles/another/file1.c.css`,
  `./dist/styles/another/file1.css`,
  [require('precss')()]
]

Cartesian product

Let's take the imaginary function with multiple globs args

mix.magic(
  glb.src('./src/some/**/*.js'),
  glb.out({ outMap: './dist', baseMap: './src' }),
  glb.arg('./src/family/**/*.fm')
);

There is no such use case in laravel-mix yet (all functions generally use one file). Unless some extension do it. And in case you use other extensions. Make sure to import laravel-mix-glob the last. 🔥🔥

Now the way the above would work. Is that we will have the two spaces arg0 and arg2 short for glb.src('./src/some/**/*.js') and glb.arg('./src/family/**/*.fm').

arg0 the space of all matched elements by the first glob
arg2 same thing with the second glob

arg0 X arg2 = { (x,y) where x in arg0 and y in arg2 } the space of all combinations couples.

if for example:

arg0 =

./src/some/main.js
./src/some/another.js

arg2 =

./src/family/dark.fm
./src/family/light.fm
./src/family/stigma.fm

The cartesian product would be a set of 2 * 3 = 6 elements (set of all compositions).

And in the example above the glob call above would be the equiv of:

mix.magic('./src/some/main.js', `./dist/some/main.js`, './src/family/dark.fm')
.magic('./src/some/main.js', `./dist/some/main.js`, './src/family/light.fm')
.magic('./src/some/main.js', `./dist/some/main.js`, './src/family/stigma.fm')
.magic('./src/some/another.js', `./dist/some/another.js`, './src/family/dark.fm')
.magic('./src/some/another.js', `./dist/some/another.js`, './src/family/light.fm')
.magic('./src/some/another.js', `./dist/some/another.js`, './src/family/stigma.fm')

You got the idea. Natural composition.

The relation between src and out is resolved naturally as well. For each cartesian product element. A one to one mapping with src value is done. As src anb out go together and the value is deduced following the config and resolution.

You can check the details in the specific section about src and out in the documentation bellow.

glb.src() & glb.out() & glb.arg()

✨✨✨ 🔥🔥

They can be used together.

src is for running a glob for the source type argument.

out is to set the output config for the output type argument and it go in pair with src and its required. Unless you set it as string to an out dir (no base resolution).

The OutManagerhandle base resolution (mapping files in src directory to dist directory with the same structure). And also extensions mapping. As well as the specifier removing (if used).

in place of

mix
  .ts('./src/reactNoArgs/specifier/some.c.tsx', './dist/reactNoArgs/specifier/some.js')
  //             ^^^^_ src arg                                 ^^^^_ out arg
  .ts('./src/reactNoArgs/specifier/another/some2.c.tsx', './dist/reactNoArgs/specifier/another/some2.js')
  .react();

With globs

mix
  .ts(
    glb.src('./src/reactNoArgs/specifier/**/*.c.tsx'), // <=== source argument
    glb.out({ // <=== out argument
      outMap: './dist',
      baseMap: './src',
      specifier: 'c',
    }),
  )
  .react();

arg is for any other argument that you want to run a glob against it. And so if you use more then one glob. The resolution will happen through the cartesian product. Meaning simply running all possibilities of the two/or more matched sets by the globs products (as explained in the precedent section).

In case of just two. The globs are run for each one of src and arg. and then the product of the two sets is iterated (cartesian product).

And out doesn't use glob. But rather match the different combination. And is used to map each matching product. To a given output. For the output argument.

glb.out() and OutManager

Internally when you pass the glb.out() param. The OutManager would take the config. And handle the output accordingly.

For options we have:

outMap (required) baseMap (optional) extensionMap (optional) specifier (optional)

All of the options can be either

string

or a function of the following signature:

type TMapFunc = (
  file: string,
  mixFuncName: string,
) => string

That allow a file to file mapping (files matched by the glb.src() glob). Again glb.out() and glb.src() go in pair.

You would like to use the function version if you want to do some conditional setting.

The baseMap

Allow you to set the src base. So it would map against the outMap dist directory keeping the same structure.

If baseMap is not set. All files will be mapped in a flat manner to the same dist directory (dist for example only).

Example:

mix
  .ts(
    glb.src('./src/reactNoArgs/specifier/**/*.c.tsx'),
    glb.out({
      baseMap: './src',
      outMap: './dist',
      specifier: 'c',
    }),
  )
  .react();

All files will be mapped keeping the same structure as in src to dist.

mix
  .ts(
    glb.src('./src/reactNoArgs/specifier/**/*.c.tsx'),
    glb.out({
      // baseMap: './src',
      outMap: './dist',
      specifier: 'c',
    }),
  )
  .react();

All files will be mapped to the same dist directory in a flat manner.

The specifier

The specifier is a feature that help you differentiate files from others. So you can set a specifier in the example above it's c. In order to glob match only the files that have the c specifier (which can stand for compile). And if you specify the specifier option. The OutManager will automatically remove it on the output. src/some.c.js => dist/some.js.

And so you can have a structure like this:

toCompile1.c.js // import both core.js and another.js
core.js
another.js
folder/toCompile2.c.js // import both util.js and manager.js
folder/util.js
folder/manager.js

with using the specifier. You would only compile and bundle toCompile1.c.js and folder/toCompile2.c.js with all of there imports (webpack bundling). But without the modules that doesn't need to.

Here an illustration in laravel:

resources

And the output will be

output

output

The extensionMap

If provided as string => that would be the used value.

However it have to be compatible with webpack support for the specific mix function.

Example:

If you go with:

mix.ts('src/index.ts', 'dist/index.ts')

The output would be:

`dist/index.ts.js`

and not ❌

`dist/index.ts` // ❌

By default if not provided. The default extension mapping will be used. Which is implemented part of the OutManager. And the OutManager will automatically resolve the extension correctly.

You can check the defaults and contribute to them on (just in case):

  • src/MixFunctionSettings/index.ts function based mapping.
  • src/MixGlob/OutManager/extensionMapping.ts standard file extension mapping.

For contribution open PR's or issues at laravel-mix-glob repo

To extend you have to use the function signature of extensionMap to build a custom extended function.

Check the glb.resolveExtension() helper section bellow to see how to extend and build custom extended extension mapper based on the default implemented mapping and resolution. Just in case you fall in that scenario.

All typical mix functions are supported. But with the different mix extensions new things can be introduced. And you have that flexibility check the section about extending and custom. As well remember you can simply just set the value directly as string.

Mainly you wouldn't need to use this option:

// no globs
mix.sass('./src/styles/noGlobs/style.scss', './dist/styles/noGlobs/')
// with src out
    .sass(
        glb.src('./src/styles/doneWithSrcOut/specifier/**/*.c.scss'),
        glb.out({
          baseMap: './src',   
          outMap: './dist',
          specifier: 'c',
        }), // Just rely on the default resolution
    );      // ✅ use it when you fall in a scenario that required you. Or to be verbose.
            // Or when webpack support multiple output extensions.

Just rely on the default resolution
✅ use it when you fall in a scenario that required you. Or to be verbose.
Or when webpack support multiple output extensions.

glb.args() helper

Allow you to run a glob and generate for each match the full list of args. It's the most flexible way. That allow conditional mapping.

Note you have the following helpers to use with it:

glb.removeSpecifier() & glb.replaceExtension()

glb.removeSpecifier() is used to remove the specifier more easily. And glb.replaceExtension() is used to replace the extension more easily as well.

  out = glb.replaceExtension(out, '.js'); // <<<<==== replace the extension easily
  out = glb.removeSpecifier(out, 'c'); // <<<<==== remove the specifier if you want easily. Here it's `c`

Full example with args:

mix.js(
  glb.args('./src/relative/doneWithArgs/specifier/**/*.c.js', (src) => {
    let out = path.resolve(
      path.resolve(__dirname, './dist'),
      path.relative(path.resolve(__dirname, './src'), src),
    ); // <<<<===== base relative resolution 
    out = glb.replaceExtension(out, '.js'); // <<<<==== helpers
    out = glb.removeSpecifier(out, 'c'); // <<<<====
    
    return [src, out]; // <<<====== returning args
  })
);

And you can see for setting the path relatively to the base.

glb.mapOutput()

Instead of the above the best and easy way would be to use glb.mapOutput(). An alias toward the internal output resolution module.

Set the baseMap (src base). Can be string or a function (per file mapping).

Set the outMap (out destination). Can be string or a function (per file mapping) as well.

Set the extensionMap (out extension). Can be string or a function (per file mapping) as well.

And finally Set the specifier if you want to use it and remove it. And it can be a string or a function (per file mapping) as well.

/**
 * With specifier
 */
mix.js(
  glb.args(
    './src/relative/doneWithArgsAndGlbMapOutput/specifier/**/*.c.js',
    (src) => {
      const out = glb.mapOutput({
        src,
        outConfig: glb.out({
          baseMap: './src',
          outMap: './dist',
          extensionMap: '.js',
          specifier: 'c',
        }),
      });
      return [src, out];
    },
  ),
);

/**
 * without specifier
 */
mix.js(
  glb.args(
    './src/relative/doneWithArgsAndGlbMapOutput/noSpecifier/**/*.js',
    (src) => {
      const out = glb.mapOutput({
        src,
        outConfig: glb.out({
          baseMap: './src',
          outMap: './dist',
          extensionMap: '.js',
        }),
      });
      return [src, out];
    },
  ),
);

With functions

mix.js(
  glb.args(
    './src/relative/doneWithArgsAndGlbMapOutput/specifier/**/*.c.js',
    (src) => {
      const out = glb.mapOutput({
        src,
        outConfig: glb.out({
          baseMap: (src, mixFuncName) => /** can conditionally set the value */ './src',
          outMap: (src, mixFuncName) => /** can conditionally set the value */ './dist',
          extensionMap: (src, mixFuncName) => /** can conditionally set the value */ '.js',
          specifier: (src, mixFuncName) => /** can conditionally set the value */ 'c',
        }),
      });
      return [src, out];
    },
  ),
);

If you want to use the extension default mapping following the mix function as well. You can add the mixFuncName param as well.

mix.js( // <-----------------same------------------------------------------
  glb.args(                                                             // |
    './src/relative/doneWithArgsAndGlbMapOutput/specifier/**/*.c.js',   // |
    (src) => {                                                          // |
      const out = glb.mapOutput({                                       // |
        src,                                                            // |
        outConfig: glb.out({                                            // |
          baseMap: './src',                                             // |
          outMap: './dist',                                             // |
          // No extension mapping specified => defaulting to default.   // |
          specifier: 'c',                                               // | 
        }),                                                             // |
        mixFuncName: 'js' // <-----------------same------------------------
      });
      return [src, out];
    },
  ),
);

glb.array() (alias: glb.resolve())

Is used to run a glob and return an array of matching. And you can map them. To be used freely wherever u need. As a pure glob matcher. And in places where an array is expected.

It is equivalent to a glob resolver.

function array(glb: TGlobValue): string[]
type TGlobValue = TGlobPattern | IGlobObj
type TGlobPattern = string | string[]
export interface IGlobObj {
  pattern: TGlobPattern;
  options?: Omit<Options, 'objectMode'>;
}
/**
 * Options is fast-glob Options object
 * import type { Options } from 'fast-glob';
 */

Example:

mix.js(
  glb.args(
    './src/somePlace/**/*.js',
    (src) => {
      const out = (specifier) => 
        glb.mapOutput({
          src,
          outConfig: glb.out({
            baseMap: './src',
            outMap: './dist',
            extensionMap: '.js'
            specifier
          }),
        });

      if (src.test(/.*?\.v\.js/)) {
        return [src, out('v')];
      }

      return [src, out('c')];
    },
  ),
)
.version(glb.array('./src/somePlace/**/*.v.js'));
/**
 * to version only the files with the `v` specifier
 */

The .version() function can take a string[] array of files. U can use glb.array() or the alias glb.resolve() to match the files. You can use something like the 'v' specifier to differentiate those files.

glb.resolveExtension()

The function that resolve the files extension following the mix function mapping if provided (used internally). As per src/MixFunctionSettings/index.ts.
Or fall back to the resolve by the standard file extension mapping as a fallback. As per src/MixGlob/OutManager/extensionMapping.ts.

You can use the relative paths above if you want to contribute any missing default mapping.

You can use this function if you want to override the default mapping or configuration.

By default:

mix
  .ts(
    glb.src('./src/reactNoArgs/specifier/**/*.c.tsx'),
    glb.out({
      outMap: './dist',
      baseMap: './src',
      specifier: 'c',
    }),
  )

You can see no extension mapping is provided. There is a default mapping and the resolution happen automatically. That was set to follow the default mapping laravel-mix setup through webpack.

To know: Laravel mix through the different functions the output extension is fixed. For instance .js() and .ts() will always output .js.

If you go with:

mix.ts('src/index.ts', 'dist/index.ts')

The output would be:

`dist/index.ts.js`

and not ❌

`dist/index.ts` // ❌

That's how mix works through webpack. And for this reason there is no point in changing extensions.

So why exposing this internal helper ?

The answer is for flexibility. In case you need to extend the default mapping before you fill a pr. For what is not supported yet through laravel-mix-glob.

Or if you need it for some scripting or tool you may be making.

const extendedExtensionMap = (src, mixFuncName) => {
  if (['some', 'bom', 'Kabom'].includes(mixFuncName)) {
    return /** your extended costume resolution */
  }
  /** you can do your custom resolution the way you want it. Just make sure it align with how mix work for given functions. Or file types. */
  return glb.resolveExtension(src, mixFuncName); // default last
}

mix
  .ts(
    glb.src('./src/reactNoArgs/specifier/**/*.c.tsx'),
    glb.out({
      outMap: './dist',
      baseMap: './src',
      extensionMap: extendedExtensionMap, // You would start using it through all functions
      specifier: 'c',
    }),
  )
  .react();

mix.kabom(
  glb.src('./src/reactNoArgs/specifier/**/*.c.tsx'),
  glb.out({
    outMap: './dist',
    baseMap: './src',
    extensionMap: extendedExtensionMap, // You would start using it through all functions
    specifier: 'c',
  }),
)

Again check src/MixFunctionSettings/index.ts and src/MixGlob/OutManager/extensionMapping.ts to know better.

Know that you can use it as:

glb.resolveExtension(src);

Without mixFuncName argument (optional). And it would only resolve by standard file extension mapping only. As per src/MixGlob/OutManager/extensionMapping.ts.

Generally however rarely you would need to use this helper. This is just a note to let you know that it does exist. And you have this flexibility just in case.

glb.EXTENSION_FILE_MAPPING & glb.MIX_DEFAULT_FUNCTIONS_SETTINGS & glb.SRC_OUT_FUNCTIONS

Those constant used in the above glb.resolveExtension() function, are exposed to you as well. Just in case you need them for whatever flexibility.

Again check src/MixFunctionSettings/index.ts and src/MixGlob/OutManager/extensionMapping.ts to know better.

glb.EXTENSION_FILE_MAPPING for standard file extension mapping resolution.

glb.MIX_DEFAULT_FUNCTIONS_SETTINGS configuration for mix functions. It includes the extension mapping per function configuration (at this moment. It's the only set configuration).

glb.SRC_OUT_FUNCTIONS the list of functions that expect src and out.

Note: If you find yourself in a situation where the default settings up to know doesn't cover your case. Please extends the resolution yourself as shown by the precedent section. And please open a PR to add the correct mapping so that it would be available by default in the next versions.

Using globs with other extensions

All you need to do is to import laravel-mix-glob last.

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

/**
 * Loading extensions
 */
require('laravel-mix-swc');
// then laravel-mix-glob
const { glb } = require('laravel-mix-glob');

/**
 * srcOut
 */

mix.swc(
  glb.src('./src/swcExtenssionWithArg/srcOut/**/*.ts'),
  glb.out({ baseMap: './src', outMap: './dist' }),
  {
    test: '.*.ts$',
    jsc: {
      parser: {
        syntax: 'typescript',
      },
    },
  },
);

/**
 * arg
 */

mix.swc(
  glb.arg('./src/swcExtenssionWithArg/arg/**/*.ts'),
  'dist/swcExtenssionWithArg/arg',
  {
    jsc: {
      parser: {
        syntax: 'ecmascript',
        jsx: false,
      },
    },
  },
);

/**
 * Works perfectly with other extension just the same way.
 * It's all about making calls.
 */

What about pre-configuration

If you want to pre-configure anything. Like in the v1. The way to go in v2. Is to create the according configuration on top of the file. And re-use it in the calls wherever you need.

Example:

Same OutConfig for output base configuration.

a great way in case you need some flexibility is to set some functions:

const outConfig1 = (specifier = 'c', extensionMap = '') => {
  glb.out({
    outMap: './dist',
    baseMap: './src',
    extensionMap,
    specifier,
  }),
};

mix
  .ts(
    glb.src('./src/reactNoArgs/specifier/**/*.c.tsx'),
    outConfig1()
  )
  .react();

mix
  .js(
    glb.src('./src/**/*.js'),
    outConfig1('')
  )

mix
  .js(
    glb.src('./src/**/*.comp.js'),
    outConfig1('comp')
  )

// or

const outConfig1 = glb.out({
  outMap: './dist',
  baseMap: './src',
  specifier,
})

mix
  .js(
    glb.src('./src/*.c.js'),
    outConfig1
  )

You got the idea and about just anything. It's better and more flexible that way. It leave the design more clean and simple.

Build Restart and watching

As in v1. V2 restart and watching system was enhanced.

If you are new. Know that in watch mode npx mix watch or hot. When you add new files or remove or rename ...., that are matched by the globs. laravel-mix-glob extension will automatically restart the build process.

The way it achieve that is through leveraging chokidar for glob file-system watching. And when an even requiring restart is detected. The extension will launch a new process. And kill the old one. Except for the master, the all starting process. Which would be put to sleep.

A re-design that augment efficiency. And in this version. The restart feature support multiple sessions or instances of laravel-mix processes or jobs. And the handling of cleaning the orphans is efficient. As well as the interruption to kill the current process. No more of the old workaround. CTRL + C works perfectly now.

Both watch and hot are supported.

# watch
npx mix watch
# hot
npx mix hot

Globs

laravel-mix-glob use fast glob internally. For full support for auto restart. You can provide the glob as a string or an array.
(You can use an object {pattern: <string> | <array> , options: <FastGlobOptions>} or a function that return files (signature: (globResolve) => <filesList>) (can be any function, and it take fastGlob resolution function as a parameter, can be used).

The function format is not supported at all by the restart functionality.

Try using string or string[] all of the time. In case you need some fast-glob options. You can use the object format. It's better supported for the restart in v2. But it may not support all of the features. In v2 a mapping to chokidar was implemented as best as possible.

Here an example of using string[] to reduce two calls to just one (rather then repeating twice for tsx and ts (here it's different folders)).

mix
  .ts(
    glb.src([
      './src/relative/doneWithSrcOut/specifier/**/*.c.ts',
      './src/reactNoArgs/specifier/**/*.c.tsx', // string[] multiple globs patterns 
    ]),
    glb.out({
      baseMap: './src',
      outMap: './dist',
      specifier: 'c',
    }),
  )
  .react();

Globbing patterns

from globby doc

Just a quick overview.

  • * matches any number of characters, but not /
  • ? matches a single character, but not /
  • ** matches any number of characters, including /, as long as it's the only thing in a path part
  • {} allows for a comma-separated list of "or" expressions
  • ! at the beginning of a pattern will negate the match

Various patterns and expected matches.

Logging

Logging was updated in v2.

Including for the debugging purpose.

As in the v1. The same system with debug package remain. The logs within the app have changed. Plus a silent mode was added in response to the issue 63.

LOGGING AND DEBUGGING

Laravel-mix-glob use debug module for it's logging! With MixGlob domaine for log. And MixGlob:error domaine for error. And MixGlob:debug domaine for debug.

Debugging logs

To activate debugging logs, you have to set the env var DEBUG to "true" or "1". And that's the simplest way!

Otherwise you can set DEBUG to anything you want! Following debug module syntax!

ex: DEBUG=*

One may need to do that if he want to see the logs of all packages that are working with debug module. However if DEBUG=1 or DEBUG=true were used! Only MixGlob logging will run. And that's the simplest form! You don't even need to know about the debug module.

Where to set the env variable for debugging ?

You can set the env var either at the script launch. And that would be on package.json developement script!

And it's preferable to use cross-env.

Example:

"scripts": {
    "dev": "npm run development",
    "development": "cross-env DEBUG=1 mix",
    "watch": "cross-env DEBUG_SHOW_HIDDEN=true DEBUG=true mix watch",
    "hot": "mix watch --hot",
    "prod": "npm run production",
    "production": "mix DEBUG=MixGlob:Error --production"
},
npm i -D cross-env

Only for example. Generally you don't need to do anything. But that does show how you can do it.

Or because it's just debugging! One can simply add this in webpack.mix.js before requiring laravel-mix-glob

process.env.DEBUG=true; // 1 works too
const MixGlob = require('laravel-mix-glob');

Logging tweaking

There is some tweaks for the logging format! Those logging tweaks are described by this from debug doc (here):

Name Purpose
DEBUG_HIDE_DATE Hide date from debug output (non-TTY).
DEBUG_COLORS Whether or not to use colors in the debug output.
DEBUG_DEPTH Object inspection depth.
DEBUG_SHOW_HIDDEN Shows hidden properties on inspected objects.

Better aliases are available:

Name Purpose
LOG_HIDE_DATE Hide date from debug output (non-TTY).
LOG_COLORS Whether or not to use colors in the debug output.
LOG_DEPTH Object inspection depth.
LOG_SHOW_HIDDEN Shows hidden properties on inspected objects.

Silent mode (no logging)

If you want to go for silent logging at the level of this extension. You can do it through the following env variables:

NO_LOG
SILENT_LOG
"watch": "cross-env SILENT_LOG=true npx mix watch"

Other laravel mix extensions

Here bellow some extension that are helpful for debugging and logging that i built:

  • laravel-mix-webpack-config to access webpack configuration as object or string unlike dump() which only print to console. With extension you can write to file or whatever you want. Check the examples.

  • laravel-mix-listen A laravel mix extension that allow us to listen to Mix internal events. More advanced then laravel-mix-webpack-config. It allow to listen to many events. Including to access webpack config. At different stages. Check the examples.

Issues and features requests

Don't hesitate to fill an issue for any bug, or feature request. :heartbeat: All contribution are appreciated :heartbeat:

Check the contribution guide bellow.

Contribution

Read the contribution guide.

  • Be nice.
  • Feel free to fill any issue.
  • Feel free to fill any PR.
  • Please contribute code examples if you see it would help you or others. And files to documentation/v2/examples and fill PR's.
  • Show your support by staring the project 💓 => one click away => let me star ✨✨✨✨✨✨✨✨.
  • Feel free to contact me at [email protected]

Don't forget to star ✨ the project. 💓 ❤️. It's a click away => let me star ✨✨✨✨✨✨✨✨

laravel-mix-glob's People

Contributors

caddydz avatar dependabot[bot] avatar elgandoz avatar mohamedlamineallal avatar venipa avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

laravel-mix-glob's Issues

.version()

Hello,

I'm having issues when using .version() in the following for example:

mixGlob.sass('app/Modules/**/Resources/assets/admin/sass/*.scss', 'public/css') .version();

Is this not supported or am I using it incorrectly?

Error: read ENOTCONN

Having an issue running 'mix watch' while using mixglob... Getting the following error:

Error: read ENOTCONN
at tryReadStart (net.js:575:20)
at WriteStream.Socket.read (net.js:586:5)
at WriteStream.Readable.read (internal/streams/readable.js:462:10)
at WriteStream.Socket.read (net.js:627:39)
at resume
(internal/streams/readable.js:958:12)
at processTicksAndRejections (internal/process/task_queues.js:82:21)
Emitted 'error' event on WriteStream instance at:
at emitErrorNT (internal/streams/destroy.js:106:8)
at emitErrorCloseNT (internal/streams/destroy.js:74:3)
at processTicksAndRejections (internal/process/task_queues.js:82:21) {
errno: -4053,
code: 'ENOTCONN',
syscall: 'read'
}

It almost seems like it's trying to call watch twice, and the files are still locked from the previous run.

Any ideas?

Vue - defaultMapExt: no mapping precised, neither it's supported by default

Hello and thanks for this amazing plugin. I have used it on other projects but never before with vue.

I am trying to get this plugin to work with an existing vue app. I experience the error defaultMapExt: no mapping precised, neither it's supported by default when building my js/vue components which is very vague and I have not been able to find a solution.

I have looked through #52 and reread the documentation and have stuck the mapping everywhere that I can think of that might make sense... does this plugin support .vue()?

I have the appropriate vue-loader and vue-template-compiler installed. When I compile without the .vue() command I get the expected You may need an appropriate loader to handle this file type. I can successfully compile these using the normal mix.js() with the sources as a stack, and call the .vue() command at the end and it works but it is a lot of files. Hence why I would like to use this plugin.

Some assistance or guidance on what I am doing wrong would be appreciated.

My webpack.mix.js contents

const mix = require("laravel-mix"),
    MixGlob = require("laravel-mix-glob"),
    srcPath = "resources",
    distPath = "public",
    mixGlob = new MixGlob({
        mix,
        mapping: {
            js: {
                ext: "js",
            },
            vue: {
                ext: "js",
            },
            sass: {
                ext: "css",
            },
            css: {
                ext: "css",
            },
            postCss: {
                ext: "css",
            },
        },
    });

mix.autoprefixer = [
    "Android 2.3",
    "Android >= 4",
    "Chrome >= 20",
    "Firefox >= 24",
    "Explorer >= 10",
    "iOS >= 6",
    "Opera >= 12",
    "Safari >= 6",
];

mix.setPublicPath(distPath)
    .options({
        processCssUrls: false,
        preset: "vanilla",
        browsers: ["last 20 versions", "ie 10-11"],
        grid: true,
        imgLoaderOptions: {
            enabled: false,
        },
    })
    .sourceMaps();

//Works just fine
mixGlob.sass([srcPath + "/sass/*.scss"], "public/css", null, {
    base: srcPath + "/sass/",
    precision: 8,
});
//
mixGlob
    .js([srcPath + "/js/**/*.{js,vue}"], "public/js", null, {
        base: srcPath + "/js/",
        mapping: {
            js: {
                ext: "js",
            },
            vue: {
                ext: "js",
            },
        },
    })
    .vue();

//JS Eloquent Classes
mix.babel([srcPath + "/js/classes/*.js"], "public/js/EloquentClasses.js");
//Copy assets
mix.copy(srcPath + "/json", "public/json")
    .copy(srcPath + "/fonts", "public/fonts")
    .copy(srcPath + "/images", "public/images")
    .copy(srcPath + "/plugins", "public/plugins")
    .copy(
        "node_modules/@fortawesome/fontawesome-free/webfonts",
        "public/webfonts"
    )
    .copy(
        "node_modules/bootstrap-sass/assets/fonts/bootstrap",
        "public/fonts/bootstrap"
    );

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


Package.json

{
   ...
    "devDependencies": {
        "@vue/compiler-sfc": "^3.2.33",
        "autoprefixer": "^10.4.7",
        "axios": "^0.27.2",
        "cross-env": "^5.1",
        "jquery": "^3.3.1",
        "laravel-mix": "^6.0.43",
        "laravel-mix-glob": "^1.1.10",
        "less": "^3.9.0",
        "lodash": "^4.17.5",
        "postcss-cssnext": "^3.1.1",
        "postcss-import": "^14.1.0",
        "resolve-url-loader": "^2.3.1",
        "sass": "^1.22.3",
        "sass-loader": "^12.6.0",
        "vue": "^3.2.33",
        "vue-loader": "^17.0.0"
    },
    "dependencies": {
        "@fancyapps/fancybox": "^3.5.7",
        "@fortawesome/fontawesome-free": "^6.1.1",
        "awesome-notifications": "^2.2.9",
        "bootstrap": "^4.3.1",
        "bootstrap-sass": "^3.4.1",
        "bootstrap-select": "1.13.5",
        "bootstrap-switch": "^3.3.4",
        "busy-load": "^0.1.2",
        "datatables.net": "^1.10.19",
        "datatables.net-bs": "^1.10.19",
        "datatables.net-buttons-bs": "^1.5.4",
        "datatables.net-colreorder-bs": "^1.5.1",
        "datatables.net-dt": "^1.10.19",
        "datatables.net-fixedheader-bs": "^3.1.5",
        "datatables.net-keytable-bs": "^2.5.0",
        "datatables.net-responsive-bs": "^2.2.3",
        "datatables.net-responsive-dt": "^2.2.3",
        "datatables.net-rowgroup-bs": "^1.1.0",
        "datatables.net-rowreorder-bs": "^1.2.5",
        "datatables.net-scroller-bs": "^1.5.1",
        "datatables.net-select-bs": "^1.2.7",
        "daterangepicker": "^3.0.3",
        "jquery-ui": "^1.12.1",
        "jquery-ui-dist": "^1.12.1",
        "jquery-validation": "^1.19.0",
        "jquery.uniform": "^4.3.0",
        "material-design-icons": "^3.0.1",
        "moment": "^2.24.0",
        "popper.js": "^1.15.0",
        "sanitize-html": "^1.20.1",
        "select2": "^4.0.13",
        "switchery": "0.0.2",
        "toastr": "^2.1.4",
        "typeahead": "^0.2.2",
        "uniform": "^0.5.1",
        "velocity-animate": "^1.5.2"
    }
 }

Compiler output

npx mix             541ms  Fri 06 May 2022 04:25:12 PM
 MixGlob Mix glob +0ms
 MixGlob mix function: sass +1ms
 MixGlob Glob: resources/sass/*.scss +0ms
 MixGlob Matched files ==== +5ms
 MixGlob [
 MixGlob   'resources/sass/app.scss',
 MixGlob   'resources/sass/dashboard.scss',
 MixGlob   'resources/sass/landing.scss',
 MixGlob   'resources/sass/login.scss',
 MixGlob   'resources/sass/opportunities.scss',
 MixGlob   'resources/sass/print.scss',
 MixGlob   'resources/sass/profiles.scss',
 MixGlob   'resources/sass/settings.scss'
 MixGlob ] +0ms
 MixGlob { file: 'app.css', out: 'public/css/app.css' } +1ms
 MixGlob { file: 'dashboard.css', out: 'public/css/dashboard.css' } +1ms
 MixGlob { file: 'landing.css', out: 'public/css/landing.css' } +0ms
 MixGlob { file: 'login.css', out: 'public/css/login.css' } +0ms
 MixGlob { file: 'opportunities.css', out: 'public/css/opportunities.css' } +0ms
 MixGlob { file: 'print.css', out: 'public/css/print.css' } +0ms
 MixGlob { file: 'profiles.css', out: 'public/css/profiles.css' } +0ms
 MixGlob { file: 'settings.css', out: 'public/css/settings.css' } +0ms
 MixGlob mix function: js +1ms
 MixGlob Glob: resources/js/**/*.{js,vue} +0ms
 MixGlob Matched files ==== +4ms
 MixGlob [
 MixGlob   'resources/js/Ajax.js',
 MixGlob   'resources/js/CoreDataTablesFilter.js',
 MixGlob   'resources/js/NotifierServerSide.js',
 MixGlob   'resources/js/app.js',
 MixGlob   'resources/js/app2.js',
 MixGlob   'resources/js/blockui.min.js',
 MixGlob   'resources/js/bootstrap.js',
 MixGlob   'resources/js/langUI-root.js',
 MixGlob   'resources/js/prism.min.js',
 MixGlob   'resources/js/progressbar.min.js',
 MixGlob   'resources/js/vue-for-jobs.js',
 MixGlob   'resources/js/vue-for-resource.js',
 MixGlob   'resources/js/vue-for-resources.js',
 MixGlob   'resources/js/vue-for-resumes.js',
 MixGlob   'resources/js/vue-for-training.js',
 MixGlob   'resources/js/vue-for-trainings.js',
 MixGlob   'resources/js/classes/AOI_Resume.js',
 MixGlob   'resources/js/classes/Award.js',
 MixGlob   'resources/js/classes/Education.js',
 MixGlob   'resources/js/classes/Employment.js',
 MixGlob   'resources/js/classes/Resume.js',
 MixGlob   'resources/js/classes/Skill.js',
 MixGlob   'resources/js/components/ApplyForJobModal.vue',
 MixGlob   'resources/js/components/BootstrapSelect.vue',
 MixGlob   'resources/js/components/DateRangePicker.vue',
 MixGlob   'resources/js/components/JobDetails.vue',
 MixGlob   'resources/js/components/JobGridListItem.vue',
 MixGlob   'resources/js/components/Modal_AddNewResume.vue',
 MixGlob   'resources/js/components/Modal_AddNewSkill.vue',
 MixGlob   'resources/js/components/Modal_ResumeAward.vue',
 MixGlob   'resources/js/components/Modal_ResumeCoverLetter.vue',
 MixGlob   'resources/js/components/Modal_ResumeEducation.vue',
 MixGlob   'resources/js/components/Modal_ResumeEmployment.vue',
 MixGlob   'resources/js/components/Modal_ResumeOverview.vue',
 MixGlob   'resources/js/components/PublicJobPostingsList.vue',
 MixGlob   'resources/js/components/Resume.vue',
 MixGlob   'resources/js/components/ResumeItemAward.vue',
 MixGlob   'resources/js/components/ResumeItemEducation.vue',
 MixGlob   'resources/js/components/ResumeItemEmployment.vue',
 MixGlob   'resources/js/components/ResumeSectionAwards.vue',
 MixGlob   'resources/js/components/ResumeSectionEducation.vue',
 MixGlob   'resources/js/components/ResumeSectionEmployment.vue',
 MixGlob   'resources/js/components/ResumeSectionInterests.vue',
 MixGlob   'resources/js/components/ResumeSectionOverview.vue',
 MixGlob   'resources/js/components/ResumeSectionSkills.vue',
 MixGlob   'resources/js/components/ResumeSectionTitle.vue',
 MixGlob   'resources/js/components/SidePanelComponent.vue',
 MixGlob   'resources/js/components/SidePanelItem.vue',
 MixGlob   'resources/js/components/SidePanelList.vue',
 MixGlob   'resources/js/mixins/EloquentMirrorVue.js',
 MixGlob   'resources/js/mixins/InfiniteScrollingList.js',
 MixGlob   'resources/js/mixins/JobSeekerSidebar.js',
 MixGlob   'resources/js/pages/add-company.js',
 MixGlob   'resources/js/pages/add-opportunity.js',
 MixGlob   'resources/js/pages/add-resource.js',
 MixGlob   'resources/js/pages/add-training.js',
 MixGlob   'resources/js/pages/add-user.js',
 MixGlob   'resources/js/pages/admin-dashboard.js',
 MixGlob   'resources/js/pages/admin-opportunities.js',
 MixGlob   'resources/js/pages/applicants-list.js',
 MixGlob   'resources/js/pages/employer-opportunities.js',
 MixGlob   'resources/js/pages/employer-profile.js',
 MixGlob   'resources/js/pages/experiences-dashboard.js',
 MixGlob   'resources/js/pages/job-opportunities.js',
 MixGlob   'resources/js/pages/language_picker.js',
 MixGlob   'resources/js/pages/login.js',
 MixGlob   'resources/js/pages/manage-companies.js',
 MixGlob   'resources/js/pages/manage-localizations.js',
 MixGlob   'resources/js/pages/manage-resources.js',
 MixGlob   'resources/js/pages/manage-training.js',
 MixGlob   'resources/js/pages/profile.js',
 MixGlob   'resources/js/pages/register.js',
 MixGlob   'resources/js/pages/resume.js',
 MixGlob   'resources/js/pages/settings.js',
 MixGlob   'resources/js/pages/users-list.js',
 MixGlob   'resources/js/pages/value-list-standard.js',
 MixGlob   'resources/js/components/Localization/Localization.vue',
 MixGlob   'resources/js/components/Localization/LocalizationRow.vue',
 MixGlob   'resources/js/components/Resources/ResourceDetails.vue',
 MixGlob   'resources/js/components/Resources/Resources.vue',
 MixGlob   'resources/js/components/Resources/ResourcesItem.vue',
 MixGlob   'resources/js/components/Training/TrainingDetails.vue',
 MixGlob   'resources/js/components/Training/Trainings.vue',
 MixGlob   'resources/js/components/Training/TrainingsItem.vue',
 MixGlob   'resources/js/upload/fileinput/fileinput.min.js',
 MixGlob   'resources/js/upload/fileinput/plugins/piexif.min.js',
 MixGlob   'resources/js/upload/fileinput/plugins/purify.min.js',
 MixGlob   'resources/js/upload/fileinput/plugins/sortable.min.js'
 MixGlob ] +0ms
 MixGlob { file: 'Ajax.js', out: 'public/js/Ajax.js' } +1ms
 MixGlob {
 MixGlob   file: 'CoreDataTablesFilter.js',
 MixGlob   out: 'public/js/CoreDataTablesFilter.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'NotifierServerSide.js',
 MixGlob   out: 'public/js/NotifierServerSide.js'
 MixGlob } +0ms
 MixGlob { file: 'app.js', out: 'public/js/app.js' } +0ms
 MixGlob { file: 'app2.js', out: 'public/js/app2.js' } +0ms
 MixGlob { file: 'blockui.min.js', out: 'public/js/blockui.min.js' } +1ms
 MixGlob { file: 'bootstrap.js', out: 'public/js/bootstrap.js' } +0ms
 MixGlob { file: 'langUI-root.js', out: 'public/js/langUI-root.js' } +0ms
 MixGlob { file: 'prism.min.js', out: 'public/js/prism.min.js' } +0ms
 MixGlob { file: 'progressbar.min.js', out: 'public/js/progressbar.min.js' } +0ms
 MixGlob { file: 'vue-for-jobs.js', out: 'public/js/vue-for-jobs.js' } +0ms
 MixGlob { file: 'vue-for-resource.js', out: 'public/js/vue-for-resource.js' } +0ms
 MixGlob { file: 'vue-for-resources.js', out: 'public/js/vue-for-resources.js' } +0ms
 MixGlob { file: 'vue-for-resumes.js', out: 'public/js/vue-for-resumes.js' } +0ms
 MixGlob { file: 'vue-for-training.js', out: 'public/js/vue-for-training.js' } +0ms
 MixGlob { file: 'vue-for-trainings.js', out: 'public/js/vue-for-trainings.js' } +0ms
 MixGlob {
 MixGlob   file: 'classes/AOI_Resume.js',
 MixGlob   out: 'public/js/classes/AOI_Resume.js'
 MixGlob } +0ms
 MixGlob { file: 'classes/Award.js', out: 'public/js/classes/Award.js' } +1ms
 MixGlob { file: 'classes/Education.js', out: 'public/js/classes/Education.js' } +0ms
 MixGlob {
 MixGlob   file: 'classes/Employment.js',
 MixGlob   out: 'public/js/classes/Employment.js'
 MixGlob } +0ms
 MixGlob { file: 'classes/Resume.js', out: 'public/js/classes/Resume.js' } +0ms
 MixGlob { file: 'classes/Skill.js', out: 'public/js/classes/Skill.js' } +0ms
 MixGlob {
 MixGlob   file: 'components/ApplyForJobModal.js',
 MixGlob   out: 'public/js/components/ApplyForJobModal.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/BootstrapSelect.js',
 MixGlob   out: 'public/js/components/BootstrapSelect.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/DateRangePicker.js',
 MixGlob   out: 'public/js/components/DateRangePicker.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/JobDetails.js',
 MixGlob   out: 'public/js/components/JobDetails.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/JobGridListItem.js',
 MixGlob   out: 'public/js/components/JobGridListItem.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/Modal_AddNewResume.js',
 MixGlob   out: 'public/js/components/Modal_AddNewResume.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/Modal_AddNewSkill.js',
 MixGlob   out: 'public/js/components/Modal_AddNewSkill.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/Modal_ResumeAward.js',
 MixGlob   out: 'public/js/components/Modal_ResumeAward.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/Modal_ResumeCoverLetter.js',
 MixGlob   out: 'public/js/components/Modal_ResumeCoverLetter.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/Modal_ResumeEducation.js',
 MixGlob   out: 'public/js/components/Modal_ResumeEducation.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/Modal_ResumeEmployment.js',
 MixGlob   out: 'public/js/components/Modal_ResumeEmployment.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/Modal_ResumeOverview.js',
 MixGlob   out: 'public/js/components/Modal_ResumeOverview.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/PublicJobPostingsList.js',
 MixGlob   out: 'public/js/components/PublicJobPostingsList.js'
 MixGlob } +0ms
 MixGlob { file: 'components/Resume.js', out: 'public/js/components/Resume.js' } +1ms
 MixGlob {
 MixGlob   file: 'components/ResumeItemAward.js',
 MixGlob   out: 'public/js/components/ResumeItemAward.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/ResumeItemEducation.js',
 MixGlob   out: 'public/js/components/ResumeItemEducation.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/ResumeItemEmployment.js',
 MixGlob   out: 'public/js/components/ResumeItemEmployment.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/ResumeSectionAwards.js',
 MixGlob   out: 'public/js/components/ResumeSectionAwards.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/ResumeSectionEducation.js',
 MixGlob   out: 'public/js/components/ResumeSectionEducation.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/ResumeSectionEmployment.js',
 MixGlob   out: 'public/js/components/ResumeSectionEmployment.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/ResumeSectionInterests.js',
 MixGlob   out: 'public/js/components/ResumeSectionInterests.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/ResumeSectionOverview.js',
 MixGlob   out: 'public/js/components/ResumeSectionOverview.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/ResumeSectionSkills.js',
 MixGlob   out: 'public/js/components/ResumeSectionSkills.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/ResumeSectionTitle.js',
 MixGlob   out: 'public/js/components/ResumeSectionTitle.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/SidePanelComponent.js',
 MixGlob   out: 'public/js/components/SidePanelComponent.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/SidePanelItem.js',
 MixGlob   out: 'public/js/components/SidePanelItem.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/SidePanelList.js',
 MixGlob   out: 'public/js/components/SidePanelList.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'mixins/EloquentMirrorVue.js',
 MixGlob   out: 'public/js/mixins/EloquentMirrorVue.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'mixins/InfiniteScrollingList.js',
 MixGlob   out: 'public/js/mixins/InfiniteScrollingList.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'mixins/JobSeekerSidebar.js',
 MixGlob   out: 'public/js/mixins/JobSeekerSidebar.js'
 MixGlob } +0ms
 MixGlob { file: 'pages/add-company.js', out: 'public/js/pages/add-company.js' } +0ms
 MixGlob {
 MixGlob   file: 'pages/add-opportunity.js',
 MixGlob   out: 'public/js/pages/add-opportunity.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'pages/add-resource.js',
 MixGlob   out: 'public/js/pages/add-resource.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'pages/add-training.js',
 MixGlob   out: 'public/js/pages/add-training.js'
 MixGlob } +0ms
 MixGlob { file: 'pages/add-user.js', out: 'public/js/pages/add-user.js' } +0ms
 MixGlob {
 MixGlob   file: 'pages/admin-dashboard.js',
 MixGlob   out: 'public/js/pages/admin-dashboard.js'
 MixGlob } +1ms
 MixGlob {
 MixGlob   file: 'pages/admin-opportunities.js',
 MixGlob   out: 'public/js/pages/admin-opportunities.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'pages/applicants-list.js',
 MixGlob   out: 'public/js/pages/applicants-list.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'pages/employer-opportunities.js',
 MixGlob   out: 'public/js/pages/employer-opportunities.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'pages/employer-profile.js',
 MixGlob   out: 'public/js/pages/employer-profile.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'pages/experiences-dashboard.js',
 MixGlob   out: 'public/js/pages/experiences-dashboard.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'pages/job-opportunities.js',
 MixGlob   out: 'public/js/pages/job-opportunities.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'pages/language_picker.js',
 MixGlob   out: 'public/js/pages/language_picker.js'
 MixGlob } +0ms
 MixGlob { file: 'pages/login.js', out: 'public/js/pages/login.js' } +0ms
 MixGlob {
 MixGlob   file: 'pages/manage-companies.js',
 MixGlob   out: 'public/js/pages/manage-companies.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'pages/manage-localizations.js',
 MixGlob   out: 'public/js/pages/manage-localizations.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'pages/manage-resources.js',
 MixGlob   out: 'public/js/pages/manage-resources.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'pages/manage-training.js',
 MixGlob   out: 'public/js/pages/manage-training.js'
 MixGlob } +1ms
 MixGlob { file: 'pages/profile.js', out: 'public/js/pages/profile.js' } +0ms
 MixGlob { file: 'pages/register.js', out: 'public/js/pages/register.js' } +0ms
 MixGlob { file: 'pages/resume.js', out: 'public/js/pages/resume.js' } +0ms
 MixGlob { file: 'pages/settings.js', out: 'public/js/pages/settings.js' } +0ms
 MixGlob { file: 'pages/users-list.js', out: 'public/js/pages/users-list.js' } +0ms
 MixGlob {
 MixGlob   file: 'pages/value-list-standard.js',
 MixGlob   out: 'public/js/pages/value-list-standard.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/Localization/Localization.js',
 MixGlob   out: 'public/js/components/Localization/Localization.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/Localization/LocalizationRow.js',
 MixGlob   out: 'public/js/components/Localization/LocalizationRow.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/Resources/ResourceDetails.js',
 MixGlob   out: 'public/js/components/Resources/ResourceDetails.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/Resources/Resources.js',
 MixGlob   out: 'public/js/components/Resources/Resources.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/Resources/ResourcesItem.js',
 MixGlob   out: 'public/js/components/Resources/ResourcesItem.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/Training/TrainingDetails.js',
 MixGlob   out: 'public/js/components/Training/TrainingDetails.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/Training/Trainings.js',
 MixGlob   out: 'public/js/components/Training/Trainings.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'components/Training/TrainingsItem.js',
 MixGlob   out: 'public/js/components/Training/TrainingsItem.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'upload/fileinput/fileinput.min.js',
 MixGlob   out: 'public/js/upload/fileinput/fileinput.min.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'upload/fileinput/plugins/piexif.min.js',
 MixGlob   out: 'public/js/upload/fileinput/plugins/piexif.min.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'upload/fileinput/plugins/purify.min.js',
 MixGlob   out: 'public/js/upload/fileinput/plugins/purify.min.js'
 MixGlob } +0ms
 MixGlob {
 MixGlob   file: 'upload/fileinput/plugins/sortable.min.js',
 MixGlob   out: 'public/js/upload/fileinput/plugins/sortable.min.js'
 MixGlob } +0ms
[webpack-cli] defaultMapExt: no mapping precised, neither it's supported by default

"No debug env var" if process.env.DEBUG* variables not present.

Hi!
(I found #5, but I want to open a new issue with more specific title + description.)

laravel-mix-glob makes noise in the debug output, if none of the process.env.DEBUG* keys are present.

Test scenario

The problem can be reduced to the following webpack.min.js:

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

-> "!!!!! ----- No debug env var ----- !!!!"

process.env.DEBUG = false;
const MixGlob = require('laravel-mix-glob');

-> no warnings

Investigation

The code in noDebugEnvVar() suggests that we need at least one of the following keys in process.env:
The variables are explained on https://github.com/visionmedia/debug, and the same variables are also used in DEBUG_ENV_VARS in laravelMixGlob.min.js.

Name Purpose
DEBUG Enables/disables specific debugging namespaces.
DEBUG_HIDE_DATE Hide date from debug output (non-TTY).
DEBUG_COLORS Whether or not to use colors in the debug output.
DEBUG_DEPTH Object inspection depth.
DEBUG_SHOW_HIDDEN Shows hidden properties on inspected objects.

Questions

This leads me to the following questions:

  • Where do I configure these variables for process.env.DEBUG*?
  • What are reasonable default values?
  • Why does this package make noise if none of the variables are defined? Is this common in other packages?
  • Why is it enough to set one of those variables?
  • Where is this documented?

Successfully setup but error on an npm command

      throw er; // Unhandled 'error' event
      ^

Error: spawn npm ENOENT
    at Process.ChildProcess._handle.onexit (internal/child_process.js:232:19)
    at onErrorNT (internal/child_process.js:407:16)
    at process._tickCallback (internal/process/next_tick.js:63:19)
Emitted 'error' event at:
    at Process.ChildProcess._handle.onexit (internal/child_process.js:238:12)
    at onErrorNT (internal/child_process.js:407:16)
    at process._tickCallback (internal/process/next_tick.js:63:19)
error Command failed with exit code 1.```

Output to single css file

Is it possible to output the compiled sass to a single css file?

At the moment I have the following:

mixGlob.sass([
    'Modules/Admins/sass/app.scss',
    'Modules/!(Admins)/sass/**/*.scss'
], 'public/css/app.css')

However, this will output each sass file it finds as a single css file. I want it to compile the sass and output to a single css file.

Erro npm run watch

When i run npm run watch i get this error:

webpack is watching the files…

events.js:180
      throw er; // Unhandled 'error' event
      ^

Error: read ENOTCONN
    at WriteStream.Socket._read (net.js:530:20)
    at WriteStream.Readable.read (_stream_readable.js:474:10)
    at resume_ (_stream_readable.js:953:12)
    at processTicksAndRejections (internal/process/task_queues.js:77:11)
Emitted 'error' event at:
    at emitErrorNT (internal/streams/destroy.js:91:8)
    at emitErrorAndCloseNT (internal/streams/destroy.js:59:3)
    at processTicksAndRejections (internal/process/task_queues.js:77:11) {
  errno: 'ENOTCONN',
  code: 'ENOTCONN',
  syscall: 'read'
}

But running the npm run dev, is totally fine!!

OS: Windows
NPM: 6.5.0
NODE: v12.7.0

Version of package installed:

        "laravel-mix": "^4.0.16",
        "laravel-mix-glob": "^1.1.2",

I think it's related to issue #2

0 info it worked if it ends with ok
1 verbose cli [
1 verbose cli   'C:\\Program Files\\nodejs\\node.exe',
1 verbose cli   'C:\\user\\AppData\\Roaming\\npm\\node_modules\\npm\\bin\\npm-cli.js',
1 verbose cli   'run',
1 verbose cli   'development',
1 verbose cli   '--',
1 verbose cli   '--watch'
1 verbose cli ]
2 info using [email protected]
3 info using [email protected]
4 verbose run-script [ 'predevelopment', 'development', 'postdevelopment' ]
5 info lifecycle @0.0.1~predevelopment: @0.0.1
6 info lifecycle @0.0.1~development: @0.0.1
7 verbose lifecycle @0.0.1~development: unsafe-perm in lifecycle true
8 verbose lifecycle @0.0.1~development: PATH: C:\User\--user--\AppData\Roaming\npm\node_modules\npm\node_modules\npm-lifecycle\node-gyp-bin;C:\project\node_modules\.bin;C:\User\--user--\AppData\Roaming\npm\node_modules\npm\node_modules\npm-lifecycle\node-gyp-bin;C:\project\node_modules\.bin;node_modules\.bin\;C:\tools\cmder\bin;C:\tools\cmder\vendor\conemu-maximus5\ConEmu\Scripts;C:\tools\cmder\vendor\conemu-maximus5;C:\tools\cmder\vendor\conemu-maximus5\ConEmu;C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\Python37\Scripts\;C:\Python37\;C:\tools\ruby25\bin;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\ProgramData\chocolatey\bin;C:\tools\php72;C:\ProgramData\ComposerSetup\bin;C:\Program Files\nodejs\;C:\Program Files\Git\cmd;C:\WINDOWS\System32\OpenSSH\;C:\Go\bin;C:\User\--user--\.dnx\bin;C:\User\--user--\AppData\Local\Microsoft\WindowsApps;C:\User\--user--\AppData\Roaming\Composer\vendor\bin;C:\User\--user--\AppData\Roaming\npm;C:\tools\cmder;C:\User\--user--\go\bin;C:\User\--user--\AppData\Local\atom\bin;C:\User\--user--\AppData\Local\Yarn\bin;C:\Program Files\Git\usr\bin;C:\Program Files\Git\usr\share\vim\vim74;C:\tools\cmder\
9 verbose lifecycle @0.0.1~development: CWD: C:\CCSDEV\UTP\app.utp.pt
10 silly lifecycle @0.0.1~development: Args: [
10 silly lifecycle   '/d /s /c',
10 silly lifecycle   'cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js "--watch"'
10 silly lifecycle ]
11 silly lifecycle @0.0.1~development: Returned: code: 1  signal: null
12 info lifecycle @0.0.1~development: Failed to exec development script
13 verbose stack Error: @0.0.1 development: `cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js "--watch"`
13 verbose stack Exit status 1
13 verbose stack     at EventEmitter.<anonymous> (C:\User\--user--\AppData\Roaming\npm\node_modules\npm\node_modules\npm-lifecycle\index.js:301:16)
13 verbose stack     at EventEmitter.emit (events.js:203:13)
13 verbose stack     at ChildProcess.<anonymous> (C:\User\--user--\AppData\Roaming\npm\node_modules\npm\node_modules\npm-lifecycle\lib\spawn.js:55:14)
13 verbose stack     at ChildProcess.emit (events.js:203:13)
13 verbose stack     at maybeClose (internal/child_process.js:1021:16)
13 verbose stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:283:5)
14 verbose pkgid @0.0.1
15 verbose cwd C:\CCSDEV\UTP\app.utp.pt
16 verbose Windows_NT 10.0.17134
17 verbose argv "C:\\Program Files\\nodejs\\node.exe" "C:\\user\\AppData\\Roaming\\npm\\node_modules\\npm\\bin\\npm-cli.js" "run" "development" "--" "--watch"
18 verbose node v12.7.0
19 verbose npm  v6.5.0
20 error code ELIFECYCLE
21 error errno 1
22 error @0.0.1 development: `cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js "--watch"`
22 error Exit status 1
23 error Failed at the @0.0.1 development script.
23 error This is probably not a problem with npm. There is likely additional logging output above.
24 verbose exit [ 1, true ]

Globbing not dealing with checking if files exist

Describe the bug or the problem

When globbing through an empty source folder, an error is output which stops other tasks to run if no files are found.

Repro link if possible

No response

Expected behavior

Globbing should ignore empty folders gracefully.

Actual behavior

Error output:

[webpack-cli] Error: No matched files for the Glob of arg of index 0

webpack.mix.js config

let mix = require('laravel-mix');
const { glb } = require('laravel-mix-glob');

const themePath = 'docroot/themes/custom/mytheme';

mix.sass(
  glb.src(
    [`./stories/01-atoms/**/*.scss`,
    `./stories/02-molecules/**/*.scss`,
    `./stories/03-organisms/**/*.scss`,
    `./stories/04-atoms/**/*.scss`,
    `./stories/04-templates/**/*.scss`]),
  glb.out({
    baseMap: `./stories`,
    outMap: `${themePath}/stories`,
  }),
);

mix.sass(`./stories/00-base/rfs.scss`, `${themePath}/css`);

mix.js(
  glb.src(
    [
      `./stories/01-atoms/**/*.js`,
      `./stories/02-molecules/**/*.js`,
      `./stories/03-organisms/**/*.js`,
      `./stories/04-templates/**/*.js`
    ]),
  glb.out({
    baseMap: `./stories`,
    outMap: `${themePath}/stories`,
  }),
);

mix.minify(`${themePath}/js/script.js`);

mix.copy(
  glb.src(`./stories/**/*.twig`),
  glb.out({
    baseMap: `./stories`,
    outMap: `${themePath}/stories`,
  }),
);

Versions

laravel-mix: 6.0.49,
laravel-mix-glob: 2.0.1,
webpack: 5.76.3

Additional context

No response

Support for mix.css() and mix.postCss()

As specified in LaravelMix doco, we can use mix.css() and mix.postCss() to compile plain css with postCss, adding autoprefixing and magic like that.

Currently running mixGlob.postCss() or its alias mixGlob.css() returns the error defaultMapExt: no mapping precised, neither it's supported by default.

I tried several combinations for mapping the functions css() and postCss(), but unfortunately I wasn't able to find the working solution. Here's a snippet of what seemed to be the most sensible one (but I tried many more):

const mix = require('laravel-mix'),
  mixPath = path.relative(process.cwd(), __dirname),
  srcPath = mixPath + '/src',
  distPath = mixPath + '/dist',
  MixGlob = require('laravel-mix-glob'),
  mixGlob = new MixGlob({
            mix,
            mapping: {
              base: {
                byFunc: {
                  css: { ext: "css" },
                  postCss: { ext: "css" } // I tried several combinations in the mapping section.
                }
              }
            }
          })
mix.setPublicPath(distPath)

mixGlob
  .sass(srcPath + '/scss/*.scss', 'css', null, {
    base: srcPath + '/scss/',
  }) // this one compiles just fine.
  .css(srcPath + '/libraries-override/css/*.css', 'libraries-override/css', null, {
    base: srcPath + '/libraries-override/css/',
  }) // this one throws the error.

Could you please indicate how should I have done the mapping? I read the doco, but I couldn't get it working.

In the end I had a look to the source and added the default mapping there:
https://github.com/MohamedLamineAllal/laravel-mix-glob/blob/master/src/index.js#L24

    var mixFuncs = {
        //default specifier = 'compile for all'
        // usage glob => *.compile.ext to check against only compile.ext. . or *.compile.* (all extensions preceded with compile)
        sass: {
            ext: 'css'
        },
        js: {
            ext: 'js'
        },
        less: {
            ext: 'css'
        },
        stylus: {
            ext: 'css'
        },
       // -- Default mapping for css() and postCss() --
        css: {
            ext: 'css'
        },
        postCss: {
            ext: 'css'
        },
       // ------------------------------------------------
        react: {
            ext: 'js'
        },
        ts: {
            ext: 'js'
        },
        preact: {
            ext: 'js'
        }
    }

This made the trick.
Since .css() and .postCss() are anyway well documented, part of the LaravelMix API and the only way to achieve "plain" postCss processing, I would recommend to add them to the default.

I will follow up with a simple MR.

Question: import whole folder inside file

Hello, thank you for this cool plugin. Is it possible to enable the import of all files inside a folder?

For example to import all scss files into one main file?

main.scss

@import "components/**/*";

Is it compatible with Laravel 8?

Is this package compatible with Laravel 8?

Why is such a beautiful package not popular enough? Should i trust? Because I don't have much time to try.

Error when executing `npm run dev`

When I execute npm run dev, I get the following error

TypeError: Cannot read property 'js' of undefined

My webpack.mix.js file is as follows:

const mix = require('laravel-mix');
const MixGlob = require('laravel-mix-glob');
const mixGlob = MixGlob({mix});

mixGlob.js('resources/js/*.js', 'public/js/app.js', null, {
    base: 'resources/js/'
})
    .sass('resources/sass/*.scss', 'public/css/app.css', null, {
        base: 'resources/sass/'
    });

If I change the order so that the sass resources are compiled first, the error message is
TypeError: Cannot read property 'sass' of undefined

npm error log:

0 info it worked if it ends with ok
1 verbose cli [ '/usr/local/Cellar/node@10/10.16.3/bin/node',
1 verbose cli   '/usr/local/opt/node@10/bin/npm',
1 verbose cli   'run',
1 verbose cli   'dev' ]
2 info using [email protected]
3 info using [email protected]
4 verbose run-script [ 'predev', 'dev', 'postdev' ]
5 info lifecycle @~predev: @
6 info lifecycle @~dev: @
7 verbose lifecycle @~dev: unsafe-perm in lifecycle true
8 verbose lifecycle @~dev: PATH: /usr/local/Cellar/node@10/10.16.3/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/Users/davidweiner/Sites/core/node_modules/.bin:/usr/local/opt/node@10/bin:/usr/local/opt/icu4c/sbin:/usr/local/opt/icu4c/bin:/Users/davidweiner/.composer/vendor/bin/:/usr/local/opt/php/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/davidweiner/Sites/core/node_modules/.bin
9 verbose lifecycle @~dev: CWD: /Users/davidweiner/Sites/core
10 silly lifecycle @~dev: Args: [ '-c', 'npm run development' ]
11 silly lifecycle @~dev: Returned: code: 1  signal: null
12 info lifecycle @~dev: Failed to exec dev script
13 verbose stack Error: @ dev: `npm run development`
13 verbose stack Exit status 1
13 verbose stack     at EventEmitter.<anonymous> (/usr/local/Cellar/node@10/10.16.3/lib/node_modules/npm/node_modules/npm-lifecycle/index.js:301:16)
13 verbose stack     at EventEmitter.emit (events.js:198:13)
13 verbose stack     at ChildProcess.<anonymous> (/usr/local/Cellar/node@10/10.16.3/lib/node_modules/npm/node_modules/npm-lifecycle/lib/spawn.js:55:14)
13 verbose stack     at ChildProcess.emit (events.js:198:13)
13 verbose stack     at maybeClose (internal/child_process.js:982:16)
13 verbose stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:259:5)
14 verbose pkgid @
15 verbose cwd /Users/davidweiner/Sites/core
16 verbose Darwin 18.7.0
17 verbose argv "/usr/local/Cellar/node@10/10.16.3/bin/node" "/usr/local/opt/node@10/bin/npm" "run" "dev"
18 verbose node v10.16.3
19 verbose npm  v6.9.0
20 error code ELIFECYCLE
21 error errno 1
22 error @ dev: `npm run development`
22 error Exit status 1
23 error Failed at the @ dev script.
23 error This is probably not a problem with npm. There is likely additional logging output above.
24 verbose exit [ 1, true ]

If I remove

mixGlob.js('resources/js/*.js', 'public/js/app.js', null, {
    base: 'resources/js/'
})
    .sass('resources/sass/*.scss', 'public/css/app.css', null, {
        base: 'resources/sass/'
    });

and replace it with

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

it will run just fine, and I get the following lines of output:

$ npm run dev

> @ dev /Users/davidweiner/Sites/core
> npm run development


> @ development /Users/davidweiner/Sites/core
> cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js

  MixGlob:debug !!!!! ----- No debug env var ----- !!!! +0ms
  MixGlob:debug env vars: +2ms
  MixGlob:debug [ 'npm_config_save_dev',
  MixGlob:debug   'npm_config_legacy_bundling',
  MixGlob:debug   'npm_config_dry_run',
  MixGlob:debug   'npm_package_devDependencies_resolve_url_loader',
  MixGlob:debug   'npm_config_only',
  MixGlob:debug   'npm_config_browser',
  MixGlob:debug   'npm_config_commit_hooks',
  MixGlob:debug   'npm_config_viewer',
  MixGlob:debug   'npm_package_gitHead',
  MixGlob:debug   'npm_package_scripts_watch_poll',
  MixGlob:debug   'LDFLAGS',
  MixGlob:debug   'npm_config_also',
  MixGlob:debug   'npm_config_sign_git_commit',
  MixGlob:debug   'npm_config_rollback',
  MixGlob:debug   'npm_config_usage',
  MixGlob:debug   'npm_config_audit',
  MixGlob:debug   'npm_package_devDependencies_popper_js',
  MixGlob:debug   'npm_package_devDependencies_laravel_mix',
  MixGlob:debug   'NODE',
  MixGlob:debug   'npm_package_dependencies_flag_icon_css',
  MixGlob:debug   'npm_package_devDependencies__fortawesome_fontawesome_free',
  MixGlob:debug   'npm_package_scripts_prod',
  MixGlob:debug   'INIT_CWD',
  MixGlob:debug   'npm_config_globalignorefile',
  MixGlob:debug   'TERM',
  MixGlob:debug   'SHELL',
  MixGlob:debug   'npm_config_init_author_url',
  MixGlob:debug   'npm_config_maxsockets',
  MixGlob:debug   'npm_config_shell',
  MixGlob:debug   'npm_package_devDependencies_vue_template_compiler',
  MixGlob:debug   'npm_config_parseable',
  MixGlob:debug   'npm_config_metrics_registry',
  MixGlob:debug   'npm_config_shrinkwrap',
  MixGlob:debug   'CPPFLAGS',
  MixGlob:debug   'TMPDIR',
  MixGlob:debug   'npm_config_timing',
  MixGlob:debug   'npm_config_init_license',
  MixGlob:debug   'npm_package_scripts_development',
  MixGlob:debug   'Apple_PubSub_Socket_Render',
  MixGlob:debug   'npm_config_if_present',
  MixGlob:debug   'npm_package_devDependencies_jquery',
  MixGlob:debug   'npm_package_scripts_dev',
  MixGlob:debug   'npm_config_sign_git_tag',
  MixGlob:debug   'npm_config_init_author_email',
  MixGlob:debug   'npm_config_cache_max',
  MixGlob:debug   'npm_package_devDependencies_sass_loader',
  MixGlob:debug   'npm_config_preid',
  MixGlob:debug   'npm_config_long',
  MixGlob:debug   'npm_config_local_address',
  MixGlob:debug   'npm_config_cert',
  MixGlob:debug   'npm_config_git_tag_version',
  MixGlob:debug   'npm_config_noproxy',
  MixGlob:debug   'npm_config_fetch_retries',
  MixGlob:debug   'npm_config_registry',
  MixGlob:debug   'npm_package_private',
  MixGlob:debug   'npm_config_versions',
  MixGlob:debug   'npm_config_key',
  MixGlob:debug   'npm_config_message',
  MixGlob:debug   'USER',
  MixGlob:debug   'npm_config_globalconfig',
  MixGlob:debug   'npm_config_prefer_online',
  MixGlob:debug   'npm_config_always_auth',
  MixGlob:debug   'npm_config_logs_max',
  MixGlob:debug   'SSH_AUTH_SOCK',
  MixGlob:debug   '__CF_USER_TEXT_ENCODING',
  MixGlob:debug   'npm_execpath',
  MixGlob:debug   'npm_config_global_style',
  MixGlob:debug   'npm_config_cache_lock_retries',
  MixGlob:debug   'npm_config_cafile',
  MixGlob:debug   'npm_config_update_notifier',
  MixGlob:debug   'npm_config_audit_level',
  MixGlob:debug   'npm_config_heading',
  MixGlob:debug   'npm_config_read_only',
  MixGlob:debug   'npm_config_offline',
  MixGlob:debug   'npm_config_fetch_retry_mintimeout',
  MixGlob:debug   'npm_config_searchlimit',
  MixGlob:debug   'npm_config_json',
  MixGlob:debug   'npm_config_access',
  MixGlob:debug   'npm_config_argv',
  MixGlob:debug   'npm_package_dependencies_selectize',
  MixGlob:debug   'PATH',
  MixGlob:debug   'npm_config_allow_same_version',
  MixGlob:debug   'TERMINAL_EMULATOR',
  MixGlob:debug   'npm_config_https_proxy',
  MixGlob:debug   'npm_config_engine_strict',
  MixGlob:debug   'npm_config_description',
  MixGlob:debug   'npm_package_scripts_hot',
  MixGlob:debug   '_',
  MixGlob:debug   'npm_config_init_module',
  MixGlob:debug   'npm_config_userconfig',
  MixGlob:debug   'npm_config_cidr',
  MixGlob:debug   'PWD',
  MixGlob:debug   'npm_config_user',
  MixGlob:debug   'npm_config_node_version',
  MixGlob:debug   'JAVA_HOME',
  MixGlob:debug   'npm_lifecycle_event',
  MixGlob:debug   'npm_config_ignore_prepublish',
  MixGlob:debug   'npm_config_auth_type',
  MixGlob:debug   'npm_config_editor',
  MixGlob:debug   'npm_config_save',
  MixGlob:debug   ... 119 more items ] +1ms
  MixGlob Mix glob +0ms
98% after emitting SizeLimitsPlugin

 DONE  Compiled successfully in 9904ms

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.