@@ -2161,22 +2161,18 @@ impl CodePressTransform {
21612161 return ;
21622162 }
21632163
2164- // Skip if file uses Next.js font loaders (same check as ensure_provider_inline)
2165- for item in & m. body {
2166- if let ModuleItem :: ModuleDecl ( ModuleDecl :: Import ( import_decl) ) = item {
2167- let src = atom_to_string ( & import_decl. src . value ) ;
2168- if src. starts_with ( "next/font/" ) || src. starts_with ( "@next/font/" ) {
2169- return ;
2170- }
2171- }
2172- }
2164+ // NOTE: We intentionally do NOT skip files with Next.js fonts here.
2165+ // Unlike the legacy per-component __CPProvider wrapping which could
2166+ // interfere with font optimization, __CPRefreshProvider only uses
2167+ // useSyncExternalStore and simply returns children - no context wrapping.
2168+ // This allows HMR to work even in files that use next/font.
21732169
21742170 // Check if file is TSX/JSX (has JSX content)
21752171 if !file. ends_with ( ".tsx" ) && !file. ends_with ( ".jsx" ) {
21762172 return ;
21772173 }
21782174
2179- // import { useSyncExternalStore } from "react";
2175+ // import { useSyncExternalStore, createElement } from "react";
21802176 let import_decl = ModuleItem :: ModuleDecl ( ModuleDecl :: Import ( ImportDecl {
21812177 span : DUMMY_SP ,
21822178 specifiers : vec ! [
@@ -2186,6 +2182,12 @@ impl CodePressTransform {
21862182 imported: None ,
21872183 is_type_only: false ,
21882184 } ) ,
2185+ ImportSpecifier :: Named ( ImportNamedSpecifier {
2186+ span: DUMMY_SP ,
2187+ local: cp_ident( "createElement" . into( ) ) ,
2188+ imported: None ,
2189+ is_type_only: false ,
2190+ } ) ,
21892191 ] ,
21902192 src : Box :: new ( Str {
21912193 span : DUMMY_SP ,
@@ -2403,14 +2405,14 @@ impl CodePressTransform {
24032405 ctxt : SyntaxContext :: empty ( ) ,
24042406 } ) ;
24052407
2406- // const _ = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
2408+ // const __cpV = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
24072409 let use_sync_stmt = Stmt :: Decl ( Decl :: Var ( Box :: new ( VarDecl {
24082410 span : DUMMY_SP ,
24092411 kind : VarDeclKind :: Const ,
24102412 declare : false ,
24112413 decls : vec ! [ VarDeclarator {
24122414 span: DUMMY_SP ,
2413- name: Pat :: Ident ( BindingIdent { id: cp_ident( "_ " . into( ) ) , type_ann: None } ) ,
2415+ name: Pat :: Ident ( BindingIdent { id: cp_ident( "__cpV " . into( ) ) , type_ann: None } ) ,
24142416 init: Some ( Box :: new( Expr :: Call ( CallExpr {
24152417 span: DUMMY_SP ,
24162418 callee: Callee :: Expr ( Box :: new( Expr :: Ident ( cp_ident( "useSyncExternalStore" . into( ) ) ) ) ) ,
@@ -2429,10 +2431,62 @@ impl CodePressTransform {
24292431 ctxt : SyntaxContext :: empty ( ) ,
24302432 } ) ) ) ;
24312433
2432- // return children;
2434+ // return createElement("div", { key: __cpV, style: { display: "contents" } }, children);
2435+ // Using a div with display:contents so it's layout-neutral but has a key to force remount
24332436 let return_children = Stmt :: Return ( ReturnStmt {
24342437 span : DUMMY_SP ,
2435- arg : Some ( Box :: new ( Expr :: Ident ( cp_ident ( "children" . into ( ) ) ) ) ) ,
2438+ arg : Some ( Box :: new ( Expr :: Call ( CallExpr {
2439+ span : DUMMY_SP ,
2440+ callee : Callee :: Expr ( Box :: new ( Expr :: Ident ( cp_ident ( "createElement" . into ( ) ) ) ) ) ,
2441+ args : vec ! [
2442+ // "div"
2443+ ExprOrSpread {
2444+ spread: None ,
2445+ expr: Box :: new( Expr :: Lit ( Lit :: Str ( Str {
2446+ span: DUMMY_SP ,
2447+ value: "div" . into( ) ,
2448+ raw: None ,
2449+ } ) ) ) ,
2450+ } ,
2451+ // { key: __cpV, style: { display: "contents" } }
2452+ ExprOrSpread {
2453+ spread: None ,
2454+ expr: Box :: new( Expr :: Object ( ObjectLit {
2455+ span: DUMMY_SP ,
2456+ props: vec![
2457+ PropOrSpread :: Prop ( Box :: new( Prop :: KeyValue ( KeyValueProp {
2458+ key: PropName :: Ident ( cp_ident_name( "key" . into( ) ) ) ,
2459+ value: Box :: new( Expr :: Ident ( cp_ident( "__cpV" . into( ) ) ) ) ,
2460+ } ) ) ) ,
2461+ PropOrSpread :: Prop ( Box :: new( Prop :: KeyValue ( KeyValueProp {
2462+ key: PropName :: Ident ( cp_ident_name( "style" . into( ) ) ) ,
2463+ value: Box :: new( Expr :: Object ( ObjectLit {
2464+ span: DUMMY_SP ,
2465+ props: vec![
2466+ PropOrSpread :: Prop ( Box :: new( Prop :: KeyValue ( KeyValueProp {
2467+ key: PropName :: Ident ( cp_ident_name( "display" . into( ) ) ) ,
2468+ value: Box :: new( Expr :: Lit ( Lit :: Str ( Str {
2469+ span: DUMMY_SP ,
2470+ value: "contents" . into( ) ,
2471+ raw: None ,
2472+ } ) ) ) ,
2473+ } ) ) ) ,
2474+ ] ,
2475+ } ) ) ,
2476+ } ) ) ) ,
2477+ ] ,
2478+ } ) ) ,
2479+ } ,
2480+ // children
2481+ ExprOrSpread {
2482+ spread: None ,
2483+ expr: Box :: new( Expr :: Ident ( cp_ident( "children" . into( ) ) ) ) ,
2484+ } ,
2485+ ] ,
2486+ type_args : None ,
2487+ #[ cfg( not( feature = "compat_0_87" ) ) ]
2488+ ctxt : SyntaxContext :: empty ( ) ,
2489+ } ) ) ) ,
24362490 } ) ;
24372491
24382492 // function __CPRefreshProvider({ children }) { ... }
0 commit comments