Skip to content

Commit

Permalink
ref: use add_include
Browse files Browse the repository at this point in the history
  • Loading branch information
JiangWeixian committed Jun 24, 2024
1 parent a17997a commit 326381d
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 129 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

18 changes: 13 additions & 5 deletions crates/rspack_binding_options/src/options/raw_builtins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,16 @@ use rspack_plugin_web_worker_template::web_worker_template_plugin;
use rspack_plugin_worker::WorkerPlugin;

pub use self::{
raw_banner::RawBannerPluginOptions, raw_copy::RawCopyRspackPluginOptions,
raw_html::RawHtmlRspackPluginOptions, raw_ignore::RawIgnorePluginOptions,
raw_limit_chunk_count::RawLimitChunkCountPluginOptions, raw_mf::RawContainerPluginOptions,
raw_progress::RawProgressPluginOptions, raw_rsc::RawRSCClientEntryRspackPluginOptions,
raw_banner::RawBannerPluginOptions,
raw_copy::RawCopyRspackPluginOptions,
raw_html::RawHtmlRspackPluginOptions,
raw_ignore::RawIgnorePluginOptions,
raw_limit_chunk_count::RawLimitChunkCountPluginOptions,
raw_mf::RawContainerPluginOptions,
raw_progress::RawProgressPluginOptions,
raw_rsc::{
RawRSCClientEntryRspackPluginOptions, RawRSCClientReferenceManifestRspackPluginOptions,
},
raw_swc_js_minimizer::RawSwcJsMinimizerRspackPluginOptions,
};
use self::{
Expand Down Expand Up @@ -497,7 +503,9 @@ impl BuiltinPlugin {
plugins.push(RSCClientEntryRspackPlugin::new(plugin_options.into()).boxed())
}
BuiltinPluginName::RSCClientReferenceManifestRspackPlugin => {
plugins.push(RSCClientReferenceManifestRspackPlugin::default().boxed())
let plugin_options: RawRSCClientReferenceManifestRspackPluginOptions =
downcast_into::<RawRSCClientReferenceManifestRspackPluginOptions>(self.options)?;
plugins.push(RSCClientReferenceManifestRspackPlugin::new(plugin_options.into()).boxed())
}
}
Ok(())
Expand Down
22 changes: 19 additions & 3 deletions crates/rspack_binding_options/src/options/raw_builtins/raw_rsc.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use napi_derive::napi;
use rspack_plugin_rsc::rsc_client_entry_rspack_plugin::{
RSCClientEntryRspackPluginOptions, ReactRoute,
};
use rspack_plugin_rsc::rsc_client_entry_rspack_plugin::RSCClientEntryRspackPluginOptions;
use rspack_plugin_rsc::rsc_client_reference_manifest_rspack_plugin::RSCClientReferenceManifestRspackPluginOptions;
use rspack_plugin_rsc::ReactRoute;
use serde::Deserialize;
use serde::Serialize;

Expand Down Expand Up @@ -30,6 +30,22 @@ pub struct RawRSCClientReferenceManifestRspackPluginOptions {
pub routes: Option<Vec<RawReactRoute>>,
}

impl From<RawRSCClientReferenceManifestRspackPluginOptions>
for RSCClientReferenceManifestRspackPluginOptions
{
fn from(value: RawRSCClientReferenceManifestRspackPluginOptions) -> Self {
let raw_routes = value.routes.unwrap_or_default();
let routes: Vec<ReactRoute> = raw_routes
.into_iter()
.map(|route| ReactRoute {
name: route.name,
import: route.import,
})
.collect();
RSCClientReferenceManifestRspackPluginOptions { routes }
}
}

