Giter Site home page Giter Site logo

panoptix-za / web-bundler Goto Github PK

View Code? Open in Web Editor NEW
11.0 9.0 3.0 54 KB

Bundles a Rust WebAssembly frontend application for publishing

License: Apache License 2.0

Rust 95.69% SCSS 1.45% HTML 2.85%
seed cargo rust build-script frontend web wasm wasm-pack

web-bundler's Introduction

Web Bundler

crates.io status-badge

Manages the building of WebAssembly single page app frontends from a build.rs script so that they can easily be embedded into Rust API projects.

Internally, the bundler uses wasm-pack to do the actual webassembly compilation.

Prerequisites

From a clean Rustup-based Rust installation, there are no additional steps. Web Bundler will download and install any dependencies it needs.

For Rust installations that are not done with Rustup, you will need to add the wasm32-unknown-unknown compilation target manually (see the wasm-pack docs for details on how to do this).

Running the Demo Example

There is an example usage in the example directory. To run the example, open a terminal in the example directory and run cargo run. Then, open a web browser and navigate to http://localhost:3030/. You should see a Seed web application.

Usage

Web-bundler expects you to have two projects: a frontend project using a single page app framework (like Seed), and a backend project using a web server framework (like warp). These projects should be in a common workspace.

Changes to your frontend project

  1. Update your index.html to allow templating in Javascript and CSS.

    Specifically, you need to add {{ stylesheet | safe }} to the <head> section, and {{ javascript | safe }} to the end of the <body>. Optionally, if you want to set the base url, add <base href="{{ base_url }}"> to the <head> as well.

    See the example frontend index.html.

  2. Create a root stylesheet for your app called ./css/style.scss.

    This stylesheet will be compiled to CSS, and embedded directly into your index.html file.

    See the example frontend style.scss.

  3. Put all of your static assets in the static directory

    All files in the static directory will be copied directly to a static folder in the output directory.

    See the example frontend static directory.

Changes to your API project

  1. Update your Cargo.toml to depend on your frontend project and web-bundler

    We depend on the frontend project in Cargo.toml so that Cargo knows to rerun build.rs whenever the frontend project changes.

    See the example backend Cargo.toml.

  2. Add a build.rs script that calls web-bundler for your frontend

    See the example backend build.rs.

  3. Use Rust Embed to embed your built frontend into your API binary

    See the example backend main.rs. Our example uses the warp web server. Rust Embed also has examples for other web servers in their repo.

target and web-target directories

When web-bundler compiles the frontend, it overrides the default target directory to be web-target instead of target. This is done because, if the backend and frontend are in the same workspace, Cargo will already be locking target while running the build.rs script.

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

web-bundler's People

Contributors

dependabot[bot] avatar edmellum avatar jworthe avatar tshepang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

web-bundler's Issues

Support hooks for loading indicators and error handling in the generated javascript and html

This is difficult to figure out how best to support from a web-bundler perspective.

In my index.html, I've started including the following. In this case, when the webassembly is loaded, Seed will take over the 'app' div.

<body>
    <div id="app"">
        <main>
            <nav>
                <!-- just the static branding part of the navbar. -->
            </nav>
            <div class="container" id="loading-content">
                <noscript>
                    <h1>Error: Your Browser Does Not Support JavaScript</h1>
                    <p class="text-danger">This application requires JavaScript. Please use a web browser that has JavaScript enabled.</p>
                </noscript>
            </div>
        </main>
        <footer>ยฉ Panoptix 2021</footer>
    </div>
    <script>
        if (!window.WebAssembly) {
            document.getElementById('loading-content').innerHTML = '<h1>Error: Your Browser Does Not Support WebAssembly</h1><p class="text-danger">This application requires a modern web browser which supports WebAssembly. Please upgrade your web browser to use this application.</p>';
        } else {
            document.getElementById('loading-content').innerHTML = '<h1>Loading</h1><div class="spinner-border" role="status"><span class="sr-only">Loading...</span></div>';
        }
    </script>
            
    {{ javascript | safe }}
