Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/calm-assets-build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'package-build-stats': patch
---

Support packages that emit auxiliary assets such as WebAssembly files.
8 changes: 8 additions & 0 deletions src/getDependencySizeTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,14 @@ async function bundleSizeTree(
const makeModule = (
mod: RspackModule,
): { path: string; source: string } | null => {
if (
mod.moduleType &&
!mod.moduleType.startsWith('javascript') &&
!mod.moduleType.startsWith('json')
) {
return null
}

const identifier = mod.identifier || ''
const resolvedPath = modulePath(identifier)
const source = normaliseModuleSource(mod)
Expand Down
13 changes: 3 additions & 10 deletions src/utils/build.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,16 +332,9 @@ const BuildUtils = {
throwIfAborted(options.signal)
const gzip = gzipSync(bundleContents, {}).length
const matches = asset.name.match(/(.+?)\.bundle\.(.+)$/)

if (!matches) {
throw new UnexpectedBuildError(
'Found an asset without the `.bundle` suffix. ' +
'A loader customization might be needed to recognize this asset type' +
asset.name,
)
}

Comment thread
pastelsky marked this conversation as resolved.
const [, entryName, extension] = matches
const parsedAssetName = path.parse(asset.name)
const entryName = matches?.[1] || parsedAssetName.name
const extension = matches?.[2] || parsedAssetName.ext.slice(1) || 'asset'

return {
name: entryName,
Expand Down
31 changes: 31 additions & 0 deletions tests/fast/build.utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { afterEach, describe, expect, test, vi } from 'vitest'
import fs from 'node:fs'
import { BuildCancelledError } from '../../src/errors/CustomError'

const mockRspack = vi.fn()
Expand All @@ -15,6 +16,8 @@ vi.mock('../../src/config/makeRspackConfig.js', () => ({
vi.mock('../../src/utils/telemetry.utils.js', () => ({
default: {
compilePackage: mockCompilePackage,
parseWebpackStats: vi.fn(),
assetsGZIPParseTime: vi.fn(),
},
}))

Expand Down Expand Up @@ -213,4 +216,32 @@ describe('BuildUtils.buildPackage', () => {
missingModules: ['missing-package'],
})
})

test('preserves emitted assets that do not use the bundle filename pattern', async () => {
const stats = {
compilation: { errors: [] },
toJson: () => ({
assets: [
{ name: 'main.bundle.js', size: 100, chunkNames: ['main'] },
{ name: 'assets/module.wasm', size: 50, chunkNames: [] },
],
}),
}

vi.spyOn(BuildUtils, 'createEntryPoint').mockReturnValue('/tmp/index.js')
vi.spyOn(BuildUtils, 'compilePackage').mockResolvedValue({
error: null,
stats: stats as any,
})
vi.spyOn(fs.promises, 'readFile').mockResolvedValue(
Buffer.from('asset contents'),
)

await expect(BuildUtils.buildPackage(buildArgs)).resolves.toMatchObject({
assets: [
{ name: 'main', type: 'js', size: 100 },
{ name: 'module', type: 'wasm', size: 50 },
],
})
})
})
26 changes: 26 additions & 0 deletions tests/fast/getDependencySizeTree.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,32 @@ describe('getDependencySizeTree - accuracy', () => {
}
})

it('does not pass non-JavaScript modules to the JavaScript minifier', async () => {
const base = '/project'
const javascriptSource = 'export const value = 42'
const stats = createStats([
{
identifier: `${base}/node_modules/wasm-package/index.js`,
moduleType: 'javascript/esm',
source: javascriptSource,
},
{
identifier: `webassembly/async|${base}/node_modules/wasm-package/module.wasm|evaluation`,
moduleType: 'webassembly/async',
source: Buffer.from([0x00, 0x01, 0x02, 0x03]),
},
])

const result = await getDependencySizeTree('fixture-pkg', stats)

expect(result).toEqual([
{
name: 'wasm-package',
approximateSize: await minifiedUtf8Size(javascriptSource),
},
])
})

it('aggregates nested pnpm, scoped, buffer, and virtual deps into accurate package sizes', async () => {
const base = '/project'
const levelOneSource = 'export const levelOne = () => "one"'
Expand Down