xtask_wasm/
lib.rs

1#![deny(missing_docs)]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3
4//! This crate aims to provide an easy and customizable way to help you build
5//! Wasm projects by extending them with custom subcommands, based on the
6//! [`xtask` concept](https://github.com/matklad/cargo-xtask/), instead of using
7//! external tooling like [`wasm-pack`](https://github.com/rustwasm/wasm-pack).
8//!
9//! # Setup
10//!
11//! The best way to add xtask-wasm to your project is to create a workspace
12//! with two packages: your project's package and the xtask package.
13//!
14//! ## Create a project using xtask
15//!
16//! * Create a new directory that will contains the two package of your project
17//!   and the workspace's `Cargo.toml`:
18//!
19//!   ```console
20//!   mkdir my-project
21//!   cd my-project
22//!   touch Cargo.toml
23//!   ```
24//!
25//! * Create the project package and the xtask package using `cargo new`:
26//!
27//!   ```console
28//!   cargo new my-project
29//!   cargo new xtask
30//!   ```
31//!
32//! * Open the workspace's `Cargo.toml` and add the following:
33//!
34//!   ```toml
35//!   [workspace]
36//!   default-members = ["my-project"]
37//!   members = [
38//!       "my-project",
39//!       "xtask",
40//!   ]
41//!   resolver = "2"
42//!   ```
43//!
44//! * Create a `.cargo/config.toml` file and add the following content:
45//!
46//!   ```toml
47//!   [alias]
48//!   xtask = "run --package xtask --"
49//!   ```
50//!
51//! The directory layout should look like this:
52//!
53//! ```console
54//! project
55//! ├── .cargo
56//! │   └── config.toml
57//! ├── Cargo.toml
58//! ├── my-project
59//! │   ├── Cargo.toml
60//! │   └── src
61//! │       └── ...
62//! └── xtask
63//!     ├── Cargo.toml
64//!     └── src
65//!         └── main.rs
66//! ```
67//!
68//! And now you can run your xtask package using:
69//!
70//! ```console
71//! cargo xtask
72//! ```
73//!
74//! You can find more informations about xtask
75//! [here](https://github.com/matklad/cargo-xtask/).
76//!
77//! ## Use xtask-wasm as a dependency
78//!
79//! Finally, add `xtask-wasm` to your dependencies:
80//!
81//! ```console
82//! cargo add -p xtask xtask-wasm
83//! ```
84//!
85//! # Usage
86//!
87//! This library gives you three structs:
88//!
89//! * [`Dist`](https://docs.rs/xtask-wasm/latest/xtask_wasm/struct.Dist.html) - Generate a distributed package for Wasm.
90//! * [`Watch`](https://docs.rs/xtask-watch/latest/xtask_watch/struct.Watch.html) -
91//!   Re-run a given command when changes are detected
92//!   (using [xtask-watch](https://github.com/rustminded/xtask-watch)).
93//! * [`DevServer`](https://docs.rs/xtask-wasm/latest/xtask_wasm/struct.DevServer.html) - Serve your project at a given IP address.
94//!
95//! They all implement [`clap::Parser`](https://docs.rs/clap/latest/clap/trait.Parser.html)
96//! allowing them to be added easily to an existing CLI implementation and are
97//! flexible enough to be customized for most use-cases.
98//!
99//! You can find further information for each type at their documentation level.
100//!
101//! # Examples
102//!
103//! ## A basic implementation
104//!
105//! ```rust,no_run
106//! use std::process::Command;
107//! use xtask_wasm::{anyhow::Result, clap, default_dist_dir};
108//!
109//! #[derive(clap::Parser)]
110//! enum Opt {
111//!     Dist(xtask_wasm::Dist),
112//!     Watch(xtask_wasm::Watch),
113//!     Start(xtask_wasm::DevServer),
114//! }
115//!
116//!
117//! fn main() -> Result<()> {
118//!     let opt: Opt = clap::Parser::parse();
119//!
120//!     match opt {
121//!         Opt::Dist(dist) => {
122//!             log::info!("Generating package...");
123//!
124//!             dist
125//!                 .dist_dir_path("dist")
126//!                 .static_dir_path("my-project/static")
127//!                 .app_name("my-project")
128//!                 .run_in_workspace(true)
129//!                 .run("my-project")?;
130//!         }
131//!         Opt::Watch(watch) => {
132//!             log::info!("Watching for changes and check...");
133//!
134//!             let mut command = Command::new("cargo");
135//!             command.arg("check");
136//!
137//!             watch.run(command)?;
138//!         }
139//!         Opt::Start(mut dev_server) => {
140//!             log::info!("Starting the development server...");
141//!
142//!             dev_server.arg("dist").start(default_dist_dir(false))?;
143//!         }
144//!     }
145//!
146//!     Ok(())
147//! }
148//! ```
149//!
150//! ## [`examples/demo`](https://github.com/rustminded/xtask-wasm/tree/main/examples/demo)
151//!
152//! Provides a basic implementation of xtask-wasm to generate the web app
153//! package, an "hello world" app using [Yew](https://yew.rs/). This example
154//! demonstrates a simple directory layout and a customized dist process
155//! that use the `wasm-opt` feature.
156//!
157//! The available subcommands are:
158//!
159//! * Build the web app package.
160//!
161//!   ```console
162//!   cargo xtask dist
163//!   ```
164//!   * Build the web app package, download the
165//!     [`wasm-opt`](https://github.com/WebAssembly/binaryen#tools)
166//!     binary (currently using the 123 version) and optimize the Wasm generated by the dist
167//!     process.
168//!
169//!     ```console
170//!     cargo xtask dist --optimize
171//!     ```
172//!
173//! * Build the web app package and watch for changes in the workspace root.
174//!
175//!   ```console
176//!   cargo xtask watch
177//!   ```
178//!
179//! * Serve an optimized web app dist on `127.0.0.1:8000` and watch for
180//!   changes in the workspace root.
181//!
182//!   ```console
183//!   cargo xtask start
184//!   ```
185//!
186//! Additional flags can be found using `cargo xtask <subcommand> --help`.
187//!
188//! This example also demonstrates the use of the `run-example` feature that allows you to use the
189//! following:
190//!
191//! ```console
192//! cargo run --example run_example
193//! ```
194//!
195//! This command will run the code in `examples/run_example` using the development server.
196//!
197//! # Features
198//!
199//! * `wasm-opt`: enable the
200//!    [`WasmOpt`](https://docs.rs/xtask-wasm/latest/xtask_wasm/struct.WasmOpt.html) struct that helps
201//!    downloading and using [`wasm-opt`](https://github.com/WebAssembly/binaryen#tools) very
202//!    easily.
203//! * `run-example`: a helper to run examples from `examples/` directory using a development
204//!    server.
205//! * `sass`: allow the use of SASS/SCSS in your project.
206//!
207//! # Troubleshooting
208//!
209//! When using the re-export of [`clap`](https://docs.rs/clap/latest/clap), you
210//! might encounter this error:
211//!
212//! ```console
213//! error[E0433]: failed to resolve: use of undeclared crate or module `clap`
214//!  --> xtask/src/main.rs:4:10
215//!   |
216//! 4 | #[derive(Parser)]
217//!   |          ^^^^^^ use of undeclared crate or module `clap`
218//!   |
219//!   = note: this error originates in the derive macro `Parser` (in Nightly builds, run with -Z macro-backtrace for more info)
220//! ```
221//!
222//! This occurs because you need to import clap in the scope too. This error can
223//! be resolved like this:
224//!
225//! ```rust
226//! use xtask_wasm::clap;
227//!
228//! #[derive(clap::Parser)]
229//! struct MyStruct {}
230//! ```
231//!
232//! Or like this:
233//!
234//! ```rust
235//! use xtask_wasm::{clap, clap::Parser};
236//!
237//! #[derive(Parser)]
238//! struct MyStruct {}
239//! ```
240
241#[macro_use]
242mod cfg;
243
244cfg_not_wasm32! {
245    use std::process::Command;
246
247    pub use xtask_watch::{
248        anyhow, cargo_metadata, cargo_metadata::camino, clap, metadata, package, xtask_command,
249        Watch,
250    };
251
252    mod dev_server;
253    mod dist;
254
255    pub use dev_server::*;
256    pub use dist::*;
257
258    cfg_run_example! {
259        pub use env_logger;
260        pub use log;
261    }
262
263    cfg_wasm_opt! {
264        mod wasm_opt;
265        pub use wasm_opt::*;
266    }
267
268    cfg_sass! {
269        pub use sass_rs;
270    }
271
272    /// Get the default command for the build in the dist process.
273    ///
274    /// This is `cargo build --target wasm32-unknown-unknown`.
275    pub fn default_build_command() -> Command {
276        let mut command = Command::new("cargo");
277        command.args(["build", "--target", "wasm32-unknown-unknown"]);
278        command
279    }
280}
281
282cfg_wasm32! {
283    cfg_run_example! {
284        pub use console_error_panic_hook;
285        pub use wasm_bindgen;
286    }
287}
288
289cfg_run_example! {
290    pub use xtask_wasm_run_example::*;
291}