cargo-web icon indicating copy to clipboard operation
cargo-web copied to clipboard

Allow cargo web deploy output to a custom folder

Open limira opened this issue 8 years ago • 7 comments

If I understand correctly, cargo-web deploy currently only:

  • deploy to target/deploy folder
  • hardcode .wasm file to the root of the web-url root.

By saying web-url root I mean the server app must serve the .wasm file at www.example.com/filename.wasm for the app to work properly.

What I want is to be able to serve .wasm file from a custom url such as www.example.com/javascript/filename.wasm. Also, I want cargo web deploy output files to a custom path such as ../../my-web-app/javascript that is relative to the location of Web.toml

To implement this, I think we must add an entry to Web.toml like this:

[deploy]
# not include domain name (www.example.com)
js-url = "/url/to/serve/javascript" 

# .js and .wasm will be copy to this (It is relative to Web.toml)
js-path = "../..my-web-app/javascript" 

# /static/*.* will be copy to this (if src/static/ exists)
static-path = "../../my-web-app/static" 

If this is acceptable. I will implement it. (I am very new to Rust and cargo-web, I hope you give me some instructions, for example: which file.rs(s) will be involved)

limira avatar Apr 30 '18 14:04 limira

A few general points regarding this:

  1. I don't think we need the static-path; e.g. if you want it to emit files so that they're available under https://example.com/static/ then you can just put them in src/static/static (as everything in src/static will get copied).

  2. As far as how this would look in Web.toml, something like this perhaps:

# This is the default; it specifies to which directory the files are copied when running `cargo deploy`; relative to where `Cargo.toml` is.
deploy-path = "target/deploy"

# This is under which URL the generated artifacts are served (*both* the `.js` file and the `.wasm` file). Relative to the `deploy-path` on the local filesystem, and relative to the hostname when serving through HTTP.
serve-path = "/"

[target.wasm32-unknown-unknown]
# These can also be overriden per each target.
deploy-path = "another/path"
serve-path = "yet/another/path
  1. In a nutshell - the main place where these would have to be added are in config.rs. The cmd_deploy.rs would have to be modified to deploy to correct directory, in deployment.rs we'd have to take into the account the path from which the .js and the .wasm are served, and the .js runtime generation would also have to be modified.

koute avatar Apr 30 '18 22:04 koute

With current wanted design of deploy-path and serve-path, it is not applicable for my particular case.

My project have static files that organize like this:

