rspack_plugin_ignore/
lib.rs1use derive_more::Debug;
2use futures::future::BoxFuture;
3use rspack_core::{
4 BeforeResolveResult, ContextModuleFactoryBeforeResolve, ModuleFactoryCreateData,
5 NormalModuleFactoryBeforeResolve, Plugin,
6};
7use rspack_error::Result;
8use rspack_hook::{plugin, plugin_hook};
9use rspack_regex::RspackRegex;
10
11pub type CheckResourceFn =
12 Box<dyn for<'a> Fn(&'a str, &'a str) -> BoxFuture<'a, Result<bool>> + Sync + Send>;
13
14pub enum CheckResourceContent {
15 Fn(CheckResourceFn),
16}
17
18#[derive(Debug)]
19pub struct IgnorePluginOptions {
20 pub resource_reg_exp: Option<RspackRegex>,
21 pub context_reg_exp: Option<RspackRegex>,
22 #[debug(skip)]
23 pub check_resource: Option<CheckResourceContent>,
24}
25
26#[plugin]
27#[derive(Debug)]
28pub struct IgnorePlugin {
29 options: IgnorePluginOptions,
30}
31
32impl IgnorePlugin {
33 pub fn new(options: IgnorePluginOptions) -> Self {
34 Self::new_inner(options)
35 }
36
37 async fn check_ignore(&self, request: &str, context: &str) -> Result<Option<bool>> {
38 if let Some(check_resource) = &self.options.check_resource {
39 match check_resource {
40 CheckResourceContent::Fn(check) => match check(request, context).await {
41 Ok(true) => return Ok(Some(false)),
42 Err(err) => return Err(err.wrap_err("IgnorePlugin: failed to call `checkResource`")),
43 _ => {}
44 },
45 }
46 }
47
48 if let Some(resource_reg_exp) = &self.options.resource_reg_exp
49 && resource_reg_exp.test(request)
50 {
51 if let Some(context_reg_exp) = &self.options.context_reg_exp {
52 if context_reg_exp.test(context) {
53 return Ok(Some(false));
54 }
55 } else {
56 return Ok(Some(false));
57 }
58 }
59
60 Ok(None)
61 }
62}
63
64#[plugin_hook(NormalModuleFactoryBeforeResolve for IgnorePlugin)]
65async fn nmf_before_resolve(&self, data: &mut ModuleFactoryCreateData) -> Result<Option<bool>> {
66 self.check_ignore(&data.request, &data.context).await
67}
68
69#[plugin_hook(ContextModuleFactoryBeforeResolve for IgnorePlugin)]
70async fn cmf_before_resolve(&self, data: BeforeResolveResult) -> Result<BeforeResolveResult> {
71 match data {
72 BeforeResolveResult::Ignored => Ok(BeforeResolveResult::Ignored),
73 BeforeResolveResult::Data(d) => {
74 if let Some(false) = self.check_ignore(&d.request, &d.context).await? {
75 Ok(BeforeResolveResult::Ignored)
76 } else {
77 Ok(BeforeResolveResult::Data(d))
78 }
79 }
80 }
81}
82
83impl Plugin for IgnorePlugin {
84 fn name(&self) -> &'static str {
85 "IgnorePlugin"
86 }
87
88 fn apply(&self, ctx: &mut rspack_core::ApplyContext<'_>) -> Result<()> {
89 ctx
90 .normal_module_factory_hooks
91 .before_resolve
92 .tap(nmf_before_resolve::new(self));
93
94 ctx
95 .context_module_factory_hooks
96 .before_resolve
97 .tap(cmf_before_resolve::new(self));
98
99 Ok(())
100 }
101}