Skip to content

Commit 1180254

Browse files
Expand plugin traits and plugin config (#9744)
* Expand plugin traits and plugin config * Use trait objects * Use Rc
1 parent 0b58e51 commit 1180254

18 files changed

+992
-19
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/parcel_core/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ description = "Core logic for the parcel bundler"
88
default = []
99

1010
[dependencies]
11+
parcel_filesystem = { path = "../parcel_filesystem" }
1112
parcel-resolver = { path = "../../packages/utils/node-resolver-rs" }
1213

1314
ahash = "0.8.11"
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub struct BundleGraph {}

crates/parcel_core/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![deny(unused_crate_dependencies)]
22
//! Core re-implementation in Rust
33
4+
pub mod bundle_graph;
45
pub mod hash;
56
pub mod plugin;
67
pub mod request_tracker;

crates/parcel_core/src/plugin.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
mod bundler;
2+
23
pub use bundler::*;
34

45
mod compressor;
@@ -13,6 +14,9 @@ pub use optimizer::*;
1314
mod packager;
1415
pub use packager::*;
1516

17+
mod plugin_config;
18+
pub use plugin_config::*;
19+
1620
mod reporter;
1721
pub use reporter::*;
1822

@@ -28,11 +32,14 @@ pub use transformer::*;
2832
mod validator;
2933
pub use validator::*;
3034

35+
#[derive(Default)]
3136
pub struct PluginContext {
3237
pub options: PluginOptions,
3338
pub logger: PluginLogger,
3439
}
3540

41+
#[derive(Default)]
3642
pub struct PluginLogger {}
3743

44+
#[derive(Default)]
3845
pub struct PluginOptions {}
+42-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,49 @@
1+
use super::PluginConfig;
2+
use crate::bundle_graph::BundleGraph;
3+
14
/// Converts an asset graph into a BundleGraph
25
///
36
/// Bundlers accept the entire asset graph and modify it to add bundle nodes that group the assets
47
/// into output bundles.
58
///
69
/// Bundle and optimize run in series and are functionally identitical.
710
///
8-
pub trait BundlerPlugin {}
11+
pub trait BundlerPlugin {
12+
/// A hook designed to load config necessary for the bundler to operate
13+
///
14+
/// This function will run once, shortly after the plugin is initialised.
15+
///
16+
fn load_config(&mut self, config: &PluginConfig) -> Result<(), anyhow::Error>;
17+
18+
// TODO: Should BundleGraph be AssetGraph or something that contains AssetGraph in the name?
19+
fn bundle(&self, bundle_graph: &mut BundleGraph) -> Result<(), anyhow::Error>;
20+
21+
fn optimize(&self, bundle_graph: &mut BundleGraph) -> Result<(), anyhow::Error>;
22+
}
23+
24+
#[cfg(test)]
25+
mod tests {
26+
use super::*;
27+
28+
#[derive(Debug)]
29+
struct TestBundlerPlugin {}
30+
31+
impl BundlerPlugin for TestBundlerPlugin {
32+
fn load_config(&mut self, _config: &PluginConfig) -> Result<(), anyhow::Error> {
33+
todo!()
34+
}
35+
36+
fn bundle(&self, _bundle_graph: &mut BundleGraph) -> Result<(), anyhow::Error> {
37+
todo!()
38+
}
39+
40+
fn optimize(&self, _bundle_graph: &mut BundleGraph) -> Result<(), anyhow::Error> {
41+
todo!()
42+
}
43+
}
44+
45+
#[test]
46+
fn can_be_dyn() {
47+
let _bundler: Box<dyn BundlerPlugin> = Box::new(TestBundlerPlugin {});
48+
}
49+
}
+43-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,44 @@
1+
use std::fs::File;
2+
3+
pub struct CompressedFile {
4+
/// An optional file extension appended to the output file
5+
///
6+
/// When no extension is returned, then the returned stream replaces the original file.
7+
///
8+
pub extension: Option<String>,
9+
10+
/// The compressed file
11+
pub file: File,
12+
}
13+
114
/// Compresses the input file stream
2-
pub trait CompressorPlugin {}
15+
pub trait CompressorPlugin {
16+
/// Compress the given file
17+
///
18+
/// The file contains the final contents of bundles and sourcemaps as they are being written.
19+
/// A new stream can be returned, or None to forward compression onto the next plugin.
20+
///
21+
fn compress(&self, file: &File) -> Result<Option<CompressedFile>, String>;
22+
}
23+
24+
#[cfg(test)]
25+
mod tests {
26+
use super::*;
27+
28+
struct TestCompressorPlugin {}
29+
30+
impl CompressorPlugin for TestCompressorPlugin {
31+
fn compress(&self, _file: &File) -> Result<Option<CompressedFile>, String> {
32+
todo!()
33+
}
34+
}
35+
36+
#[test]
37+
fn can_be_defined_in_dyn_vec() {
38+
let mut compressors = Vec::<Box<dyn CompressorPlugin>>::new();
39+
40+
compressors.push(Box::new(TestCompressorPlugin {}));
41+
42+
assert_eq!(compressors.len(), 1);
43+
}
44+
}
+56-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,60 @@
1+
use std::path::PathBuf;
2+
3+
use super::PluginConfig;
4+
use crate::bundle_graph::BundleGraph;
5+
use crate::types::Bundle;
6+
17
/// Determines the output filename for a bundle
28
///
39
/// Namers run in a pipeline until one returns a result.
410
///
5-
pub trait NamerPlugin {}
11+
pub trait NamerPlugin {
12+
/// A hook designed to setup config needed for naming bundles
13+
///
14+
/// This function will run once, shortly after the plugin is initialised.
15+
///
16+
fn load_config(&mut self, config: &PluginConfig) -> Result<(), anyhow::Error>;
17+
18+
/// Names the given bundle
19+
///
20+
/// The returned file path should be relative to the target dist directory, and will be used to
21+
/// name the bundle. Naming can be forwarded onto the next plugin by returning None.
22+
///
23+
fn name(
24+
&mut self,
25+
config: &PluginConfig,
26+
bundle: &Bundle,
27+
bundle_graph: &BundleGraph,
28+
) -> Result<Option<PathBuf>, anyhow::Error>;
29+
}
30+
31+
#[cfg(test)]
32+
mod tests {
33+
use super::*;
34+
35+
struct TestNamerPlugin {}
36+
37+
impl NamerPlugin for TestNamerPlugin {
38+
fn load_config(&mut self, _config: &PluginConfig) -> Result<(), anyhow::Error> {
39+
todo!()
40+
}
41+
42+
fn name(
43+
&mut self,
44+
_config: &PluginConfig,
45+
_bundle: &Bundle,
46+
_bundle_graph: &BundleGraph,
47+
) -> Result<Option<PathBuf>, anyhow::Error> {
48+
todo!()
49+
}
50+
}
51+
52+
#[test]
53+
fn can_be_defined_in_dyn_vec() {
54+
let mut namers = Vec::<Box<dyn NamerPlugin>>::new();
55+
56+
namers.push(Box::new(TestNamerPlugin {}));
57+
58+
assert_eq!(namers.len(), 1);
59+
}
60+
}

crates/parcel_core/src/plugin/optimizer.rs

+64-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,23 @@
1+
use std::fs::File;
2+
3+
use super::PluginConfig;
4+
use crate::bundle_graph::BundleGraph;
5+
use crate::types::Bundle;
6+
use crate::types::SourceMap;
7+
8+
pub struct OptimizeContext<'a> {
9+
pub bundle: &'a Bundle,
10+
pub bundle_graph: &'a BundleGraph,
11+
pub contents: &'a File, // TODO We may want this to be a String or File later
12+
pub map: Option<&'a SourceMap>,
13+
// TODO getSourceMapReference?
14+
}
15+
16+
pub struct OptimizedBundle {
17+
pub contents: File,
18+
// TODO ast, map, type
19+
}
20+
121
/// Optimises a bundle
222
///
323
/// Optimizers are commonly used to implement minification, tree shaking, dead code elimination,
@@ -8,4 +28,47 @@
828
/// Multiple optimizer plugins may run in series, and the result of each optimizer is passed to
929
/// the next.
1030
///
11-
pub trait OptimizerPlugin: Send + Sync {}
31+
pub trait OptimizerPlugin: Send + Sync {
32+
/// A hook designed to setup config needed for optimizing bundles
33+
///
34+
/// This function will run once, shortly after the plugin is initialised.
35+
///
36+
fn load_config(&mut self, config: &PluginConfig) -> Result<(), anyhow::Error>;
37+
38+
/// Transforms the contents of a bundle and its source map
39+
fn optimize(
40+
&mut self,
41+
config: &PluginConfig,
42+
ctx: OptimizeContext,
43+
) -> Result<OptimizedBundle, anyhow::Error>;
44+
}
45+
46+
#[cfg(test)]
47+
mod tests {
48+
use super::*;
49+
50+
struct TestOptimizerPlugin {}
51+
52+
impl OptimizerPlugin for TestOptimizerPlugin {
53+
fn load_config(&mut self, _config: &PluginConfig) -> Result<(), anyhow::Error> {
54+
todo!()
55+
}
56+
57+
fn optimize(
58+
&mut self,
59+
_config: &PluginConfig,
60+
_ctx: OptimizeContext,
61+
) -> Result<OptimizedBundle, anyhow::Error> {
62+
todo!()
63+
}
64+
}
65+
66+
#[test]
67+
fn can_be_defined_in_dyn_vec() {
68+
let mut optimizers = Vec::<Box<dyn OptimizerPlugin>>::new();
69+
70+
optimizers.push(Box::new(TestOptimizerPlugin {}));
71+
72+
assert_eq!(optimizers.len(), 1);
73+
}
74+
}
+60-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,65 @@
1+
use std::fs::File;
2+
3+
use super::PluginConfig;
4+
use crate::bundle_graph::BundleGraph;
5+
use crate::types::Bundle;
6+
use crate::types::SourceMap;
7+
8+
pub struct PackageContext<'a> {
9+
pub bundle: &'a Bundle,
10+
pub bundle_graph: &'a BundleGraph,
11+
pub contents: &'a File, // TODO We may want this to be a String or File later
12+
pub map: Option<&'a SourceMap>,
13+
// TODO getSourceMapReference?
14+
}
15+
16+
pub struct PackagedBundle {
17+
pub contents: File,
18+
// TODO ast, map, type
19+
}
20+
121
/// Combines all the assets in a bundle together into an output file
222
///
323
/// Packagers are also responsible for resolving URL references, bundle inlining, and generating
424
/// source maps.
525
///
6-
pub trait PackagerPlugin: Send + Sync {}
26+
pub trait PackagerPlugin: Send + Sync {
27+
/// A hook designed to setup config needed for packaging
28+
///
29+
/// This function will run once, shortly after the plugin is initialised.
30+
///
31+
fn load_config(&mut self, config: &PluginConfig) -> Result<(), anyhow::Error>;
32+
33+
/// Combines assets in a bundle
34+
fn package(
35+
&mut self,
36+
config: &PluginConfig,
37+
ctx: PackageContext,
38+
) -> Result<PackagedBundle, anyhow::Error>;
39+
}
40+
41+
#[cfg(test)]
42+
mod tests {
43+
use super::*;
44+
45+
struct TestPackagerPlugin {}
46+
47+
impl PackagerPlugin for TestPackagerPlugin {
48+
fn load_config(&mut self, _config: &PluginConfig) -> Result<(), anyhow::Error> {
49+
todo!()
50+
}
51+
52+
fn package(
53+
&mut self,
54+
_config: &PluginConfig,
55+
_ctx: PackageContext,
56+
) -> Result<PackagedBundle, anyhow::Error> {
57+
todo!()
58+
}
59+
}
60+
61+
#[test]
62+
fn can_be_dyn() {
63+
let _packager: Box<dyn PackagerPlugin> = Box::new(TestPackagerPlugin {});
64+
}
65+
}

0 commit comments

Comments
 (0)