81 lines
2.6 KiB
JavaScript
81 lines
2.6 KiB
JavaScript
import { basename, dirname, join } from 'node:path';
|
|
|
|
/**
|
|
* Webpack plugin to emit all transpiled modules as individual files without bundling.
|
|
* This is useful for libraries, making them easier to consume and tree shake.
|
|
*
|
|
* Gutenberg solves this by custom scripting around Babel (which is rather complex).
|
|
* WooCommerce uses TypeScript (which doesn't work with Webpack plugins).
|
|
*
|
|
* See:
|
|
* https://github.com/webpack/webpack/issues/5866
|
|
* https://github.com/webpack/webpack/issues/11230
|
|
*
|
|
* Inspired by: https://github.com/DrewML/webpack-emit-all-plugin
|
|
*/
|
|
export class WebpackEmitAllPlugin {
|
|
constructor(opts = {}) {
|
|
this.context = opts.context;
|
|
this.ignorePattern = opts.ignorePattern || /node_modules/;
|
|
}
|
|
|
|
apply(compiler) {
|
|
compiler.hooks.environment.tap('EmitAllPlugin', (args) => {
|
|
compiler.options.optimization = {
|
|
...compiler.options.optimization,
|
|
minimize: false,
|
|
minimizer: [],
|
|
concatenateModules: false,
|
|
splitChunks: false,
|
|
realContentHash: false,
|
|
removeEmptyChunks: false,
|
|
};
|
|
});
|
|
|
|
compiler.hooks.compilation.tap('EmitAllPlugin', (compilation) => {
|
|
compilation.hooks.processAssets.tap(
|
|
{
|
|
name: 'EmitAllPlugin',
|
|
stage: compilation.PROCESS_ASSETS_STAGE_ADDITIONS,
|
|
additionalAssets: true,
|
|
},
|
|
() => {
|
|
Object.keys(compilation.assets).forEach((asset) => {
|
|
if (asset.endsWith('.js')) {
|
|
compilation.deleteAsset(asset);
|
|
}
|
|
});
|
|
},
|
|
);
|
|
});
|
|
|
|
compiler.hooks.afterEmit.tapPromise('EmitAllPlugin', (compilation) =>
|
|
Promise.all(
|
|
Array.from(compilation.modules).map((module) =>
|
|
this.#processModule(compiler, module),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
async #processModule(compiler, module) {
|
|
const fs = compiler.outputFileSystem.promises;
|
|
const outputPath = compiler.options.output.path;
|
|
const originalSource = module.originalSource();
|
|
if (!originalSource || this.ignorePattern.test(module.resource)) {
|
|
return;
|
|
}
|
|
|
|
const path = module.resource.replace(this.context ?? compiler.context, '');
|
|
const dest = join(outputPath, path).replace(/\.[jt]sx?$/i, '.js');
|
|
const { source, map } = originalSource.sourceAndMap();
|
|
const suffix = map ? `\n//# sourceMappingURL=${basename(dest)}.map` : '';
|
|
|
|
await fs.mkdir(dirname(dest), { recursive: true });
|
|
return Promise.all([
|
|
fs.writeFile(dest, `${source}${suffix}`),
|
|
map ? fs.writeFile(`${dest}.map`, JSON.stringify(map)) : undefined,
|
|
]);
|
|
}
|
|
}
|