Skip to content

Commit

Permalink
Modify SondaWebpackPlugin to work in both webpack and rspack
Browse files Browse the repository at this point in the history
  • Loading branch information
filipsobol committed Oct 11, 2024
1 parent 4a3ad06 commit 5335e31
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 114 deletions.
69 changes: 0 additions & 69 deletions packages/sonda/src/bundlers/rspack.ts

This file was deleted.

75 changes: 33 additions & 42 deletions packages/sonda/src/bundlers/webpack.ts
Original file line number Diff line number Diff line change
@@ -1,78 +1,69 @@
import { join } from 'path';
import { normalizeOptions, normalizePath } from '../utils';
import { generateReportFromAssets } from '../report/generate';
import type { Compiler, StatsModule } from 'webpack';
import type { Options, ModuleFormat, JsonReport } from '../types';
import { NormalModule, type Compiler, type Module } from 'webpack';

const jsRegexp = /\.[c|m]?[t|j]s[x]?$/;

export class SondaWebpackPlugin {
options: Partial<Options>;
inputs: JsonReport[ 'inputs' ];

constructor ( options?: Partial<Options> ) {
this.options = options || {};
this.inputs = {};
}

apply( compiler: Compiler ): void {
compiler.options.output.devtoolModuleFilenameTemplate = '[absolute-resource-path]';

compiler.hooks.compilation.tap( 'SondaWebpackPlugin', ( compilation ) => {
compilation.hooks.optimizeModules.tap( 'SondaWebpackPlugin', ( modules ) => {
Array
.from( modules )
.forEach( module => {
if ( !isNormalModule( module ) ) {
return;
}
compiler.hooks.afterEmit.tapPromise( 'SondaWebpackPlugin', compilation => {
const inputs: JsonReport[ 'inputs' ] = {};
const stats = compilation.getStats().toJson( {
modules: true,
providedExports: true
} );

const imports = module.dependencies.reduce( ( acc, dependency ) => {
const module = compilation.moduleGraph.getModule( dependency );
const outputPath = stats.outputPath || compiler.outputPath;
const modules = stats.modules?.filter( mod => mod.nameForCondition && mod.moduleType !== 'asset/inline' ) || [];

if ( isNormalModule( module ) ) {
acc.push( normalizePath( module.resource ) );
}
modules.forEach( module => {
const imports = modules.reduce( ( acc, { nameForCondition, issuerName, reasons } ) => {
if ( issuerName === module.name || reasons?.some( reason => reason.resolvedModule === module.name ) ) {
acc.push( normalizePath( nameForCondition! ) );
}

return acc;
}, [] as Array<string> );
return acc;
}, [] as Array<string> );

this.inputs[ normalizePath( module.resource ) ] = {
bytes: module.size(),
format: getFormat( module ),
imports,
belongsTo: null,
};
} );
inputs[ normalizePath( module.nameForCondition! ) ] = {
bytes: module.size || 0,
format: getFormat( module ),
imports,
belongsTo: null
};
} );
} );

compiler.hooks.emit.tapAsync( 'SondaWebpackPlugin', ( compilation, callback ) => {
const outputPath = compiler.options.output.path || compiler.outputPath || process.cwd();
const assets = Object.keys( compilation.assets ).map( name => join( outputPath, name ) );

generateReportFromAssets(
assets,
this.inputs,
return generateReportFromAssets(
stats.assets?.map( asset => join( outputPath, asset.name ) ) || [],
inputs,
normalizeOptions( this.options )
)
.then(() => callback());
);
} );
}
}

function getFormat( module: NormalModule ): ModuleFormat {
if ( !jsRegexp.test( module.resource ) ) {
function getFormat( module: StatsModule ): ModuleFormat {
if ( !jsRegexp.test( module.nameForCondition! ) ) {
return 'unknown';
}

if ( module.type === 'javascript/esm' || module.buildMeta?.exportsType === 'namespace' ) {
if ( module.moduleType === 'javascript/esm' ) {
return 'esm';
}

return 'cjs';
}
if ( Array.isArray( module.providedExports ) && module.providedExports.length > 0 ) {
return 'esm';
}

function isNormalModule( module: Module | NormalModule | null ): module is NormalModule {
return module !== null && 'resource' in module;
return 'cjs';
}
1 change: 0 additions & 1 deletion packages/sonda/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export { SondaEsbuildPlugin } from './bundlers/esbuild.js';
export { SondaRollupPlugin } from './bundlers/rollup.js';
export { SondaRspackPlugin } from './bundlers/rspack.js';
export { SondaWebpackPlugin } from './bundlers/webpack.js';

export type {
Expand Down
4 changes: 2 additions & 2 deletions playground/rspack/rsbuild.config.mjs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { defineConfig } from '@rsbuild/core';
import { SondaRspackPlugin } from 'sonda';
import { SondaWebpackPlugin } from 'sonda';

export default defineConfig( {
tools: {
rspack: {
devtool: 'source-map',
plugins: [
new SondaRspackPlugin( {
new SondaWebpackPlugin( {
gzip: true,
brotli: true,
detailed: true
Expand Down

0 comments on commit 5335e31

Please sign in to comment.