bpms_site/.svn/pristine/60/60686ddadbdce410203dbe51fe0590f82773015a.svn-base
2025-11-02 16:38:49 +03:30

219 lines
10 KiB
Plaintext

import * as path from "path";
import { webpack, ModuleFilenameHelpers, sources } from "next/dist/compiled/webpack/webpack";
import pLimit from "next/dist/compiled/p-limit";
import { Worker } from "next/dist/compiled/jest-worker";
import { spans } from "../../profiling-plugin";
function getEcmaVersion(environment) {
// ES 6th
if (environment.arrowFunction || environment.const || environment.destructuring || environment.forOf || environment.module) {
return 2015;
}
// ES 11th
if (environment.bigIntLiteral || environment.dynamicImport) {
return 2020;
}
return 5;
}
function buildError(error, file) {
if (error.line) {
return new Error(`${file} from Terser\n${error.message} [${file}:${error.line},${error.col}]${error.stack ? `\n${error.stack.split("\n").slice(1).join("\n")}` : ""}`);
}
if (error.stack) {
return new Error(`${file} from Terser\n${error.message}\n${error.stack}`);
}
return new Error(`${file} from Terser\n${error.message}`);
}
const debugMinify = process.env.NEXT_DEBUG_MINIFY;
export class TerserPlugin {
constructor(options = {}){
const { terserOptions = {}, parallel, swcMinify } = options;
this.options = {
swcMinify,
parallel,
terserOptions
};
}
async optimize(compiler, compilation, assets, optimizeOptions, cache, { SourceMapSource, RawSource }) {
const compilationSpan = spans.get(compilation) || spans.get(compiler);
const terserSpan = compilationSpan.traceChild("terser-webpack-plugin-optimize");
terserSpan.setAttribute("compilationName", compilation.name);
terserSpan.setAttribute("swcMinify", this.options.swcMinify);
return terserSpan.traceAsyncFn(async ()=>{
let numberOfAssetsForMinify = 0;
const assetsList = Object.keys(assets);
const assetsForMinify = await Promise.all(assetsList.filter((name)=>{
if (!ModuleFilenameHelpers.matchObject.bind(// eslint-disable-next-line no-undefined
undefined, {
test: /\.[cm]?js(\?.*)?$/i
})(name)) {
return false;
}
const res = compilation.getAsset(name);
if (!res) {
console.log(name);
return false;
}
// don't minify _middleware as it can break in some cases
// and doesn't provide too much of a benefit as it's server-side
if (name.match(/(edge-runtime-webpack\.js|edge-chunks|middleware\.js$)/)) {
return false;
}
const { info } = res;
// Skip double minimize assets from child compilation
if (info.minimized) {
return false;
}
return true;
}).map(async (name)=>{
const { info, source } = compilation.getAsset(name);
const eTag = cache.getLazyHashedEtag(source);
const output = await cache.getPromise(name, eTag);
if (!output) {
numberOfAssetsForMinify += 1;
}
if (debugMinify && debugMinify === "1") {
console.dir({
name,
source: source.source().toString()
}, {
breakLength: Infinity,
maxStringLength: Infinity
});
}
return {
name,
info,
inputSource: source,
output,
eTag
};
}));
const numberOfWorkers = Math.min(numberOfAssetsForMinify, optimizeOptions.availableNumberOfCores);
let initializedWorker;
// eslint-disable-next-line consistent-return
const getWorker = ()=>{
if (this.options.swcMinify) {
return {
minify: async (options)=>{
const result = await require("../../../../swc").minify(options.input, {
...options.inputSourceMap ? {
sourceMap: {
content: JSON.stringify(options.inputSourceMap)
}
} : {},
compress: true,
mangle: true
});
return result;
}
};
}
if (initializedWorker) {
return initializedWorker;
}
initializedWorker = new Worker(path.join(__dirname, "./minify.js"), {
numWorkers: numberOfWorkers,
enableWorkerThreads: true
});
initializedWorker.getStdout().pipe(process.stdout);
initializedWorker.getStderr().pipe(process.stderr);
return initializedWorker;
};
const limit = pLimit(// When using the SWC minifier the limit will be handled by Node.js
this.options.swcMinify ? Infinity : numberOfAssetsForMinify > 0 ? numberOfWorkers : Infinity);
const scheduledTasks = [];
for (const asset of assetsForMinify){
scheduledTasks.push(limit(async ()=>{
const { name, inputSource, info, eTag } = asset;
let { output } = asset;
const minifySpan = terserSpan.traceChild("minify-js");
minifySpan.setAttribute("name", name);
minifySpan.setAttribute("cache", typeof output === "undefined" ? "MISS" : "HIT");
return minifySpan.traceAsyncFn(async ()=>{
if (!output) {
const { source: sourceFromInputSource, map: inputSourceMap } = inputSource.sourceAndMap();
const input = Buffer.isBuffer(sourceFromInputSource) ? sourceFromInputSource.toString() : sourceFromInputSource;
const options = {
name,
input,
inputSourceMap,
terserOptions: {
...this.options.terserOptions
}
};
if (typeof options.terserOptions.module === "undefined") {
if (typeof info.javascriptModule !== "undefined") {
options.terserOptions.module = info.javascriptModule;
} else if (/\.mjs(\?.*)?$/i.test(name)) {
options.terserOptions.module = true;
} else if (/\.cjs(\?.*)?$/i.test(name)) {
options.terserOptions.module = false;
}
}
try {
output = await getWorker().minify(options);
} catch (error) {
compilation.errors.push(buildError(error, name));
return;
}
if (output.map) {
output.source = new SourceMapSource(output.code, name, output.map, input, inputSourceMap, true);
} else {
output.source = new RawSource(output.code);
}
await cache.storePromise(name, eTag, {
source: output.source
});
}
const newInfo = {
minimized: true
};
const { source } = output;
compilation.updateAsset(name, source, newInfo);
});
}));
}
await Promise.all(scheduledTasks);
if (initializedWorker) {
await initializedWorker.end();
}
});
}
apply(compiler) {
var _compiler_webpack;
const { SourceMapSource, RawSource } = (compiler == null ? void 0 : (_compiler_webpack = compiler.webpack) == null ? void 0 : _compiler_webpack.sources) || sources;
const { output } = compiler.options;
if (typeof this.options.terserOptions.ecma === "undefined") {
this.options.terserOptions.ecma = getEcmaVersion(output.environment || {});
}
const pluginName = this.constructor.name;
const availableNumberOfCores = this.options.parallel;
compiler.hooks.thisCompilation.tap(pluginName, (compilation)=>{
const cache = compilation.getCache("TerserWebpackPlugin");
const handleHashForChunk = (hash, _chunk)=>{
// increment 'c' to invalidate cache
hash.update("c");
};
const JSModulesHooks = webpack.javascript.JavascriptModulesPlugin.getCompilationHooks(compilation);
JSModulesHooks.chunkHash.tap(pluginName, (chunk, hash)=>{
if (!chunk.hasRuntime()) return;
return handleHashForChunk(hash, chunk);
});
compilation.hooks.processAssets.tapPromise({
name: pluginName,
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE
}, (assets)=>this.optimize(compiler, compilation, assets, {
availableNumberOfCores
}, cache, {
SourceMapSource,
RawSource
}));
compilation.hooks.statsPrinter.tap(pluginName, (stats)=>{
stats.hooks.print.for("asset.info.minimized").tap("terser-webpack-plugin", (minimized, { green, formatFlag })=>// eslint-disable-next-line no-undefined
minimized ? green(formatFlag("minimized")) : undefined);
});
});
}
}
//# sourceMappingURL=index.js.map