#web #assets

webpacker

A Rust wrapper for using Webpacker to manage assets

11 releases

Uses old Rust 2015

0.3.4 Jan 18, 2021
0.3.3 Nov 22, 2018
0.2.0 Nov 16, 2018
0.1.4 Nov 16, 2018

#143 in Build Utils

LGPL-3.0

9KB
107 lines

Webpacker-rs

Webpacker-rs is a Rust wrapper for using WebpackerCli/Webpacker/Webpack in your Rust web framework's deployment and asset management.

Usage

Add the following to your Cargo.toml

[dependencies]
webpacker = "~0.3"

[build-dependencies]
webpacker = "~0.3"

Before you can build you need to initialize the webpacker environment with:

gem install webpacker_cli
webpacker-cli init

Now your build script will be able to compile. In your build script you can do the following:

use webpacker;
fn main() {
    // Validating dependencies…
    assert!(webpacker::valid_project_dir());

    // Compiling assets…
    let _ = webpacker::compile();
}

And then in your application during web start up you can generate a hash of the file manifest with:

use webpacker;

// Returns `Manifest` object which is an
// immutable Hashmap
webpacker::manifest()

You can use the Manifest object in your routing tables.

Gotham

In Gotham one way you can use the manifest for the router as follows:

pub fn router() -> Router {
    build_simple_router(|route| {
        for (key, value) in webpacker::manifest(None).unwrap() {
            route
                .get(&format!("public/{}", key))
                .to_file(format!("public{}", value));
        }
    })
}

And in each of your webpages you link to your assets as though they were in the public/ folder. This will map the normal file names like application.js to their hashed version /packs/application-285f2db5acb1800187f0.js. I'm not sure having the router do this lets the cache invalidation work as intended.

The recommended way to use this is to have a helper method write the mapped file name right to the generated webpage HTML source. So if you're using tera then you could do something like:

pub static ASSET_DIRECTORY: &'static str = "public";

lazy_static! {
    pub static ref MANIFEST: Manifest = webpacker::manifest(None).unwrap();
}

mod assets {
    use super::{ASSET_DIRECTORY, MANIFEST};
    use webpacker::asset_path::AssetPath;
    use std::ops::Deref;

    pub fn source(key: &str) -> String {
        AssetPath::new(ASSET_DIRECTORY, key, MANIFEST.deref()).into()
    }
}

pub fn index_page(state: State) -> (State, (mime::Mime, String)) {
    let mut context = Context::new();
    context.insert("application_source", &assets::source("application.js"));

    let rendered = TERA.render("landing_page/index.html.tera", &context).unwrap();

    (state, (mime::TEXT_HTML, rendered))
}
<script src="{{ application_source }}"></script>

Doing this preferred way means you should have the folder /public/* routed with something like this:

pub fn router() -> Router {
    build_simple_router(|route| {
        route.get("public/*").to_dir(
            FileOptions::new("public")
                .with_cache_control("no-cache")
                .with_gzip(true)
                .build(),
        );
    })  
}

FileOptions here provides Async file support.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/danielpclark/webpacker-cli

License

The gem is available as open source under the terms of the GNU Lesser General Public License version 3.

Dependencies

~1MB
~25K SLoC