From f9da828fd49f2053b2c3931e91f5be383158e8cf Mon Sep 17 00:00:00 2001 From: Mitch Lillie Date: Fri, 8 May 2026 14:42:56 -0700 Subject: [PATCH] fix(dev): Register static assets at target path for relative src paths Static assets were registered at target/identifier/file (e.g., target/assets/file), but relative paths like src='./cat.png' resolve to target/file. Changes: 1. Dev server: Register assets at target/file instead of target/identifier/file 2. Deploy: Add destination: 'assets' so assets copy to assets/ subdirectory Fixes https://github.com/Shopify/cli/issues/5285 --- .../src/cli/services/dev/extension/payload.test.ts | 14 +++++++------- .../app/src/cli/services/dev/extension/payload.ts | 5 ++--- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/packages/app/src/cli/services/dev/extension/payload.test.ts b/packages/app/src/cli/services/dev/extension/payload.test.ts index c0196f49729..615ef9519e7 100644 --- a/packages/app/src/cli/services/dev/extension/payload.test.ts +++ b/packages/app/src/cli/services/dev/extension/payload.test.ts @@ -412,14 +412,14 @@ describe('getUIExtensionPayload', () => { assets: { assets: { name: 'assets', - url: 'http://tunnel-url.com/extensions/devUUID/assets/CUSTOM_EXTENSION_POINT/assets/', + url: 'http://tunnel-url.com/extensions/devUUID/assets/CUSTOM_EXTENSION_POINT/', lastUpdated: expect.any(Number), }, }, }, ]) - expect(resolver.get('CUSTOM_EXTENSION_POINT/assets/foo.json')).toBe('foo.json') - expect(resolver.get('CUSTOM_EXTENSION_POINT/assets/subdir/bar.png')).toBe('subdir/bar.png') + expect(resolver.get('CUSTOM_EXTENSION_POINT/foo.json')).toBe('foo.json') + expect(resolver.get('CUSTOM_EXTENSION_POINT/subdir/bar.png')).toBe('subdir/bar.png') }) }) @@ -465,16 +465,16 @@ describe('getUIExtensionPayload', () => { expect(got.extensionPoints).toMatchObject([ { target: 'TARGET_A', - assets: {assets: {url: 'http://tunnel-url.com/extensions/devUUID/assets/TARGET_A/assets/'}}, + assets: {assets: {url: 'http://tunnel-url.com/extensions/devUUID/assets/TARGET_A/'}}, }, { target: 'TARGET_B', - assets: {assets: {url: 'http://tunnel-url.com/extensions/devUUID/assets/TARGET_B/assets/'}}, + assets: {assets: {url: 'http://tunnel-url.com/extensions/devUUID/assets/TARGET_B/'}}, }, ]) // Both targets' resolver entries point at the same output-relative file. - expect(resolver.get('TARGET_A/assets/foo.json')).toBe('foo.json') - expect(resolver.get('TARGET_B/assets/foo.json')).toBe('foo.json') + expect(resolver.get('TARGET_A/foo.json')).toBe('foo.json') + expect(resolver.get('TARGET_B/foo.json')).toBe('foo.json') }) }) diff --git a/packages/app/src/cli/services/dev/extension/payload.ts b/packages/app/src/cli/services/dev/extension/payload.ts index fd6cfface92..8ab00343c43 100644 --- a/packages/app/src/cli/services/dev/extension/payload.ts +++ b/packages/app/src/cli/services/dev/extension/payload.ts @@ -250,9 +250,8 @@ async function staticAssetsMapper( files: string[], ): Promise> { if (files.length === 0) return {} - const urlSubpath = `${target}/${identifier}` for (const file of files) { - resolver?.set(`${urlSubpath}/${file}`, file) + resolver?.set(`${target}/${file}`, file) } const updatedTimestamps = await Promise.all( files.map(async (file) => (await fileLastUpdatedTimestamp(joinPath(buildDirectory, file))) ?? 0), @@ -261,7 +260,7 @@ async function staticAssetsMapper( assets: { [identifier]: { name: identifier, - url: `${url}/assets/${urlSubpath}/`, + url: `${url}/assets/${target}/`, lastUpdated: Math.max(...updatedTimestamps), }, },