diff --git a/code/frameworks/nextjs/package.json b/code/frameworks/nextjs/package.json index d5ba68b05c9f..5395127a6398 100644 --- a/code/frameworks/nextjs/package.json +++ b/code/frameworks/nextjs/package.json @@ -100,7 +100,7 @@ "find-up": "^5.0.0", "fs-extra": "^11.1.0", "image-size": "^1.0.0", - "loader-utils": "^3.2.0", + "loader-utils": "^3.2.1", "node-polyfill-webpack-plugin": "^2.0.1", "pnp-webpack-plugin": "^1.7.0", "postcss": "^8.4.21", @@ -108,6 +108,7 @@ "resolve-url-loader": "^5.0.0", "sass-loader": "^12.4.0", "semver": "^7.3.5", + "sharp": "^0.32.6", "style-loader": "^3.3.1", "styled-jsx": "5.1.1", "ts-dedent": "^2.0.0", @@ -119,6 +120,7 @@ "@types/babel__core": "^7", "@types/babel__plugin-transform-runtime": "^7", "@types/babel__preset-env": "^7", + "@types/loader-utils": "^2.0.5", "next": "^14.0.0", "typescript": "^4.9.3", "webpack": "^5.65.0" diff --git a/code/frameworks/nextjs/src/next-image-loader-stub.ts b/code/frameworks/nextjs/src/next-image-loader-stub.ts index 04a97fdead81..6f69e8e274d3 100644 --- a/code/frameworks/nextjs/src/next-image-loader-stub.ts +++ b/code/frameworks/nextjs/src/next-image-loader-stub.ts @@ -1,29 +1,52 @@ -// @ts-expect-error (loader-utils has no webpack5 compatible types) import { interpolateName } from 'loader-utils'; import imageSizeOf from 'image-size'; import type { RawLoaderDefinition } from 'webpack'; import type { NextConfig } from 'next'; +import sharp from 'sharp'; +import { cpus } from 'os'; interface LoaderOptions { filename: string; nextConfig: NextConfig; } -const nextImageLoaderStub: RawLoaderDefinition = function (content) { +if (sharp.concurrency() > 1) { + // Reducing concurrency reduces the memory usage too. + const divisor = process.env.NODE_ENV === 'development' ? 4 : 2; + sharp.concurrency(Math.floor(Math.max(cpus().length / divisor, 1))); +} + +const nextImageLoaderStub: RawLoaderDefinition = async function NextImageLoader( + content +) { const { filename, nextConfig } = this.getOptions(); - const outputPath = interpolateName(this, filename.replace('[ext]', '.[ext]'), { + const opts = { context: this.rootContext, content, - }); + }; + const outputPath = interpolateName(this, filename.replace('[ext]', '.[ext]'), opts); + const extension = interpolateName(this, '[ext]', opts); this.emitFile(outputPath, content); - const { width, height } = imageSizeOf(this.resourcePath); - if (nextConfig.images?.disableStaticImages) { return `const src = '${outputPath}'; export default src;`; } + let width; + let height; + + if (extension === 'avif') { + const transformer = sharp(content); + const result = await transformer.metadata(); + width = result.width; + height = result.height; + } else { + const result = imageSizeOf(this.resourcePath); + width = result.width; + height = result.height; + } + return `export default ${JSON.stringify({ src: outputPath, height, diff --git a/code/frameworks/nextjs/template/stories/Image.stories.jsx b/code/frameworks/nextjs/template/stories/Image.stories.jsx index 7a8803a6e992..d0da833485d4 100644 --- a/code/frameworks/nextjs/template/stories/Image.stories.jsx +++ b/code/frameworks/nextjs/template/stories/Image.stories.jsx @@ -3,6 +3,7 @@ import Image from 'next/image'; import { waitFor } from '@storybook/testing-library'; import Accessibility from '../../assets/accessibility.svg'; +import AvifImage from '../../assets/avif-test-image.avif'; export default { component: Image, @@ -14,6 +15,13 @@ export default { export const Default = {}; +export const Avif = { + args: { + src: AvifImage, + alt: 'Avif Test Image', + }, +}; + export const BlurredPlaceholder = { args: { placeholder: 'blur', diff --git a/code/lib/cli/rendererAssets/common/assets/avif-test-image.avif b/code/lib/cli/rendererAssets/common/assets/avif-test-image.avif new file mode 100644 index 000000000000..530709bc1217 Binary files /dev/null and b/code/lib/cli/rendererAssets/common/assets/avif-test-image.avif differ diff --git a/code/yarn.lock b/code/yarn.lock index e985d4e8c31e..af3b0fc1bc99 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -7320,12 +7320,13 @@ __metadata: "@types/babel__core": "npm:^7" "@types/babel__plugin-transform-runtime": "npm:^7" "@types/babel__preset-env": "npm:^7" + "@types/loader-utils": "npm:^2.0.5" "@types/node": "npm:^18.0.0" css-loader: "npm:^6.7.3" find-up: "npm:^5.0.0" fs-extra: "npm:^11.1.0" image-size: "npm:^1.0.0" - loader-utils: "npm:^3.2.0" + loader-utils: "npm:^3.2.1" next: "npm:^14.0.0" node-polyfill-webpack-plugin: "npm:^2.0.1" pnp-webpack-plugin: "npm:^1.7.0" @@ -7334,6 +7335,7 @@ __metadata: resolve-url-loader: "npm:^5.0.0" sass-loader: "npm:^12.4.0" semver: "npm:^7.3.5" + sharp: "npm:^0.32.6" style-loader: "npm:^3.3.1" styled-jsx: "npm:5.1.1" ts-dedent: "npm:^2.0.0" @@ -9467,6 +9469,16 @@ __metadata: languageName: node linkType: hard +"@types/loader-utils@npm:^2.0.5": + version: 2.0.5 + resolution: "@types/loader-utils@npm:2.0.5" + dependencies: + "@types/node": "npm:*" + "@types/webpack": "npm:^4" + checksum: cea54ca7c1b220ddaf281dd5420bea52ceef3150e6fe0708c4a5793a1ac61c478355178c23479eb84c1d2667235156dc2b13dbc377646ed08055f3d552354e4f + languageName: node + linkType: hard + "@types/lodash@npm:^4.14.167": version: 4.14.199 resolution: "@types/lodash@npm:4.14.199" @@ -11856,6 +11868,13 @@ __metadata: languageName: node linkType: hard +"b4a@npm:^1.6.4": + version: 1.6.4 + resolution: "b4a@npm:1.6.4" + checksum: a0af707430c3643fd8d9418c732849d3626f1c9281489e021fcad969fb4808fb9f67b224de36b59c9c3b5a13d853482fee0c0eb53f7aec12d540fa67f63648b6 + languageName: node + linkType: hard + "babel-core@npm:^7.0.0-bridge.0": version: 7.0.0-bridge.0 resolution: "babel-core@npm:7.0.0-bridge.0" @@ -13649,13 +13668,23 @@ __metadata: languageName: node linkType: hard -"color-name@npm:~1.1.4": +"color-name@npm:^1.0.0, color-name@npm:~1.1.4": version: 1.1.4 resolution: "color-name@npm:1.1.4" checksum: a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 languageName: node linkType: hard +"color-string@npm:^1.9.0": + version: 1.9.1 + resolution: "color-string@npm:1.9.1" + dependencies: + color-name: "npm:^1.0.0" + simple-swizzle: "npm:^0.2.2" + checksum: b0bfd74c03b1f837f543898b512f5ea353f71630ccdd0d66f83028d1f0924a7d4272deb278b9aef376cacf1289b522ac3fb175e99895283645a2dc3a33af2404 + languageName: node + linkType: hard + "color-support@npm:^1.1.2, color-support@npm:^1.1.3": version: 1.1.3 resolution: "color-support@npm:1.1.3" @@ -13665,6 +13694,16 @@ __metadata: languageName: node linkType: hard +"color@npm:^4.2.3": + version: 4.2.3 + resolution: "color@npm:4.2.3" + dependencies: + color-convert: "npm:^2.0.1" + color-string: "npm:^1.9.0" + checksum: 7fbe7cfb811054c808349de19fb380252e5e34e61d7d168ec3353e9e9aacb1802674bddc657682e4e9730c2786592a4de6f8283e7e0d3870b829bb0b7b2f6118 + languageName: node + linkType: hard + "colorette@npm:^2.0.10, colorette@npm:^2.0.19, colorette@npm:^2.0.20": version: 2.0.20 resolution: "colorette@npm:2.0.20" @@ -14771,6 +14810,13 @@ __metadata: languageName: node linkType: hard +"deep-extend@npm:^0.6.0": + version: 0.6.0 + resolution: "deep-extend@npm:0.6.0" + checksum: 1c6b0abcdb901e13a44c7d699116d3d4279fdb261983122a3783e7273844d5f2537dc2e1c454a23fcf645917f93fbf8d07101c1d03c015a87faa662755212566 + languageName: node + linkType: hard + "deep-is@npm:^0.1.3": version: 0.1.4 resolution: "deep-is@npm:0.1.4" @@ -14994,6 +15040,13 @@ __metadata: languageName: node linkType: hard +"detect-libc@npm:^2.0.0, detect-libc@npm:^2.0.2": + version: 2.0.2 + resolution: "detect-libc@npm:2.0.2" + checksum: a9f4ffcd2701525c589617d98afe5a5d0676c8ea82bcc4ed6f3747241b79f781d36437c59a5e855254c864d36a3e9f8276568b6b531c28d6e53b093a15703f11 + languageName: node + linkType: hard + "detect-newline@npm:3.1.0, detect-newline@npm:^3.0.0": version: 3.1.0 resolution: "detect-newline@npm:3.1.0" @@ -16894,6 +16947,13 @@ __metadata: languageName: node linkType: hard +"expand-template@npm:^2.0.3": + version: 2.0.3 + resolution: "expand-template@npm:2.0.3" + checksum: 1c9e7afe9acadf9d373301d27f6a47b34e89b3391b1ef38b7471d381812537ef2457e620ae7f819d2642ce9c43b189b3583813ec395e2938319abe356a9b2f51 + languageName: node + linkType: hard + "expand-tilde@npm:^2.0.2": version: 2.0.2 resolution: "expand-tilde@npm:2.0.2" @@ -17076,6 +17136,13 @@ __metadata: languageName: node linkType: hard +"fast-fifo@npm:^1.1.0, fast-fifo@npm:^1.2.0": + version: 1.3.2 + resolution: "fast-fifo@npm:1.3.2" + checksum: d53f6f786875e8b0529f784b59b4b05d4b5c31c651710496440006a398389a579c8dbcd2081311478b5bf77f4b0b21de69109c5a4eabea9d8e8783d1eb864e4c + languageName: node + linkType: hard + "fast-glob@npm:3.2.7": version: 3.2.7 resolution: "fast-glob@npm:3.2.7" @@ -18235,6 +18302,13 @@ __metadata: languageName: node linkType: hard +"github-from-package@npm:0.0.0": + version: 0.0.0 + resolution: "github-from-package@npm:0.0.0" + checksum: 737ee3f52d0a27e26332cde85b533c21fcdc0b09fb716c3f8e522cfaa9c600d4a631dec9fcde179ec9d47cca89017b7848ed4d6ae6b6b78f936c06825b1fcc12 + languageName: node + linkType: hard + "github-release-from-changelog@npm:^2.1.1": version: 2.1.1 resolution: "github-release-from-changelog@npm:2.1.1" @@ -19518,7 +19592,7 @@ __metadata: languageName: node linkType: hard -"ini@npm:^1.3.2, ini@npm:^1.3.4, ini@npm:^1.3.5": +"ini@npm:^1.3.2, ini@npm:^1.3.4, ini@npm:^1.3.5, ini@npm:~1.3.0": version: 1.3.8 resolution: "ini@npm:1.3.8" checksum: ec93838d2328b619532e4f1ff05df7909760b6f66d9c9e2ded11e5c1897d6f2f9980c54dd638f88654b00919ce31e827040631eab0a3969e4d1abefa0719516a @@ -19714,6 +19788,13 @@ __metadata: languageName: node linkType: hard +"is-arrayish@npm:^0.3.1": + version: 0.3.2 + resolution: "is-arrayish@npm:0.3.2" + checksum: f59b43dc1d129edb6f0e282595e56477f98c40278a2acdc8b0a5c57097c9eff8fe55470493df5775478cf32a4dc8eaf6d3a749f07ceee5bc263a78b2434f6a54 + languageName: node + linkType: hard + "is-async-function@npm:^2.0.0": version: 2.0.0 resolution: "is-async-function@npm:2.0.0" @@ -22071,7 +22152,7 @@ __metadata: languageName: node linkType: hard -"loader-utils@npm:3.2.1, loader-utils@npm:^3.2.0": +"loader-utils@npm:3.2.1, loader-utils@npm:^3.2.1": version: 3.2.1 resolution: "loader-utils@npm:3.2.1" checksum: d3e1f217d160e8e894a0385a33500d4ce14065e8ffb250f5a81ae65bc2c3baa50625ec34182ba4417b46b4ac6725aed64429e1104d6401e074af2aa1dd018394 @@ -23730,7 +23811,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.2.0, minimist@npm:^1.2.5, minimist@npm:^1.2.6, minimist@npm:^1.2.7": +"minimist@npm:^1.2.0, minimist@npm:^1.2.3, minimist@npm:^1.2.5, minimist@npm:^1.2.6, minimist@npm:^1.2.7": version: 1.2.8 resolution: "minimist@npm:1.2.8" checksum: 19d3fcdca050087b84c2029841a093691a91259a47def2f18222f41e7645a0b7c44ef4b40e88a1e58a40c84d2ef0ee6047c55594d298146d0eb3f6b737c20ce6 @@ -23863,7 +23944,7 @@ __metadata: languageName: node linkType: hard -"mkdirp-classic@npm:^0.5.2": +"mkdirp-classic@npm:^0.5.2, mkdirp-classic@npm:^0.5.3": version: 0.5.3 resolution: "mkdirp-classic@npm:0.5.3" checksum: 95371d831d196960ddc3833cc6907e6b8f67ac5501a6582f47dfae5eb0f092e9f8ce88e0d83afcae95d6e2b61a01741ba03714eeafb6f7a6e9dcc158ac85b168 @@ -24060,6 +24141,13 @@ __metadata: languageName: node linkType: hard +"napi-build-utils@npm:^1.0.1": + version: 1.0.2 + resolution: "napi-build-utils@npm:1.0.2" + checksum: 37fd2cd0ff2ad20073ce78d83fd718a740d568b225924e753ae51cb69d68f330c80544d487e5e5bd18e28702ed2ca469c2424ad948becd1862c1b0209542b2e9 + languageName: node + linkType: hard + "natural-compare-lite@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare-lite@npm:1.4.0" @@ -24201,6 +24289,15 @@ __metadata: languageName: node linkType: hard +"node-abi@npm:^3.3.0": + version: 3.51.0 + resolution: "node-abi@npm:3.51.0" + dependencies: + semver: "npm:^7.3.5" + checksum: 2f0a56a9923bd21ff13650b6e8d2caebda211795761b40ae0ec3ea08e6687f6722535302cde87c928d6959a6afec196db3c54f8ae2db0bbaa401459dcf0f073c + languageName: node + linkType: hard + "node-abort-controller@npm:^3.0.1": version: 3.1.1 resolution: "node-abort-controller@npm:3.1.1" @@ -24217,6 +24314,15 @@ __metadata: languageName: node linkType: hard +"node-addon-api@npm:^6.1.0": + version: 6.1.0 + resolution: "node-addon-api@npm:6.1.0" + dependencies: + node-gyp: "npm:latest" + checksum: d2699c4ad15740fd31482a3b6fca789af7723ab9d393adc6ac45250faaee72edad8f0b10b2b9d087df0de93f1bdc16d97afdd179b26b9ebc9ed68b569faa4bac + languageName: node + linkType: hard + "node-cleanup@npm:^2.1.2": version: 2.1.2 resolution: "node-cleanup@npm:2.1.2" @@ -26334,6 +26440,28 @@ __metadata: languageName: node linkType: hard +"prebuild-install@npm:^7.1.1": + version: 7.1.1 + resolution: "prebuild-install@npm:7.1.1" + dependencies: + detect-libc: "npm:^2.0.0" + expand-template: "npm:^2.0.3" + github-from-package: "npm:0.0.0" + minimist: "npm:^1.2.3" + mkdirp-classic: "npm:^0.5.3" + napi-build-utils: "npm:^1.0.1" + node-abi: "npm:^3.3.0" + pump: "npm:^3.0.0" + rc: "npm:^1.2.7" + simple-get: "npm:^4.0.0" + tar-fs: "npm:^2.0.0" + tunnel-agent: "npm:^0.6.0" + bin: + prebuild-install: bin.js + checksum: 6dc70f36b0f4adcb2fe0ed38d874ab28b571fb1a9725d769e8ba3f64a15831e58462de09f3e6e64569bcc4a3e03b9328b56faa0d45fe10ae1574478814536c76 + languageName: node + linkType: hard + "prelude-ls@npm:^1.2.1": version: 1.2.1 resolution: "prelude-ls@npm:1.2.1" @@ -26983,6 +27111,13 @@ __metadata: languageName: node linkType: hard +"queue-tick@npm:^1.0.1": + version: 1.0.1 + resolution: "queue-tick@npm:1.0.1" + checksum: 0db998e2c9b15215317dbcf801e9b23e6bcde4044e115155dae34f8e7454b9a783f737c9a725528d677b7a66c775eb7a955cf144fe0b87f62b575ce5bfd515a9 + languageName: node + linkType: hard + "queue@npm:6.0.2": version: 6.0.2 resolution: "queue@npm:6.0.2" @@ -27088,6 +27223,20 @@ __metadata: languageName: node linkType: hard +"rc@npm:^1.2.7": + version: 1.2.8 + resolution: "rc@npm:1.2.8" + dependencies: + deep-extend: "npm:^0.6.0" + ini: "npm:~1.3.0" + minimist: "npm:^1.2.0" + strip-json-comments: "npm:~2.0.1" + bin: + rc: ./cli.js + checksum: 24a07653150f0d9ac7168e52943cc3cb4b7a22c0e43c7dff3219977c2fdca5a2760a304a029c20811a0e79d351f57d46c9bde216193a0f73978496afc2b85b15 + languageName: node + linkType: hard + "react-colorful@npm:^5.1.2": version: 5.6.1 resolution: "react-colorful@npm:5.6.1" @@ -29157,6 +29306,23 @@ __metadata: languageName: node linkType: hard +"sharp@npm:^0.32.6": + version: 0.32.6 + resolution: "sharp@npm:0.32.6" + dependencies: + color: "npm:^4.2.3" + detect-libc: "npm:^2.0.2" + node-addon-api: "npm:^6.1.0" + node-gyp: "npm:latest" + prebuild-install: "npm:^7.1.1" + semver: "npm:^7.5.4" + simple-get: "npm:^4.0.1" + tar-fs: "npm:^3.0.4" + tunnel-agent: "npm:^0.6.0" + checksum: f6a756fec5051ef2f9341e0543cde1da4e822982dd5398010baad92e2262bd177e08b753eb19b2fbee30f2fcb0e8756f24088fafc48293a364e9a8f8dc65a300 + languageName: node + linkType: hard + "shebang-command@npm:^1.2.0": version: 1.2.0 resolution: "shebang-command@npm:1.2.0" @@ -29245,6 +29411,33 @@ __metadata: languageName: node linkType: hard +"simple-concat@npm:^1.0.0": + version: 1.0.1 + resolution: "simple-concat@npm:1.0.1" + checksum: 62f7508e674414008910b5397c1811941d457dfa0db4fd5aa7fa0409eb02c3609608dfcd7508cace75b3a0bf67a2a77990711e32cd213d2c76f4fd12ee86d776 + languageName: node + linkType: hard + +"simple-get@npm:^4.0.0, simple-get@npm:^4.0.1": + version: 4.0.1 + resolution: "simple-get@npm:4.0.1" + dependencies: + decompress-response: "npm:^6.0.0" + once: "npm:^1.3.1" + simple-concat: "npm:^1.0.0" + checksum: b0649a581dbca741babb960423248899203165769747142033479a7dc5e77d7b0fced0253c731cd57cf21e31e4d77c9157c3069f4448d558ebc96cf9e1eebcf0 + languageName: node + linkType: hard + +"simple-swizzle@npm:^0.2.2": + version: 0.2.2 + resolution: "simple-swizzle@npm:0.2.2" + dependencies: + is-arrayish: "npm:^0.3.1" + checksum: df5e4662a8c750bdba69af4e8263c5d96fe4cd0f9fe4bdfa3cbdeb45d2e869dff640beaaeb1ef0e99db4d8d2ec92f85508c269f50c972174851bc1ae5bd64308 + languageName: node + linkType: hard + "simple-update-notifier@npm:^2.0.0": version: 2.0.0 resolution: "simple-update-notifier@npm:2.0.0" @@ -29824,6 +30017,16 @@ __metadata: languageName: node linkType: hard +"streamx@npm:^2.15.0": + version: 2.15.1 + resolution: "streamx@npm:2.15.1" + dependencies: + fast-fifo: "npm:^1.1.0" + queue-tick: "npm:^1.0.1" + checksum: e3b0e997726a2a499e1069efea7d720e54fc262011dfcb32e6704f90b5a31bb55b8f48964649d787be03d8718dcf9aa413d24ce48823d92fcbad06a3c337ec61 + languageName: node + linkType: hard + "strict-uri-encode@npm:^2.0.0": version: 2.0.0 resolution: "strict-uri-encode@npm:2.0.0" @@ -30063,7 +30266,7 @@ __metadata: languageName: node linkType: hard -"strip-json-comments@npm:^2.0.0": +"strip-json-comments@npm:^2.0.0, strip-json-comments@npm:~2.0.1": version: 2.0.1 resolution: "strip-json-comments@npm:2.0.1" checksum: b509231cbdee45064ff4f9fd73609e2bcc4e84a4d508e9dd0f31f70356473fde18abfb5838c17d56fb236f5a06b102ef115438de0600b749e818a35fbbc48c43 @@ -30388,6 +30591,17 @@ __metadata: languageName: node linkType: hard +"tar-fs@npm:^3.0.4": + version: 3.0.4 + resolution: "tar-fs@npm:3.0.4" + dependencies: + mkdirp-classic: "npm:^0.5.2" + pump: "npm:^3.0.0" + tar-stream: "npm:^3.1.5" + checksum: 120f026d891e5b4f7147a5ae5816e3a9b7f2c5b4ca61714dab3fe1244961607dccca40c11cafc584e625838c57d1308da5bb28b13d70b85ab566bc4c9f1c88b1 + languageName: node + linkType: hard + "tar-stream@npm:^2.1.4, tar-stream@npm:~2.2.0": version: 2.2.0 resolution: "tar-stream@npm:2.2.0" @@ -30401,6 +30615,17 @@ __metadata: languageName: node linkType: hard +"tar-stream@npm:^3.1.5": + version: 3.1.6 + resolution: "tar-stream@npm:3.1.6" + dependencies: + b4a: "npm:^1.6.4" + fast-fifo: "npm:^1.2.0" + streamx: "npm:^2.15.0" + checksum: 7d52d1a56eb25b8434c9544becb737eb6c4f0ed19d205e739fdd2537ad8d1d623a6c93f7f8e58d9028cb0cdf86c0d8b67164e070cd1702cc78b8ab7cba0f3702 + languageName: node + linkType: hard + "tar@npm:6.1.11": version: 6.1.11 resolution: "tar@npm:6.1.11" @@ -31087,6 +31312,15 @@ __metadata: languageName: node linkType: hard +"tunnel-agent@npm:^0.6.0": + version: 0.6.0 + resolution: "tunnel-agent@npm:0.6.0" + dependencies: + safe-buffer: "npm:^5.0.1" + checksum: 4c7a1b813e7beae66fdbf567a65ec6d46313643753d0beefb3c7973d66fcec3a1e7f39759f0a0b4465883499c6dc8b0750ab8b287399af2e583823e40410a17a + languageName: node + linkType: hard + "type-check@npm:^0.4.0, type-check@npm:~0.4.0": version: 0.4.0 resolution: "type-check@npm:0.4.0"