diff --git a/code/frameworks/nextjs/package.json b/code/frameworks/nextjs/package.json index 82211af63c6c..bfff210775c3 100644 --- a/code/frameworks/nextjs/package.json +++ b/code/frameworks/nextjs/package.json @@ -102,7 +102,7 @@ "@types/babel__core": "^7", "@types/babel__plugin-transform-runtime": "^7", "@types/babel__preset-env": "^7", - "next": "^13.2.4", + "next": "^13.4.8", "typescript": "^4.9.3", "webpack": "^5.65.0" }, @@ -143,8 +143,17 @@ "./src/preset.ts", "./src/preview.tsx", "./src/next-image-loader-stub.ts", + "./src/images/context.ts", + "./src/images/next-future-image.tsx", + "./src/images/next-legacy-image.tsx", + "./src/images/next-image.tsx", "./src/font/webpack/loader/storybook-nextjs-font-loader.ts" ], + "externals": [ + "sb-original/next/image", + "sb-original/next/future/image", + "sb-original/next/legacy/image" + ], "platform": "node" }, "gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae17" diff --git a/code/frameworks/nextjs/src/images/next-future-image.tsx b/code/frameworks/nextjs/src/images/next-future-image.tsx new file mode 100644 index 000000000000..559d2e857d39 --- /dev/null +++ b/code/frameworks/nextjs/src/images/next-future-image.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import type * as _NextImage from 'next/image'; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore import is aliased in webpack config +import OriginalNextFutureImage from 'sb-original/next/future/image'; +import { ImageContext } from './context'; +import { defaultLoader } from './next-image-default-loader'; + +function NextFutureImage(props: _NextImage.ImageProps) { + const imageParameters = React.useContext(ImageContext); + + return ( + + ); +} + +export default NextFutureImage; diff --git a/code/frameworks/nextjs/src/images/next-image-default-loader.tsx b/code/frameworks/nextjs/src/images/next-image-default-loader.tsx new file mode 100644 index 000000000000..6029390979ac --- /dev/null +++ b/code/frameworks/nextjs/src/images/next-image-default-loader.tsx @@ -0,0 +1,28 @@ +import type * as _NextImage from 'next/image'; + +export const defaultLoader = ({ src, width, quality }: _NextImage.ImageLoaderProps) => { + const missingValues = []; + if (!src) { + missingValues.push('src'); + } + + if (!width) { + missingValues.push('width'); + } + + if (missingValues.length > 0) { + throw new Error( + `Next Image Optimization requires ${missingValues.join( + ', ' + )} to be provided. Make sure you pass them as props to the \`next/image\` component. Received: ${JSON.stringify( + { + src, + width, + quality, + } + )}` + ); + } + + return `${src}?w=${width}&q=${quality ?? 75}`; +}; diff --git a/code/frameworks/nextjs/src/images/next-image-stub.tsx b/code/frameworks/nextjs/src/images/next-image-stub.tsx deleted file mode 100644 index 3fc92c7b29a6..000000000000 --- a/code/frameworks/nextjs/src/images/next-image-stub.tsx +++ /dev/null @@ -1,88 +0,0 @@ -/* eslint-disable no-underscore-dangle, @typescript-eslint/no-non-null-assertion */ -import * as React from 'react'; -import type * as _NextImage from 'next/image'; -import type * as _NextLegacyImage from 'next/legacy/image'; -import semver from 'semver'; -import { ImageContext } from './context'; - -const defaultLoader = ({ src, width, quality }: _NextImage.ImageLoaderProps) => { - const missingValues = []; - if (!src) { - missingValues.push('src'); - } - - if (!width) { - missingValues.push('width'); - } - - if (missingValues.length > 0) { - throw new Error( - `Next Image Optimization requires ${missingValues.join( - ', ' - )} to be provided. Make sure you pass them as props to the \`next/image\` component. Received: ${JSON.stringify( - { - src, - width, - quality, - } - )}` - ); - } - - return `${src}?w=${width}&q=${quality ?? 75}`; -}; - -const NextImage = require('next/image') as typeof _NextImage; - -const OriginalNextImage = NextImage.default; - -Object.defineProperty(NextImage, 'default', { - configurable: true, - value: (props: _NextImage.ImageProps) => { - const imageParameters = React.useContext(ImageContext); - - return ( - - ); - }, -}); - -if (semver.satisfies(process.env.__NEXT_VERSION!, '^13.0.0')) { - const LegacyNextImage = require('next/legacy/image') as typeof _NextLegacyImage; - const OriginalNextLegacyImage = LegacyNextImage.default; - - Object.defineProperty(OriginalNextLegacyImage, 'default', { - configurable: true, - value: (props: _NextLegacyImage.ImageProps) => { - const imageParameters = React.useContext(ImageContext); - - return ( - - ); - }, - }); -} - -if (semver.satisfies(process.env.__NEXT_VERSION!, '^12.2.0')) { - const NextFutureImage = require('next/future/image') as typeof _NextImage; - const OriginalNextFutureImage = NextFutureImage.default; - - Object.defineProperty(OriginalNextFutureImage, 'default', { - configurable: true, - value: (props: _NextImage.ImageProps) => { - const imageParameters = React.useContext(ImageContext); - - return ( - - ); - }, - }); -} diff --git a/code/frameworks/nextjs/src/images/next-image.tsx b/code/frameworks/nextjs/src/images/next-image.tsx new file mode 100644 index 000000000000..74e252d93a7d --- /dev/null +++ b/code/frameworks/nextjs/src/images/next-image.tsx @@ -0,0 +1,17 @@ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore import is aliased in webpack config +import OriginalNextImage from 'sb-original/next/image'; +import type * as _NextImage from 'next/image'; +import React from 'react'; +import { ImageContext } from './context'; +import { defaultLoader } from './next-image-default-loader'; + +const MockedNextImage = (props: _NextImage.ImageProps) => { + const imageParameters = React.useContext(ImageContext); + + return ( + + ); +}; + +export default MockedNextImage; diff --git a/code/frameworks/nextjs/src/images/next-legacy-image.tsx b/code/frameworks/nextjs/src/images/next-legacy-image.tsx new file mode 100644 index 000000000000..8d899cc341a5 --- /dev/null +++ b/code/frameworks/nextjs/src/images/next-legacy-image.tsx @@ -0,0 +1,21 @@ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore import is aliased in webpack config +import OriginalNextLegacyImage from 'sb-original/next/legacy/image'; +import type * as _NextLegacyImage from 'next/legacy/image'; +import React from 'react'; +import { ImageContext } from './context'; +import { defaultLoader } from './next-image-default-loader'; + +function NextLegacyImage(props: _NextLegacyImage.ImageProps) { + const imageParameters = React.useContext(ImageContext); + + return ( + + ); +} + +export default NextLegacyImage; diff --git a/code/frameworks/nextjs/src/images/webpack.ts b/code/frameworks/nextjs/src/images/webpack.ts index 967387f7b027..51064d40cc8a 100644 --- a/code/frameworks/nextjs/src/images/webpack.ts +++ b/code/frameworks/nextjs/src/images/webpack.ts @@ -1,11 +1,38 @@ import semver from 'semver'; import type { Configuration as WebpackConfig, RuleSetRule } from 'webpack'; import type { NextConfig } from 'next'; -import { addScopedAlias, getNextjsVersion } from '../utils'; +import path from 'path'; +import { getNextjsVersion } from '../utils'; export const configureImages = (baseConfig: WebpackConfig, nextConfig: NextConfig): void => { configureStaticImageImport(baseConfig, nextConfig); - addScopedAlias(baseConfig, 'next/image'); + configureImageDefaults(baseConfig); +}; + +const configureImageDefaults = (baseConfig: WebpackConfig): void => { + const version = getNextjsVersion(); + const resolve = baseConfig.resolve ?? {}; + resolve.alias = { + ...resolve.alias, + 'sb-original/next/image': require.resolve('next/image'), + 'next/image': path.resolve(__dirname, './images/next-image'), + }; + + if (semver.satisfies(version, '^13.0.0')) { + resolve.alias = { + ...resolve.alias, + 'sb-original/next/legacy/image': require.resolve('next/legacy/image'), + 'next/legacy/image': path.resolve(__dirname, './images/next-legacy-image'), + }; + } + + if (semver.satisfies(version, '^12.2.0')) { + resolve.alias = { + ...resolve.alias, + 'sb-original/next/future/image': require.resolve('next/future/image'), + 'next/future/image': path.resolve(__dirname, './images/next-future-image'), + }; + } }; const configureStaticImageImport = (baseConfig: WebpackConfig, nextConfig: NextConfig): void => { diff --git a/code/frameworks/nextjs/src/preview.tsx b/code/frameworks/nextjs/src/preview.tsx index d089aa27f0d9..9f30af9d787d 100644 --- a/code/frameworks/nextjs/src/preview.tsx +++ b/code/frameworks/nextjs/src/preview.tsx @@ -3,7 +3,6 @@ import './config/preview'; import { ImageDecorator } from './images/decorator'; import { RouterDecorator } from './routing/decorator'; import { StyledJsxDecorator } from './styledJsx/decorator'; -import './images/next-image-stub'; import { HeadManagerDecorator } from './head-manager/decorator'; function addNextHeadCount() { diff --git a/code/frameworks/nextjs/src/routing/app-router-provider.tsx b/code/frameworks/nextjs/src/routing/app-router-provider.tsx index ab09406a14d6..75c6c5629b87 100644 --- a/code/frameworks/nextjs/src/routing/app-router-provider.tsx +++ b/code/frameworks/nextjs/src/routing/app-router-provider.tsx @@ -68,6 +68,7 @@ const AppRouterProvider: React.FC = ({ children, action, changeByServerResponse() { // NOOP }, + buildId: 'storybook', tree, focusAndScrollRef: { apply: false, diff --git a/code/yarn.lock b/code/yarn.lock index 3f1268af1fd3..a768a840654d 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -3951,72 +3951,72 @@ __metadata: languageName: node linkType: hard -"@next/env@npm:13.4.4": - version: 13.4.4 - resolution: "@next/env@npm:13.4.4" - checksum: 8fd3e3682b17d163e806e60fca546b6146182d4b74d21b3e3b5ccc6cf574d08443663863408be66e9b6f5a22a65afe379952e1e1792f92360bf91a3a85ce112d +"@next/env@npm:13.4.8": + version: 13.4.8 + resolution: "@next/env@npm:13.4.8" + checksum: ac774fde7ec7802f93199db57de5b0ff4642198d7f38d24fa3c8e627bd264c631d405ad17887aed25febc5481f32328b5d345082785ea184acd26240a411450c languageName: node linkType: hard -"@next/swc-darwin-arm64@npm:13.4.4": - version: 13.4.4 - resolution: "@next/swc-darwin-arm64@npm:13.4.4" +"@next/swc-darwin-arm64@npm:13.4.8": + version: 13.4.8 + resolution: "@next/swc-darwin-arm64@npm:13.4.8" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@next/swc-darwin-x64@npm:13.4.4": - version: 13.4.4 - resolution: "@next/swc-darwin-x64@npm:13.4.4" +"@next/swc-darwin-x64@npm:13.4.8": + version: 13.4.8 + resolution: "@next/swc-darwin-x64@npm:13.4.8" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@next/swc-linux-arm64-gnu@npm:13.4.4": - version: 13.4.4 - resolution: "@next/swc-linux-arm64-gnu@npm:13.4.4" +"@next/swc-linux-arm64-gnu@npm:13.4.8": + version: 13.4.8 + resolution: "@next/swc-linux-arm64-gnu@npm:13.4.8" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-arm64-musl@npm:13.4.4": - version: 13.4.4 - resolution: "@next/swc-linux-arm64-musl@npm:13.4.4" +"@next/swc-linux-arm64-musl@npm:13.4.8": + version: 13.4.8 + resolution: "@next/swc-linux-arm64-musl@npm:13.4.8" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@next/swc-linux-x64-gnu@npm:13.4.4": - version: 13.4.4 - resolution: "@next/swc-linux-x64-gnu@npm:13.4.4" +"@next/swc-linux-x64-gnu@npm:13.4.8": + version: 13.4.8 + resolution: "@next/swc-linux-x64-gnu@npm:13.4.8" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-x64-musl@npm:13.4.4": - version: 13.4.4 - resolution: "@next/swc-linux-x64-musl@npm:13.4.4" +"@next/swc-linux-x64-musl@npm:13.4.8": + version: 13.4.8 + resolution: "@next/swc-linux-x64-musl@npm:13.4.8" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@next/swc-win32-arm64-msvc@npm:13.4.4": - version: 13.4.4 - resolution: "@next/swc-win32-arm64-msvc@npm:13.4.4" +"@next/swc-win32-arm64-msvc@npm:13.4.8": + version: 13.4.8 + resolution: "@next/swc-win32-arm64-msvc@npm:13.4.8" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@next/swc-win32-ia32-msvc@npm:13.4.4": - version: 13.4.4 - resolution: "@next/swc-win32-ia32-msvc@npm:13.4.4" +"@next/swc-win32-ia32-msvc@npm:13.4.8": + version: 13.4.8 + resolution: "@next/swc-win32-ia32-msvc@npm:13.4.8" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@next/swc-win32-x64-msvc@npm:13.4.4": - version: 13.4.4 - resolution: "@next/swc-win32-x64-msvc@npm:13.4.4" +"@next/swc-win32-x64-msvc@npm:13.4.8": + version: 13.4.8 + resolution: "@next/swc-win32-x64-msvc@npm:13.4.8" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -6585,7 +6585,7 @@ __metadata: fs-extra: ^11.1.0 image-size: ^1.0.0 loader-utils: ^3.2.0 - next: ^13.2.4 + next: ^13.4.8 node-polyfill-webpack-plugin: ^2.0.1 pnp-webpack-plugin: ^1.7.0 postcss: ^8.4.21 @@ -22641,25 +22641,26 @@ __metadata: languageName: node linkType: hard -"next@npm:^13.2.4": - version: 13.4.4 - resolution: "next@npm:13.4.4" +"next@npm:^13.4.8": + version: 13.4.8 + resolution: "next@npm:13.4.8" dependencies: - "@next/env": 13.4.4 - "@next/swc-darwin-arm64": 13.4.4 - "@next/swc-darwin-x64": 13.4.4 - "@next/swc-linux-arm64-gnu": 13.4.4 - "@next/swc-linux-arm64-musl": 13.4.4 - "@next/swc-linux-x64-gnu": 13.4.4 - "@next/swc-linux-x64-musl": 13.4.4 - "@next/swc-win32-arm64-msvc": 13.4.4 - "@next/swc-win32-ia32-msvc": 13.4.4 - "@next/swc-win32-x64-msvc": 13.4.4 + "@next/env": 13.4.8 + "@next/swc-darwin-arm64": 13.4.8 + "@next/swc-darwin-x64": 13.4.8 + "@next/swc-linux-arm64-gnu": 13.4.8 + "@next/swc-linux-arm64-musl": 13.4.8 + "@next/swc-linux-x64-gnu": 13.4.8 + "@next/swc-linux-x64-musl": 13.4.8 + "@next/swc-win32-arm64-msvc": 13.4.8 + "@next/swc-win32-ia32-msvc": 13.4.8 + "@next/swc-win32-x64-msvc": 13.4.8 "@swc/helpers": 0.5.1 busboy: 1.6.0 caniuse-lite: ^1.0.30001406 postcss: 8.4.14 styled-jsx: 5.1.1 + watchpack: 2.4.0 zod: 3.21.4 peerDependencies: "@opentelemetry/api": ^1.1.0 @@ -22695,7 +22696,7 @@ __metadata: optional: true bin: next: dist/bin/next - checksum: dd4b958c5a006288c616b08045657b371891432b87441564e41641015b4c5876fad11173edb039b9dab705976231e47040234029d8302de26c53b11d541a17f3 + checksum: 2a91f5118a81f6922331ea5dcb3b95cceb4e97dca7b5d6c9d72f2e843afbd95c0c20daa9f8a5c1df257d9ef9e7b064ae41d650fed48e09c8a284f9a210cac0cb languageName: node linkType: hard @@ -30857,7 +30858,7 @@ __metadata: languageName: node linkType: hard -"watchpack@npm:^2.2.0, watchpack@npm:^2.4.0": +"watchpack@npm:2.4.0, watchpack@npm:^2.2.0, watchpack@npm:^2.4.0": version: 2.4.0 resolution: "watchpack@npm:2.4.0" dependencies: