From 5dbb8704cc6780e377e68574a4aa55352b873b6b Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Thu, 23 Sep 2021 18:26:51 -0500 Subject: [PATCH] Ensure static image works correctly with basePath (#29307) This ensures we prefix the `src` for static images with the `basePath` correctly, this also copies over the static image tests to the basePath image-component suite. ## Bug - [x] Related issues linked using `fixes #number` - [x] Integration tests added - [x] Errors have helpful link attached, see `contributing.md` Fixes: https://github.com/vercel/next.js/issues/29289 --- .../webpack/loaders/next-image-loader.js | 4 +- packages/next/server/config.ts | 7 ++ packages/next/server/image-optimizer.ts | 4 +- .../base-path/components/TallImage.js | 20 ++++ .../base-path/components/tall.png | Bin 0 -> 6391 bytes .../base-path/pages/static-img.js | 54 +++++++++ .../base-path/public/foo/test-rect.jpg | Bin 0 -> 6089 bytes .../image-component/base-path/public/test.ico | Bin 0 -> 4286 bytes .../base-path/public/test.webp | Bin 0 -> 1018 bytes .../base-path/test/static.test.js | 105 ++++++++++++++++++ 10 files changed, 191 insertions(+), 3 deletions(-) create mode 100644 test/integration/image-component/base-path/components/TallImage.js create mode 100644 test/integration/image-component/base-path/components/tall.png create mode 100644 test/integration/image-component/base-path/pages/static-img.js create mode 100644 test/integration/image-component/base-path/public/foo/test-rect.jpg create mode 100644 test/integration/image-component/base-path/public/test.ico create mode 100644 test/integration/image-component/base-path/public/test.webp create mode 100644 test/integration/image-component/base-path/test/static.test.js diff --git a/packages/next/build/webpack/loaders/next-image-loader.js b/packages/next/build/webpack/loaders/next-image-loader.js index e4aff1b76e32f..4a4198b39154e 100644 --- a/packages/next/build/webpack/loaders/next-image-loader.js +++ b/packages/next/build/webpack/loaders/next-image-loader.js @@ -17,7 +17,7 @@ function nextImageLoader(content) { '/static/image/[path][name].[hash].[ext]', opts ) - const outputPath = '/_next' + interpolatedName + const outputPath = assetPrefix + '/_next' + interpolatedName let extension = loaderUtils.interpolateName(this, '[ext]', opts) if (extension === 'jpg') { @@ -32,7 +32,7 @@ function nextImageLoader(content) { if (isDev) { const prefix = 'http://localhost' const url = new URL('/_next/image', prefix) - url.searchParams.set('url', assetPrefix + outputPath) + url.searchParams.set('url', outputPath) url.searchParams.set('w', BLUR_IMG_SIZE) url.searchParams.set('q', BLUR_QUALITY) blurDataURL = url.href.slice(prefix.length) diff --git a/packages/next/server/config.ts b/packages/next/server/config.ts index 5690e59b984d7..24fa19b07bdab 100644 --- a/packages/next/server/config.ts +++ b/packages/next/server/config.ts @@ -196,6 +196,13 @@ function assignDefaults(userConfig: { [key: string]: any }) { ) } + // static images are automatically prefixed with assetPrefix + // so we need to ensure _next/image allows downloading from + // this resource + if (config.assetPrefix?.startsWith('http')) { + images.domains.push(new URL(config.assetPrefix).hostname) + } + if (images.domains.length > 50) { throw new Error( `Specified images.domains exceeds length of 50, received length (${images.domains.length}), please reduce the length of the array to continue.\nSee more info here: https://nextjs.org/docs/messages/invalid-images-config` diff --git a/packages/next/server/image-optimizer.ts b/packages/next/server/image-optimizer.ts index a2d7c6a664d0c..4a4227aeeb1f5 100644 --- a/packages/next/server/image-optimizer.ts +++ b/packages/next/server/image-optimizer.ts @@ -135,7 +135,9 @@ export async function imageOptimizer( } // Should match output from next-image-loader - const isStatic = url.startsWith('/_next/static/image') + const isStatic = url.startsWith( + `${nextConfig.basePath || ''}/_next/static/image` + ) const width = parseInt(w, 10) diff --git a/test/integration/image-component/base-path/components/TallImage.js b/test/integration/image-component/base-path/components/TallImage.js new file mode 100644 index 0000000000000..c0fbbcfe6d63c --- /dev/null +++ b/test/integration/image-component/base-path/components/TallImage.js @@ -0,0 +1,20 @@ +import React from 'react' +import Image from 'next/image' + +import testTall from './tall.png' + +const Page = () => { + return ( +
+

Static Image

+ +
+ ) +} + +export default Page diff --git a/test/integration/image-component/base-path/components/tall.png b/test/integration/image-component/base-path/components/tall.png new file mode 100644 index 0000000000000000000000000000000000000000..a792dda6c172ffb6254d0d82e3a9a8a7cfe4d3e3 GIT binary patch literal 6391 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 { + return ( +
+

Static Image

+ + + + + +
+ + + + + + + +
+ +
+ ) +} + +export default Page diff --git a/test/integration/image-component/base-path/public/foo/test-rect.jpg b/test/integration/image-component/base-path/public/foo/test-rect.jpg new file mode 100644 index 0000000000000000000000000000000000000000..68d3a8415f5e640fa5dc79e09d2f9fd455067a4b GIT binary patch literal 6089 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 literal 0 HcmV?d00001 diff --git a/test/integration/image-component/base-path/public/test.ico b/test/integration/image-component/base-path/public/test.ico new file mode 100644 index 0000000000000000000000000000000000000000..55cce0b4a854789496f8e303aa4937d87eed7d32 GIT binary patch literal 4286 zcmeHKI|_q95FNo%AyvReQc3U>dJYfbNz_uyl!B-55FSBWJ16@r(j>a8=2y(f$nxHs z55ue=k)@u?h47}^iRes3SLF(#NICG?6!*edVd63a*#X%B*?|{3U|H7Yx$KEq`VI#{ zz(rATRaIP;<*GviEn=4PZN**J<)&%a)SyMo);eqYIF7mRduuIu_yA7@~u@$b;#jt#>wdlW@qt&RS1$MQU%{Zsc%Hz(is8Lra_ SFaH;^1F{2ux&x}M-`O2o>eJW& literal 0 HcmV?d00001 diff --git a/test/integration/image-component/base-path/public/test.webp b/test/integration/image-component/base-path/public/test.webp new file mode 100644 index 0000000000000000000000000000000000000000..4b306cb0898cc93e83dd6f72566e13cbd1339eaa GIT binary patch literal 1018 zcmWIYbaVT}%)k)t>J$(bV4?5~$lhSgFqctl0^gPIDuB8qHv48H-EEbk|FBuIt(=eGzI!$@2M@ z#TTkpe-pQ_(pI`{*bt+CqK4g>WuD^-8`F(nA0CC+|Bv@@pq)xt!UWH|e=J2I&PYA^ zWlqk)0|9oTHfu`3u4+!vT_4xYrvJXmxxu=z`*eD{~o~@4h9AWfq9;% zqR$+A*q{}?M)}6!)9;$Um~P0+FB3LdlX7i)VN-;n!!5QNkGLvHafX9Y89~=x2}Fh~ z6{=Xw=Xf8owQpHQQhfe*DWBsR$IZ_)v2DNh4;YT~5_h_!EDZl17V~0$^#W^&%R;M9 z1TEjSC+p$CeWvFQFka)8vCV&;F*&+u0)t$j-NbM5|Eshts#iT?RJqI9Y@6$P?sJE; z(L-rLjkkxn89m~?Lr5i{_oxx zSN0*UK=A6}>)z2FvXA5!`;<=WJryi<{b@Bvy@XxL&U~+rMl7KV^LSQ#f56oEGG)cK z=rpw;j*oejQy>@ zO`}}>1>=?-D{WT%kUkpAsF(X!&bNaVHSjask0+H4Wp zPLZ)O`L|h_E7aw-7d((IxEm7R?EL(E9LSfq9oZdPx)1Qg`#-(@lK0TJ8-elG*X7c( z`yam$?FnSP{2}Dw-$B|+seK+ P+udJbdSnVPy+8l}7RKRp literal 0 HcmV?d00001 diff --git a/test/integration/image-component/base-path/test/static.test.js b/test/integration/image-component/base-path/test/static.test.js new file mode 100644 index 0000000000000..c3b050cb54387 --- /dev/null +++ b/test/integration/image-component/base-path/test/static.test.js @@ -0,0 +1,105 @@ +import { + findPort, + killApp, + nextBuild, + nextStart, + renderViaHTTP, + File, + waitFor, +} from 'next-test-utils' +import webdriver from 'next-webdriver' +import { join } from 'path' + +const appDir = join(__dirname, '../') +let appPort +let app +let browser +let html + +const indexPage = new File(join(appDir, 'pages/static-img.js')) + +const runTests = () => { + it('Should allow an image with a static src to omit height and width', async () => { + expect(await browser.elementById('basic-static')).toBeTruthy() + expect(await browser.elementById('blur-png')).toBeTruthy() + expect(await browser.elementById('blur-webp')).toBeTruthy() + expect(await browser.elementById('blur-jpg')).toBeTruthy() + expect(await browser.elementById('static-svg')).toBeTruthy() + expect(await browser.elementById('static-gif')).toBeTruthy() + expect(await browser.elementById('static-bmp')).toBeTruthy() + expect(await browser.elementById('static-ico')).toBeTruthy() + expect(await browser.elementById('static-unoptimized')).toBeTruthy() + }) + it('Should use immutable cache-control header for static import', async () => { + await browser.eval( + `document.getElementById("basic-static").scrollIntoView()` + ) + await waitFor(1000) + const url = await browser.eval( + `document.getElementById("basic-static").src` + ) + const res = await fetch(url) + expect(res.headers.get('cache-control')).toBe( + 'public, max-age=315360000, immutable' + ) + }) + it('Should use immutable cache-control header even when unoptimized', async () => { + await browser.eval( + `document.getElementById("static-unoptimized").scrollIntoView()` + ) + await waitFor(1000) + const url = await browser.eval( + `document.getElementById("static-unoptimized").src` + ) + const res = await fetch(url) + expect(res.headers.get('cache-control')).toBe( + 'public, max-age=31536000, immutable' + ) + }) + it('Should automatically provide an image height and width', async () => { + expect(html).toContain('width:400px;height:300px') + }) + it('Should allow provided width and height to override intrinsic', async () => { + expect(html).toContain('width:200px;height:200px') + expect(html).not.toContain('width:400px;height:400px') + }) + it('Should add a blurry placeholder to statically imported jpg', async () => { + expect(html).toContain( + `style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%;filter:blur(20px);background-size:cover;background-image:url("data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoKCgoKCgsMDAsPEA4QDxYUExMUFiIYGhgaGCIzICUgICUgMy03LCksNy1RQDg4QFFeT0pPXnFlZXGPiI+7u/sBCgoKCgoKCwwMCw8QDhAPFhQTExQWIhgaGBoYIjMgJSAgJSAzLTcsKSw3LVFAODhAUV5PSk9ecWVlcY+Ij7u7+//CABEIAAgACAMBIgACEQEDEQH/xAAUAAEAAAAAAAAAAAAAAAAAAAAH/9oACAEBAAAAADX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oACAECEAAAAH//xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oACAEDEAAAAH//xAAdEAABAgcAAAAAAAAAAAAAAAATEhUAAwUUIzLS/9oACAEBAAE/AB0ZlUac43GqMYuo/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAgEBPwB//8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAwEBPwB//9k=");background-position:0% 0%"` + ) + }) + it('Should add a blurry placeholder to statically imported png', async () => { + expect(html).toContain( + `style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%;filter:blur(20px);background-size:cover;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAQAAABuBnYAAAAATklEQVR42i2I0QmAMBQD869Q9K+IsxU6RkfoiA6T55VXDpJLJC9uUJIzcx+XFd2dXMbx8n+QpoeYDpgY66RaDA83jCUfVpK2pER1dcEUP+KfSBtXK+BpAAAAAElFTkSuQmCC");background-position:0% 0%"` + ) + }) +} + +describe('Build Error Tests for basePath', () => { + it('should throw build error when import statement is used with missing file', async () => { + await indexPage.replace( + '../public/foo/test-rect.jpg', + '../public/foo/test-rect-broken.jpg' + ) + + const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) + await indexPage.restore() + + expect(stderr).toContain( + "Error: Can't resolve '../public/foo/test-rect-broken.jpg" + ) + }) +}) +describe('Static Image Component Tests for basePath', () => { + beforeAll(async () => { + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) + html = await renderViaHTTP(appPort, '/docs/static-img') + browser = await webdriver(appPort, '/docs/static-img') + }) + afterAll(() => { + killApp(app) + }) + runTests() +})