From d00397d645904cd45ec16dabf7c9555d56cce670 Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Mon, 29 Apr 2024 14:22:12 +0100 Subject: [PATCH 1/2] cache bust at start of file --- packages/cache-buster/src/cacheBuster.ts | 18 ++++++++++++++++-- packages/spine/test/spineAtlasAll.test.ts | 16 ++++++++-------- .../test/texturePackerAll.test.ts | 12 ++++++------ 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/packages/cache-buster/src/cacheBuster.ts b/packages/cache-buster/src/cacheBuster.ts index cc30d18..fe038e2 100644 --- a/packages/cache-buster/src/cacheBuster.ts +++ b/packages/cache-buster/src/cacheBuster.ts @@ -1,4 +1,4 @@ -import { createNewAssetAt, swapExt } from '@play-co/assetpack-core'; +import { createNewAssetAt, stripTags, swapExt } from '@play-co/assetpack-core'; import type { Asset, AssetPipe } from '@play-co/assetpack-core'; @@ -27,7 +27,21 @@ export function cacheBuster(): AssetPipe async transform(asset: Asset) { const hash = asset.hash; - const newFileName = swapExt(asset.filename, `-${hash}${asset.extension}`); + + // first try to stick the has on the end of the original file name + const originalFileName = swapExt(stripTags(asset.rootTransformAsset.filename), ''); + + let newFileName: string; + + if (asset.filename.includes(originalFileName)) + { + newFileName = asset.filename.replace(originalFileName, `${originalFileName}-${hash}`); + } + else + { + // failing that just stick it on the end! + newFileName = swapExt(asset.filename, `-${hash}${asset.extension}`); + } const newAsset = createNewAssetAt(asset, newFileName); diff --git a/packages/spine/test/spineAtlasAll.test.ts b/packages/spine/test/spineAtlasAll.test.ts index 0fe8030..6f4c95a 100644 --- a/packages/spine/test/spineAtlasAll.test.ts +++ b/packages/spine/test/spineAtlasAll.test.ts @@ -131,22 +131,22 @@ describe('Spine Atlas All', () => [ { - atlas: `dragon@0.5x.webp-gWXF6w.atlas`, - png1: `dragon@0.5x-7mmX8g.webp`, - png2: `dragon2@0.5x-k_22pw.webp` + atlas: `dragon-ZmGiUA@0.5x.webp.atlas`, + png1: `dragon-7mmX8g@0.5x.webp`, + png2: `dragon2-k_22pw@0.5x.webp` }, { - atlas: `dragon.webp-spj8.atlas`, + atlas: `dragon-spj8.webp.atlas`, png1: `dragon-rSwKOg.webp`, png2: `dragon2-ws3uhw.webp` }, { - atlas: `dragon@0.5x.png-jg5ydg.atlas`, - png1: `dragon@0.5x-3--s.png`, - png2: `dragon2@0.5x-vflfww.png` + atlas: `dragon-wstH@0.5x.png.atlas`, + png1: `dragon-3--s@0.5x.png`, + png2: `dragon2-vflfww@0.5x.png` }, { - atlas: `dragon.png-O471eg.atlas`, + atlas: `dragon-O471eg.png.atlas`, png1: `dragon-vezElA.png`, png2: `dragon2-3UnJNw.png` } diff --git a/packages/texture-packer/test/texturePackerAll.test.ts b/packages/texture-packer/test/texturePackerAll.test.ts index a73c09a..f5b44ab 100644 --- a/packages/texture-packer/test/texturePackerAll.test.ts +++ b/packages/texture-packer/test/texturePackerAll.test.ts @@ -79,20 +79,20 @@ describe('Texture Packer All', () => [ { - json: `sprites@0.5x.webp-1it4Qw.json`, - image: `sprites@0.5x-g_W8Sw.webp`, + json: `sprites-dvKKlQ@0.5x.webp.json`, + image: `sprites-g_W8Sw@0.5x.webp`, }, { - json: `sprites.webp-RCqjNQ.json`, + json: `sprites-RCqjNQ.webp.json`, image: `sprites-wXEUjA.webp`, }, { - json: `sprites@0.5x.png--5BuTA.json`, - image: `sprites@0.5x-TV3-Lg.png`, + json: `sprites-1Cv-Yg@0.5x.png.json`, + image: `sprites-TV3-Lg@0.5x.png`, }, { - json: `sprites.png-FYLGeg.json`, + json: `sprites-FYLGeg.png.json`, image: `sprites-Ef_oOA.png`, } ].forEach(({ json, image }) => From 1b5bde4843b9d66b7c1b9bd842594c1975380bfa Mon Sep 17 00:00:00 2001 From: Mat Groves Date: Mon, 29 Apr 2024 14:23:00 +0100 Subject: [PATCH 2/2] adjust cache naming --- packages/cache-buster/src/cacheBuster.ts | 53 ++++++ packages/spine/test/spineAtlasAll.test.ts | 164 ++++++++++++++++++ .../test/texturePackerAll.test.ts | 105 +++++++++++ 3 files changed, 322 insertions(+) create mode 100644 packages/cache-buster/src/cacheBuster.ts create mode 100644 packages/spine/test/spineAtlasAll.test.ts create mode 100644 packages/texture-packer/test/texturePackerAll.test.ts diff --git a/packages/cache-buster/src/cacheBuster.ts b/packages/cache-buster/src/cacheBuster.ts new file mode 100644 index 0000000..fe038e2 --- /dev/null +++ b/packages/cache-buster/src/cacheBuster.ts @@ -0,0 +1,53 @@ +import { createNewAssetAt, stripTags, swapExt } from '@play-co/assetpack-core'; + +import type { Asset, AssetPipe } from '@play-co/assetpack-core'; + +/** + * Cache buster asset pipe. This pipe will add a hash to the end of the filename + * the hash is calculated from the contents of the file. + * + * worth noting that when combined with the texture packer plugin, an additional + * plugin is required to update the texture packer json files to point to the new + * file names (`texturePackerCacheBuster.ts`) + * + * @returns the cache buster asset pipe + */ +export function cacheBuster(): AssetPipe +{ + const defaultOptions = {}; + + return { + folder: false, + name: 'cache-buster', + defaultOptions, + test(asset: Asset) + { + return !asset.isFolder; + }, + async transform(asset: Asset) + { + const hash = asset.hash; + + // first try to stick the has on the end of the original file name + const originalFileName = swapExt(stripTags(asset.rootTransformAsset.filename), ''); + + let newFileName: string; + + if (asset.filename.includes(originalFileName)) + { + newFileName = asset.filename.replace(originalFileName, `${originalFileName}-${hash}`); + } + else + { + // failing that just stick it on the end! + newFileName = swapExt(asset.filename, `-${hash}${asset.extension}`); + } + + const newAsset = createNewAssetAt(asset, newFileName); + + newAsset.buffer = asset.buffer; + + return [newAsset]; + }, + }; +} diff --git a/packages/spine/test/spineAtlasAll.test.ts b/packages/spine/test/spineAtlasAll.test.ts new file mode 100644 index 0000000..6f4c95a --- /dev/null +++ b/packages/spine/test/spineAtlasAll.test.ts @@ -0,0 +1,164 @@ +import { existsSync, readFileSync } from 'fs-extra'; +import { assetPath, createFolder, getInputDir, getOutputDir } from '../../../shared/test'; +import { spineAtlasCacheBuster } from '../src/spineAtlasCacheBuster'; +import { spineAtlasCompress } from '../src/spineAtlasCompress'; +import { spineAtlasMipmap } from '../src/spineAtlasMipmap'; +import { AssetPack } from '@play-co/assetpack-core'; +import { cacheBuster } from '@play-co/assetpack-plugin-cache-buster'; +import { compress, mipmap } from '@play-co/assetpack-plugin-image'; + +const pkg = 'spine'; + +describe('Spine Atlas All', () => +{ + it('should correctly create files when Mipmap and Compress are used', async () => + { + const testName = 'spine-atlas-compress-mip'; + const inputDir = getInputDir(pkg, testName); + const outputDir = getOutputDir(pkg, testName); + + createFolder( + pkg, + { + name: testName, + files: [ + { + name: 'dragon{spine}.atlas', + content: assetPath(pkg, 'dragon.atlas'), + }, + { + name: 'dragon.png', + content: assetPath(pkg, 'dragon.png'), + }, + { + name: 'dragon2.png', + content: assetPath(pkg, 'dragon2.png'), + }, + ], + folders: [], + }); + + const assetpack = new AssetPack({ + entry: inputDir, + output: outputDir, + cache: false, + pipes: [ + compress({ + png: true, + webp: true, + jpg: true, + }), + mipmap({ + resolutions: { default: 1, low: 0.5 }, + }), + spineAtlasMipmap({ + resolutions: { default: 1, low: 0.5 }, + }), + spineAtlasCompress({ + png: true, + jpg: true, + webp: true, + }), + ] + }); + + await assetpack.run(); + + const rawAtlasWebpHalf = readFileSync(`${outputDir}/dragon@0.5x.webp.atlas`); + const rawAtlasHalf = readFileSync(`${outputDir}/dragon@0.5x.png.atlas`); + + expect(rawAtlasHalf.includes('dragon@0.5x.png')).toBeTruthy(); + expect(rawAtlasHalf.includes('dragon2@0.5x.png')).toBeTruthy(); + + expect(rawAtlasWebpHalf.includes('dragon@0.5x.webp')).toBeTruthy(); + expect(rawAtlasWebpHalf.includes('dragon2@0.5x.webp')).toBeTruthy(); + }); + + it('should correctly create files when Mipmap and CacheBuster are used', async () => + { + const testName = 'spine-atlas-mip-cache-buster'; + const inputDir = getInputDir(pkg, testName); + const outputDir = getOutputDir(pkg, testName); + + createFolder( + pkg, + { + name: testName, + files: [ + { + name: 'dragon{spine}.atlas', + content: assetPath(pkg, 'dragon.atlas'), + }, + { + name: 'dragon.png', + content: assetPath(pkg, 'dragon.png'), + }, + { + name: 'dragon2.png', + content: assetPath(pkg, 'dragon2.png'), + }, + ], + folders: [], + }); + + const assetpack = new AssetPack({ + entry: inputDir, + output: outputDir, + cache: false, + pipes: [ + mipmap({ + resolutions: { default: 1, low: 0.5 }, + }), + compress({ + png: true, + webp: true, + jpg: true, + }), + spineAtlasMipmap({ + resolutions: { default: 1, low: 0.5 }, + }), + spineAtlasCompress({ + png: true, + jpg: true, + webp: true, + }), + cacheBuster(), + spineAtlasCacheBuster() + ] + }); + + await assetpack.run(); + + [ + { + atlas: `dragon-ZmGiUA@0.5x.webp.atlas`, + png1: `dragon-7mmX8g@0.5x.webp`, + png2: `dragon2-k_22pw@0.5x.webp` + }, + { + atlas: `dragon-spj8.webp.atlas`, + png1: `dragon-rSwKOg.webp`, + png2: `dragon2-ws3uhw.webp` + }, + { + atlas: `dragon-wstH@0.5x.png.atlas`, + png1: `dragon-3--s@0.5x.png`, + png2: `dragon2-vflfww@0.5x.png` + }, + { + atlas: `dragon-O471eg.png.atlas`, + png1: `dragon-vezElA.png`, + png2: `dragon2-3UnJNw.png` + } + ].forEach(({ atlas, png1, png2 }) => + { + const rawAtlas = readFileSync(`${outputDir}/${atlas}`); + + expect(rawAtlas.includes(png1)).toBeTruthy(); + expect(rawAtlas.includes(png2)).toBeTruthy(); + + expect(existsSync(`${outputDir}/${png1}`)).toBeTruthy(); + expect(existsSync(`${outputDir}/${png2}`)).toBeTruthy(); + }); + }); +}); diff --git a/packages/texture-packer/test/texturePackerAll.test.ts b/packages/texture-packer/test/texturePackerAll.test.ts new file mode 100644 index 0000000..f5b44ab --- /dev/null +++ b/packages/texture-packer/test/texturePackerAll.test.ts @@ -0,0 +1,105 @@ +import { readJSONSync } from 'fs-extra'; +import { assetPath, createFolder, getInputDir, getOutputDir } from '../../../shared/test/index'; +import { texturePacker } from '../src/texturePacker'; +import { texturePackerCacheBuster } from '../src/texturePackerCacheBuster'; +import { texturePackerCompress } from '../src/texturePackerCompress'; +import { AssetPack } from '@play-co/assetpack-core'; +import { cacheBuster } from '@play-co/assetpack-plugin-cache-buster'; +import { compress, mipmap } from '@play-co/assetpack-plugin-image'; + +import type { File } from 'shared/test'; + +const pkg = 'texture-packer'; + +function genFolder(testName: string) +{ + const sprites: File[] = []; + + for (let i = 0; i < 10; i++) + { + sprites.push({ + name: `sprite${i}.png`, + content: assetPath(pkg, `sp-${i + 1}.png`), + }); + } + createFolder( + pkg, + { + name: testName, + files: [], + folders: [ + { + name: 'sprites{tps}', + files: sprites, + folders: [], + }, + ], + }); +} + +describe('Texture Packer All', () => +{ + it('should create a sprite sheet mip, compress and cache bust', async () => + { + const testName = 'tp-all'; + const inputDir = getInputDir(pkg, testName); + const outputDir = getOutputDir(pkg, testName); + + genFolder(testName); + + const assetpack = new AssetPack({ + entry: inputDir, + output: outputDir, + cache: false, + pipes: [ + texturePacker({ + resolutionOptions: { + resolutions: { default: 1, low: 0.5 }, + }, + }), + mipmap({ + resolutions: { default: 1, low: 0.5 }, + }), + compress({ + png: true, + jpg: true, + webp: true, + }), + texturePackerCompress({ + png: true, + jpg: true, + webp: true, + }), + cacheBuster(), + texturePackerCacheBuster() + ] + }); + + await assetpack.run(); + + [ + { + json: `sprites-dvKKlQ@0.5x.webp.json`, + image: `sprites-g_W8Sw@0.5x.webp`, + }, + { + json: `sprites-RCqjNQ.webp.json`, + image: `sprites-wXEUjA.webp`, + }, + { + json: `sprites-1Cv-Yg@0.5x.png.json`, + image: `sprites-TV3-Lg@0.5x.png`, + + }, + { + json: `sprites-FYLGeg.png.json`, + image: `sprites-Ef_oOA.png`, + } + ].forEach(({ json, image }) => + { + const jsonData = readJSONSync(`${outputDir}/${json}`); + + expect(jsonData.meta.image).toEqual(image); + }); + }); +});