.
This commit is contained in:
Generated
Vendored
+35
@@ -0,0 +1,35 @@
|
||||
import type { webpack } from 'next/dist/compiled/webpack/webpack';
|
||||
import { type UseCacheTrackerKey } from './use-cache-tracker-utils';
|
||||
/**
|
||||
* List of target triples next-swc native binary supports.
|
||||
*/
|
||||
export type SWC_TARGET_TRIPLE = 'x86_64-apple-darwin' | 'x86_64-unknown-linux-gnu' | 'x86_64-pc-windows-msvc' | 'i686-pc-windows-msvc' | 'aarch64-unknown-linux-gnu' | 'armv7-unknown-linux-gnueabihf' | 'aarch64-apple-darwin' | 'aarch64-linux-android' | 'arm-linux-androideabi' | 'x86_64-unknown-freebsd' | 'x86_64-unknown-linux-musl' | 'aarch64-unknown-linux-musl' | 'aarch64-pc-windows-msvc';
|
||||
export type Feature = 'next/image' | 'next/future/image' | 'next/legacy/image' | 'next/script' | 'next/dynamic' | '@next/font/google' | '@next/font/local' | 'next/font/google' | 'next/font/local' | 'swcLoader' | 'swcRelay' | 'swcStyledComponents' | 'swcReactRemoveProperties' | 'swcExperimentalDecorators' | 'swcRemoveConsole' | 'swcImportSource' | 'swcEmotion' | `swc/target/${SWC_TARGET_TRIPLE}` | 'turbotrace' | 'transpilePackages' | 'skipProxyUrlNormalize' | 'skipTrailingSlashRedirect' | 'modularizeImports' | 'esmExternals' | 'webpackPlugins' | UseCacheTrackerKey;
|
||||
interface FeatureUsage {
|
||||
featureName: Feature;
|
||||
invocationCount: number;
|
||||
}
|
||||
export type TelemetryLoaderContext = {
|
||||
eliminatedPackages?: Set<string>;
|
||||
useCacheTracker?: Map<UseCacheTrackerKey, number>;
|
||||
};
|
||||
/**
|
||||
* Plugin that queries the ModuleGraph to look for modules that correspond to
|
||||
* certain features (e.g. next/image and next/script) and record how many times
|
||||
* they are imported.
|
||||
*/
|
||||
export declare class TelemetryPlugin implements webpack.WebpackPluginInstance {
|
||||
private usageTracker;
|
||||
constructor(buildFeaturesMap: Map<Feature, boolean>);
|
||||
addUsage(featureName: Feature, invocationCount: FeatureUsage['invocationCount']): void;
|
||||
apply(compiler: webpack.Compiler): void;
|
||||
usages(): FeatureUsage[];
|
||||
packagesUsedInServerSideProps(): string[];
|
||||
getUseCacheTracker(): Record<UseCacheTrackerKey, number>;
|
||||
}
|
||||
export type TelemetryPluginState = {
|
||||
usages: ReturnType<TelemetryPlugin['usages']>;
|
||||
packagesUsedInServerSideProps: ReturnType<TelemetryPlugin['packagesUsedInServerSideProps']>;
|
||||
useCacheTracker: ReturnType<TelemetryPlugin['getUseCacheTracker']>;
|
||||
};
|
||||
export {};
|
||||
Generated
Vendored
+188
@@ -0,0 +1,188 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(exports, "TelemetryPlugin", {
|
||||
enumerable: true,
|
||||
get: function() {
|
||||
return TelemetryPlugin;
|
||||
}
|
||||
});
|
||||
const _usecachetrackerutils = require("./use-cache-tracker-utils");
|
||||
// Map of a feature module to the file it belongs in the next package.
|
||||
const FEATURE_MODULE_MAP = new Map([
|
||||
[
|
||||
'next/image',
|
||||
'/next/image.js'
|
||||
],
|
||||
[
|
||||
'next/future/image',
|
||||
'/next/future/image.js'
|
||||
],
|
||||
[
|
||||
'next/legacy/image',
|
||||
'/next/legacy/image.js'
|
||||
],
|
||||
[
|
||||
'next/script',
|
||||
'/next/script.js'
|
||||
],
|
||||
[
|
||||
'next/dynamic',
|
||||
'/next/dynamic.js'
|
||||
]
|
||||
]);
|
||||
const FEATURE_MODULE_REGEXP_MAP = new Map([
|
||||
[
|
||||
'@next/font/google',
|
||||
/\/@next\/font\/google\/target.css?.+$/
|
||||
],
|
||||
[
|
||||
'@next/font/local',
|
||||
/\/@next\/font\/local\/target.css?.+$/
|
||||
],
|
||||
[
|
||||
'next/font/google',
|
||||
/\/next\/font\/google\/target.css?.+$/
|
||||
],
|
||||
[
|
||||
'next/font/local',
|
||||
/\/next\/font\/local\/target.css?.+$/
|
||||
]
|
||||
]);
|
||||
// List of build features used in webpack configuration
|
||||
const BUILD_FEATURES = [
|
||||
'swcLoader',
|
||||
'swcRelay',
|
||||
'swcStyledComponents',
|
||||
'swcReactRemoveProperties',
|
||||
'swcExperimentalDecorators',
|
||||
'swcRemoveConsole',
|
||||
'swcImportSource',
|
||||
'swcEmotion',
|
||||
'swc/target/x86_64-apple-darwin',
|
||||
'swc/target/x86_64-unknown-linux-gnu',
|
||||
'swc/target/x86_64-pc-windows-msvc',
|
||||
'swc/target/i686-pc-windows-msvc',
|
||||
'swc/target/aarch64-unknown-linux-gnu',
|
||||
'swc/target/armv7-unknown-linux-gnueabihf',
|
||||
'swc/target/aarch64-apple-darwin',
|
||||
'swc/target/aarch64-linux-android',
|
||||
'swc/target/arm-linux-androideabi',
|
||||
'swc/target/x86_64-unknown-freebsd',
|
||||
'swc/target/x86_64-unknown-linux-musl',
|
||||
'swc/target/aarch64-unknown-linux-musl',
|
||||
'swc/target/aarch64-pc-windows-msvc',
|
||||
'turbotrace',
|
||||
'transpilePackages',
|
||||
'skipProxyUrlNormalize',
|
||||
'skipTrailingSlashRedirect',
|
||||
'modularizeImports',
|
||||
'esmExternals',
|
||||
'webpackPlugins'
|
||||
];
|
||||
const eliminatedPackages = new Set();
|
||||
const useCacheTracker = (0, _usecachetrackerutils.createUseCacheTracker)();
|
||||
/**
|
||||
* Determine if there is a feature of interest in the specified 'module'.
|
||||
*/ function findFeatureInModule(module) {
|
||||
if (module.type !== 'javascript/auto') {
|
||||
return;
|
||||
}
|
||||
for (const [feature, path] of FEATURE_MODULE_MAP){
|
||||
var _module_resource;
|
||||
// imports like "http" will be undefined resource in rspack
|
||||
if ((_module_resource = module.resource) == null ? void 0 : _module_resource.endsWith(path)) {
|
||||
return feature;
|
||||
}
|
||||
}
|
||||
const normalizedIdentifier = module.identifier().replace(/\\/g, '/');
|
||||
for (const [feature, regexp] of FEATURE_MODULE_REGEXP_MAP){
|
||||
if (regexp.test(normalizedIdentifier)) {
|
||||
return feature;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Find unique origin modules in the specified 'connections', which possibly
|
||||
* contains more than one connection for a module due to different types of
|
||||
* dependency.
|
||||
*/ function findUniqueOriginModulesInConnections(connections, originModule) {
|
||||
const originModules = new Set();
|
||||
for (const connection of connections){
|
||||
if (!originModules.has(connection.originModule) && connection.originModule !== originModule) {
|
||||
originModules.add(connection.originModule);
|
||||
}
|
||||
}
|
||||
return originModules;
|
||||
}
|
||||
class TelemetryPlugin {
|
||||
// Build feature usage is on/off and is known before the build starts
|
||||
constructor(buildFeaturesMap){
|
||||
this.usageTracker = new Map();
|
||||
for (const featureName of BUILD_FEATURES){
|
||||
this.usageTracker.set(featureName, {
|
||||
featureName,
|
||||
invocationCount: buildFeaturesMap.get(featureName) ? 1 : 0
|
||||
});
|
||||
}
|
||||
for (const featureName of FEATURE_MODULE_MAP.keys()){
|
||||
this.usageTracker.set(featureName, {
|
||||
featureName,
|
||||
invocationCount: 0
|
||||
});
|
||||
}
|
||||
for (const featureName of FEATURE_MODULE_REGEXP_MAP.keys()){
|
||||
this.usageTracker.set(featureName, {
|
||||
featureName,
|
||||
invocationCount: 0
|
||||
});
|
||||
}
|
||||
}
|
||||
addUsage(featureName, invocationCount) {
|
||||
this.usageTracker.set(featureName, {
|
||||
featureName,
|
||||
invocationCount
|
||||
});
|
||||
}
|
||||
apply(compiler) {
|
||||
compiler.hooks.make.tapAsync(TelemetryPlugin.name, async (compilation, callback)=>{
|
||||
compilation.hooks.finishModules.tapAsync(TelemetryPlugin.name, async (modules, modulesFinish)=>{
|
||||
for (const module of modules){
|
||||
const feature = findFeatureInModule(module);
|
||||
if (!feature) {
|
||||
continue;
|
||||
}
|
||||
const connections = compilation.moduleGraph.getIncomingConnections(module);
|
||||
const originModules = findUniqueOriginModulesInConnections(connections, module);
|
||||
this.usageTracker.get(feature).invocationCount = originModules.size;
|
||||
}
|
||||
modulesFinish();
|
||||
});
|
||||
callback();
|
||||
});
|
||||
if (compiler.options.mode === 'production' && !compiler.watchMode) {
|
||||
compiler.hooks.thisCompilation.tap(TelemetryPlugin.name, (compilation)=>{
|
||||
const moduleHooks = compiler.webpack.NormalModule.getCompilationHooks(compilation);
|
||||
moduleHooks.loader.tap(TelemetryPlugin.name, (loaderContext)=>{
|
||||
;
|
||||
loaderContext.eliminatedPackages = eliminatedPackages;
|
||||
loaderContext.useCacheTracker = useCacheTracker;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
usages() {
|
||||
return [
|
||||
...this.usageTracker.values()
|
||||
];
|
||||
}
|
||||
packagesUsedInServerSideProps() {
|
||||
return Array.from(eliminatedPackages);
|
||||
}
|
||||
getUseCacheTracker() {
|
||||
return Object.fromEntries(useCacheTracker);
|
||||
}
|
||||
}
|
||||
|
||||
//# sourceMappingURL=telemetry-plugin.js.map
|
||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
import type { TelemetryLoaderContext } from './telemetry-plugin';
|
||||
export type SwcTransformTelemetryOutput = {
|
||||
eliminatedPackages?: string;
|
||||
useCacheTelemetryTracker?: string;
|
||||
};
|
||||
export declare function updateTelemetryLoaderCtxFromTransformOutput(ctx: TelemetryLoaderContext, output: SwcTransformTelemetryOutput): void;
|
||||
Generated
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(exports, "updateTelemetryLoaderCtxFromTransformOutput", {
|
||||
enumerable: true,
|
||||
get: function() {
|
||||
return updateTelemetryLoaderCtxFromTransformOutput;
|
||||
}
|
||||
});
|
||||
function updateTelemetryLoaderCtxFromTransformOutput(ctx, output) {
|
||||
if (output.eliminatedPackages && ctx.eliminatedPackages) {
|
||||
for (const pkg of JSON.parse(output.eliminatedPackages)){
|
||||
ctx.eliminatedPackages.add(pkg);
|
||||
}
|
||||
}
|
||||
if (output.useCacheTelemetryTracker && ctx.useCacheTracker) {
|
||||
for (const [key, value] of JSON.parse(output.useCacheTelemetryTracker)){
|
||||
const prefixedKey = `useCache/${key}`;
|
||||
const numericValue = Number(value);
|
||||
if (!isNaN(numericValue)) {
|
||||
ctx.useCacheTracker.set(prefixedKey, (ctx.useCacheTracker.get(prefixedKey) || 0) + numericValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//# sourceMappingURL=update-telemetry-loader-context-from-swc.js.map
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../../../src/build/webpack/plugins/telemetry-plugin/update-telemetry-loader-context-from-swc.ts"],"sourcesContent":["import type { TelemetryLoaderContext } from './telemetry-plugin'\nexport type SwcTransformTelemetryOutput = {\n eliminatedPackages?: string\n useCacheTelemetryTracker?: string\n}\n\nexport function updateTelemetryLoaderCtxFromTransformOutput(\n ctx: TelemetryLoaderContext,\n output: SwcTransformTelemetryOutput\n) {\n if (output.eliminatedPackages && ctx.eliminatedPackages) {\n for (const pkg of JSON.parse(output.eliminatedPackages)) {\n ctx.eliminatedPackages.add(pkg)\n }\n }\n\n if (output.useCacheTelemetryTracker && ctx.useCacheTracker) {\n for (const [key, value] of JSON.parse(output.useCacheTelemetryTracker)) {\n const prefixedKey = `useCache/${key}` as const\n const numericValue = Number(value)\n if (!isNaN(numericValue)) {\n ctx.useCacheTracker.set(\n prefixedKey,\n (ctx.useCacheTracker.get(prefixedKey) || 0) + numericValue\n )\n }\n }\n }\n}\n"],"names":["updateTelemetryLoaderCtxFromTransformOutput","ctx","output","eliminatedPackages","pkg","JSON","parse","add","useCacheTelemetryTracker","useCacheTracker","key","value","prefixedKey","numericValue","Number","isNaN","set","get"],"mappings":";;;;+BAMgBA;;;eAAAA;;;AAAT,SAASA,4CACdC,GAA2B,EAC3BC,MAAmC;IAEnC,IAAIA,OAAOC,kBAAkB,IAAIF,IAAIE,kBAAkB,EAAE;QACvD,KAAK,MAAMC,OAAOC,KAAKC,KAAK,CAACJ,OAAOC,kBAAkB,EAAG;YACvDF,IAAIE,kBAAkB,CAACI,GAAG,CAACH;QAC7B;IACF;IAEA,IAAIF,OAAOM,wBAAwB,IAAIP,IAAIQ,eAAe,EAAE;QAC1D,KAAK,MAAM,CAACC,KAAKC,MAAM,IAAIN,KAAKC,KAAK,CAACJ,OAAOM,wBAAwB,EAAG;YACtE,MAAMI,cAAc,CAAC,SAAS,EAAEF,KAAK;YACrC,MAAMG,eAAeC,OAAOH;YAC5B,IAAI,CAACI,MAAMF,eAAe;gBACxBZ,IAAIQ,eAAe,CAACO,GAAG,CACrBJ,aACA,AAACX,CAAAA,IAAIQ,eAAe,CAACQ,GAAG,CAACL,gBAAgB,CAAA,IAAKC;YAElD;QACF;IACF;AACF","ignoreList":[0]}
|
||||
Generated
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
export type UseCacheTrackerKey = `useCache/${string}`;
|
||||
export declare const createUseCacheTracker: () => Map<`useCache/${string}`, number>;
|
||||
/**
|
||||
* Example usage:
|
||||
*
|
||||
* const tracker1 = { 'useCache/file1': 1, 'useCache/file2': 2 };
|
||||
* const tracker2 = { 'useCache/file2': 3, 'useCache/file3': 4 };
|
||||
* const merged = mergeUseCacheTrackers(tracker1, tracker2);
|
||||
*
|
||||
* // Result: { 'useCache/file1': 1, 'useCache/file2': 5, 'useCache/file3': 4 }
|
||||
*/
|
||||
export declare const mergeUseCacheTrackers: (tracker1: Record<UseCacheTrackerKey, number> | undefined, tracker2: Record<UseCacheTrackerKey, number> | undefined) => Record<UseCacheTrackerKey, number>;
|
||||
Generated
Vendored
+43
@@ -0,0 +1,43 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
0 && (module.exports = {
|
||||
createUseCacheTracker: null,
|
||||
mergeUseCacheTrackers: null
|
||||
});
|
||||
function _export(target, all) {
|
||||
for(var name in all)Object.defineProperty(target, name, {
|
||||
enumerable: true,
|
||||
get: all[name]
|
||||
});
|
||||
}
|
||||
_export(exports, {
|
||||
createUseCacheTracker: function() {
|
||||
return createUseCacheTracker;
|
||||
},
|
||||
mergeUseCacheTrackers: function() {
|
||||
return mergeUseCacheTrackers;
|
||||
}
|
||||
});
|
||||
const createUseCacheTracker = ()=>new Map();
|
||||
const mergeUseCacheTrackers = (tracker1, tracker2)=>{
|
||||
const mergedTracker = {
|
||||
...tracker1
|
||||
};
|
||||
if (tracker2) {
|
||||
for(const key in tracker2){
|
||||
if (Object.prototype.hasOwnProperty.call(tracker2, key)) {
|
||||
const typedKey = key;
|
||||
if (mergedTracker[typedKey] !== undefined) {
|
||||
mergedTracker[typedKey] += tracker2[typedKey];
|
||||
} else {
|
||||
mergedTracker[typedKey] = tracker2[typedKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return mergedTracker;
|
||||
};
|
||||
|
||||
//# sourceMappingURL=use-cache-tracker-utils.js.map
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../../../src/build/webpack/plugins/telemetry-plugin/use-cache-tracker-utils.ts"],"sourcesContent":["export type UseCacheTrackerKey = `useCache/${string}`\n\nexport const createUseCacheTracker = () => new Map<UseCacheTrackerKey, number>()\n\n/**\n * Example usage:\n *\n * const tracker1 = { 'useCache/file1': 1, 'useCache/file2': 2 };\n * const tracker2 = { 'useCache/file2': 3, 'useCache/file3': 4 };\n * const merged = mergeUseCacheTrackers(tracker1, tracker2);\n *\n * // Result: { 'useCache/file1': 1, 'useCache/file2': 5, 'useCache/file3': 4 }\n */\nexport const mergeUseCacheTrackers = (\n tracker1: Record<UseCacheTrackerKey, number> | undefined,\n tracker2: Record<UseCacheTrackerKey, number> | undefined\n): Record<UseCacheTrackerKey, number> => {\n const mergedTracker: Record<UseCacheTrackerKey, number> = { ...tracker1 }\n\n if (tracker2) {\n for (const key in tracker2) {\n if (Object.prototype.hasOwnProperty.call(tracker2, key)) {\n const typedKey = key as UseCacheTrackerKey\n if (mergedTracker[typedKey] !== undefined) {\n mergedTracker[typedKey] += tracker2[typedKey]\n } else {\n mergedTracker[typedKey] = tracker2[typedKey]\n }\n }\n }\n }\n\n return mergedTracker\n}\n"],"names":["createUseCacheTracker","mergeUseCacheTrackers","Map","tracker1","tracker2","mergedTracker","key","Object","prototype","hasOwnProperty","call","typedKey","undefined"],"mappings":";;;;;;;;;;;;;;;IAEaA,qBAAqB;eAArBA;;IAWAC,qBAAqB;eAArBA;;;AAXN,MAAMD,wBAAwB,IAAM,IAAIE;AAWxC,MAAMD,wBAAwB,CACnCE,UACAC;IAEA,MAAMC,gBAAoD;QAAE,GAAGF,QAAQ;IAAC;IAExE,IAAIC,UAAU;QACZ,IAAK,MAAME,OAAOF,SAAU;YAC1B,IAAIG,OAAOC,SAAS,CAACC,cAAc,CAACC,IAAI,CAACN,UAAUE,MAAM;gBACvD,MAAMK,WAAWL;gBACjB,IAAID,aAAa,CAACM,SAAS,KAAKC,WAAW;oBACzCP,aAAa,CAACM,SAAS,IAAIP,QAAQ,CAACO,SAAS;gBAC/C,OAAO;oBACLN,aAAa,CAACM,SAAS,GAAGP,QAAQ,CAACO,SAAS;gBAC9C;YACF;QACF;IACF;IAEA,OAAON;AACT","ignoreList":[0]}
|
||||
Reference in New Issue
Block a user