Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
4a4505b
react_server_components transform
SyMind Oct 13, 2025
31c656c
Merge remote-tracking branch 'origin' into react-server-component
SyMind Oct 13, 2025
62ce9de
fix: ReactServerComponents
SyMind Oct 13, 2025
b3b4fcb
ReactServerComponentPlugin
SyMind Oct 15, 2025
1b0c818
chore: merge origin main
SyMind Oct 28, 2025
c87018b
Merge remote-tracking branch 'origin' into react-server-component
SyMind Nov 10, 2025
82925c0
fix: rspack_loader_swc Wtf8Atom
SyMind Nov 11, 2025
58288ed
feat: ReactServerComponentPlugin
SyMind Nov 11, 2025
ac7e626
feat: ServerEntryModules
SyMind Nov 12, 2025
107db20
exports_info
SyMind Nov 13, 2025
99d57f3
temp
SyMind Nov 17, 2025
be58a45
chore: merge origin main
SyMind Nov 17, 2025
4a8c912
feat: import with layer
SyMind Nov 18, 2025
e1015a8
fix: before pass
SyMind Nov 20, 2025
208cc52
export ReactServerComponentsPlugin
SyMind Nov 20, 2025
af4d829
ServerEntries
SyMind Nov 21, 2025
a9253fd
feat: client_entry_loader
SyMind Nov 24, 2025
a2b0457
feat: client compiler
SyMind Nov 25, 2025
2e3accd
feat: traverse_modules
SyMind Nov 25, 2025
fb39548
feat: ClientReferenceManifestPlugin
SyMind Nov 25, 2025
8e5c091
feat: react_server_components layer
SyMind Nov 26, 2025
95a7401
fix ReactClientPlugin
SyMind Nov 26, 2025
68ff4c2
fix: ClientReferenceManifestPlugin
SyMind Nov 26, 2025
cedca6d
refactor: rename to ReactServerPlugin
SyMind Nov 26, 2025
5b0cc98
remove eager
SyMind Nov 27, 2025
4c953cb
feat: collect entry css files
SyMind Nov 27, 2025
137db08
feat: use server-entry
SyMind Dec 1, 2025
b3b67bb
server actions transform
SyMind Dec 1, 2025
31f38e9
feat: action_entry_loader
SyMind Dec 2, 2025
ed7be7f
collect server_actions
SyMind Dec 2, 2025
2c0904e
temp
SyMind Dec 9, 2025
5757e63
manifest-loader
SyMind Dec 17, 2025
3d623f7
RscManifestRuntimeModule
SyMind Dec 17, 2025
8d630e5
fix: build_server_consumer_module_map
SyMind Dec 18, 2025
939e4f5
fix: entry_css_files
SyMind Dec 19, 2025
7b6e552
feat: record_entry_js_files
SyMind Dec 19, 2025
cb2d8ae
refactor: entry_css_files
SyMind Dec 19, 2025
6503ea7
fix: entry js files and entry css files should concat prefix
SyMind Dec 20, 2025
07671a3
remove unused code
SyMind Dec 20, 2025
538a9d6
chore: rename loader and plugin
SyMind Dec 20, 2025
1816837
fix: Coordinator
SyMind Dec 20, 2025
f9da86a
fix: entry js files prevent hot-module files from being included
SyMind Dec 20, 2025
5682885
clear PLUGIN_STATE_BY_COMPILER_ID
SyMind Dec 21, 2025
28444af
feat: add_include client action
SyMind Dec 21, 2025
a4e78f3
feat: prev_server_component_hashs
SyMind Dec 22, 2025
79bceac
fix: client compiler not rebuild right
SyMind Dec 22, 2025
4017bc1
export RSC_LAYERS_NAMES
SyMind Dec 22, 2025
32a395d
fix: remove import with layer
SyMind Dec 22, 2025
3edfdb9
refactor: rsc_pass
SyMind Dec 22, 2025
6350970
refactor: rsc_meta
SyMind Dec 23, 2025
2486463
refactor: to_module_ref
SyMind Dec 23, 2025
c3bbc5a
chore: merge origin main
SyMind Dec 23, 2025
7d7644c
fix: cargo clippy
SyMind Dec 23, 2025
57b70b9
fix: lint and spelling
SyMind Dec 23, 2025
ecf3f75
api changed
SyMind Dec 23, 2025
48927fb
refactor: use get_module_resource
SyMind Dec 23, 2025
5f38eb6
fix: ts type
SyMind Dec 23, 2025
4941195
fix: compiler watching
SyMind Dec 24, 2025
bc09b12
feat: check should_inject_ssr_modules
SyMind Dec 25, 2025
9a46804
fix: only invalidate client after proxying client watching
SyMind Dec 25, 2025
5e52ec1
fix: client module chunks should exclude hot module replacement js
SyMind Dec 26, 2025
2413e2d
chore: rename coordinator mod
SyMind Dec 29, 2025
233e1b2
fix: collect_component_info_from_entry_denendency
SyMind Dec 29, 2025
53525da
fix: panic in create_client_entries
SyMind Dec 30, 2025
151c4ae
fix: browser action
SyMind Dec 30, 2025
a79dfbd
rm ACTION_BROWSER layer
SyMind Dec 31, 2025
7878acb
fix: use atomic ref
SyMind Dec 31, 2025
b4aa13e
refactor client plugin
SyMind Dec 31, 2025
b303a91
fix: should handle compile failed
SyMind Dec 31, 2025
09dd289
chore: rm unused print
SyMind Jan 4, 2026
3576c7d
fix: use server-entry mix use client
SyMind Jan 4, 2026
c95987a
feat: ensureServerActions
SyMind Jan 4, 2026
d07a6c5
fix: RSC_HOT_RELOADER
SyMind Jan 4, 2026
0bd447a
refactor: create_client_entries
SyMind Jan 4, 2026
6e3e3b1
fix: encryptActionBoundArgs and decryptActionBoundArgs
SyMind Jan 4, 2026
a1af972
fix: should collect entry css files in after_process_assets hook
SyMind Jan 5, 2026
26c11d2
fix: with concat module
SyMind Jan 6, 2026
aa18a19
chore(deps): update patch npm dependencies (#12647)
renovate[bot] Jan 7, 2026
ece0fee
chore(deps): update patch crates (#12646)
renovate[bot] Jan 7, 2026
edce5bd
chore: run ci/eco-ci/eco-benchmark on v2 branch (#12650)
LingyuCoder Jan 7, 2026
44a7564
fix: report error when access module_graph in loader (#12639)
hardfist Jan 7, 2026
25a4021
feat(rstest): add preserveNewUrl option to keep new URL untouched (#1…
fi3ework Jan 7, 2026
d424733
fix(lint): enable @typescript-eslint/await-thenable rule (#12644)
tt-a1i Jan 7, 2026
a5c4032
chore: merge origin main
SyMind Jan 7, 2026
ba1ce5f
fix: cargo clippy
SyMind Jan 8, 2026
c5ba0b6
refactor: rm RSC_HOT_RELOADER runtime module
SyMind Jan 16, 2026
d3db545
chore: merge origin v2
SyMind Jan 16, 2026
ee7bda8
fix: lint check
SyMind Jan 16, 2026
7224564
refactor: rename RscPluginLayers
SyMind Jan 19, 2026
965a498
warp rsc in namespace
SyMind Jan 19, 2026
0b48f4e
fix: rsc client plugin
SyMind Jan 19, 2026
0e85d4d
fix: cargo fmt
SyMind Jan 20, 2026
ac05ef7
add next.js Copyright
SyMind Jan 20, 2026
3c5ea37
fix: user can change fileDependencies in done hook
SyMind Jan 20, 2026
40268c3
chore: merge origin v2
SyMind Jan 22, 2026
148860c
chore: add comments
SyMind Jan 22, 2026
f3303ce
fix: cargo fmt
SyMind Jan 22, 2026
0cfbe8e
rm ustr dependencies
SyMind Jan 22, 2026
4276a07
chore: merge origin main
SyMind Jan 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ dyn-clone = { version = "1.0.20", default-features = false }
either = { version = "1.15.0", default-features = false }
enum-tag = { version = "0.3.0", default-features = false }
fast-glob = { version = "1.0.0", default-features = false }
form_urlencoded = { version = "1.2.2", default-features = false }
futures = { version = "0.3.31", default-features = false, features = ["std"] }
glob = { version = "0.3.3", default-features = false }
hashlink = { version = "0.10.0", default-features = false }
Expand Down Expand Up @@ -224,6 +225,7 @@ rspack_plugin_progress = { version = "=0.100.0-alpha.0", path =
rspack_plugin_real_content_hash = { version = "=0.100.0-alpha.0", path = "crates/rspack_plugin_real_content_hash", default-features = false }
rspack_plugin_remove_duplicate_modules = { version = "=0.100.0-alpha.0", path = "crates/rspack_plugin_remove_duplicate_modules", default-features = false }
rspack_plugin_remove_empty_chunks = { version = "=0.100.0-alpha.0", path = "crates/rspack_plugin_remove_empty_chunks", default-features = false }
rspack_plugin_rsc = { version = "=0.100.0-alpha.0", path = "crates/rspack_plugin_rsc", default-features = false }
rspack_plugin_rsdoctor = { version = "=0.100.0-alpha.0", path = "crates/rspack_plugin_rsdoctor", default-features = false }
rspack_plugin_rslib = { version = "=0.100.0-alpha.0", path = "crates/rspack_plugin_rslib", default-features = false }
rspack_plugin_rstest = { version = "=0.100.0-alpha.0", path = "crates/rspack_plugin_rstest", default-features = false }
Expand Down
20 changes: 19 additions & 1 deletion crates/node_binding/napi-binding.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ export interface JsSource {
source: string | Buffer
map?: string
}

export type CompilerId = void;
/* -- banner.d.ts end -- */

/* -- napi-rs generated below -- */
Expand Down Expand Up @@ -334,6 +336,7 @@ export declare class JsCompiler {
rebuild(changed_files: string[], removed_files: string[], callback: (err: null | Error) => void): void
close(): Promise<void>
getVirtualFileStore(): VirtualFileStore | null
getCompilerId(): ExternalObject<CompilerId>
}

export declare class JsContextModuleFactoryAfterResolveData {
Expand Down Expand Up @@ -361,6 +364,10 @@ export declare class JsContextModuleFactoryBeforeResolveData {
set recursive(recursive: boolean)
}

export declare class JsCoordinator {
constructor(getServerCompilerIdJsFn: () => ExternalObject<CompilerId>)
}

export declare class JsDependencies {
get fileDependencies(): Array<string>
get addedFileDependencies(): Array<string>
Expand Down Expand Up @@ -602,7 +609,9 @@ export declare enum BuiltinPluginName {
LazyCompilationPlugin = 'LazyCompilationPlugin',
ModuleInfoHeaderPlugin = 'ModuleInfoHeaderPlugin',
HttpUriPlugin = 'HttpUriPlugin',
CssChunkingPlugin = 'CssChunkingPlugin'
CssChunkingPlugin = 'CssChunkingPlugin',
RscServerPlugin = 'RscServerPlugin',
RscClientPlugin = 'RscClientPlugin'
}

export declare function cleanupGlobalTrace(): void
Expand Down Expand Up @@ -1028,6 +1037,15 @@ export interface JsResourceData {
descriptionFilePath?: string
}

export interface JsRscClientPluginOptions {
coordinator: JsCoordinator
}

export interface JsRscServerPluginOptions {
coordinator: JsCoordinator
onServerComponentChanges?: (() => void) | undefined | null
}

export interface JsRsdoctorAsset {
ukey: number
path: string
Expand Down
1 change: 1 addition & 0 deletions crates/node_binding/rspack.wasi-browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export const JsCompilation = __napiModule.exports.JsCompilation
export const JsCompiler = __napiModule.exports.JsCompiler
export const JsContextModuleFactoryAfterResolveData = __napiModule.exports.JsContextModuleFactoryAfterResolveData
export const JsContextModuleFactoryBeforeResolveData = __napiModule.exports.JsContextModuleFactoryBeforeResolveData
export const JsCoordinator = __napiModule.exports.JsCoordinator
export const JsDependencies = __napiModule.exports.JsDependencies
export const JsEntries = __napiModule.exports.JsEntries
export const JsExportsInfo = __napiModule.exports.JsExportsInfo
Expand Down
1 change: 1 addition & 0 deletions crates/node_binding/rspack.wasi.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ module.exports.JsCompilation = __napiModule.exports.JsCompilation
module.exports.JsCompiler = __napiModule.exports.JsCompiler
module.exports.JsContextModuleFactoryAfterResolveData = __napiModule.exports.JsContextModuleFactoryAfterResolveData
module.exports.JsContextModuleFactoryBeforeResolveData = __napiModule.exports.JsContextModuleFactoryBeforeResolveData
module.exports.JsCoordinator = __napiModule.exports.JsCoordinator
module.exports.JsDependencies = __napiModule.exports.JsDependencies
module.exports.JsEntries = __napiModule.exports.JsEntries
module.exports.JsExportsInfo = __napiModule.exports.JsExportsInfo
Expand Down
2 changes: 2 additions & 0 deletions crates/node_binding/scripts/banner.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ export interface JsSource {
source: string | Buffer
map?: string
}

export type CompilerId = void;
/* -- banner.d.ts end -- */

/* -- napi-rs generated below -- */
1 change: 1 addition & 0 deletions crates/rspack_binding_api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ rspack_paths = { workspace = true }
rspack_plugin_esm_library = { workspace = true }
rspack_plugin_html = { workspace = true }
rspack_plugin_javascript = { workspace = true }
rspack_plugin_rsc = { workspace = true }
rspack_plugin_rsdoctor = { workspace = true }
rspack_plugin_rslib = { workspace = true }
rspack_plugin_rstest = { workspace = true }
Expand Down
7 changes: 7 additions & 0 deletions crates/rspack_binding_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ impl JsCompiler {
rspack_loader_lightningcss::LightningcssLoaderPlugin::new(),
));
plugins.push(Box::new(rspack_loader_swc::SwcLoaderPlugin::new()));
plugins.push(Box::new(rspack_plugin_rsc::ClientEntryLoaderPlugin::new()));
plugins.push(Box::new(rspack_plugin_rsc::ActionEntryLoaderPlugin::new()));
plugins.push(Box::new(
rspack_loader_react_refresh::ReactRefreshLoaderPlugin::new(),
));
Expand Down Expand Up @@ -416,6 +418,11 @@ impl JsCompiler {
.as_ref()
.map(|store| JsVirtualFileStore::new(store.clone()))
}

#[napi]
pub fn get_compiler_id(&self) -> External<CompilerId> {
External::new(self.compiler.id())
}
}

struct RunGuard {
Expand Down
2 changes: 2 additions & 0 deletions crates/rspack_binding_api/src/plugins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ mod interceptor;
mod js_cleanup_plugin;
mod js_hooks_plugin;
mod js_loader;
mod rsc;

pub use js_cleanup_plugin::*;
pub use js_hooks_plugin::*;
pub(super) use js_loader::{JsLoaderItem, JsLoaderRspackPlugin, JsLoaderRunnerGetter};
pub mod buildtime_plugins;
pub use interceptor::*;
pub use rsc::{JsCoordinator, JsRscClientPluginOptions, JsRscServerPluginOptions};
114 changes: 114 additions & 0 deletions crates/rspack_binding_api/src/plugins/rsc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
use std::sync::Arc;

use futures::future::BoxFuture;
use napi::{
Env, Status,
bindgen_prelude::{
ClassInstance, Either3, External, ExternalRef, FromNapiValue, Function, JsObjectValue, Null,
Object, Promise, Reference, Undefined, WeakReference,
},
threadsafe_function::ThreadsafeFunction,
};
use once_cell::unsync::OnceCell;
use rspack_core::{Compiler, CompilerId};
use rspack_error::ToStringResultToRspackResultExt;
use rspack_plugin_rsc::{Coordinator, RscClientPluginOptions, RscServerPluginOptions};

use crate::JsCompiler;

type InvalidateTsFn = Arc<ThreadsafeFunction<(), (), (), Status, false, true, 0>>;

#[napi]
pub struct JsCoordinator {
Comment thread
SyMind marked this conversation as resolved.
i: Arc<Coordinator>,
}

#[napi]
impl JsCoordinator {
#[napi(constructor)]
pub fn new(
get_server_compiler_id_js_fn: Function<'static, (), &'static External<CompilerId>>,
) -> napi::Result<Self> {
let get_server_compiler_id = {
let ts_fn = Arc::new(
get_server_compiler_id_js_fn
.build_threadsafe_function::<()>()
.callee_handled::<false>()
.max_queue_size::<0>()
.weak::<true>()
.build()?,
);
Box::new(
move || -> BoxFuture<'static, rspack_error::Result<CompilerId>> {
let ts_fn = ts_fn.clone();
Box::pin(async move {
let external = ts_fn.call_async(()).await.to_rspack_result()?;
Ok(**external)
})
},
)
};

Ok(Self {
i: Arc::new(Coordinator::new(get_server_compiler_id)),
})
}
}

impl From<&JsCoordinator> for Arc<Coordinator> {
fn from(value: &JsCoordinator) -> Self {
value.i.clone()
}
}

#[napi(object, object_to_js = false)]
pub struct JsRscClientPluginOptions<'a> {
pub coordinator: ClassInstance<'a, JsCoordinator>,
}

impl From<&JsRscClientPluginOptions<'_>> for RscClientPluginOptions {
fn from(value: &JsRscClientPluginOptions) -> Self {
Self {
coordinator: value.coordinator.i.clone(),
}
}
}

#[napi(object, object_to_js = false)]
pub struct JsRscServerPluginOptions<'a> {
pub coordinator: ClassInstance<'a, JsCoordinator>,
pub on_server_component_changes: Option<Either3<Function<'static, (), ()>, Undefined, Null>>,
}

impl TryFrom<&JsRscServerPluginOptions<'_>> for RscServerPluginOptions {
type Error = napi::Error;

fn try_from(value: &JsRscServerPluginOptions) -> napi::Result<Self> {
let on_server_component_changes: Option<
Box<dyn Fn() -> BoxFuture<'static, rspack_error::Result<()>> + Sync + Send>,
> = match value.on_server_component_changes {
Some(Either3::A(js_fn)) => {
let ts_fn = Arc::new(
js_fn
.build_threadsafe_function::<()>()
.callee_handled::<false>()
.max_queue_size::<0>()
.weak::<true>()
.build()?,
);
Some(Box::new(
move || -> BoxFuture<'static, rspack_error::Result<()>> {
let ts_fn = ts_fn.clone();
Box::pin(async move { ts_fn.call_async(()).await.to_rspack_result() })
},
))
}
_ => None,
};

Ok(Self {
coordinator: value.coordinator.i.clone(),
on_server_component_changes,
})
}
}
22 changes: 20 additions & 2 deletions crates/rspack_binding_api/src/raw_options/raw_builtins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use std::cell::RefCell;

use napi::{
Either, Env, Unknown,
bindgen_prelude::{FromNapiValue, JsObjectValue, Object},
bindgen_prelude::{ClassInstance, FromNapiValue, JsObjectValue, Object},
};
use napi_derive::napi;
use raw_dll::{RawDllReferenceAgencyPluginOptions, RawFlagAllModulesAsUsedPluginOptions};
Expand Down Expand Up @@ -85,6 +85,7 @@ use rspack_plugin_no_emit_on_errors::NoEmitOnErrorsPlugin;
use rspack_plugin_real_content_hash::RealContentHashPlugin;
use rspack_plugin_remove_duplicate_modules::RemoveDuplicateModulesPlugin;
use rspack_plugin_remove_empty_chunks::RemoveEmptyChunksPlugin;
use rspack_plugin_rsc::{RscClientPlugin, RscServerPlugin};
use rspack_plugin_rslib::RslibPlugin;
use rspack_plugin_runtime::{
ArrayPushCallbackChunkFormatPlugin, BundlerInfoPlugin, ChunkPrefetchPreloadPlugin,
Expand Down Expand Up @@ -126,7 +127,10 @@ use self::{
};
use crate::{
options::entry::JsEntryPluginOptions,
plugins::{JsLoaderRspackPlugin, JsLoaderRunnerGetter},
plugins::{
JsCoordinator, JsLoaderRspackPlugin, JsLoaderRunnerGetter, JsRscClientPluginOptions,
JsRscServerPluginOptions,
},
raw_options::{
RawDynamicEntryPluginOptions, RawEvalDevToolModulePluginOptions, RawExternalItemWrapper,
RawExternalsPluginOptions, RawHttpExternalsRspackPluginOptions, RawSplitChunksOptions,
Expand Down Expand Up @@ -236,6 +240,10 @@ pub enum BuiltinPluginName {
ModuleInfoHeaderPlugin,
HttpUriPlugin,
CssChunkingPlugin,

// react server components
RscServerPlugin,
RscClientPlugin,
}

#[doc(hidden)]
Expand Down Expand Up @@ -839,6 +847,16 @@ impl<'a> BuiltinPlugin<'a> {
.map_err(|report| napi::Error::from_reason(report.to_string()))?;
plugins.push(CssChunkingPlugin::new(options.into()).boxed());
}
BuiltinPluginName::RscServerPlugin => {
let options = &downcast_into::<JsRscServerPluginOptions>(self.options)
.map_err(|report| napi::Error::from_reason(report.to_string()))?;
plugins.push(RscServerPlugin::new(options.try_into()?).boxed());
}
BuiltinPluginName::RscClientPlugin => {
let options = &downcast_into::<JsRscClientPluginOptions>(self.options)
.map_err(|report| napi::Error::from_reason(report.to_string()))?;
plugins.push(RscClientPlugin::new(options.into()).boxed());
}
}
Ok(())
}
Expand Down
Loading
Loading