Rust Package: Crateの比較サイトを作ってみた

# Crate Trends

## Rust
みなさんRustという言語は知ってますか？将来的にC++の代わりになるかもしれないという比較的新しい言語です。バックエンドから組み込み系まで幅広く使える優秀な言語です。場合によってはC++よりも速度がでるらしいですよ！

## Crateとは？
これから目が離せないRustですが、Rustの開発時は基本Crate(クレート)というRust専用のパッケージを使います。CrateはJavaScriptでいうnpmパッケージのような物で使い勝手もnpmと非常に似ています(どっちもMozillaが開発してるから)。Rustは他言語とは違って標準ライブラリを小さくする方針を取っています。なので、開発時にCrateは切っても切れない仲なのです！

そんなCrateですがライブラリ選定の時に似たような物が多くてどれがいいのかわからない、ダウンロード数やライセンス等をまとめて比較したい！なんてことはRustのCrateに限らずどんな時にでもあると思います。もしかしたら他のプログラミング言語にはそういったライブラリ比較サイトやツールがあるかもしれませんが、Rustにはそういったものが見つかりませんでした。<-調べ方悪いのかな？
なのでそんな時は自分で作ろう！ということでRustの勉強も兼ねてCrate比較サイト、称して`Crate Trends`という物をAPIは言語がRustでフレームワークはActix-web、フロントは言語がTypescriptでフレームワークはNext.js作ってみました。


## Crate Trends
###はじめに

ここから[Crate Trends](https://crate-trends.vercel.app)が見れます。

https://crate-trends.vercel.app

一緒に動かしながら見ていきましょう！

### Code

#### Cargo.toml
```rust
[dependencies]
actix-web = "2.0.0"
actix-rt = "1.1.1"
actix-cors = "0.2.0"
crates_io_api = "0.6.0"
serde_json = "1.0.55"
```

#### Actix-web
```rust
use actix_cors::Cors;
use actix_web::{http::header, middleware::Logger, web, App, HttpResponse, HttpServer};
use crates_io_api::{AsyncClient, Error};

#[actix_rt::main]
async fn main() -> std::io::Result<()> {

  HttpServer::new(|| {
    App::new()
      .service(
        web::scope("/api")
          .route("/{id}/download", web::get().to(get_crate_recent_downloads)),
      )
  })
  .bind("127.0.0.1:8080")?
  .run()
  .await
}

async fn get_crate_recent_downloads(path: web::Path<(String,)>) -> HttpResponse {
  let download_data = fetch_recent_downloads(&path.0).await;
  match download_data {
    Ok(value) => HttpResponse::Ok().json(value),
    Err(_) => HttpResponse::Ok().json(()),
  }
}

async fn fetch_recent_downloads(crate_name: &str) -> Result<crates_io_api::Downloads, Error> {
  // Instantiate the client.
  let client = AsyncClient::new(
    "my-user-agent (my-contact@domain.com)",
    std::time::Duration::from_millis(1000),
  )?;

  // Retrieve download data.
  let data = client.crate_downloads(crate_name).await?;
  let val = serde_json::to_value(data).unwrap();
  let downloads: crates_io_api::Downloads = serde_json::from_value(val).unwrap();
  Ok(downloads)
}

```

#### Next.js

```tsx
const CratesCompare = ({ cratesData, downloadsData }: Props): JSX.Element => {
  const router = useRouter();
  const { crate_names } = router.query;

  return (
    <Wrapper>
      <Head>
        <title>Crate Trends | Results</title>
      </Head>
      <InputForm />
      <DownloadChart downloadsData={downloadsData} />
      <CratesTable cratesData={cratesData} />
      <ExtraInfo />
    </Wrapper>
  );
};
```

[GitHub](https://github.com/Gumichocopengin8/crate-trends)

### ページ

ホーム画面はシンプルにこんな感じです。
ちなみにRustの非公式キャラクターのFerrisはカニなのでカニの絵文字を使ってます。

<img width="1416" alt="Screen Shot 2020-06-22 at 8.11.37 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311915/ae350819-c3a2-e641-8a7c-af1ef4a13c35.png">


調べたいCrateの名前を入力することでそのCrateのデータを表示します。
まずは言わずともしれた`Futures`を調べてみましょう。
`Futures`とタイプしてEnterを押すか検索ボタンをおして検索できます。

<img width="1411" alt="Screen Shot 2020-06-22 at 8.13.09 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311915/9f08d17b-1a35-18bc-8c61-ed4d1fd00bcc.png">

やっぱRustは爆速でめちゃはやです！！！瞬間でデータを取ってきました。
まず上の折れ線グラフですが過去90日間の１日のダウンロード数を表示しています。
土日にダウンロードが落ちてるってことは結構みんな業務で開発している人がいるってことかな？
次にグラフの下の`Stats`ですが各Crateの
`名前、トータルダウンロード数、過去90日間のダウンロード数、更新日、作成日、ドキュメントURL、ホームページURL、リポジトリURL`
が見れるようになっています。ちなみにCrateの名前をクリックすることでそのCrateの[crates.io](https://crates.io)のページに飛ぶことができます。

これだけだとつまらないと思ったのともっとデータがみたい！と思ったので一番右にある下向きの矢印ボタンを押すとそのCrateの簡単な説明やバージョン情報、ライセンス情報が見れます。ちなみにYankedかどうかのステータスも入れてます！！
こんな感じです。

<img width="1415" alt="Screen Shot 2020-06-22 at 8.25.14 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311915/fcffd129-051f-719d-6e22-35d9927803f4.png">

どのバージョンが一番使われているかやライセンス情報が瞬時にわかるのでCrate選定の時におすすめです。

### 複数検索

今のところ１つのCrateだけで検索していましたが複数のCratesでやってみましょう。
次は`actix-web, rocket, iron, warp`の４つを調べてみます。

<img width="1400" alt="Screen Shot 2020-06-22 at 8.30.14 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311915/08629449-26cc-a4bc-7ebf-48ba578c8c41.png">

グラフはこんな感じになりました。自分の中で`actix-web`が一番だと思っていたのですが`Warp`が意外と伸びていますね。RocketやIronは比較的落ち着いています。

<img width="1383" alt="Screen Shot 2020-06-22 at 8.32.07 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311915/4f18b248-febe-d1a3-92ce-85982412fdbe.png">

Statsもこんな感じで複数みれます。
そのCrateを候補から消したい場合は左のバツボタンを押すと消せます。

---

いかがでしたか？
気に入っていただけたらぜひ他の人にもこの[Crate Trends](https://crate-trends.vercel.app)を紹介してあげてください。たくさんの人に使っていただけると幸いです。

また、この[Crate Trends](https://crate-trends.vercel.app)のGitHubは公開してあるのでコントリビューションできるよって人やバグや新機能欲しいという人はPRやIssueをください！
コメントでもOKです。

LGTMやGitHubでStarなどで応援お願いします！！
よろしくお願いします。

https://crate-trends.vercel.app