Skip to content

Commit 7a6b20c

Browse files
authored
fix(font): don't break directives with inserted next/font import (#72350)
the `next_font_loaders` transform replaces imports from `next/font` with slightly different ones. unfortunately it was inserting these imports **at the top** of the file, which broke the `server_actions` transform because it expects "use server"/"use cache" directives to be the first item in the file. this PR changes the logic in the font transform to insert the import in the place where the original `next/font` import occurred instead of at the top of the file. (i suppose that we could just reorder the transforms and run `server_actions` before `next_font_loaders`, but this feels more robust) Fixes #72179
1 parent f6e9bd9 commit 7a6b20c

File tree

15 files changed

+96
-15
lines changed

15 files changed

+96
-15
lines changed

crates/next-custom-transforms/src/transforms/fonts/mod.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,24 @@ impl VisitMut for NextFontLoaders {
7474
};
7575
items.visit_with(&mut wrong_scope);
7676

77+
fn is_removable(ctx: &NextFontLoaders, item: &ModuleItem) -> bool {
78+
ctx.state.removeable_module_items.contains(&item.span_lo())
79+
}
80+
81+
let first_removable_index = items
82+
.iter()
83+
.position(|item| is_removable(self, item))
84+
.unwrap();
85+
7786
// Remove marked module items
78-
items.retain(|item| !self.state.removeable_module_items.contains(&item.span_lo()));
87+
items.retain(|item| !is_removable(self, item));
7988

8089
// Add font imports and exports
81-
let mut new_items = Vec::new();
82-
new_items.append(&mut self.state.font_imports);
83-
new_items.append(items);
84-
new_items.append(&mut self.state.font_exports);
85-
*items = new_items;
90+
items.splice(
91+
first_removable_index..first_removable_index,
92+
std::mem::take(&mut self.state.font_imports),
93+
);
94+
items.append(&mut self.state.font_exports);
8695
}
8796
}
8897
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
import React from 'react';
12
import firaCode from '@next/font/google/target.css?{"path":"pages/test.tsx","import":"Abel","arguments":[],"variableName":"firaCode"}';
23
import inter from '@next/font/google/target.css?{"path":"pages/test.tsx","import":"Inter","arguments":[],"variableName":"inter"}';
3-
import React from 'react';
44
export { firaCode };
55
export { inter };

crates/next-custom-transforms/tests/fixture.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,35 @@ fn server_actions_server_fixture(input: PathBuf) {
430430
);
431431
}
432432

433+
#[fixture("tests/fixture/next-font-with-directive/**/input.js")]
434+
fn next_font_with_directive_fixture(input: PathBuf) {
435+
let output = input.parent().unwrap().join("output.js");
436+
test_fixture(
437+
syntax(),
438+
&|_tr| {
439+
(
440+
resolver(Mark::new(), Mark::new(), false),
441+
next_font_loaders(FontLoaderConfig {
442+
relative_file_path_from_root: "app/test.tsx".into(),
443+
font_loaders: vec!["@next/font/google".into()],
444+
}),
445+
server_actions(
446+
&FileName::Real("/app/test.tsx".into()),
447+
server_actions::Config {
448+
is_react_server_layer: true,
449+
enabled: true,
450+
hash_salt: "".into(),
451+
},
452+
_tr.comments.as_ref().clone(),
453+
),
454+
)
455+
},
456+
&input,
457+
&output,
458+
Default::default(),
459+
);
460+
}
461+
433462
#[fixture("tests/fixture/server-actions/client/**/input.js")]
434463
fn server_actions_client_fixture(input: PathBuf) {
435464
let output = input.parent().unwrap().join("output.js");
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
import React from 'react';
12
import firaCode from '@next/font/google/target.css?{"path":"pages/test.tsx","import":"Abel","arguments":[],"variableName":"firaCode"}';
23
import inter from '@next/font/google/target.css?{"path":"pages/test.tsx","import":"Inter","arguments":[],"variableName":"inter"}';
3-
import React from 'react';
44
export { firaCode };
55
export { inter };
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
import React from 'react';
12
import firaCode from '@next/font/google/target.css?{"path":"pages/test.tsx","import":"Abel","arguments":[],"variableName":"firaCode"}';
23
import inter from '@next/font/google/target.css?{"path":"pages/test.tsx","import":"Inter","arguments":[],"variableName":"inter"}';
3-
import React from 'react';
44
export { firaCode };
55
export default inter;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
import firaCode from '@next/font/google/target.css?{"path":"pages/test.tsx","import":"Fira_Code","arguments":[{"variant":"400","fallback":["system-ui",{"key":false},[]],"preload":true,"key":{"key2":{}}}],"variableName":"firaCode"}';
21
import React from 'react';
2+
import firaCode from '@next/font/google/target.css?{"path":"pages/test.tsx","import":"Fira_Code","arguments":[{"variant":"400","fallback":["system-ui",{"key":false},[]],"preload":true,"key":{"key2":{}}}],"variableName":"firaCode"}';
33
console.log(firaCode);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
import acme1 from 'cool-fonts/target.css?{"path":"pages/test.tsx","import":"Acme","arguments":[{"variant":"400"}],"variableName":"acme1"}';
21
import React from 'react';
2+
import acme1 from 'cool-fonts/target.css?{"path":"pages/test.tsx","import":"Acme","arguments":[{"variant":"400"}],"variableName":"acme1"}';
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1+
import React from 'react';
12
import inter from '@next/font/google/target.css?{"path":"pages/test.tsx","import":"Inter","arguments":[{"variant":"900","display":"swap"}],"variableName":"inter"}';
23
import inter from '@next/font/google/target.css?{"path":"pages/test.tsx","import":"Inter","arguments":[{"variant":"900","display":"swap"}],"variableName":"inter"}';
3-
import React from 'react';
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1+
import React from 'react';
12
import inter from '@next/font/google/target.css?{"path":"pages/test.tsx","import":"Inter","arguments":[{"variant":"900"}],"variableName":"inter"}';
23
import fira from 'cool-fonts/target.css?{"path":"pages/test.tsx","import":"Fira_Code","arguments":[{"variant":"400","display":"swap"}],"variableName":"fira"}';
3-
import React from 'react';
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1+
import React from 'react';
12
import firaCode from '@next/font/google/target.css?{"path":"pages/test.tsx","import":"Fira_Code","arguments":[{"variant":"400","fallback":["system-ui"]}],"variableName":"firaCode"}';
23
import inter from '@next/font/google/target.css?{"path":"pages/test.tsx","import":"Inter","arguments":[{"variant":"900","display":"swap"}],"variableName":"inter"}';
3-
import React from 'react';

0 commit comments

Comments
 (0)