laravel-mix
Version:
The power of webpack, distilled for the rest of us.
116 lines (95 loc) • 2.99 kB
JavaScript
let Log = require('../Log');
let collect = require('collect.js');
class CustomTasksPlugin {
/**
*
* @param {import('../Mix')} mix
*/
constructor(mix) {
this.mix = mix || global.Mix;
}
/**
* Apply the plugin.
*
* @param {import("webpack").Compiler} compiler
*/
apply(compiler) {
compiler.hooks.done.tapPromise(this.constructor.name, async stats => {
await this.runTasks(stats);
if (this.mix.components.get('version') && !this.mix.isUsing('hmr')) {
this.applyVersioning();
}
if (this.mix.inProduction()) {
await this.minifyAssets();
}
if (this.mix.isWatching()) {
this.mix.tasks.forEach(task => task.watch(this.mix.isPolling()));
}
this.mix.manifest.refresh();
});
}
/**
* Add asset to the webpack stats.
*
* @param {import("../File")} asset
* @param {import("webpack").Stats} stats
*/
async addAsset(asset, stats) {
// Skip adding directories to the manifest
// TODO: We should probably add the directory but skip hashing
if (asset.isDirectory()) {
return;
}
const path = asset.pathFromPublic();
// Add the asset to the manifest
this.mix.manifest.add(path);
// Update the Webpack assets list for better terminal output.
stats.compilation.assets[path] = {
size: () => asset.size(),
emitted: true
};
}
/**
* Execute potentially asynchronous tasks sequentially.
*
* @param stats
*/
async runTasks(stats) {
let assets = []
for (const task of this.mix.tasks) {
await Promise.resolve(task.run());
assets.push(...task.assets)
}
await Promise.allSettled(assets.map(asset => this.addAsset(asset, stats)));
}
/**
* Minify the given asset file.
*/
async minifyAssets() {
const assets = collect(this.mix.tasks)
.where('constructor.name', '!==', 'VersionFilesTask')
.where('constructor.name', '!==', 'CopyFilesTask')
.flatMap(({ assets }) => assets);
const tasks = assets.map(async asset => {
try {
await asset.minify();
} catch (e) {
Log.error(
`Whoops! We had trouble minifying "${asset.relativePath()}". ` +
`Perhaps you need to use mix.babel() instead?`
);
throw e;
}
});
await Promise.allSettled(tasks);
}
/**
* Version all files that are present in the manifest.
*/
applyVersioning() {
for (const [key, value] of Object.entries(this.mix.manifest.get())) {
this.mix.manifest.hash(key)
}
}
}
module.exports = CustomTasksPlugin;