diff --git a/.changeset/rude-points-ring.md b/.changeset/rude-points-ring.md new file mode 100644 index 000000000..450a80644 --- /dev/null +++ b/.changeset/rude-points-ring.md @@ -0,0 +1,5 @@ +--- +"@callstack/repack": patch +--- + +Fix how size of a scaled assets is obtained (aligned with metro) diff --git a/packages/repack/src/loaders/assetsLoader/__tests__/assetsLoader.test.ts b/packages/repack/src/loaders/assetsLoader/__tests__/assetsLoader.test.ts index a834b50bf..1ee622fa9 100644 --- a/packages/repack/src/loaders/assetsLoader/__tests__/assetsLoader.test.ts +++ b/packages/repack/src/loaders/assetsLoader/__tests__/assetsLoader.test.ts @@ -126,36 +126,9 @@ describe('assetLoader', () => { 'star@3x.png' ); - describe('on ios', () => { + describe.each(['ios', 'android'])('on %s', (platform) => { it('should load and extract asset without scales', async () => { - const { code, volume } = await compileBundle('ios', { - ...fixtures, - './index.js': "export { default } from './__fixtures__/logo.png';", - }); - const context: { Export?: { default: Record } } = {}; - vm.runInNewContext(code, context); - - expect(context.Export?.default).toMatchSnapshot(); - expect(volume.toTree()).toMatchSnapshot(); - }); - - it('should load and extract asset with scales', async () => { - const { code, volume } = await compileBundle('ios', { - ...fixtures, - './index.js': "export { default } from './__fixtures__/star.png';", - }); - - const context: { Export?: { default: Record } } = {}; - vm.runInNewContext(code, context); - - expect(context.Export?.default).toMatchSnapshot(); - expect(volume.toTree()).toMatchSnapshot(); - }); - }); - - describe('on android', () => { - it('should load and extract asset without scales', async () => { - const { code, volume } = await compileBundle('android', { + const { code, volume } = await compileBundle(platform, { ...fixtures, './index.js': "export { default } from './__fixtures__/logo.png';", }); @@ -168,7 +141,7 @@ describe('assetLoader', () => { }); it('should load and extract asset with scales', async () => { - const { code, volume } = await compileBundle('android', { + const { code, volume } = await compileBundle(platform, { ...fixtures, './index.js': "export { default } from './__fixtures__/star.png';", }); diff --git a/packages/repack/src/loaders/assetsLoader/assetsLoader.ts b/packages/repack/src/loaders/assetsLoader/assetsLoader.ts index de07a4808..413048e18 100644 --- a/packages/repack/src/loaders/assetsLoader/assetsLoader.ts +++ b/packages/repack/src/loaders/assetsLoader/assetsLoader.ts @@ -113,12 +113,13 @@ export default async function repackAssetsLoader( } : null; + // assets are sorted by scale, in ascending order const assets = await Promise.all( scaleKeys.map(async (scaleKey) => { const assetPath = scales[scaleKey]; - const isDefault = assetPath === resourcePath; + const isLoaded = assetPath === resourcePath; // use raw Buffer passed to loader to avoid unnecessary read - const content = isDefault ? assetData : await readFileAsync(assetPath); + const content = isLoaded ? assetData : await readFileAsync(assetPath); let destination: string; @@ -197,7 +198,6 @@ export default async function repackAssetsLoader( return { data: content, - default: isDefault, dimensions, filename: destination, scale, diff --git a/packages/repack/src/loaders/assetsLoader/convertToRemoteAssets.ts b/packages/repack/src/loaders/assetsLoader/convertToRemoteAssets.ts index a7fa25082..21f6d41e2 100644 --- a/packages/repack/src/loaders/assetsLoader/convertToRemoteAssets.ts +++ b/packages/repack/src/loaders/assetsLoader/convertToRemoteAssets.ts @@ -1,7 +1,7 @@ import path from 'node:path'; import dedent from 'dedent'; import type { Asset } from './types'; -import { getDefaultAsset } from './utils'; +import { getAssetSize } from './utils'; export function convertToRemoteAssets({ assets, @@ -29,7 +29,8 @@ export function convertToRemoteAssets({ // works on both unix & windows const publicPathURL = new URL(path.join(remotePublicPath, assetPath)); - const size = getDefaultAsset(assets).dimensions; + const size = getAssetSize(assets); + const asset = JSON.stringify({ name: resourceFilename, type: resourceExtensionType, diff --git a/packages/repack/src/loaders/assetsLoader/extractAssets.ts b/packages/repack/src/loaders/assetsLoader/extractAssets.ts index af7b25252..91524a5d6 100644 --- a/packages/repack/src/loaders/assetsLoader/extractAssets.ts +++ b/packages/repack/src/loaders/assetsLoader/extractAssets.ts @@ -2,7 +2,7 @@ import crypto from 'node:crypto'; import path from 'node:path'; import dedent from 'dedent'; import type { Asset } from './types'; -import { getDefaultAsset } from './utils'; +import { getAssetSize } from './utils'; export function extractAssets( { @@ -39,7 +39,7 @@ export function extractAssets( publicPath = path.join(customPublicPath, publicPath); } - const size = getDefaultAsset(assets).dimensions; + const size = getAssetSize(assets); const scales = assets.map((asset) => asset.scale); const hashes = assets.map((asset) => crypto.createHash('md5').update(asset.data).digest('hex') diff --git a/packages/repack/src/loaders/assetsLoader/types.ts b/packages/repack/src/loaders/assetsLoader/types.ts index dd20c60e6..2f8f73467 100644 --- a/packages/repack/src/loaders/assetsLoader/types.ts +++ b/packages/repack/src/loaders/assetsLoader/types.ts @@ -1,6 +1,5 @@ export interface Asset { data: Buffer; - default: boolean; dimensions: AssetDimensions | null; filename: string; scale: number; diff --git a/packages/repack/src/loaders/assetsLoader/utils.ts b/packages/repack/src/loaders/assetsLoader/utils.ts index 258d873f1..bdb011104 100644 --- a/packages/repack/src/loaders/assetsLoader/utils.ts +++ b/packages/repack/src/loaders/assetsLoader/utils.ts @@ -6,13 +6,10 @@ export function getScaleNumber(scaleKey: string) { return Number.parseFloat(scaleKey.replace(/[^\d.]/g, '')); } -/** Default asset is the one with scale that was originally requested in the loader */ -export function getDefaultAsset(assets: Asset[]) { - const defaultAsset = assets.find((asset) => asset.default === true); - if (!defaultAsset) { - throw new Error('Malformed assets array - no default asset found'); - } - return defaultAsset; +export function getAssetSize(assets: Asset[]) { + // Use first asset for reference as size, just like in metro: + // https://github.com/facebook/metro/blob/main/packages/metro/src/Assets.js#L223 + return assets[0].dimensions; } export function getAssetDimensions({