Skip to content

Commit

Permalink
feat: Add support for excludeAssets and excludeModules options
Browse files Browse the repository at this point in the history
  • Loading branch information
vio committed Jun 10, 2024
1 parent ef546cd commit d37fe30
Show file tree
Hide file tree
Showing 7 changed files with 415 additions and 192 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ export default defineConfig((env) => ({
### Options

- `fileName` - JSON stats file inside rollup/vite output directory
- `excludeAssets` - exclude matching assets: `string | RegExp | ((filepath: string) => boolean) | Array<string | RegExp | ((filepath: string) => boolean)>`
- `excludeModules` - exclude matching modules: `string | RegExp | ((filepath: string) => boolean) | Array<string | RegExp | ((filepath: string) => boolean)>`


## Resources

Expand Down
9 changes: 9 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Plugin, OutputOptions } from 'rollup';

import type { ExcludeFilepathOption } from './types';
import { BundleTransformOptions, bundleToWebpackStats } from './transform';

export { bundleToWebpackStats } from './transform';
Expand All @@ -12,6 +13,14 @@ interface WebpackStatsOptions extends BundleTransformOptions {
* default: webpack-stats.json
*/
fileName?: string;
/**
* Exclude matching assets
*/
excludeAssets?: ExcludeFilepathOption;
/**
* Exclude matching modules
*/
excludeModules?: ExcludeFilepathOption;
}

type WebpackStatsOptionsOrBuilder =
Expand Down
26 changes: 19 additions & 7 deletions src/transform.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import path from 'path';
import { OutputBundle } from 'rollup';
import type { OutputBundle } from 'rollup';

import type { ExcludeFilepathConfig } from "./types";
import { getByteSize, getChunkId } from "./utils";
import type { ExcludeFilepathOption } from "./types";
import { checkExcludeFilepath, getByteSize, getChunkId } from "./utils";

// https://github.com/relative-ci/bundle-stats/blob/master/packages/plugin-webpack-filter/src/index.ts
export type WebpackStatsFilteredAsset = {
Expand Down Expand Up @@ -51,20 +51,20 @@ export type BundleTransformOptions = {
/**
* Exclude asset
*/
excludeAssets?: ExcludeFilepathConfig | Array<ExcludeFilepathConfig>;
excludeAssets?: ExcludeFilepathOption;
/**
* Exclude module
*/
excludeModules?: ExcludeFilepathConfig | Array<ExcludeFilepathConfig>;
excludeModules?: ExcludeFilepathOption;
};

export const bundleToWebpackStats = (
bundle: OutputBundle,
customOptions?: BundleTransformOptions
pluginOptions?: BundleTransformOptions
): WebpackStatsFiltered => {
const options = {
moduleOriginalSize: false,
...customOptions,
...pluginOptions,
};

const items = Object.values(bundle);
Expand All @@ -76,6 +76,10 @@ export const bundleToWebpackStats = (

items.forEach(item => {
if (item.type === 'chunk') {
if (checkExcludeFilepath(item.fileName, options.excludeAssets)) {
return;
}

assets.push({
name: item.fileName,
size: getByteSize(item.code),
Expand All @@ -92,6 +96,10 @@ export const bundleToWebpackStats = (
});

Object.entries(item.modules).forEach(([modulePath, moduleInfo]) => {
if (checkExcludeFilepath(modulePath, options.excludeModules)) {
return;
}

// Remove unexpected rollup null prefix
const normalizedModulePath = modulePath.replace('\u0000', '');

Expand Down Expand Up @@ -120,6 +128,10 @@ export const bundleToWebpackStats = (
}
});
} else if (item.type === 'asset') {
if (checkExcludeFilepath(item.fileName, options.excludeAssets)) {
return;
}

assets.push({
name: item.fileName,
size: getByteSize(item.source.toString()),
Expand Down
4 changes: 3 additions & 1 deletion src/types.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export type ExcludeFilepathConfig = string | RegExp | ((filepath: string) => boolean);
export type ExcludeFilepathParam = string | RegExp | ((filepath: string) => boolean);

export type ExcludeFilepathOption = ExcludeFilepathParam | Array<ExcludeFilepathParam>;
24 changes: 12 additions & 12 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import path from 'path';
import crypto from 'crypto';
import type { OutputChunk } from 'rollup';

import type { ExcludeFilepathConfig } from './types';
import type { ExcludeFilepathOption } from './types';

const HASH_LENGTH = 7;

Expand Down Expand Up @@ -42,32 +42,32 @@ export function getChunkId(chunk: OutputChunk): string {
*/
export function checkExcludeFilepath(
filepath: string,
config?: ExcludeFilepathConfig | Array<ExcludeFilepathConfig>
option?: ExcludeFilepathOption,
): boolean {
if (!config) {
if (!option) {
return false;
}

if (Array.isArray(config)) {
if (Array.isArray(option)) {
let res = false;

for (let i = 0; i <= config.length - 1 && res === false; i++) {
res = checkExcludeFilepath(filepath, config[i]);
for (let i = 0; i <= option.length - 1 && res === false; i++) {
res = checkExcludeFilepath(filepath, option[i]);
}

return res;
}

if (typeof config === 'function') {
return config(filepath);
if (typeof option === 'function') {
return option(filepath);
}

if (typeof config === 'string') {
return Boolean(filepath.match(config));
if (typeof option === 'string') {
return Boolean(filepath.match(option));
}

if ('test' in config) {
return config.test(filepath);
if ('test' in option) {
return option.test(filepath);
}

return false;
Expand Down
176 changes: 176 additions & 0 deletions test/unit/fixtures/rollup-bundle-stats.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
import path from 'path';
import type { OutputBundle } from 'rollup';

const ROOT_DIR = path.join(__dirname, '../../../');

export default {
'assets/logo-abcd1234.svg': {
name: undefined,
fileName: 'assets/logo-abcd1234.svg',
type: 'asset',
source: '<svg></svg>',
needsCodeReference: true,
},
'assets/main-abcd1234.js': {
name: 'main',
fileName: 'assets/main-abcd1234.js',
preliminaryFileName: 'assets/main-abcd1234.js',
sourcemapFileName: 'assets/main-abcd1234.js.map',
type: 'chunk',
code: 'export default function () {}',
isEntry: true,
isDynamicEntry: false,
facadeModuleId: null,
map: null,
isImplicitEntry: false,
implicitlyLoadedBefore: [],
importedBindings: {},
referencedFiles: [],
moduleIds: [
path.join(ROOT_DIR, 'src/component-a.js'),
path.join(ROOT_DIR, 'src/index.js'),
],
modules: {
[path.join(ROOT_DIR, 'src/component-a.js')]: {
code: 'export default A = 1;',
originalLength: 10,
renderedLength: 8,
removedExports: [],
renderedExports: [],
},
[path.join(ROOT_DIR, 'src/index.js')]: {
code: '',
originalLength: 100,
renderedLength: 80,
removedExports: [],
renderedExports: [],
},
},
imports: [],
exports: [],
dynamicImports: [],
},
'assets/vendors-abcd1234.js': {
name: 'vendors',
fileName: 'assets/vendors-abcd1234.js',
preliminaryFileName: 'assets/vendors-abcd1234.js',
sourcemapFileName: 'assets/vendors-abcd1234.js.map',
type: 'chunk',
code: 'export default function () {}',
isEntry: true,
isDynamicEntry: false,
facadeModuleId: null,
map: null,
isImplicitEntry: false,
implicitlyLoadedBefore: [],
importedBindings: {},
referencedFiles: [],
moduleIds: [
path.join(ROOT_DIR, 'node_modules', 'package-a', 'index.js'),
path.join(ROOT_DIR, 'node_modules', 'package-b', 'index.js'),
],
modules: {
[path.join(
ROOT_DIR,
'node_modules',
'package-a',
'index.js'
)]: {
code: '',
originalLength: 10,
renderedLength: 8,
removedExports: [],
renderedExports: [],
},
[path.join(
ROOT_DIR,
'node_modules',
'package-b',
'index.js'
)]: {
code: '',
originalLength: 100,
renderedLength: 80,
removedExports: [],
renderedExports: [],
},
},
imports: [],
exports: [],
dynamicImports: [],
},
'assets/index-abcd1234.js': {
name: 'index',
fileName: 'assets/index-abcd1234.js',
preliminaryFileName: 'assets/index-abcd1234.js',
sourcemapFileName: 'assets/index-abcd1234.js.map',
type: 'chunk',
code: 'export default function () {}',
isEntry: false,
isDynamicEntry: true,
facadeModuleId: null,
map: null,
isImplicitEntry: false,
implicitlyLoadedBefore: [],
importedBindings: {},
referencedFiles: [],
moduleIds: [
path.join(ROOT_DIR, 'src', 'components/component-b/index.js'),
],
modules: {
[path.join(
ROOT_DIR,
'src',
'components',
'component-b',
'index.js',
)]: {
code: '',
originalLength: 10,
renderedLength: 8,
removedExports: [],
renderedExports: [],
},
},
imports: [],
exports: [],
dynamicImports: [],
},
'assets/index-efab5678.js': {
name: 'index',
fileName: 'assets/index-efab5678.js',
preliminaryFileName: 'assets/index-efab5678.js',
sourcemapFileName: 'assets/index-efab5678.js.map',
type: 'chunk',
code: 'export default function () {}',
isEntry: false,
isDynamicEntry: true,
facadeModuleId: null,
map: null,
isImplicitEntry: false,
implicitlyLoadedBefore: [],
importedBindings: {},
referencedFiles: [],
moduleIds: [
path.join(ROOT_DIR, 'src', 'components/component-c/index.js'),
],
modules: {
[path.join(
ROOT_DIR,
'src',
'components',
'component-c',
'index.js',
)]: {
code: '',
originalLength: 10,
renderedLength: 8,
removedExports: [],
renderedExports: [],
},
},
imports: [],
exports: [],
dynamicImports: [],
},
} satisfies OutputBundle;
Loading

0 comments on commit d37fe30

Please sign in to comment.