impl From<RawRSCClientEntryRspackPluginOptions> for RSCClientEntryRspackPluginOptions {
fn from(value: RawRSCClientEntryRspackPluginOptions) -> Self {
let raw_routes = value.routes.unwrap_or_default();
Expand Down
1 change: 1 addition & 0 deletions crates/rspack_plugin_rsc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ version = "0.1.0"
async-trait = { workspace = true }
bitflags = { workspace = true }
dashmap = { workspace = true }
futures = { workspace = true }
indexmap = { workspace = true }
itertools = { workspace = true }
linked_hash_set = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion crates/rspack_plugin_rsc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ mod plugin;
pub use crate::loader::*;
pub use crate::plugin::*;
pub use crate::utils::{
decl::RSCAdditionalData, export_visitor, has_client_directive, rsc_visitor,
decl::RSCAdditionalData, decl::ReactRoute, export_visitor, has_client_directive, rsc_visitor,
};
mod loader;
mod utils;
133 changes: 58 additions & 75 deletions crates/rspack_plugin_rsc/src/loader/rsc_client_entry_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,36 @@ use std::{

use indexmap::set::IndexSet;
use itertools::Itertools;
use once_cell::sync::Lazy;
use regex::Regex;
use rspack_core::{Mode, RunnerContext};
use rspack_error::Result;
use rspack_loader_runner::{Identifiable, Identifier, Loader, LoaderContext};
use serde::{Deserialize, Serialize};
use url::form_urlencoded;

use crate::{utils::shared_data::SHARED_CLIENT_IMPORTS, ReactRoute};
use crate::utils::shared_data::SHARED_CLIENT_IMPORTS;

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RSCClientEntryLoaderOptions {
entry: HashMap<String, String>,
root: String,
routes: Option<Vec<ReactRoute>>,
}

#[derive(Debug)]
pub struct RSCClientEntryLoader {
identifier: Identifier,
options: RSCClientEntryLoaderOptions,
}
#[derive(Debug, Clone, Default)]
struct QueryParsedRequest {
pub is_client_entry: bool,
pub is_route_entry: bool,
pub chunk_name: String,
}

static RSC_CLIENT_ENTRY_RE: Lazy<Regex> =
Lazy::new(|| Regex::new(r"rsc-client-entry-loader").expect("regexp init failed"));

impl RSCClientEntryLoader {
pub fn new(options: RSCClientEntryLoaderOptions) -> Self {
Expand All @@ -34,74 +44,44 @@ impl RSCClientEntryLoader {
}
}

pub fn get_routes_code(&self) -> String {
if let Some(routes) = self.options.routes.as_ref() {
let code = routes
.iter()
.map(|f| {
format!(
r#"import(/* webpackChunkName: "{}" */ "{}");"#,
f.name, f.import
)
})
.join("\n");
code
} else {
String::from("")
}
pub fn get_client_imports_by_name(&self, chunk_name: &str) -> Option<IndexSet<String>> {
let all_client_imports = &SHARED_CLIENT_IMPORTS.lock().unwrap();
let client_imports = all_client_imports.get(&String::from(chunk_name)).cloned();
client_imports
}

pub fn get_entry_chunk_name(&self, resource_path: &str) -> Option<String> {
let result = self
.options
.entry
.clone()
.into_iter()
.find(|(_, path)| path == resource_path);
let chunk_name = if let Some(result) = result {
let resolved_name = if result.0 == "client-entry" {
String::from("server-entry")
} else {
result.0
};
Some(resolved_name)
} else {
None
};
chunk_name
pub fn format_client_imports(&self, chunk_name: &str) -> Option<PathBuf> {
let file_name = format!("[{}]_client_imports.json", chunk_name);
Some(Path::new(&self.options.root).join(file_name))
}

pub fn get_route_chunk_name(&self, resource_path: &str) -> Option<String> {
if let Some(routes) = self.options.routes.as_ref() {
let route = routes.into_iter().find(|f| f.import == resource_path);
let chunk_name = if let Some(route) = route {
Some(route.name.clone())
} else {
None
};
chunk_name
fn parse_query(&self, query: Option<&str>) -> QueryParsedRequest {
if let Some(query) = query {
let hash_query: HashMap<_, _> =
form_urlencoded::parse(query.trim_start_matches('?').as_bytes())
.into_owned()
.collect();
QueryParsedRequest {
chunk_name: String::from(hash_query.get("name").unwrap_or(&String::from(""))),
is_client_entry: hash_query
.get("from")
.unwrap_or(&String::from(""))
.eq("client-entry"),
is_route_entry: hash_query
.get("from")
.unwrap_or(&String::from(""))
.eq("route-entry"),
}
} else {
None
QueryParsedRequest::default()
}
}

pub fn get_client_imports_by_name(&self, chunk_name: &str) -> Option<IndexSet<String>> {
let all_client_imports = &SHARED_CLIENT_IMPORTS.lock().unwrap();
let client_imports = all_client_imports.get(&String::from(chunk_name)).cloned();
client_imports
}

pub fn format_client_imports(
&self,
entry_chunk_name: Option<&String>,
route_chunk_name: Option<&String>,
) -> Option<PathBuf> {
let chunk_name = entry_chunk_name.or(route_chunk_name);
if let Some(chunk_name) = chunk_name {
let file_name = format!("[{}]_client_imports.json", chunk_name);
Some(Path::new(&self.options.root).join(file_name))
pub fn is_match(&self, resource_path: Option<&str>) -> bool {
if let Some(resource_path) = resource_path {
RSC_CLIENT_ENTRY_RE.is_match(resource_path)
} else {
None
false
}
}

Expand All @@ -122,15 +102,19 @@ impl Loader<RunnerContext> for RSCClientEntryLoader {
let content = std::mem::take(&mut loader_context.content).expect("Content should be available");
let resource_path = loader_context.resource_path().to_str();
let mut source = content.try_into_string()?;

if let Some(resource_path) = resource_path {
let chunk_name = self.get_entry_chunk_name(resource_path);
let route_chunk_name = self.get_route_chunk_name(resource_path);
let client_imports_path =
self.format_client_imports(chunk_name.as_ref(), route_chunk_name.as_ref());
let query = loader_context.resource_query();

if self.is_match(resource_path) {
let parsed = self.parse_query(query);
let chunk_name = parsed.chunk_name;
let is_client_entry = parsed.is_client_entry;
let is_route_entry = parsed.is_route_entry;
// let route_chunk_name = self.get_route_chunk_name(resource_path);
let mut hmr = String::from("");
let development =
Some(Mode::is_development(&loader_context.context.options.mode)).unwrap_or(false);
let client_imports_path = self.format_client_imports(&chunk_name);

if development {
if let Some(client_imports_path) = client_imports_path {
// HMR
Expand All @@ -144,10 +128,9 @@ impl Loader<RunnerContext> for RSCClientEntryLoader {
}
}
}

// Entrypoint
if let Some(chunk_name) = &chunk_name {
let client_imports = self.get_client_imports_by_name(chunk_name);
if is_client_entry {
let client_imports = self.get_client_imports_by_name(&chunk_name);

if let Some(client_imports) = client_imports {
let code = client_imports
Expand All @@ -156,12 +139,12 @@ impl Loader<RunnerContext> for RSCClientEntryLoader {
.join("\n");
source = format!("{}{}", code, source);
}
let routes = self.get_routes_code();
source = format!("{}{}{}", hmr, routes, source);
source = format!("{}{}", hmr, source);
}

// Route
if let Some(chunk_name) = &route_chunk_name {
let client_imports = self.get_client_imports_by_name(chunk_name);
if is_route_entry {
let client_imports = self.get_client_imports_by_name(&chunk_name);

if let Some(client_imports) = client_imports {
let code = client_imports
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,13 @@ use rspack_core::{
};
use rspack_error::Result;
use rspack_hook::{plugin, plugin_hook};
use serde::{Deserialize, Serialize};
use serde_json::to_string;

use crate::utils::decl::ClientImports;
use crate::utils::decl::{ClientImports, ReactRoute};
use crate::utils::has_client_directive;
use crate::utils::sever_reference::RSCServerReferenceManifest;
use crate::utils::shared_data::SHARED_CLIENT_IMPORTS;

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ReactRoute {
pub name: String,
pub import: String,
}

#[derive(Debug, Default, Clone)]
pub struct RSCClientEntryRspackPluginOptions {
pub routes: Vec<ReactRoute>,
Expand Down Expand Up @@ -56,6 +49,7 @@ impl RSCClientEntryRspackPlugin {
fn get_route_entry(&self, resource: &str) -> Option<&ReactRoute> {
self.options.routes.iter().find(|&f| f.import == resource)
}

fn filter_client_components(
&self,
compilation: &Compilation,
Expand Down
Loading

0 comments on commit 326381d

Please sign in to comment.