Skip to content

Commit 821d796

Browse files
authored
fix: manifest file sizes for texture packer (#163)
1 parent 988f5f2 commit 821d796

File tree

8 files changed

+386
-28
lines changed

8 files changed

+386
-28
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
],
1010
"scripts": {
1111
"build": "npm run build --workspace @assetpack/core",
12-
"clean": "rimraf dist **/*/.testInput **/*/.testOutput .assetpack packages/assetpack/test/cache/**/*",
12+
"clean": "rimraf --glob dist 'packages/assetpack/test/**/.testInput' 'packages/assetpack/test/**/.testOutput' .assetpack 'packages/assetpack/test/cache'",
1313
"lint:fix": "eslint . --fix",
1414
"prepare": "husky",
1515
"version:main": "node scripts/version.mjs",

packages/assetpack/src/manifest/pixiManifest.ts

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import fs from 'fs-extra';
2-
import zlib from 'node:zlib';
32
import { BuildReporter, path, stripTags } from '../core/index.js';
3+
import { getFileSizeInKB } from './utils.js';
44

55
import type { Asset, AssetPipe, PipeSystem, PluginOptions } from '../core/index.js';
66

@@ -44,7 +44,7 @@ export interface PixiManifestOptions extends PluginOptions {
4444
/**
4545
* if true, the file sizes of each asset will be included in the manifest.
4646
* The sizes are in kilobytes (KB) and represent the gzipped size of each asset.
47-
* @default true
47+
* @default false
4848
*/
4949
includeFileSizes?: false | 'gzip' | 'raw';
5050
/**
@@ -277,29 +277,14 @@ function collectAssets(
277277
src: sortFn(
278278
finalManifestAssets.map((finalAsset) => {
279279
const src = path.relative(outputPath, finalAsset.path);
280-
let size: number;
281280

282281
if (!options.includeFileSizes) {
283282
return src;
284283
}
285284

286-
try {
287-
if (options.includeFileSizes === 'raw') {
288-
size = fs.statSync(finalAsset.path).size;
289-
} else {
290-
size = zlib.gzipSync(fs.readFileSync(finalAsset.path)).length;
291-
}
292-
size = Number((size / 1024).toFixed(2));
293-
} catch (_e) {
294-
BuildReporter.warn(
295-
`[AssetPack][manifest] Unable to get size for asset '${finalAsset.path}'. Skipping file size entry.`,
296-
);
297-
size = 1;
298-
}
299-
300285
return {
301286
src,
302-
progressSize: size,
287+
progressSize: getFileSizeInKB(finalAsset.path, options.includeFileSizes === 'raw'),
303288
};
304289
}),
305290
),

packages/assetpack/src/manifest/utils.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import fs from 'fs-extra';
2+
import zlib from 'node:zlib';
3+
import { BuildReporter } from '../core/index.js';
4+
15
export function getManifestName(path: string, entry: string): string | null {
26
// Get the string after the entry path
37
const val = path.replace(entry, '');
@@ -20,3 +24,21 @@ export function getManifestName(path: string, entry: string): string | null {
2024

2125
return targetPath;
2226
}
27+
28+
export function getFileSizeInKB(filePath: string, useRaw = false): number {
29+
let size = 0;
30+
31+
try {
32+
if (useRaw) {
33+
size = fs.statSync(filePath).size;
34+
} else {
35+
size = zlib.gzipSync(fs.readFileSync(filePath)).length;
36+
}
37+
size = Number((size / 1024).toFixed(2));
38+
} catch (_e) {
39+
BuildReporter.warn(`[AssetPack] Unable to get size for asset '${filePath}'. Skipping file size entry.`);
40+
size = 1;
41+
}
42+
43+
return size;
44+
}

packages/assetpack/src/pixi/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { spineAtlasMipmap } from '../spine/spineAtlasMipmap.js';
1212
import { texturePacker } from '../texture-packer/texturePacker.js';
1313
import { texturePackerCacheBuster } from '../texture-packer/texturePackerCacheBuster.js';
1414
import { texturePackerCompress } from '../texture-packer/texturePackerCompress.js';
15+
import { texturePackerManifestMod } from '../texture-packer/texturePackerManifestMod.js';
1516
import { webfont } from '../webfont/webfont.js';
1617

1718
import type { AssetPipe } from '../core/index.js';
@@ -102,7 +103,11 @@ export function pixiPipes(config: PixiAssetPack) {
102103
...apConfig.manifest,
103104
};
104105

105-
pipes.push(pixiManifest(manifestOptions), spineAtlasManifestMod(manifestOptions));
106+
pipes.push(
107+
pixiManifest(manifestOptions),
108+
spineAtlasManifestMod(manifestOptions),
109+
texturePackerManifestMod(manifestOptions),
110+
);
106111

107112
return pipes;
108113
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export * from './texturePacker.js';
22
export * from './texturePackerCacheBuster.js';
33
export * from './texturePackerCompress.js';
4+
export * from './texturePackerManifestMod.js';
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import fs from 'fs-extra';
2+
import { findAssets, path } from '../core/index.js';
3+
import { type PixiManifest, type PixiManifestOptions } from '../manifest/pixiManifest.js';
4+
import { getFileSizeInKB } from '../manifest/utils.js';
5+
6+
import type { Asset, AssetPipe } from '../core/index.js';
7+
8+
export type TexturePackerManifestOptions = Pick<PixiManifestOptions, 'output' | 'includeFileSizes'>;
9+
10+
/**
11+
* This pipe will modify the manifest generated by 'pixiManifest'. It will replace the progressSize
12+
* of each src to ensure it includes the size of the texture and the json combined
13+
*
14+
* Once done, it rewrites the manifest.
15+
*
16+
* This should be added after the `pixiManifest` pipe.
17+
*
18+
* ensure that the same output path is passed to the pipe as the `pixiManifest` pipe. Otherwise
19+
* the manifest will not be found.
20+
*
21+
* As this pipe needs to know about all the textures in the texture files most of the work is done
22+
* in the finish method.
23+
*
24+
* Kind of like applying a patch at the end of the manifest process.
25+
*
26+
* @param _options
27+
* @returns
28+
*/
29+
export function texturePackerManifestMod(
30+
_options: TexturePackerManifestOptions = {},
31+
): AssetPipe<TexturePackerManifestOptions> {
32+
const defaultOptions: TexturePackerManifestOptions = {
33+
output: 'manifest.json',
34+
includeFileSizes: false,
35+
..._options,
36+
};
37+
38+
return {
39+
folder: false,
40+
name: 'texture-packer-manifest',
41+
defaultOptions,
42+
43+
async finish(asset: Asset, options, pipeSystem) {
44+
if (options.includeFileSizes === false) {
45+
return;
46+
}
47+
const spritesheets = findAssets(
48+
(asset) => asset.extension === '.json' && asset.allMetaData.tps && asset.transformChildren.length === 0,
49+
asset,
50+
true,
51+
);
52+
53+
const manifestLocation = options.output;
54+
55+
const newFileName =
56+
path.dirname(manifestLocation) === '.'
57+
? path.joinSafe(pipeSystem.outputPath, manifestLocation)
58+
: manifestLocation;
59+
60+
const manifest = fs.readJsonSync(newFileName);
61+
62+
spritesheets.forEach((atlasAsset) => {
63+
const buffer = atlasAsset.buffer;
64+
const json = JSON.parse(buffer.toString());
65+
66+
if (!json.meta || !json.meta.image) {
67+
return;
68+
}
69+
70+
const textures: string[] = Array.isArray(json.meta.image) ? json.meta.image : [json.meta.image];
71+
72+
textures.forEach((texture) => {
73+
let size = 0;
74+
const manifestPath = path.relative(pipeSystem.outputPath, atlasAsset.path);
75+
const texturePath = path.resolve(atlasAsset.directory, texture);
76+
77+
if (texturePath) {
78+
size = getFileSizeInKB(texturePath, options.includeFileSizes === 'raw');
79+
}
80+
findAndAddManifestAsset(manifest, `${manifestPath}`, size);
81+
});
82+
});
83+
84+
fs.writeJSONSync(newFileName, manifest, { spaces: 2 });
85+
},
86+
};
87+
}
88+
89+
function findAndAddManifestAsset(manifest: PixiManifest, assetPath: string, totalSize: number) {
90+
for (let i = 0; i < manifest.bundles.length; i++) {
91+
const assets = manifest.bundles[i].assets;
92+
93+
const manifestAsset = assets.find((asset) => {
94+
return asset.src.find((src) => (typeof src === 'string' ? src : src.src) === assetPath);
95+
});
96+
97+
if (manifestAsset) {
98+
const src = manifestAsset.src.find((src) => (typeof src === 'string' ? src : src.src) === assetPath);
99+
100+
if (typeof src === 'object') {
101+
src.progressSize = Number(((src.progressSize || 0) + totalSize).toFixed(2));
102+
} else {
103+
// convert to object
104+
const index = manifestAsset.src.indexOf(src!);
105+
106+
manifestAsset.src[index] = {
107+
src: src!,
108+
progressSize: totalSize,
109+
};
110+
}
111+
break;
112+
}
113+
}
114+
}

0 commit comments

Comments
 (0)