rust-lang / mdBook

Create book from markdown files. Like Gitbook but implemented in Rust
https://rust-lang.github.io/mdBook/
Mozilla Public License 2.0
17.3k stars 1.59k forks source link

Break out the core book from everything else #1234

Open Michael-F-Bryan opened 4 years ago

Michael-F-Bryan commented 4 years ago

In the same vein as #1211 and #1076, a massive pain point when developing plugins is that you need to import mdbook (which is fine) and this pulls in half of crates.io as transitive dependencies (which is not).

My thoughts are we could have a mdbook-core crate containing the bare minimum needed to load a book from disk, plus common traits:

This then opens the way for making the HTML renderer just another renderer (e.g. by installing a mdbook-html binary alongside mdbook).

It's quite a big change in terms of work and backwards compatibility (although we could probably re-export items from mdbook-core in mdbook?) and I'm happy with doing most of the grunt work, but thought I'd get some thoughts before making changes.

Does this seem like a reasonable idea? Or would it just be a bunch of busy work which is going to break a lot of in-flight PRs and waste time?

ehuss commented 4 years ago

I think it would be great to have a more stripped-down core library. I'm uncertain if it is necessary to make it a separate crate. My concern is that adds some maintenance overhead. Would it be OK to just use features more aggressively? I assume the main dependencies to avoid are:

That seems relatively easy to make those optional, default features.

Michael-F-Bryan commented 4 years ago

I think the biggest offenders are all the extras used by the binary, and the HTML renderer. For example, a library doesn't actually need to instantiate a logger (env_logger), parse arguments (clap), or spin up a web server.

From what I can tell the only thing you really need for the Book and configuration are pulldown-cmark (which is really cheap because it's just text processing) and serde (expensive, but configuration is coupled to it). Likewise, the Renderer and Preprocessor traits a result just dumb objects, possibly with a #[derive(Serialize, Deserialize)] or two.

I'm uncertain if it is necessary to make it a separate crate. My concern is that adds some maintenance overhead

I'm not sold on this... We use workspaces a lot to keep compile times down and maintain separation in work projects and in practice it's no different from putting things into modules, they're just different folders on disc.

Tools like cargo-release also make releasing a dozen crates in a workspace is as easy as releasing one crate.

Would it be OK to just use features more aggressively?

I've found using more than one or two feature flags in a crate tends to make things harder to maintain. It clutters the code a lot, and you've got to be careful to try different permutations of feature flags in case one feature accidentally uses something that only exists with another feature.

Often you'll just run cargo test --no-default-features and cargo test --all-features in CI, so these oddball permutations are never checked.


This weekend I'll do an experiment to see what the bare minimum in terms of functionality and dependencies is needed for using mdbook as a library (r.g. for plugins). We should be able to take it from there.

willcrichton commented 1 year ago

I did a proof-of-concept in #1937 to see how many dependencies I could strip away while enabling my mdbook-quiz preprocessor to still work. I removed: