-
Notifications
You must be signed in to change notification settings - Fork 258
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
Trunk lib: Bundle & hash images/other resources referenced in Rust WASM source code #9
Comments
I would love to see something like this supported by Trunk. One way it could be achieved would be by having Trunk do a pre-build compile step, which only exists to create access to a dynamically linked function I started something similar to this on an old Yew branch that was abandoned. https://github.com/yewstack/yew/pull/1419/files#diff-f7645ea6b210138a842badb6858a7f96809d3f7ae896312a10f4f74e62aeea49R4 |
One way to do this I think is via Say we have an images folder and we add a gif.
Stage 1 Trunk copies the file to the dist folder and adds the hash.
Stage 2 When the image is added or changes in the images folder, pub struct Images {
pub get_never_gonna_give_you_up_gif() -> String {
String::from("never-gonna-give-you-up-a23f4576.gif")
}
} And in my code I do something like html! {
<img src=Images::get_never_gonna_give_you_up_gif() />
} The image will bust the cache on change. Also with this pattern if I remove an image or change the name the compiler will let me know. |
I just came up with a barebones implementation. For now, it has nothing to do with Trunk, but I would love to work on this (should I wait for #207?). Here's what it does: First, the user is supposed to configure the build.rs: use preprocess_hash::ConfigHashPreprocessorExt;
fn main() {
preprocess::configure()
.hash() // adds hash to file name
.run();
} Then, the build script processes files in the assets folder (src/assets by default) and writes the results to the dist folder (dist by default). The following code will be generated: pub const NEVER_GONNA_GIVE_YOU_UP_GIF: &str = "/never_gonna_give_you_up.e55dbac5.gif"; But in order to actually use it, the user has to manually include it: mod assets {
include!(concat!(env!("OUT_DIR"), "/assets.rs"));
}
#[function_component(App)]
fn app() -> Html {
html! {
<img alt="" src={assets::NEVER_GONNA_GIVE_YOU_UP_GIF}/>
}
} This is all good until it comes to using Trunk. The user runs [[hooks]]
stage = "post_build"
command = "sh"
command_arguments = ["-c", "cp -r ./dist/* $TRUNK_STAGING_DIR"] |
Hi the approach use by ructe https://github.com/kaj/ructe wouldn't require the hook step. They don't transform the files they just use the files to calculate a hash. So for example
So in your code you call #[function_component(App)]
fn app() -> Html {
html! {
<img alt="" src={never_gonna_give_you_up_gif.name}/> // <-- src="never_gonna_give_you_up-1234545.gif"
}
}
Then on the server you have another helper that converts hashed names back to the original file name. In Axum it looks like the following async fn static_path(Path(path): Path<String>) -> impl IntoResponse {
let path = path.trim_start_matches('/');
if let Some(data) = StaticFile::get(path) {
Response::builder()
.status(StatusCode::OK)
.header(
header::CONTENT_TYPE,
HeaderValue::from_str(data.mime.as_ref()).unwrap(),
)
.body(body::boxed(Body::from(data.content)))
.unwrap()
} else {
Response::builder()
.status(StatusCode::NOT_FOUND)
.body(body::boxed(Empty::new()))
.unwrap()
}
} Notice the |
The issue is not about just hashing. An average app will also need compression, minification, compilation (e.g. sass) etc. |
In ParcelJS, the JS import system is overloaded to allow users to "import" images, css, sass and the like into their JS, and then Parcel will intercept those non-JS imports and build/bundle/hash them. It would be awesome to do something similar for trunk.
option 0
Create a compile-time macro which will take a path to a resource, maybe a few config options as well. Something like
trunk::include!("assets/my-image.png")
, ortrunk::include!("my-component.css", Opt::Hash, Opt::Compress)
.trunk::include!("src/**/*.css")
, to spawn pipelines for, and include, all css files under thesrc
dir. A similar pattern is already planned as part of Support additional asset types #3. Will probably support both.A variant of the macro will be exported, say
trunk::include_ref!(...)
, which will return a String value which will be the public url of the asset, hashed and all, once the trunk pipeline is complete. This will allow applications to include an image directly in their Rust source code and have a correct ref to the asset after hashing and all.considerations
cargo build
is executed outside of the context of trunk./<asset>
or/static/<asset>
&c)./
as the base path of the asset, but users will be able to set an env var to overwrite the default. When cargo is invoked by trunk during atrunk build
(which is how all of this is intended to be used), trunk will be able to set the env var based on the value of--public-url
to coordinate the values.option n
Definitely open to other design options here. Please comment and let me know if you've got ideas you would like to share.
The text was updated successfully, but these errors were encountered: