From 4a6b511ca0c4d21b994f179eddb30213314d8856 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Tue, 23 Apr 2024 13:37:49 +0200 Subject: [PATCH] Fix next/image usage in mdx (#64875) ### What Apply the react aliases for app dir also to the files with `pagesExtension` ### Why In the page bundle of mdx page: In RSC layer react is referencing to the insatlled react 18.2.0 's `jsx-runtime` to create each JSX element. The react 18.2 JSX runtime access `propTypes` of the component type and then it crashes :boom: In RSC layer it should use the built-in react canary's `jsx-runtime`. The reason that it didn't use the built-in one is we're using customized `pageExtension` `["mdx"]` for mdx, where we didn't apply all these rules for the files with `pageExtension`, but only the js and ts files by default. For mdx specifically, we cannot only applied to `(page|layout|route).[page extension]` cause every mdx file needs to have proper resolution. Since this doesn't break transform, it's safe to apply for all files with page extension. Fixes #58888 Closes NEXT-3187 --- packages/next/src/build/webpack-config.ts | 11 +++++++---- test/e2e/app-dir/mdx/app/image/page.mdx | 7 +++++++ test/e2e/app-dir/mdx/mdx.test.ts | 7 +++++++ test/e2e/app-dir/mdx/public/test.jpg | Bin 0 -> 6765 bytes test/turbopack-build-tests-manifest.json | 1 + 5 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 test/e2e/app-dir/mdx/app/image/page.mdx create mode 100644 test/e2e/app-dir/mdx/public/test.jpg diff --git a/packages/next/src/build/webpack-config.ts b/packages/next/src/build/webpack-config.ts index 2afeab36080e1..8e41373005982 100644 --- a/packages/next/src/build/webpack-config.ts +++ b/packages/next/src/build/webpack-config.ts @@ -819,6 +819,7 @@ export default async function getBaseWebpackConfig( const shouldIncludeExternalDirs = config.experimental.externalDir || !!config.transpilePackages + const pageExtensionsRegex = new RegExp(`\\.(${pageExtensions.join('|')})$`) const codeCondition = { test: { or: [/\.(tsx|ts|js|cjs|mjs|jsx)$/, /__barrel_optimize__/] }, ...(shouldIncludeExternalDirs @@ -840,6 +841,8 @@ export default async function getBaseWebpackConfig( }, } + const aliasCodeConditionTest = [codeCondition.test, pageExtensionsRegex] + let webpackConfig: webpack.Configuration = { parallelism: Number(process.env.NEXT_WEBPACK_PARALLELISM) || undefined, ...(isNodeServer ? { externalsPresets: { node: true } } : {}), @@ -1326,7 +1329,7 @@ export default async function getBaseWebpackConfig( // Resolve it if it is a source code file, and it has NOT been // opted out of bundling. and: [ - codeCondition.test, + aliasCodeConditionTest, { not: [optOutBundlingPackageRegex, asyncStoragesRegex], }, @@ -1388,7 +1391,7 @@ export default async function getBaseWebpackConfig( // Resolve it if it is a source code file, and it has NOT been // opted out of bundling. and: [ - codeCondition.test, + aliasCodeConditionTest, { not: [optOutBundlingPackageRegex, asyncStoragesRegex], }, @@ -1405,7 +1408,7 @@ export default async function getBaseWebpackConfig( }, }, { - test: codeCondition.test, + test: aliasCodeConditionTest, issuerLayer: WEBPACK_LAYERS.serverSideRendering, resolve: { alias: createRSCAliases(bundledReactChannel, { @@ -1418,7 +1421,7 @@ export default async function getBaseWebpackConfig( ], }, { - test: codeCondition.test, + test: aliasCodeConditionTest, issuerLayer: WEBPACK_LAYERS.appPagesBrowser, resolve: { alias: createRSCAliases(bundledReactChannel, { diff --git a/test/e2e/app-dir/mdx/app/image/page.mdx b/test/e2e/app-dir/mdx/app/image/page.mdx new file mode 100644 index 0000000000000..f85224c1ea1a9 --- /dev/null +++ b/test/e2e/app-dir/mdx/app/image/page.mdx @@ -0,0 +1,7 @@ +import Image from 'next/image' + +# Title + +This is a markdown page + +Next.js Logo diff --git a/test/e2e/app-dir/mdx/mdx.test.ts b/test/e2e/app-dir/mdx/mdx.test.ts index 33dc0aea63ca4..099de81affc17 100644 --- a/test/e2e/app-dir/mdx/mdx.test.ts +++ b/test/e2e/app-dir/mdx/mdx.test.ts @@ -59,6 +59,13 @@ for (const type of [ const $ = await next.render$('/') expect($('h2').text()).toBe('This is a client component') }) + + it('should work with next/image', async () => { + const $ = await next.render$('/image') + expect($('img').attr('src')).toBe( + '/_next/image?url=%2Ftest.jpg&w=384&q=75' + ) + }) }) describe('pages directory', () => { diff --git a/test/e2e/app-dir/mdx/public/test.jpg b/test/e2e/app-dir/mdx/public/test.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d536c882412ed3df0dc162823ca5146bcc033499 GIT binary patch literal 6765 zcmeHK2~-nT7rx0%2m%J#v>-x6R0=4dR1uMV3krk?xD*$JK%#*_5>`=Mq0&}Bt+uvD zP_X#B;ZodCL7{GyilVZ(22r4jfQlku=6@4bJyo#&zvukt{4ZzTd~@G@_ulWmJMT@1 z3gSKt@o;6i0)+zLj($K$VTMaAKLo(j6N~{s5vUY(z!0LKA0+bumt%l2=ng>5q;^Xv zX_;6rCI^WIuwwIs5}}wUj9^Y2Zw^+DEKi)YfSMeSmct>}M|@YA3WxCe6@z|!((1UJ zsHWGkoSYW0Io__U87}ew=@o$y5dta`AS_%W;-chvT=_s}*UxYt%@4saK@{RFZ~CZL5iglJ9o>x(_cg(R&Lkd> z@ZO+6mzf9~B3u>C_xI|;vIvPI2Vqn#RD-A`ehvtux}v&=h+O>;Ms}zoUX*(`-Wt#I zorUB>k^F4xVnl#}sP#PgiUI7#{C#ep7dgmn)Y;L$8nNJc&gFht@xFCc@s1Jg0cmqt}fEzfXdjyEkNC@yj zfFxWr%0&_`dg|60C!Z&VB}mSPX!)2J^=!Fj=ge+hCWInsIMm5?gTP5|CqyAjJa~en zydIlOa6(T}NEZ4YJDsuAci9o*!*FwaBD$vHGw^A+6+Q)+xE*ef+v3hhIt8EFW1EfU zbTcC3sYhNq?L;DvT)Cb<;(i8klt3WrrAR{v;vNfcWhG4~%BXi_m1qG!=t^o+pIq_L z%q2Y<u823gk1xP!{-zGq(@taeZx^PdNESueTfcv4Ap_^9dp0X*#`9G7H>fua{o1%CuK% zUT)rCe#3mbdA9juY$KM3ox+Y|C$P)F#0s%9SOInp%f<40^gmQXJ!=nSU;=kI-y z?+U-i5?TYwU{nG8UXO3pfFFvO4>8E52<4lsw{VCZh^DjsctK>=DTex zxF|R)H~>?@SYe8Sg@Ol(yWeGnv1n`x>RtNAhU%k7<1MCK2{)EJPrykS5hvn@@+8a& z=H`=`4(RCPGFjn4<4u`?0s&J#BxZ`ZVy-Bf8$2G!bCaA0@SGz*4=F>h^vWcj0MnkL zy|1)aHa7}juNYvMWv|Q#?Uh;?0LLZ;MTw$2?V*FZ1V9`zaf1ArqT-15ue${C9PMND z4FGS_38H-mLA=RA_HP3e3W!2bQ>3I((lCkvP}L}y8ignZbktC26nX113=}Gc(-i26 zgOrq!Lf#PcVS-^)9HY_54+_dMG!D2LO?{+=gMx-nAl)ERbHd8>?TVuu51!HDTx~L( zxJa~WkkZg$Uuf%$9y8YHOJmEgCQY`QV(sMY;_Bwk@|fxC=RXV43kv3jg!1@{#geG# znAo`Z)oa!!C4aLnWy8izKWyIe<4;?6WM%LCHD}kqb{{(YTi%hQ$Bv&kTU7k}x$_q; zUbO`#DHujmL~FM+12dijYT$2Pa}{K%HY9+ zwKTL0H8c$Ut+(i(pN7A@59n^qn*XrrO3}Hh%Dh`U-_$%1FkgB#v}Tkp zEv0AktJ@K6Wdx zR#mAJJ#IVcZ<1j)^`X$2o>BZlucgJ*!cC~|pw!^Z-kp_+t*}$7wxLO-JL;9i)&ykF zThWkyDYq%N#g+h%Mjq@)F`{bkSRcD>(54CQJ7?>y(NoOboZz`*dgkJ16;`(MW1P>o zrfpM|mbRy~9Xh73ADh^|#C`Il$FlUr%DH>S+j3=DcURbokQvg{KrW2SF*iIX-y@eC-T5|DK##QDKmLB}7hQF`Z&#kXbsuA>_-OC6Vv zUDmfTd>Q%6@@0b)@=Q5SCQe4ibsh(%Iq0g{s|=XnK)1j>RpA+tyYCg{%>C}-M4H~+ z>~_k2v2S3GNWAaVqT7-iv$tWU*U=lly?)W2zUe2A zjG&6th`3DEbl#q-%^8t9@0H}-QDG@-*~-=|RlBg;av*Ogg&5!_{K_n8x!$CkCHwD~ zHI5w~NIw)KES9ald-7Jr5E^V0fNABGH^Ff_GH7BHFQ0=Yy`NJ11D$x`dH_h0-!Ns`n1+&Q| z;c#`B`aEpb<}+uWJwGwVu6RvTA|v@WTY;wOW8dGUPYmP)*#Dq#xt{FSO}t$B=OqE| zvhVJlEm&96t^_SYN^C6egyZc$3+jh0oEj|J(_!+)yWm=WRc~!}*Qosdo|i2DFC*-M zhsm+#+T?eW{MLuD^E=BlL_59V zzkX=D-~P&d>sgxyC~U+E7E<5yW3oW78&*t$hZz@d5jj|(#0A{;N#`S6$ks{XFp zeGoUVpY_rw`Z?YH>CvEKXso$(TXu#hZlBJ3)~$Q5Ih^Ndeb2A#QQ3Z14%gT_Kra)$ zXJ{5yGj6)~v1^Tw%AO_}u1(2Ebe#50ji1gdvvsHS+C2|FzPV@13VaizzOsNC_p)tP zQYpnnll{Jn-rt${czg4`lzr9iBlD}$cllARn$UZcAMm{KQ(_PTv8M%o~4<$gE{yPEB+X+akCZL)}z}nRaynaK#g~-I_ug>|{kI3jS z)gMN{l}4G$w4nG?+ygV@d`kpUSY=*>+dRji}!=Evf|9{