🦀 Publishing My First Rust Crate
Tags: rust, beginners
Published: 2021-01-11 20:49:51

So, I've published [my first Rust crate](https://crates.io/crates/doctor). 
This post is a brief summary of my experience going through the process. There is no TLDR, because the whole post a TLDR, essentially.😛

# 🤗 Positive

- The dev process is super smooth with tests that just work out of the box and require zero additional configuration.
- There are [official guidelines](https://rust-lang.github.io/api-guidelines/checklist.html) documenting the API design best practices.
- Doc comments can (and should) include example code snippets that also [serve as additional tests](https://doc.rust-lang.org/rustdoc/documentation-tests.html) for your crate's public API.
- The process of publishing is [well-documented](https://doc.rust-lang.org/cargo/reference/publishing.html).
- Documentation is automatically generated for every published crate by [docs.rs](https://docs.rs/doctor).
- The release ritual can be automated with [`cargo-release`](https://github.com/sunng87/cargo-release).

# 😢 Negative

- Need to keep a lot of things in mind to make sure your crate has great interoperability with the existing Rust ecosystem, e.g. because of the [orphan rule](https://github.com/Ixrec/rust-orphan-rules#what-are-the-orphan-rules) the users of your crate won't be able to implement the traits defined in `std` or `serde` for the types from your crate, so you have to decide which ones it makes sense to implement and provide that implementation yourself.
- [It is currently not possible](https://github.com/rust-lang/cargo/issues/2179) to specify that a certain version of a crate implementing some `cargo-*` subcommand must be installed when working on my crate. It's quite limiting, especially coming from JS where you can explicitly declare a cli package as a dependency of your own package and use it in build scripts, etc.

# 🤷🏻‍♂️ Confusing

- Where should I put the main documentation for my crate? Should it be `README.md` or a `//!` doc comment in `src/lib.rs`? Eventually, I ended up placing the crate documentation in `lib.rs` and using [`cargo-readme`](https://crates.io/crates/cargo-readme) to extract it into `README.md` whenever I publish a new release. It's cool that it's possible, but it's also an additional build step I have to care about. Don't know how people solve it usually, so please comment if you have a better workflow.

# 👨🏻‍🏫 Recommendations

- Use clippy with a config, as annoying as you can still handle. Mine is:

    ```rust
    #![warn(clippy::all, clippy::pedantic, clippy::nursery, clippy::cargo)]
    ```

- Use [`cargo-release`](https://github.com/sunng87/cargo-release) and setup pre-release hooks and replacements.
- Use [`cargo-readme`](https://crates.io/crates/cargo-readme) for extracting the crate documentation from `src/lib.rs` into `README.md`, thus avoiding duplicating it manually.

# 🔮 Final thoughts

Coming from a JS background and only recently starting dabbling in Rust I'd say the overall experience working on a Rust library is far more enjoyable than what you are going through authoring an npm package. 
This is, mostly, because the language itself comes with a bigger part of the tooling that you need to be productive. I really appreciate things like the built-in testing framework and excellent workflow around crate's documentation. At the same time, it doesn't feel like the `cargo` ecosystem is fully matured yet, and certain things I'm used to having accessible in `npm` world are missing (or maybe I'm just not aware of the alternatives).

Anyways, I'd be happy to read your take on how to setup and maintain a crate in the comments, let me know what you think.