Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: lazy compilation #5915

Merged
merged 1 commit into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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