Skip to content

Commit

Permalink
feat: Finished the specilize module name plugin (#10)
Browse files Browse the repository at this point in the history
* feat: Finished the specilize module name plugin

* refactor: test and core code

---------

Co-authored-by: 空堂 <[email protected]>
  • Loading branch information
lbfsc and 空堂 authored Nov 15, 2023
1 parent 3cae4b0 commit 133a9f3
Show file tree
Hide file tree
Showing 12 changed files with 291 additions and 1 deletion.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ members = [
"crates/binding_options",
"crates/node_binding",
"crates/loader_compilation",
"crates/plugin_manifest"
"crates/plugin_manifest",
"crates/plugin_specilize_module_name"
]
resolver = "2"

Expand Down
15 changes: 15 additions & 0 deletions crates/plugin_specilize_module_name/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "plugin_specilize_module_name"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
async-trait = { workspace = true }
tracing = { workspace = true }
rspack_core = { path = "../.rspack_crates/rspack_core" }
rspack_error = { path = "../.rspack_crates/rspack_error" }

[dev-dependencies]
rspack_testing = { path = "../.rspack_crates/rspack_testing" }
39 changes: 39 additions & 0 deletions crates/plugin_specilize_module_name/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# plugin_specilize_module_name

## Introduction

This is a plugin that specializes the module name of the generated code. It use the rspack `before_resolve` plugin hook to do this.

## Usage

1. Add the following configuration to your `Cargo.toml` file

```toml
[plugins]
plugin_specilize_module_name = { version = "0.1.0", default-features = false }
```

2. Add the plugin to rspack-core and pass the argument(the package names you want to specialize)

```rs
Box::new(SpecilizeModuleNamePlugin::new(Some(vec![<your package name>])))
```

## Example

You put the `lodash` as point package name in rspack-core

```rs
Box::new(SpecilizeModuleNamePlugin::new(Some(vec!["lodash"])))
```

Then you can use it in your code

```js
const { add } = require("lodash");
```

The package name will be transformed to `lodash.js?id=1`. The `id` is unique for each package.

## License
MIT
2 changes: 2 additions & 0 deletions crates/plugin_specilize_module_name/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mod plugin;
pub use plugin::*;
97 changes: 97 additions & 0 deletions crates/plugin_specilize_module_name/src/plugin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
use std::sync::RwLock;
use rspack_core::{
Plugin,
PluginContext,
NormalModuleBeforeResolveArgs,
PluginNormalModuleFactoryBeforeResolveOutput,
};

#[derive(Debug)]
pub struct SpecilizeModuleNamePlugin {
// this value will auto-increase in concurrence situation
uid: RwLock<i32>,
target_module_names: Vec<String>,
}

impl SpecilizeModuleNamePlugin {
pub fn new(target_module_names: Option<Vec<String>>) -> Self {
Self {
uid: RwLock::new(0),
target_module_names: match target_module_names {
Some(value) => value,
None => vec![],
},
}
}

fn increase_uid(&self) -> i32 {
let mut cur_id = self.uid.write().unwrap();
*cur_id += 1;
*cur_id
}
}

#[async_trait::async_trait]
impl Plugin for SpecilizeModuleNamePlugin {
fn name(&self) -> &'static str {
"SpecilizeModuleNamePlugin"
}

async fn before_resolve(
&self,
_ctx: PluginContext,
_args: &mut NormalModuleBeforeResolveArgs
) -> PluginNormalModuleFactoryBeforeResolveOutput {
if self.target_module_names.is_empty() {
return Ok(None);
}
for name in &self.target_module_names {
if _args.request.contains(name) {
let uid = self.increase_uid().to_string();
_args.request.push_str("?id=");
_args.request.push_str(&uid);
break;
}
}
Ok(None)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_create_instance_without_argument() {
let specilize_module_name_plugin = SpecilizeModuleNamePlugin::new(None);

assert_eq!(*specilize_module_name_plugin.uid.read().unwrap(), 0);
assert_eq!(
specilize_module_name_plugin.target_module_names.as_slice(),
&vec![] as &[&'static str]
);
}
#[test]
fn test_create_instance_with_argument() {
let target = vec!["a".to_string(), "b".to_string()];
let specilize_module_name_plugin = SpecilizeModuleNamePlugin::new(Some(target.clone()));

assert_eq!(*specilize_module_name_plugin.uid.read().unwrap(), 0);
assert_eq!(specilize_module_name_plugin.target_module_names.as_slice(), &target);
}

#[test]
fn test_increase_uid_method() {
let specilize_module_name_plugin = SpecilizeModuleNamePlugin::new(None);
specilize_module_name_plugin.increase_uid();
let result_1 = specilize_module_name_plugin.increase_uid();
assert_eq!(result_1, 2);
assert_eq!(*specilize_module_name_plugin.uid.read().unwrap(), 2);
}

#[test]
fn test_name_method() {
let specilize_module_name_plugin = SpecilizeModuleNamePlugin::new(None);
assert_eq!(specilize_module_name_plugin.name(), "SpecilizeModuleNamePlugin");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const { add } = require("./utils");
const { add_3 } = require("./util_1");

export function cal() {
const result = add(2 + 2);
console.log("2 + 2 is %s, it is a %s number", result, isNumber(result));
}

export function cal2() {
return add_3(0);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
console.log("Hello World!");

const { cal } = require("./function")
const { add } = require("./utils");

cal();

console.log("1 + 1 is %s", add(1, 1));
console.log("The 'string' is String type is %s", isString('string'));
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
source: crates/.rspack_crates/rspack_testing/src/run_fixture.rs
assertion_line: 146
---
```js title=main.js
(self['webpackChunkwebpack'] = self['webpackChunkwebpack'] || []).push([["main"], {
"./function.js": function (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
'use strict';
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
'cal': function() { return cal; },
'cal2': function() { return cal2; }
});
const { add } = __webpack_require__(/* ./utils */"./utils.js?id=2");
const { add_3 } = __webpack_require__(/* ./util_1 */"./util_1.js");
function cal() {
const result = add(2 + 2);
console.log("2 + 2 is %s, it is a %s number", result, isNumber(result));
}
function cal2() {
return add_3(0);
}
},
"./index.js": function (__unused_webpack_module, exports, __webpack_require__) {
console.log("Hello World!");
const { cal } = __webpack_require__(/* ./function */"./function.js");
const { add } = __webpack_require__(/* ./utils */"./utils.js?id=1");
cal();
console.log("1 + 1 is %s", add(1, 1));
console.log("The 'string' is String type is %s", isString('string'));
},
"./util_1.js": function (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
'use strict';
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
'add_3': function() { return add_3; }
});
function add_3(a) {
return a + 3;
}
},
"./utils.js?id=1": function (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
'use strict';
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
'add': function() { return add; },
'add_3_plus_1': function() { return add_3_plus_1; }
});
const { add_3 } = __webpack_require__(/* ./util_1 */"./util_1.js");
function add(x, y) {
return x + y;
}
function add_3_plus_1(x) {
return add_3(x) + 1;
}
},
"./utils.js?id=2": function (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
'use strict';
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
'add': function() { return add; },
'add_3_plus_1': function() { return add_3_plus_1; }
});
const { add_3 } = __webpack_require__(/* ./util_1 */"./util_1.js");
function add(x, y) {
return x + y;
}
function add_3_plus_1(x) {
return add_3(x) + 1;
}
},
},function(__webpack_require__) {
var __webpack_exec__ = function(moduleId) { return __webpack_require__(__webpack_require__.s = moduleId) }
var __webpack_exports__ = (__webpack_exec__("./index.js"));
}
]);
```
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function add_3(a) {
return a + 3;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const { add_3 } = require("./util_1");

export function add(x, y) {
return x + y;
}

export function add_3_plus_1(x) {
return add_3(x) + 1;
}
24 changes: 24 additions & 0 deletions crates/plugin_specilize_module_name/tests/plugin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use std::fs;
use std::process::Command;
use std::path::PathBuf;
use rspack_testing::{ fixture, test_fixture_insta };
use plugin_specilize_module_name::SpecilizeModuleNamePlugin;

#[fixture("tests/fixtures/basic")]
fn test_rspack_hook_invoke(fixture_path: PathBuf) {
test_fixture_insta(
&fixture_path,
&(|filename| filename == "main.js"),
Box::new(|plugins, _| {
plugins.push(Box::new(SpecilizeModuleNamePlugin::new(Some(vec!["utils".to_string()]))))
})
);

let target_asset_path = fixture_path.join("./dist/main.js");

assert!(target_asset_path.exists());

let file_contents = fs::read_to_string(target_asset_path).expect("Failed to read file");

assert!(file_contents.contains("utils.js?id="));
}

0 comments on commit 133a9f3

Please sign in to comment.