初めてのnpm パッケージをTypeScript で作って公開してみた

`TypeScript`の勉強のために小さな`npm`パッケージを作成・公開しました。本記事は、パッケージを作成・公開するときに学んだこと・つまづいたことをまとめた内容になります。

本記事で言いたいことは、**TypeScript の勉強法として`npm`パッケージ作成は適しており、公開するだけであればその敷居は思ったより低くない**ということです。

## 作ったもの

**commitlint**という、コミットメッセージがコミット規約に従っているのかどうかをチェックする`npm`ツールがあります。

https://commitlint.js.org/#/

[ESlint](https://eslint.org/)のように、プラグイン・ルールを組み合わせて拡張することで、プロジェクトに合ったコミット規約をカスタマイズできます。

今回は、コミットメッセージが**Issue 駆動開発**のコミット命名規則に則っているかどうかをチェックする、とても小さなプラグインを作りました。コミットメッセージ本文に`#issue番号`があるかどうかをチェックするだけのルールで、ほぼ自分用に作ったものではありますが、もしよければ使ってくださると幸いです。

https://www.npmjs.com/package/commitlint-plugin-issue-driven-dev

## 作った動機

自分は普段`Go`でバックエンド開発をしているのですが、直近で`TypeScript`の知識が必要になりました。
そこで、[プログラミング TypeScript](https://www.oreilly.co.jp/books/9784873119045/)等を読んで基本的な読み書きができるようになったのですが、何か1つ作ってみるかとなり、`React`×`TypeScript`でのアプリ開発を考えました。しかし、筆者は`React`に精通しているわけでもないため、ハマった時に何が原因なのかが混乱してしまい、学習効果が薄くなるだろうと考えました。

- **TypeScript 単体の勉強としてコードを書きたかった**
- **node_module の勉強もしたかった**

上記の動機から、簡単な`npm`パッケージを作ることにしました。

## どのようにして作っていったか

以下の順番で進めていきました。

1. npmパッケージの作成・公開フローを知る
2. [commitlint](https://commitlint.js.org/#/reference-plugins?id=share-plugins)のプラグインの開発ルールを知る
3. npmパッケージ公開用のTypeScriptのビルド設定を知る
4. 他のcommitlintプラグインのコードを真似ながら、開発していく

また、開発を進める際は以下の資料を参考にしました。

### npm パッケージの作り方

https://qiita.com/TsutomuNakamura/items/f943e0490d509f128ae2

### TypeScript のビルド設定周り

https://www.typescriptlang.org/ja/tsconfig

https://www.oreilly.co.jp/books/9784873119045/

の[TypeScriptのビルドと実行]の章。

あとは、@commitlintの型を使うため[@commitlint/types](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/types)のソースコードを読んだり、[npm](https://www.npmjs.com/)で他のcommitlintのプラグインのソースコードを探して読んだりしました。

## 学べたこと

実際にTypeScriptで書いたコードは、ちょっとしたスクリプト程度の量でした。そのため、「TypeScript完全に理解した」というより、JavaScript・TypeScriptのエコシステムについて学んだことが多かったです。

### TypeScript のビルド周りの設定

TypeScriptはバイナリではなく、JavaScriptのソースコードをビルドします。そのため、どのプラットフォームで動くJavaScriptを生成するか等を決める必要があり、それらの設定は`tsconfig.json`で細かく指定ができます。
業務では、他の開発者の方が設定してくれているので、今回位置から設定することでTypeScriptのビルド設定を知る良い機会になりました。  
また、「`export` ？ `module.exports`？どっちがどっちで、何がちがうのか？」といった`CommonJs`と`Node.js`の記述の違いについて理解しておかないといけないため、開発前のタイミングで他の方が書かれた[JavaScript の変遷について説明した記事](https://zenn.dev/naoki_mochizuki/articles/46928ccb420ee733f78f#%E7%AC%AC%E4%BA%94%E7%AB%A0%3A-%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B9%E3%83%91%E3%82%A4%E3%83%AB%E8%A8%80%E8%AA%9E%E3%81%A8%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA)などで知識を整理できたのも良かったです。

### TypeScript の型定義

今回作成した`commitlint`プラグインのソースコードでは、`@commitlint`の型を使用しています。その際に`@commitlint`のソースコードを読んだのですが、ジェネリクスの使い方などは非常に参考になりました。
保守性・拡張性の高いOSSのコードを読むことは、TypeScript初心者にとってとても良い勉強方法だったのではないかと思います。

### npm パッケージの公開の仕方

npmパッケージはインストールして使ったことは何回もありますが、公開したことはありませんでした。開発前は設定が色々必要なのかな？と思っていたのですが、npmパッケージ開発の方法について解説している記事が多く、そもそもnpmパッケージの公開が簡単だったこともあるため敷居は低かったです。

## つまづいたポイント

### 開発に必要なツールの設定

**`eslint`や`prettier`、`jest`の設定につまづきました。**TypeScriptの開発をするために、どのパッケージをインストールしたり、設定を追加すればよいのかを把握するのに時間をかけてしまいました。よくわからないまま他のプロジェクトを真似て突っ込むのではなく、ドキュメントを確認しながら1つづつ入れていけば良かったです。
個人の感想ですが、`Go`と比較すると、こちらは諸々の設定が面倒だなと感じました（単に自分に知識が足りないことや慣れの問題もあります）。`Go`は言語に標準でフォーマッタやテストツールが付属しており、`Go`用のVSCode拡張を入れれば動くので使いやすいです。
また、設定ファイルは`.js`・`yml`・`json`なんでもござれという点には面食らいました。

### 動作確認方法

`yarn`や`npm`には、`link`というローカルの開発中のnpmパッケージに対してシンボリックリンクを貼り、手元で動作確認できる仕組みがあります。

https://classic.yarnpkg.com/en/docs/cli/link/

**誠に恥ずかしながら、開発中の自分はこの仕組みを知りませんでした。
**「テストに通っているからこれでええやろ!」と一通りユニットテストを行いつつ、パッケージとして組み込んだ際の動作はスクリプトをそのままcommitlintに組み込んだりして確認していました。  
そのため、実際の動作確認は`npm`に公開してから行っていました。今振り返るととんでもないことです。普通に考えると何かしら動作確認ができる仕組みはあるはずなのですが、自分は気づきませんでした。npmほどのプラットフォームであれば、必ず開発ツールは充実しているはずなので、焦らずうまく検索Wordを変えて根気よく調べられれば良かったです。

## おわりに

npmパッケージをTypeScriptで書くことによって、コードの書き方だけでなく巨大な`JavaScript`のエコシステムについてもある程度学べる機会となりました。
ある程度入門的な内容（リテラルの書き方など）を勉強した後に、何かサラッと書いてみる分には、npmパッケージ開発はうってつけだと思います。