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: Optional Optimization #66

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cli-support/examples/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ fn link() {
let _ = std::fs::remove_dir_all(&assets_dir);

// And copy the static assets to the public directory
assets.copy_static_assets_to(&assets_dir).unwrap();
assets.copy_static_assets_to(&assets_dir, true).unwrap();

// Then collect the tailwind CSS
let css = assets.collect_tailwind_css(true, &mut Vec::new());
Expand Down
90 changes: 69 additions & 21 deletions cli-support/src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use manganis_common::{
JsonOptions,
};
use std::{
fs,
io::{BufWriter, Write},
path::Path,
sync::Arc,
Expand All @@ -15,19 +16,33 @@ use swc_common::{sync::Lrc, FileName};
use swc_common::{SourceMap, GLOBALS};

pub trait Process {
fn process(&self, source: &AssetSource, output_path: &Path) -> anyhow::Result<()>;
fn process(
&self,
source: &AssetSource,
output_path: &Path,
should_opt: bool,
) -> anyhow::Result<()>;
}

/// Process a specific file asset
pub fn process_file(file: &FileAsset, output_folder: &Path) -> anyhow::Result<()> {
/// Process a specific file asset, specifying the output folder and if the file should be optimized.
pub fn process_file(
file: &FileAsset,
output_folder: &Path,
should_opt: bool,
) -> anyhow::Result<()> {
let location = file.location();
let source = location.source();
let output_path = output_folder.join(location.unique_name());
file.options().process(source, &output_path)
file.options().process(source, &output_path, should_opt)
}

impl Process for FileOptions {
fn process(&self, source: &AssetSource, output_path: &Path) -> anyhow::Result<()> {
fn process(
&self,
source: &AssetSource,
output_path: &Path,
should_opt: bool,
) -> anyhow::Result<()> {
if output_path.exists() {
return Ok(());
}
Expand All @@ -42,16 +57,16 @@ impl Process for FileOptions {
})?;
}
Self::Css(options) => {
options.process(source, output_path)?;
options.process(source, output_path, should_opt)?;
}
Self::Js(options) => {
options.process(source, output_path)?;
options.process(source, output_path, should_opt)?;
}
Self::Json(options) => {
options.process(source, output_path)?;
options.process(source, output_path, should_opt)?;
}
Self::Image(options) => {
options.process(source, output_path)?;
options.process(source, output_path, should_opt)?;
}
_ => todo!(),
}
Expand All @@ -61,7 +76,18 @@ impl Process for FileOptions {
}

impl Process for ImageOptions {
fn process(&self, source: &AssetSource, output_path: &Path) -> anyhow::Result<()> {
fn process(
&self,
source: &AssetSource,
output_path: &Path,
should_opt: bool,
) -> anyhow::Result<()> {
if !should_opt {
if let Some(path) = source.as_path() {
fs::copy(path, output_path)?;
return Ok(());
}
}
let mut image = image::ImageReader::new(std::io::Cursor::new(&*source.read_to_bytes()?))
.with_guessed_format()?
.decode()?;
Expand Down Expand Up @@ -161,10 +187,19 @@ fn compress_png(image: DynamicImage, output_location: &Path) {
}

impl Process for CssOptions {
fn process(&self, source: &AssetSource, output_path: &Path) -> anyhow::Result<()> {
fn process(
&self,
source: &AssetSource,
output_path: &Path,
should_opt: bool,
) -> anyhow::Result<()> {
let css = source.read_to_string()?;

let css = if self.minify() { minify_css(&css) } else { css };
let css = if self.minify() && should_opt {
minify_css(&css)
} else {
css
};

std::fs::write(output_path, css).with_context(|| {
format!(
Expand Down Expand Up @@ -226,8 +261,13 @@ pub(crate) fn minify_js(source: &AssetSource) -> anyhow::Result<String> {
}

impl Process for JsOptions {
fn process(&self, source: &AssetSource, output_path: &Path) -> anyhow::Result<()> {
let js = if self.minify() {
fn process(
&self,
source: &AssetSource,
output_path: &Path,
should_opt: bool,
) -> anyhow::Result<()> {
let js = if self.minify() && should_opt {
minify_js(source)?
} else {
source.read_to_string()?
Expand All @@ -253,14 +293,22 @@ pub(crate) fn minify_json(source: &str) -> anyhow::Result<String> {
}

impl Process for JsonOptions {
fn process(&self, source: &AssetSource, output_path: &Path) -> anyhow::Result<()> {
fn process(
&self,
source: &AssetSource,
output_path: &Path,
should_opt: bool,
) -> anyhow::Result<()> {
let source = source.read_to_string()?;
let json = match minify_json(&source) {
Ok(json) => json,
Err(err) => {
tracing::error!("Failed to minify json: {}", err);
source
}
let json = match should_opt {
false => source,
true => match minify_json(&source) {
Ok(json) => json,
Err(err) => {
tracing::error!("Failed to minify json: {}", err);
source
}
},
};

std::fs::write(output_path, json).with_context(|| {
Expand Down
2 changes: 1 addition & 1 deletion cli-support/src/folder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,6 @@ fn process_file_minimal(input_path: &Path, output_path: &Path) -> anyhow::Result
let options =
FileOptions::default_for_extension(input_path.extension().and_then(|e| e.to_str()));
let source = manganis_common::AssetSource::Local(input_path.to_path_buf());
options.process(&source, output_path)?;
options.process(&source, output_path, true)?;
Ok(())
}
16 changes: 12 additions & 4 deletions cli-support/src/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,12 @@ pub trait AssetManifestExt {
///
/// The asset descriptions are stored inside a manifest file that is produced when the linker is intercepted.
fn load_from_objects(object_paths: Vec<PathBuf>) -> Self;
/// Optimize and copy all assets in the manifest to a folder
fn copy_static_assets_to(&self, location: impl Into<PathBuf>) -> anyhow::Result<()>;
/// Copy all assets in the manifest to a folder with the option to optimize.
fn copy_static_assets_to(
&self,
location: impl Into<PathBuf>,
should_opt: bool,
) -> anyhow::Result<()>;
/// Collect all tailwind classes and generate string with the output css
fn collect_tailwind_css(
&self,
Expand Down Expand Up @@ -76,7 +80,11 @@ impl AssetManifestExt for AssetManifest {
Self::load(json)
}

fn copy_static_assets_to(&self, location: impl Into<PathBuf>) -> anyhow::Result<()> {
fn copy_static_assets_to(
&self,
location: impl Into<PathBuf>,
should_opt: bool,
) -> anyhow::Result<()> {
let location = location.into();
match std::fs::create_dir_all(&location) {
Ok(_) => {}
Expand All @@ -91,7 +99,7 @@ impl AssetManifestExt for AssetManifest {
AssetType::File(file_asset) => {
tracing::info!("Optimizing and bundling {}", file_asset);
tracing::trace!("Copying asset from {:?} to {:?}", file_asset, location);
match process_file(file_asset, &location) {
match process_file(file_asset, &location, should_opt) {
Ok(_) => {}
Err(err) => {
tracing::error!("Failed to copy static asset: {}", err);
Expand Down
2 changes: 1 addition & 1 deletion cli-support/tests/collects_assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ fn link() {

// Then copy the assets to a temporary directory and run the application
let assets_dir = PathBuf::from("./assets");
assets.copy_static_assets_to(assets_dir).unwrap();
assets.copy_static_assets_to(assets_dir, true).unwrap();

// Then run the application
let status = Command::new("cargo")
Expand Down
2 changes: 1 addition & 1 deletion macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ pub(crate) fn url_encoded_asset(
format!("Failed to create output folder: {}", e),
)
})?;
manganis_cli_support::process_file(file_asset, &output_folder).map_err(|e| {
manganis_cli_support::process_file(file_asset, &output_folder, true).map_err(|e| {
syn::Error::new(
proc_macro2::Span::call_site(),
format!("Failed to process file: {}", e),
Expand Down
2 changes: 2 additions & 0 deletions test-package/test-package-nested-dependency/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![allow(unused)]

mod file;
pub use file::*;
mod font;
Expand Down