Skip to content

Commit

Permalink
feat: lazy compilation
Browse files Browse the repository at this point in the history
  • Loading branch information
JSerFeng committed May 16, 2024
1 parent 27042bb commit fa8e500
Show file tree
Hide file tree
Showing 44 changed files with 2,371 additions and 87 deletions.
18 changes: 18 additions & 0 deletions Cargo.lock

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

24 changes: 23 additions & 1 deletion crates/node_binding/binding.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export type JsFilename =
| ((pathData: JsPathData, assetInfo?: JsAssetInfo) => string);

export type LocalJsFilename = JsFilename;

export type RawLazyCompilationTest = RegExp | ((m: JsModule) => boolean);
/* -- banner.d.ts end -- */

/* -- napi-rs generated below -- */
Expand Down Expand Up @@ -171,7 +173,8 @@ export enum BuiltinPluginName {
SwcCssMinimizerRspackPlugin = 'SwcCssMinimizerRspackPlugin',
BundlerInfoRspackPlugin = 'BundlerInfoRspackPlugin',
CssExtractRspackPlugin = 'CssExtractRspackPlugin',
JsLoaderRspackPlugin = 'JsLoaderRspackPlugin'
JsLoaderRspackPlugin = 'JsLoaderRspackPlugin',
LazyCompilationPlugin = 'LazyCompilationPlugin'
}

export function cleanupGlobalTrace(): void
Expand Down Expand Up @@ -966,6 +969,14 @@ export interface RawJavascriptParserOptions {
wrappedContextCritical: boolean
}

export interface RawLazyCompilationOption {
module: (err: Error | null, arg: RawModuleArg) => any
test?: RawLazyCompilationTest
entries: boolean
imports: boolean
cacheable: boolean
}

