Skip to content

Commit

Permalink
Auto merge of rust-lang#136253 - notriddle:notriddle/aot-minify, r=Gu…
Browse files Browse the repository at this point in the history
…illaumeGomez

rustdoc: run css and html minifier at build instead of runtime

This way, adding a bunch of comments to the JS files won't make rustdoc slower.

Meant to address rust-lang#136161 (comment)
  • Loading branch information
bors committed Feb 5, 2025
2 parents d4bdd1e + 68646e9 commit a9730c3
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 32 deletions.
1 change: 1 addition & 0 deletions src/librustdoc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"]

[build-dependencies]
sha2 = "0.10.8"
minifier = { version = "0.3.2", default-features = false }

[dev-dependencies]
expect-test = "1.4.0"
Expand Down
24 changes: 20 additions & 4 deletions src/librustdoc/build.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use std::str;

use sha2::Digest;
fn main() {
// generate sha256 files
// this avoids having to perform hashing at runtime
Expand Down Expand Up @@ -40,14 +43,27 @@ fn main() {
for path in files {
let inpath = format!("html/{path}");
println!("cargo::rerun-if-changed={inpath}");
let bytes = std::fs::read(inpath).expect("static path exists");
use sha2::Digest;
let bytes = sha2::Sha256::digest(bytes);
let mut digest = format!("-{bytes:x}");
let data_bytes = std::fs::read(&inpath).expect("static path exists");
let hash_bytes = sha2::Sha256::digest(&data_bytes);
let mut digest = format!("-{hash_bytes:x}");
digest.truncate(9);
let outpath = std::path::PathBuf::from(format!("{out_dir}/{path}.sha256"));
std::fs::create_dir_all(outpath.parent().expect("all file paths are in a directory"))
.expect("should be able to write to out_dir");
std::fs::write(&outpath, digest.as_bytes()).expect("write to out_dir");
let minified_path = std::path::PathBuf::from(format!("{out_dir}/{path}.min"));
if path.ends_with(".js") || path.ends_with(".css") {
let minified: String = if path.ends_with(".css") {
minifier::css::minify(str::from_utf8(&data_bytes).unwrap())
.unwrap()
.to_string()
.into()
} else {
minifier::js::minify(str::from_utf8(&data_bytes).unwrap()).to_string().into()
};
std::fs::write(&minified_path, minified.as_bytes()).expect("write to out_dir");
} else {
std::fs::copy(&inpath, &minified_path).unwrap();
}
}
}
4 changes: 2 additions & 2 deletions src/librustdoc/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ impl Options {
let to_check = matches.opt_strs("check-theme");
if !to_check.is_empty() {
let mut content =
std::str::from_utf8(static_files::STATIC_FILES.rustdoc_css.bytes).unwrap();
std::str::from_utf8(static_files::STATIC_FILES.rustdoc_css.src_bytes).unwrap();
if let Some((_, inside)) = content.split_once("/* Begin theme: light */") {
content = inside;
}
Expand Down Expand Up @@ -638,7 +638,7 @@ impl Options {
let mut themes = Vec::new();
if matches.opt_present("theme") {
let mut content =
std::str::from_utf8(static_files::STATIC_FILES.rustdoc_css.bytes).unwrap();
std::str::from_utf8(static_files::STATIC_FILES.rustdoc_css.src_bytes).unwrap();
if let Some((_, inside)) = content.split_once("/* Begin theme: light */") {
content = inside;
}
Expand Down
10 changes: 2 additions & 8 deletions src/librustdoc/html/render/write_shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,14 +207,8 @@ fn write_static_files(
if opt.emit.is_empty() || opt.emit.contains(&EmitType::Toolchain) {
static_files::for_each(|f: &static_files::StaticFile| {
let filename = static_dir.join(f.output_filename());
let contents: &[u8];
let contents_vec: Vec<u8>;
if opt.disable_minification {
contents = f.bytes;
} else {
contents_vec = f.minified();
contents = &contents_vec;
};
let contents: &[u8] =
if opt.disable_minification { f.src_bytes } else { f.minified_bytes };
fs::write(&filename, contents).map_err(|e| PathError::new(e, &filename))
})?;
}
Expand Down
28 changes: 10 additions & 18 deletions src/librustdoc/html/static_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,18 @@ use std::{fmt, str};

pub(crate) struct StaticFile {
pub(crate) filename: PathBuf,
pub(crate) bytes: &'static [u8],
pub(crate) src_bytes: &'static [u8],
pub(crate) minified_bytes: &'static [u8],
}

impl StaticFile {
fn new(filename: &str, bytes: &'static [u8], sha256: &'static str) -> StaticFile {
Self { filename: static_filename(filename, sha256), bytes }
}

pub(crate) fn minified(&self) -> Vec<u8> {
let extension = match self.filename.extension() {
Some(e) => e,
None => return self.bytes.to_owned(),
};
if extension == "css" {
minifier::css::minify(str::from_utf8(self.bytes).unwrap()).unwrap().to_string().into()
} else if extension == "js" {
minifier::js::minify(str::from_utf8(self.bytes).unwrap()).to_string().into()
} else {
self.bytes.to_owned()
}
fn new(
filename: &str,
src_bytes: &'static [u8],
minified_bytes: &'static [u8],
sha256: &'static str,
) -> StaticFile {
Self { filename: static_filename(filename, sha256), src_bytes, minified_bytes }
}

pub(crate) fn output_filename(&self) -> &Path {
Expand Down Expand Up @@ -68,7 +60,7 @@ macro_rules! static_files {

// sha256 files are generated in build.rs
pub(crate) static STATIC_FILES: std::sync::LazyLock<StaticFiles> = std::sync::LazyLock::new(|| StaticFiles {
$($field: StaticFile::new($file_path, include_bytes!($file_path), include_str!(concat!(env!("OUT_DIR"), "/", $file_path, ".sha256"))),)+
$($field: StaticFile::new($file_path, include_bytes!($file_path), include_bytes!(concat!(env!("OUT_DIR"), "/", $file_path, ".min")), include_str!(concat!(env!("OUT_DIR"), "/", $file_path, ".sha256"))),)+
});

pub(crate) fn for_each<E>(f: impl Fn(&StaticFile) -> Result<(), E>) -> Result<(), E> {
Expand Down

0 comments on commit a9730c3

Please sign in to comment.