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:
- Full re-write using typescript and modularity (cleaner code).
- A whole new more natural and flexible design that bring
less coupling
and anit 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 ✨✨✨)
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.
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.
And the output will be
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 isglb.args()
to have more dynamic around setting up the args (more advanced usage. You may never need that.). Andglb.arg()
is just likeglb.src()
but for args that are notsrc,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')];
},
),
);
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.
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')()]
]
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.
✨✨✨ 🔥🔥
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 OutManager
handle 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.
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:
And the output will be
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 asstring
.
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.
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()
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.
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];
},
),
);
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.
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
andsrc/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.
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
andsrc/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.
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.
*/
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.
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
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();
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 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.
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.
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');
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. |
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"
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.
Don't hesitate to fill an issue for any bug, or feature request. :heartbeat: All contribution are appreciated :heartbeat:
Check the contribution guide bellow.
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 allalmohamedlamine@gmail.com
Don't forget to star ✨ the project. 💓 ❤️. It's a click away => let me star ✨✨✨✨✨✨✨✨