export interface RawLibraryAuxiliaryComment {
root?: string
commonjs?: string
Expand Down Expand Up @@ -1001,6 +1012,11 @@ export interface RawLimitChunkCountPluginOptions {
maxChunks: number
}

export interface RawModuleArg {
module: string
path: string
}

export interface RawModuleFilenameTemplateFnCtx {
identifier: string
shortIdentifier: string
Expand All @@ -1015,6 +1031,12 @@ export interface RawModuleFilenameTemplateFnCtx {
namespace: string
}

export interface RawModuleInfo {
active: boolean
client: string
data: string
}

export interface RawModuleOptions {
rules: Array<RawModuleRule>
parser?: Record<string, RawParserOptions>
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 @@ -7,6 +7,8 @@ export type JsFilename =
| ((pathData: JsPathData, assetInfo?: JsAssetInfo) => string);

export type LocalJsFilename = JsFilename;

export type RawLazyCompilationTest = RegExp | ((m: JsModule) => boolean);
/* -- banner.d.ts end -- */

/* -- napi-rs generated below -- */
1 change: 1 addition & 0 deletions crates/rspack_binding_options/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ rspack_plugin_html = { path = "../rspack_plugin_html" }
rspack_plugin_ignore = { path = "../rspack_plugin_ignore" }
rspack_plugin_javascript = { path = "../rspack_plugin_javascript" }
rspack_plugin_json = { path = "../rspack_plugin_json" }
rspack_plugin_lazy_compilation = { path = "../rspack_plugin_lazy_compilation" }
rspack_plugin_library = { path = "../rspack_plugin_library" }
rspack_plugin_limit_chunk_count = { path = "../rspack_plugin_limit_chunk_count" }
rspack_plugin_merge_duplicate_chunks = { path = "../rspack_plugin_merge_duplicate_chunks" }
Expand Down
18 changes: 17 additions & 1 deletion crates/rspack_binding_options/src/options/raw_builtins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod raw_copy;
mod raw_css_extract;
mod raw_html;
mod raw_ignore;
mod raw_lazy_compilation;
mod raw_limit_chunk_count;
mod raw_mf;
mod raw_progress;
Expand All @@ -14,7 +15,7 @@ mod raw_to_be_deprecated;

use napi::{bindgen_prelude::FromNapiValue, Env, JsUnknown};
use napi_derive::napi;
use rspack_core::{BoxPlugin, Define, DefinePlugin, PluginExt, Provide, ProvidePlugin};
use rspack_core::{BoxPlugin, Define, DefinePlugin, Plugin, PluginExt, Provide, ProvidePlugin};
use rspack_error::Result;
use rspack_ids::{
DeterministicChunkIdsPlugin, DeterministicModuleIdsPlugin, NamedChunkIdsPlugin,
Expand Down Expand Up @@ -79,6 +80,7 @@ pub use self::{
use self::{
raw_bundle_info::{RawBundlerInfoModeWrapper, RawBundlerInfoPluginOptions},
raw_css_extract::RawCssExtractPluginOption,
raw_lazy_compilation::{JsBackend, RawLazyCompilationOption},
raw_mf::{RawConsumeSharedPluginOptions, RawContainerReferencePluginOptions, RawProvideOptions},
raw_runtime_chunk::RawRuntimeChunkOptions,
raw_size_limits::RawSizeLimitsPluginOptions,
Expand Down Expand Up @@ -165,6 +167,7 @@ pub enum BuiltinPluginName {
// rspack js adapter plugins
// naming format follow XxxRspackPlugin
JsLoaderRspackPlugin,
LazyCompilationPlugin,
}

#[napi(object)]
Expand Down Expand Up @@ -468,6 +471,19 @@ impl BuiltinPlugin {
JsLoaderResolverPlugin::new(downcast_into::<JsLoaderRunner>(self.options)?).boxed(),
);
}
BuiltinPluginName::LazyCompilationPlugin => {
let options = downcast_into::<RawLazyCompilationOption>(self.options)?;
let js_backend = JsBackend::from(&options);
plugins.push(Box::new(
rspack_plugin_lazy_compilation::plugin::LazyCompilationPlugin::new(
options.cacheable,
js_backend,
options.test.map(|test| test.into()),
options.entries,
options.imports,
),
) as Box<dyn Plugin>)
}
}
Ok(())
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
use napi::{
bindgen_prelude::{FromNapiValue, ToNapiValue, ValidateNapiValue},
Either,
};
use napi_derive::napi;
use rspack_binding_values::{JsModule, ToJsModule};
use rspack_core::ModuleIdentifier;
use rspack_napi::threadsafe_function::ThreadsafeFunction;
use rspack_plugin_lazy_compilation::{
backend::{Backend, ModuleInfo},
plugin::{LazyCompilationTest, LazyCompilationTestCheck},
};
use rspack_regex::RspackRegex;

use crate::RawRegexMatcher;

#[derive(Debug)]
pub struct RawLazyCompilationTest<F = ThreadsafeFunction<JsModule, Option<bool>>>(
pub Either<RawRegexMatcher, F>,
);

impl<F: FromNapiValue + ValidateNapiValue> FromNapiValue for RawLazyCompilationTest<F> {
unsafe fn from_napi_value(
env: napi::sys::napi_env,
napi_val: napi::sys::napi_value,
) -> napi::Result<Self> {
Ok(Self(Either::from_napi_value(env, napi_val)?))
}
}

impl<F: ToNapiValue> ToNapiValue for RawLazyCompilationTest<F> {
unsafe fn to_napi_value(
env: napi::sys::napi_env,
val: Self,
) -> napi::Result<napi::sys::napi_value> {
Either::to_napi_value(env, val.0)
}
}

#[derive(Debug)]
pub struct LazyCompilationTestFn {
tsfn: ThreadsafeFunction<JsModule, Option<bool>>,
}

impl LazyCompilationTestCheck for LazyCompilationTestFn {
fn test(&self, m: &dyn rspack_core::Module) -> bool {
let res = self
.tsfn
.blocking_call_with_sync(
m.to_js_module()
.expect("failed to convert module to js module"),
)
.expect("failed to invoke lazyCompilation.test");

res.unwrap_or(false)
}
}

impl From<RawLazyCompilationTest> for LazyCompilationTest<LazyCompilationTestFn> {
fn from(value: RawLazyCompilationTest) -> Self {
match value.0 {
Either::A(regex) => Self::Regex(
RspackRegex::with_flags(&regex.source, &regex.flags).unwrap_or_else(|_| {
let msg = format!("[lazyCompilation]incorrect regex {:?}", regex);
panic!("{msg}");
}),
),
Either::B(tsfn) => Self::Fn(LazyCompilationTestFn { tsfn }),
}
}
}

#[napi(object)]
pub struct RawModuleInfo {
pub active: bool,
pub client: String,
pub data: String,
}

#[napi(object, object_to_js = false)]
pub struct RawLazyCompilationOption {
pub module: ThreadsafeFunction<RawModuleArg, RawModuleInfo>,
pub test: Option<RawLazyCompilationTest>,
pub entries: bool,
pub imports: bool,
pub cacheable: bool,
}

#[napi(object)]
pub struct RawModuleArg {
pub module: String,
pub path: String,
}

pub(crate) struct JsBackend {
module: ThreadsafeFunction<RawModuleArg, RawModuleInfo>,
}

impl std::fmt::Debug for JsBackend {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("JsBackend").finish()
}
}

impl From<&RawLazyCompilationOption> for JsBackend {
fn from(value: &RawLazyCompilationOption) -> Self {
Self {
module: value.module.clone(),
}
}
}

#[async_trait::async_trait]
impl Backend for JsBackend {
async fn module(
&mut self,
identifier: ModuleIdentifier,
path: String,
) -> rspack_error::Result<ModuleInfo> {
let module_info = self
.module
.call(RawModuleArg {
module: identifier.to_string(),
path,
})
.await
.expect("channel should have result");

Ok(ModuleInfo {
active: module_info.active,
client: module_info.client,
data: module_info.data,
})
}
}
2 changes: 2 additions & 0 deletions crates/rspack_core/src/dependency/dependency_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ pub enum DependencyType {
/// Webpack is included
WebpackIsIncluded,
LoaderImport,
LazyImport,
Custom(Box<str>), // TODO it will increase large layout size
}

Expand Down Expand Up @@ -149,6 +150,7 @@ impl DependencyType {
DependencyType::ProvideModuleForShared => Cow::Borrowed("provide module for shared"),
DependencyType::ConsumeSharedFallback => Cow::Borrowed("consume shared fallback"),
DependencyType::WebpackIsIncluded => Cow::Borrowed("__webpack_is_included__"),
DependencyType::LazyImport => Cow::Borrowed("lazy import()"),
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/rspack_core/src/module_factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use sugar_path::SugarPath;

use crate::{BoxDependency, BoxModule, Context, ModuleIdentifier, Resolve};

#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct ModuleFactoryCreateData {
pub resolve_options: Option<Box<Resolve>>,
pub context: Context,
Expand Down
8 changes: 8 additions & 0 deletions crates/rspack_core/src/utils/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ impl<T, K: Eq + PartialEq + std::hash::Hash> WorkerQueue<T, K> {
}
}

pub fn len(&self) -> usize {
self.inner.len()
}

pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}

pub fn add_task(&mut self, task: T) -> usize {
self.inner.push_back(task);
self.inner.len()
Expand Down
8 changes: 8 additions & 0 deletions crates/rspack_database/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ impl<Item: Any> Database<Item> {
}
}

pub fn len(&self) -> usize {
self.inner.len()
}

pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}

pub fn contains(&self, id: &Ukey<Item>) -> bool {
self.inner.contains_key(id)
}
Expand Down
Loading

0 comments on commit fa8e500

Please sign in to comment.