/ static
    /files-from-other-source/*.*          (hundreds of them, rarely change)
    /wasm-static/*.*     (other files related to .wasm project)
    /name.js
    /name.wasm
    /index.html

I want all of them to be in one directory to be easily served by one instance of StaticFile server. But if I have:

Web.toml
deploy-path = path/to/my/static
serve-path = /

Then, cargo web deploy will remove current contents of /static before copying new output to it. Then, /files-from-other-source/ must be recopied (I don't want this).

If putting all wasm related things into it own folder:

/ static
    /other-files/*
    /wasm-files
        /wasm-static/*
        /name.js
        /name.wasm
        /index.html

Web.toml

deploy-path = path/to/wasm-files
serve-path = /

Then, the .js will load .wasm file at /, but it is actually serve at /wasm-files.

So, I want to add a third parameter like this: Web.toml

# `deploy-path` is where to deploy current project.
# Content of `static/*.*` will be copied here.
# `.js` and `.wasm` files will be in this path or sub-path depend
# on value of `js-wasm-deploy-path` (see next).
deploy-path = path/to/deploy

# `js-wasm-deploy-path` (sub and relative to `deploy-path`) is where to
# output `.js` and `.wasm` files.
# Default is '/' (means the same as `deploy-path`)
#
# This apply to all command `cargo web build/deploy/start`
js-wasm-deploy-path = /

# [Optional]
# `serve-path` is the `url` that `.js` and `.wasm` are served by the server
# If omitted, its value will be the same as `js-wasm-deploy-path`
#
# This apply to all command `cargo web build/deploy/start`
serve-path = /wasm-files

What do you think about this?

limira avatar May 29 '18 03:05 limira

Right, yes, it will clear the directory out - good point. In that case we could just add a parameter with which you could disable that (or actually - enable it; ideally we should have it clear the directory by default only when using default deploy path.)

koute avatar May 31 '18 21:05 koute

On this particular front, I think there is a lot to be gathered from the ParcelJS & Webpack projects — as well as other bundling tools. First, a few reflections:

  • in Webpack & Parcel, the static or dist output directory is considered completely ephemeral & should not go into version control; files in said directory may be overwritten on each invocation of these tools; and lastly, all of the contents of these directories may be optionally cleaned out at the developer's will (very often the JS community will just use rimraf, a cross platform rm -rf tool essentially, to do the clean op).
  • given WASM's position in the JS community (at least on the web front), I would wager that the best path forward would be to target a maximum level of interoperability with these other toolchains, as opposed to attempting to replace them (replacement does not seem like a current goal, to be sure).
  • lastly, consider that a production grade web application is going to have things like SASS/CSS compilation, inlining of images, inclusion of fonts, and a fair number of other things. It would be great for this cargo-web project to not have to worry about doing stuff like that. It would be freed up to continue focusing on having an awesome WASM story.

Given the above reflections, I think that being able to output the wasm artifact to a specific directory is paramount for interop with Webpack, ParcelJS & other bundlers.

I definitely see an ideal setup for production grade web apps using this tool. Let's say we have an all wasm project, which is using SASS for styles: For development:

  • we could have a new cargo web command which just runs the build in watch mode (or use cargo watch -s 'cargo web build'). This would incrementally compile your project as you are developing and then output your .wasm artifact and the generated JS file to your dist directory.
  • you could then keep your parceljs bundler running in watch mode as well, pointing to your base .html file. Parcel would take care of running the SASS builds, generating the final .html file from your base .html file, and then would also include your .wasm file, either due to the app.js file which this project generates, or you could have your own JS files which import it.

For deployment: the pipeline would look something like this:

  • invoke a release build of cargo web, which would send the needed artifacts to dist directory.
  • invoke a release build of parceljs, which would look at your base .html file, run the SASS builds, transpile any JS which would also pull in the .wasm app, and then it would generate cache busting file names for all of the assets to make sure production cache busting works as needed.
  • point a decent web server to the directory, something that can serve e-tags, and then you've got a pretty badass setup.

I do everything in Docker, so I would just have all of this execute in a docker container, and then deploy the docker container with all of the built artifacts.

Thoughts?

thedodd avatar Jun 02 '18 16:06 thedodd

These are just my personal experiences. I want to make clear that I am not an experienced developer (but a crazy one :grin: ). I have never built a real web app before. Currently I am building my first ever web app. I hope it will go into production in someday. [And sorry for my poor English]

I actually started my current project in JS (using ReactJS, Webpack) and Go. After roughly a year, I replaced Go by Rust. About 2 months ago, I want to have a big change in JS part of my application. I was hesitate..., after nearly 2 years working with JS, I think JS is not a good language to make (even a single) big change into its app source code. I counted my JS code: 40k lines, I don't know it is big for you or not. But for me, it not good to introduce a big change into that much code in a language like JS. Another bad thing: my code is is a mess (I am not an experienced developer). I also want to rewrite it! In JS again? NO..... NEVER JS AGAIN!

Again, I am not an experienced developer. I need helps to write better code, Rust - as a language itself - give helps that I need. I look around, wow, there is thing like yew to replace ReactJS. It is not mature yet, but is growing. And I am happy to contribute to make it work for me, some contributions reach out to stdweb, cargo-web... Now I am in the process of rewrite my entirely app of about 100k lines of code in both back-end and front-end, everything (almost) in Rust. There will be zero .js file that written by myself in my project any more. (Everything is just because I am a crazy developer).

  • Why do I need something like Webpack or Parcel if there is zero .js file (that written by myself) in my app? (If you use these tools, maybe someday you will pay a look at this tool ). I am more than happy to add feature into stdweb than installing Node, then Webpack (Not Parcel here because it does not fully support wasm yet).
  • Sass? I may try rsass (also in early stage) but I am happy to try it.
  • If you want cargo-web just only do compilation: Ignore the deploy-related parameters.

I think I understand why you say that long comment above. It come from good will to make other people aware the situation and not to reinvent the wheel (am I correct?). But there are still many people that crazy enough to try to reinvent it. Not all crazy people have the ability to change the world (I am among them). But the world changes because of some great crazy people, and I am happy to support them.

limira avatar Jun 03 '18 04:06 limira

I'm running into a similar issue where I just want to serve my JS and WASM from a static/ route, but since the WASM path is hardcoded in the JS I can't do that.

LaylBongers avatar Sep 25 '18 13:09 LaylBongers

I have a similar requirement, to be able to deploy an example similar to ´cargo run --example foo´

I mention it here rather than an own issue as it might be part of this line of development (and to keep the issue count reasonable).

paulirotta avatar Feb 20 '20 08:02 paulirotta