</body>

The important parts here:

  • The high level static layout of my page is there right from the beginning.
  • If the browser doesn't support JavaScript, it tells you about it (with the noscript tag).
  • If your browser does support JavaScript, but not WebAssembly, we put a warning about it.
  • If the browser supports all the things, show a loading indicator.

Something that's missing here is that there isn't any error handling if the .wasm file fails to load, since web-bundler doesn't expose the wasm fetching code generated by wasm-pack.

I think each site might do different things with these, but I think the list of error events is the same for all sites. It would be nice if web-bundler exposed them in some unified way.

Can't compile bevy

Compiling bevy for the web fails, but works using wasm-pack, unless CARGO_TARGET_DIR is set to web-target. I've made a minimal example. Seems like something about the target dir causes certain builds to fail, but I haven't been able to figure it out yet.

The error messages are a bunch of messages like this:

  error[E0433]: failed to resolve: use of undeclared crate or module `imp`
    --> /Users/username/.cargo/registry/src/github.com-1ecc6299db9ec823/libloading-0.6.7/src/lib.rs:66:20
     |
  66 | pub struct Library(imp::Library);
     |                    ^^^ use of undeclared crate or module `imp`

Print the frontend's files and dependencies for cargo to know when to rebuild

Currently, to get Cargo to retrigger when the frontend is changed, we recommend adding the frontend as a build-dependency. This works, but isn't strictly correct since the build.rs script doesn't use the frontend code at all.

build.rs scripts can tell Cargo about files that should trigger rebuilds with println!("cargo:rerun-if-changed={}", file);

We currently do this for the non-rust frontend code, like CSS. We should do this for all of the Rust code in the frontend, as well as the files for its dependencies (see the .d files in target/release/deps/, they seem like they probably have the info needed to do this)

Project very similar to web-bundler

Hey ๐Ÿ‘‹

I just found out your project today and I noticed it is very very close to what wasm-run does.

I created wasm-run because I needed a finer control on the index.html that is created so I can bundle the JS and the CSS together inside the index.html. I think web-bundler allows this which is great!

There aren't many differences with wasm-run:

  • The main difference is that web-bundler uses the build.rs to generate the frontend files while wasm-run uses a cargo [bin] that the user needs to put in their crate. Example here where lib.rs is meant to be the frontend compiled in wasm and main.rs is meant to be the bin that starts a standalone frontend.
  • wasm-run supports frontend-only applications and provides a small web server (tide) for that. If I'm not mistaken, I think web-bundler only supports backend+frontend scenario.
  • web-bundler uses wasm-pack which benefits from all the logic of wasm-pack. wasm-run opted for wasmbindgen-cli in hope to reduce the amount of dependencies. Because of that some features are still missing in wasm-run like the JS snippets generation. Ideally I wanted to go deeper and depends only on wasmbindgen (there isn't much to do to get the snippets working).

I'm not into re-inventing the wheel and I'm all for community effort and working on common goals so I was wondering if you think we could combine our projects? Take the best ideas of both worlds and cover all the use cases. I'm not sure yet how that will translate but let me know your opinions.

(There is also the project substrate-wasm-builder that also uses the build.rs to build the WASM but it's more focused on the WASM itself.)

Best

cc @fstephany @yozhgoor

Does not work with latest version of wasm-bindgen

web-bundler inlines the javascript generated by wasm-bindgen and calls its init function.

https://github.com/panoptix-za/web-bundler/blob/main/src/lib.rs#L278C19-L278C19

    let javascript = format!(
        r#"<script type="module">{} init('{}'); </script>"#,
        package_js_content,
        wasm_path.display()
    );

Unfortunately it looks like in wasm-bindgen 0.2.85 it no longer generates a function named init.

Both before and after, the init function is exported as the default export of the javascript module that wasm-bindgen generates, so web-bunder should use that instead.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.