写给前端看的Rust教程(2)从npm到cargo

4,847 阅读3分钟

原文:24 days from node.js to Rust

前言

rust世界中,cargo所扮演的角色是包管理器,类似Node.jsnpm的作用。默认情况下cargo会从 crates.io 下载所需要的依赖包,你可以在这上面注册账号并推送包,类似你在 npmjs.com 所做的那样

对应关系

项目配置文件

Node.js中我们使用package.json作为配置文件,而在rust中我们采用Cargo.tomlCargo.toml采用的是 toml 格式而非JSONCargo.toml文件的作用是告诉cargo当前项目依赖哪些模块、如何运行测试以及如何build你的项目,更多信息可见 The Manifest Format

初始化新项目

Node.js中我们使用npm init命令进行初始化,在rust中我们使用cargo initcargo new命令做同样的事情。cargo init会在当前文件夹中做初始化,cargo new则是会指定一个文件夹

安装依赖

Node.js中我们使用npm install [dep]命令来安装依赖的模块,如果安装了 cargo-edit 那么在rust中我们可以使用cargo add [dep]来增添依赖,安装方法:

cargo install cargo-edit

安装完毕后,会增加4个子命令:addrmupgradeset-version

全局安装

类比Node.js中的npm install --global,在rust中我们使用cargo install

运行测试

类比Node.js中的npm test,在rust中我们使用cargo test

发布模块

类比Node.js中的npm publish,在rust中我们使用cargo publish

运行任务

Node.js中我们使用npm run xxx来运行任务,然而在rust中除了几个常见的命令外,其余的都是取决于用户自己。例如我们可以通过cargo run来运行一个代码,或者用cargo bench分析一段代码的性能,或者是用cargo build来做打包,或者是用cargo clean来清空打包目录(默认是target),或者是用cargo doc生成文档。cargo还支持 Build Scripts 机制确保可以打包之前运行指定的程序。

JavaScript中已经不需要Makefile,但在Rust中就没那么幸运了,Makefile还是很常见。不过 just 正在被广泛接受,它弥补了Makefile的一些弱点,语法上也很相似,可以如下安装:

$ cargo install just

cargo-makecargo-cmd也是很好的替代方案

workspace与monorepo

包管理器在处理大项目中的小模块时一般都会用到workspace概念,在Rust中你可以在根目录下创建一个Cargo.toml文件作为workspace的入口,描述清楚workspace中所包含的内容,大体上类似如下:

[workspace]
members = [
  "crates/*"
]

workspace中相互引用的各个模块可以指向本地的文件夹作为依赖项:

[dependencies]
other-project = { path = "../other-project" }

额外的工具

cargo-edit

上文已经介绍、不再赘述

cargo-workspaces

cargo workspaces(或cargo ws)将workspaces的创建和管理进行了简化,受Node.jslerna启发,最大的价值在于自动发布workspaces中的模块以及替换本地依赖。我们可以通过如下方式进行安装:

$ cargo install cargo-workspaces

cargo-expand

Rust中宏是如此的常见,以至于即便是你的第一个hello word程序也离不开宏的使用。宏可以帮助你减少冗余代码,但是却会增加调试的困难,cargo-expand有助于减少调试中遇到的困难。cargo-expand依赖于nightly工具链:

rustup install nightly

然后安装cargo-expand

$ cargo install cargo-expand

安装完成后,可以通过cargo expand [item]打印出完整的源码

注意:cargo expand接受一个名称,不是一个文件路径。cargo expand main命令不是展开src/main.rs,而是展开项目的根目录中的main()函数。通常来说,展开src/some_module/another文件中的模块,可以运行cargo expand some_module::another。 不用担心,后面会继续深入介绍。

举例来说,执行cargo new命令会生成一个src/main.rs文件:

fn main() {
  println!("Hello, world!");
}

其中println!()就是一个宏,我们运行cargo expand命令来看看生成的结果:

fn main() {
    {
        ::std::io::_print(::core::fmt::Arguments::new_v1(
            &["Hello, world!\n"],
            &match () {
                () => [],
            },
        ));
    };
}

tomlq

这不是一个cargo xx类型的命令,在查询.toml文件中的数据时很有用处

总结

当你添加了cargo-edit之后从npmcargo的对照显得非常清晰,后面会介绍如何在Visual Studio Code中配置rust开发环境

更多