From da03037ca469e607dde41c577c670f2469373e39 Mon Sep 17 00:00:00 2001 From: neon_arch Date: Mon, 30 Oct 2023 19:16:43 +0300 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20perf:=20add=20code=20minif?= =?UTF-8?q?y=20`js`=20and=20`css`=20during=20the=20initial=20build=20proce?= =?UTF-8?q?ss=20when=20the=20`pkg=5Fenv`=20enviroment=20variable=20is=20se?= =?UTF-8?q?t=20to=20`prod`=20(#359)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.rs | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 build.rs diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..26ff500 --- /dev/null +++ b/build.rs @@ -0,0 +1,80 @@ +//! A build module of the application which minifies the project's css and js files on build which +//! helps reduce the initial page by loading the files faster. + +#![forbid(unsafe_code, clippy::panic)] +#![deny(missing_docs, clippy::missing_docs_in_private_items, clippy::perf)] +#![warn(clippy::cognitive_complexity, rust_2018_idioms)] + +// ------- Imports ------- +use lightningcss::stylesheet::{MinifyOptions, ParserOptions, PrinterOptions, StyleSheet}; +use minify_js::{minify, Session, TopLevelMode}; +use std::{ + fs::{read_dir, read_to_string, File, OpenOptions}, + io::{Read, Write}, +}; + +// ------- Constants ------- +const COMMON_STATIC_SOURCE_CODE_FOLDER: &str = "./public/static/"; +const STYLE_FOLDERS: [&str; 2] = ["themes", "colorschemes"]; +const PACKAGE_ENVIRONMENT_VARIABLE: &str = "PKG_ENV"; +const PRODUCTION_PKG_ENV_VARIABLE_VALUE: &str = "prod"; + +/// A main function which minifies both css and js files using `lightningcss` and `minify_js` when +/// the `PKG_ENV` environment and it is set to the value of `prod`. +/// +/// # Error +/// +/// This function returns the unit type when the minification process runs successfully otherwise +/// it returns a standard error. +fn main() -> Result<(), Box> { + if let Ok(pkg_env_var) = std::env::var(PACKAGE_ENVIRONMENT_VARIABLE) { + if pkg_env_var.to_lowercase() == PRODUCTION_PKG_ENV_VARIABLE_VALUE { + // A for loop that loops over each file name containing in the `colorschemes` and `themes` folders + // and minifies it using the `lightningcss` minifier. + for folder_name in STYLE_FOLDERS { + for file in read_dir(format!("{COMMON_STATIC_SOURCE_CODE_FOLDER}{folder_name}/"))? { + let file_path = file?.path(); + let source = read_to_string(file_path.clone())?; + + let mut stylesheet = StyleSheet::parse(&source, ParserOptions::default()) + .map_err(|err| format!("{err}\n{:?}", file_path.file_name().unwrap()))?; + + stylesheet.minify(MinifyOptions::default())?; + let minified_css = stylesheet.to_css(PrinterOptions::default())?; + + let mut old_css_file = OpenOptions::new() + .write(true) + .truncate(true) + .open(file_path)?; + old_css_file.write_all(minified_css.code.as_bytes())?; + old_css_file.flush()?; + } + } + + // A for loop that loops over each file name containing in the `public/static` folder and minifies + // it using the `minify-js` minifier. + for file in read_dir(COMMON_STATIC_SOURCE_CODE_FOLDER)? { + let file_path = file?.path(); + if file_path.is_file() { + let mut code = Vec::new(); + let mut js_file = File::open(file_path.clone())?; + js_file.read_to_end(&mut code)?; + + drop(js_file); + + let mut out = Vec::new(); + minify(&Session::new(), TopLevelMode::Global, &code, &mut out) + .map_err(|err| format!("{err}\n{:?}", file_path.file_name().unwrap()))?; + + let mut old_js_file = OpenOptions::new() + .write(true) + .truncate(true) + .open(file_path)?; + old_js_file.write_all(&out)?; + old_js_file.flush()?; + } + } + } + } + Ok(()) +}