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}