Skip to content

Commit

Permalink
feat: prepend comment node
Browse files Browse the repository at this point in the history
  • Loading branch information
ClarkXia committed Sep 19, 2023
1 parent c19574b commit af7832a
Show file tree
Hide file tree
Showing 9 changed files with 75 additions and 12 deletions.
37 changes: 29 additions & 8 deletions packages/react-server-component/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use serde::Deserialize;
use swc_core::{
common::{
comments::{Comment, CommentKind, Comments},
FileName,
Span,DUMMY_SP,
errors::HANDLER
Expand All @@ -11,16 +12,19 @@ use swc_core::{
visit::{Fold, FoldWith, VisitMut, as_folder, noop_visit_mut_type, VisitMutWith},
utils::{prepend_stmts, quote_ident, quote_str, ExprFactory}
},
plugin::{plugin_transform, proxies::TransformPluginProgramMetadata, metadata::TransformPluginMetadataContextKind},
plugin::{plugin_transform, proxies::{TransformPluginProgramMetadata, PluginCommentsProxy}, metadata::TransformPluginMetadataContextKind},
};

struct ModuleImports {
source: (JsWord, Span),
specifiers: Vec<(JsWord, Span)>,
}

pub fn react_server_component(file_name: FileName, is_server: bool) -> impl Fold + VisitMut {
pub fn react_server_component<C>(file_name: FileName, is_server: bool, comments: C) -> impl Fold + VisitMut
where C: Comments,
{
as_folder(ReactServerComponent {
comments,
filepath: file_name.to_string(),
is_server,
export_names: vec![],
Expand Down Expand Up @@ -59,17 +63,17 @@ struct Config {
pub is_server: bool
}

struct ReactServerComponent {
struct ReactServerComponent<C: Comments> {
filepath: String,
is_server: bool,
comments: C,
export_names: Vec<String>,
invalid_server_imports: Vec<JsWord>,
invalid_client_imports: Vec<JsWord>,
invalid_server_react_apis: Vec<JsWord>,
invalid_server_ice_imports: Vec<JsWord>,
}

impl ReactServerComponent {
impl<C: Comments> ReactServerComponent<C> {
fn create_module_proxy(&self, module: &mut Module) {
// Clear all statements and module decalarations.
module.body.clear();
Expand Down Expand Up @@ -127,6 +131,7 @@ impl ReactServerComponent {
})),
].into_iter(),
);
self.prepend_comment_node(module);
}

fn collect_top_level_directives_and_imports(&mut self, module: &mut Module) -> (bool, bool, Vec<ModuleImports>) {
Expand Down Expand Up @@ -348,13 +353,27 @@ impl ReactServerComponent {
}
}
}

fn prepend_comment_node(&self, module: &Module) {
// Prepend a special comment at the top of file, so that we can identify client boundary in webpack plugin
// just by reading the firist line of file.
self.comments.add_leading(
module.span.lo,
Comment {
kind: CommentKind::Block,
span: DUMMY_SP,
text: format!("__ice_internal_client_entry_do_not_use__ {}", self.export_names.join(",")).into(),
},
);
}
}

impl VisitMut for ReactServerComponent {
impl <C: Comments> VisitMut for ReactServerComponent<C> {
noop_visit_mut_type!();

fn visit_mut_module(&mut self, module: &mut Module) {
let (is_client_entry, is_action_file, imports) = self.collect_top_level_directives_and_imports(module);
tracing::debug!("is_client_entry: {}, is_action_file: {}", is_client_entry, is_action_file);
if self.is_server {
if !is_client_entry {
self.assert_server_import(&imports);
Expand All @@ -367,7 +386,9 @@ impl VisitMut for ReactServerComponent {
if !is_action_file {
self.assert_client_import(&imports);
}
// TODO: handle client entry in the future.
if is_client_entry {
self.prepend_comment_node(module);
}
}
module.visit_mut_children_with(self)
}
Expand All @@ -385,5 +406,5 @@ pub fn process_transform(program: Program, _metadata: TransformPluginProgramMeta
Some(s) => FileName::Real(s.into()),
None => FileName::Anon,
};
program.fold_with(&mut react_server_component(file_name, config.is_server))
program.fold_with(&mut react_server_component(file_name, config.is_server, PluginCommentsProxy))
}
24 changes: 21 additions & 3 deletions packages/react-server-component/tests/fixture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ use swc_core::{
use swc_plugin_react_server_component::react_server_component;

#[fixture("tests/fixture/server/**/input.js")]
fn fixture(input: PathBuf) {
fn fixture_server(input: PathBuf) {
let parent = input.parent().unwrap();
let output = parent.join("output.js");

test_fixture(
Default::default(),
&|_t| {
react_server_component(FileName::Real("file_path.js".into()), true)
&|t| {
react_server_component(FileName::Real("file_path.js".into()), true, t.comments.clone())
},
&input,
&output,
Expand All @@ -23,3 +23,21 @@ fn fixture(input: PathBuf) {
},
);
}

#[fixture("tests/fixture/client/**/input.js")]
fn fixture_client(input: PathBuf) {
let parent = input.parent().unwrap();
let output = parent.join("output.js");

test_fixture(
Default::default(),
&|t| {
react_server_component(FileName::Real("file_path.js".into()), false, t.comments.clone())
},
&input,
&output,
FixtureTestConfig {
..Default::default()
},
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Home() {
return 'home';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Home() {
return 'home';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'use client';

import react from "react";

export default function Home() {
return 'home';
}

export const dataLoader = {};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*__ice_internal_client_entry_do_not_use__ default,dataLoader*/ import react from "react";

export default function Home() {
return 'home';
}

export const dataLoader = {};
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// comments
export default function () {
return null
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// comments
export default function () {
return null
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
const { createClientModuleProxy } = require("react-server-dom-webpack/server.node");
/*__ice_internal_client_entry_do_not_use__ default*/ const { createClientModuleProxy } = require("react-server-dom-webpack/server.node");
module.exports = createClientModuleProxy("file_path.js");

0 comments on commit af7832a

Please sign in to comment.