具体的に理解する楽しいOSS貢献 (Svelteを具体例に説明します)

# はじめに

## この記事でわかること💁‍♀️

OSS貢献のモチベーションや楽しさを理解できます。🏖
また、OSSへの貢献方法を具体的に理解できます。🕵️‍♀️
特に、Svelteに貢献したいと思っている方は比較的解像度高く貢献までの手順を理解できると思います。👩‍🔬

## この記事でわからないこと🙅‍♂️

コードの読み方など、OSS貢献に必要な技術的スキルに関しては言及しません。
また、OSS自体を最初に作る人 (例えばSvelteでいうRich　Harris氏) のモチベーションについては言及しません。
あくまで既にあるOSSへの貢献、という観点で記述します。

## 対象読者👀

- OSSへの貢献をしたことがないが、貢献したいと思っている方
- Svelteへの貢献をしたことがないが、貢献したいと思っている方
- OSSへ貢献するメリットを知りたい方
- 技術レベルは問いません (この記事を読めばあなたの技術レベルに合わせた貢献方法を見つけることができるはずです)

## 筆者について

大手SIerで5年間ソフトウエアエンジニアをした後、現在は [Flyle](https://flyle.io/jp) というスタートアップでフルスタックエンジニアをしています。
本業では、フロントエンドに Vue.js を使用しています。
2021年の7月にSvelteを知り、Svelte のコントリビューターを始めました。(私のこれまでの[コミット](https://github.com/search?q=author%3Abaseballyama+commenter%3Abaseballyama+user%3Asveltejs&type=commits))
私にとってSvelteは初めて貢献したOSSです。💪
[Twitter](https://twitter.com/yamashita_yuich)と[GitHub](https://github.com/baseballyama) をフォローして頂けると嬉しいです。☺️

# 本題

## 結論

今回は最初にこの記事の結論を述べます。

**👊 頑張って取り組んで最後は度胸 👊**

結局のところ、我々はOSSのメンテナよリもそのOSSに対する理解が浅いので、どこまで行っても理解を誤っている可能性があります。
でもそれを言っていたらいつまでも身動きが取れないので、色々と調べ尽くしてコードを修正した上で、
最後は手をプルプルさせながら `Create pull request` を押すしかないのです。
ここから先は、手のプルプルを抑えるための少しばかりの知識が書いてあると思って頂けると嬉しいです。😄

## なぜOSS貢献をするのか + なぜ僕がOSS貢献をするのか

まず、OSS貢献をする前に、OSS貢献をするモチベーションを理解する必要があります。

そもそも、OSS貢献に勤しんでも大抵はお金になりません。
一部、Vue.js や Vite の開発者で知られる [Evan You](https://github.com/yyx990803) 氏など、天才と呼ばれる人たちは、
沢山のスポンサーがついてOSS開発で生きていくことができていますが、
ほとんどのOSSの開発者はそれ自体ではお金を稼ぐことはできません。

ではなぜOSSに貢献するのか。それは主に以下2個の理由 + 1個 だと考えています。

**1. 自社に必要な機能をOSS自体に実装する**

大抵の場合、自社で1からサービスを開発するよりもOSSを使用した方が早く低コストで開発できます。
(Webサービスを作っている方であれば、Vue.js, React, Svelte, JQuery など、なんらかのOSSを使用していると思います。)

しかし、既製品を使用することのデメリットは、自社に最適化しづらいことです。
これを解消するために、自社が欲しい機能を実装してOSSに取り込む場合があります。

**2. OSSに貢献していることをアピールする**

個人のレベルでは、
OSSに貢献しているということは、

- コミュニケーションができて、
- マージまでの適切な開発手順を踏めて、
- コードとテストを書けるスキルがあること

を一定示唆できます。
また、その技術に一定詳しいことも示唆できます。
それが転職や独立の時に役に立つ可能性があります。
(例えばFindyではGitHubのアクティビティを偏差値として表現していたりするわけですし。)

また、会社レベルでは、
OSSコミッターがいる会社は、技術力をアピールできるので、採用で有利になります。

このように、技術力をアピールするためにOSS貢献をする、というのもOSS貢献のモチベーションの一つだと思います。

**3. 楽しい**

個人的に、OSS貢献は以下の点で楽しいです。

**自分の知らない技術や考え方を知ることができる⚡️**

OSS開発する上でコミュニケーションは必須ですが、周りの発言を見続けることで、自分の知らなかった技術や考え方に触れることができます。
これにより、自分の技術的な引き出しが増え、それにより自分の技術力で実現できることが増えます。

**目の前のissueを解決すること自体が楽しい🧠**

大抵、修正しようと思ったバグは、初見では何がなんだかわからないものです。
これを整理しながら原因を特定して修正方法を特定する作業は、ゲームを解いているようで面白いです。
「シカクいアタマをマルくする」的な。

**世の中の役に立っている気がして誇らしい💪**

例えば [私が修正したこのissue](https://github.com/sveltejs/svelte/issues/6575#issuecomment-903475018) は、[Svelte Native](https://github.com/halfnelson/svelte-native) の全ての利用をブロックするような重大な問題でした。これを修正したことで、Svelte Native は再び最新版のSvelteを使用することができるようになりました。issueを報告したユーザーに感謝された時、自分の技術が人のために役立ったのだなぁと思いなんだか嬉しい気持ちになりました。🕺

これらに共感できるあなたはきっと楽しめるので、是非OSS開発を始めてみましょう🚀🚀🚀

## OSSへの貢献方法

さて、ここからが本題です。
まず、OSSへの貢献には、大きく8種類あると思います。
貢献のハードルが低い順に7個、最後に番外編を1個記載します。

### 1. コミュニティで質問に答える

Svelteでは、[Discord](https://svelte.dev/chat) 上にコミュニティがあります。(ちなみに[日本コミュニティのDiscord](https://discord.com/invite/YTXq3ZtBbx)もあります!)
Discordの Users 配下にあるチャンネルは、Svelteユーザーが問題に直面した時に質問ができる場所です。
メンテナだけでは全ての質問に対応することはできないので、ユーザー同士で問題を解決することは、重要な貢献の1個です。
(メンテナも[GitHub](https://github.com/sveltejs/kit/issues/2100#issuecomment-894936305) 上で、DiscordやStackOverflowで質問に答えることは良いことであると言及しています。)

### 2. バグを報告する

Svelteの場合、全てのissueは、[GitHub issues](https://github.com/sveltejs/svelte/issues) で管理しています。
メンテナとて、全知全能ではないので、彼らも気づいていないバグがあります。
なので、バグを報告することも重要な貢献の方法です。

ここで、バグを報告する際に気をつけることを記載します。

- 報告対象のバグを再現する最小のコードを用意する
- 既に同じissueがないかを調べる
- フォーマットに従ってissueを記載する
- 一度issueを書いたらすぐに送らず、後で読み返してから送る

1点目について、Svelteの場合、issueを報告する時は、再現コードの提供を求めています。
その際、コードが長いと何が原因かを突き止めるのに時間がかかります。
何より、バグを報告する時点では、あなたが世界で一番その問題に詳しいわけですから、
問題となっている要素だけを抽出した再現コードを用意するのは、あなたにしかできないはずです。

2点目について、メンテナは、issueをなるべく綺麗に保とうとします。
重複したissueは、issueの数が増えるだけで情報は増えないので邪魔です。
なので、issueを報告する前に重複がないかを事前に調べることは重要です。
もし重複していた場合、即座にissueが閉じられるので、そうするとなんだか悲しい気持ちになります。

3点目について、メンテナもあなたと同じく忙しいので、素早く理解できるissueの方がありがたい訳です。
メンテナが提供するフォーマットがある場合はそれに従いましょう。

4点目について、特に初めはissueを報告することが目標になっている場合があります。
そうすると、考慮漏れやtypoや説明のわかりづらさを含んだissueになる場合があります。
そうすると、辛辣なコメントが来たりissueを閉じられる場合があり悲しい気持ちになります。
僕のおすすめは、一晩そのissueを寝かせて、翌日改めて読んで論理を振り返ってから報告することです。

そこまでしたのにすぐにissueを閉じられたら、涙を流した後にそこから学んで次のissueを報告しましょう。

### 3. ドキュメントを修正する

ここからは、実際にコードをコミットする貢献です。
まずは、ドキュメントの修正に関して、Svelteを例に手順を説明します。

- [Svelteのドキュメント](https://svelte.dev/docs)を読んで修正した方が良さそうな場所 (typoなど) を探す
- [GitHub](https://github.com/sveltejs/svelte/issues) で修正した方が良い場所に対するissueを報告する
  - (合意が取れたら自分で修正する旨を記載した方が良いと思います)
- メンテナの同意が得られたら、該当のドキュメントを修正してPRを出す
  - (PRを出す前に、[PRを出すルール](https://github.com/sveltejs/svelte/blob/master/CONTRIBUTING.md) を読んでおきましょう)
- コメントが来たら適宜返信する

注意点として、Svelteの場合、作者のRich Harris氏がイギリス人であるため、イギリス式のスペリングになっている箇所があります。
我々は主にアメリカ式のスペリングを学んできたので、一見typoに見える単語がある場合がありますが、
イギリス時のスペリングかどうかを確認することをおすすめします。

### 4. バグ修正や小規模改善する

次に、バグ修正、小規模改善です。
コードで貢献する最初の1手は、バグ修正や小規模改善が個人的におすすめです。
なぜなら、ゴールが明確で、かつ修正規模が小さい可能性が高いからです。
例えば、GitHubのアドバンスド検索で、[Good First Issue](https://github.com/search?q=label%3A%22Good+First+Issue%22+state%3Aopen+no%3Aassignee+language%3AJavaScript+language%3AJavaScript&type=Issues&ref=advsearch&l=JavaScript&l=JavaScript) や [contribution welcome](https://github.com/search?l=JavaScript&q=label%3A%22contribution+welcome%22+state%3Aopen+no%3Aassignee&type=Issues) で検索します。
Svelteであれば、[bug](https://github.com/sveltejs/svelte/issues?q=is%3Aopen+is%3Aissue+label%3Abug+sort%3Acreated-desc)でフィルターするのが良いかもしれません。
必要であれば他にも色々と検索して、自分が貢献できそうなissueを見つけます。

貢献できそうなissueを見つけても、実際に貢献できるとは限りません。
例えば、僕がVue.jsのissueに取り組んだ時、ようやく該当のコードにたどり着いたらissueの内容がTODOで記述されていて、確かにこれを修正するのは至難の技 (少なくとも僕のスキルでは) だと気づいて諦めたことがあります。
10個取り組んで1個貢献できればOKくらいの気持ちで取り組むのが良いと思います。

貢献できそうなissueを見つけたら、実際に貢献します。
実際に貢献するための手段は大きく分けて以下の7ステップです。

**a. issueを再現する**

まずはなんにせよ事象を正しく理解する必要があります。
Svelteの場合、issueを報告した人が再現REPLを用意しているので、それを使用して何が起きているのかを正しく理解します。

**b. 原因を特定する**

issueの再現ができたら、なぜそれが発生しているのかを理解します。
個人的なおすすめは、事象を再現するSvelteプロジェクトをローカルで構築し、それをブラウザで開いてデバッグします。
必ずコード上にissueの原因が含まれているはずなので、それを特定します。
コード上で原因を特定したあとは、そのコードがコンパイラによって生成されたコードなのか、
ランタイムとして用意されていたコードなのかを判別します。
ランタイムとして用意されているコードであるかは、[このフォルダ配下](https://github.com/sveltejs/svelte/tree/master/src/runtime)に実装されているコードであるかで判別できます。
ここに実装されていないコードの場合は、コンパイラで生成されたコードです。

**c. コードを修正する**

原因が判明したら、コードの修正をします。
ランタイムが原因の場合は、単にランタイムを修正すれば良いです。
コンパイラの修正が必要な場合は、コンパイラの修正をします。
コンパイラは、いきなりコードを読んでも理解に時間がかかる可能性があるので、僕が参考になった資料を共有します。
[SvelteのメンテナーであるTan Li Hau氏のブログ](https://lihautan.com/compile-svelte-in-your-head-part-1/)
[Svelteのコンパイラの解説記事(日本語)](https://lealog.hateblo.jp/entry/2020/07/15/211032)

また補足として、Svelteコンパイラは、rollupから呼ばれるのですが、呼ばれるのは、[compile](https://github.com/sveltejs/svelte/blob/master/src/compiler/compile/index.ts#L85) 関数です。
コードで迷子になったら、一旦この関数に戻ってきて再度処理を追っていくと理解しやすいと思います。
また、VSCodeのデバッグ機能を使用すれば処理を追うことができるので、コードの全体像が理解できない場合は使用してみても良いかもしれません。

**d. テストを書く**

コードの修正ができたらテストを記述します。
テストは、REPLのコードを参考に作成することをおすすめします。
その方がレビュアーもその修正の確からしさを確認するのが簡単ですし、
何よりテスト自体が間違っていた、という状況を回避することができます。
また、コードの修正の過程で気づいた他のテスト観点があれば、適宜追加します。

**e. 既存のテストと新しいテストが全てパスすることを確認する**

特に初めてコードを修正する際はコードの全体像が理解できていないので、間違った修正をしてしまう可能性があります。
それに気づくために、既存の全テストを実行します。
テストが失敗する場合は何かの理解が誤っているので、再度コードを理解して修正します。

**f. PRを作成する**

無事にテストが通ったら、[PRを出すルール](https://github.com/sveltejs/svelte/blob/master/CONTRIBUTING.md) を読んでPRを作成します。
PRを作成する際に、テンプレートが用意されている場合があるので、
その場合はテンプレートを読んで、やるべきことを実施してからPRを作成します。

ここで、個人的なおすすめは、PRを提出する前に1晩おくことです。
コードを修正してテストが通った時、自分の修正は完璧だと思い込む可能性がありますが、
コード全体の理解が十分ではないので、根本的に何かが間違っている可能性があります。
PRを1晩寝かせて他の可能性を検討することで、間違いに気づける可能性が高くなります。
間違いに気づかないままPRを出すと、この修正は間違っていますと言われて少し恥ずかしい気持ちになります。

ただ、1晩寝かせたところで不安は拭えないのですが、もうこれ以上できることはないので、
勇気を振りぼって手をプルプルさせながら`Create pull request` を押しましょう。

PRを出した後の注意点なのですが、メンテナも大抵は本業の傍らOSS開発をしているので、すぐに返信がこない場合があります。
また、例えば現在のSvelteは、kitプロジェクトに集中しているので、Svelte自体へのPRは優先度が低くなっています。
もし、PRを出して暫く返答がなかったとしても、それは無視されているのではなく、単に優先順位の問題なので、
気長に待ちまししょう。もし返答がなかったとしても、レビューを急がせるようなコメントはしない方が良いと思います。

**g. コメントを貰ったら適宜返信する**

レビュアーから質問や指摘のコメントを貰うことがあります。
そうしたら、返信しましょう。

以上が、バグ修正や小規模改善の流れです。

### 5. 新機能を実装する

何個もバグ修正や小改善を繰り返すうちに、コードの理解が深まります。
コードの理解が深まると、気づけば新機能の実装ができるほどの理解に到達している可能性があります。
まずは、手元で新機能の実装を試してみて、実装できそうであれば、新機能が提案されているissueやrfcsに自分が実装したい旨を伝えて、同意が得られれば、実装とテストを実装してPRを作成します。
ただ、今回の対象読者にとっては現時点ではあまり関係がないので詳細な説明は割愛します。

### 6. 新機能を提案する

これはOSSによって運営方法が異なるのですが、Svelteの場合、[rfcs](https://github.com/sveltejs/rfcs/pulls) というリポジトリにて、新機能や大きなリファクタリングのディスカッションが行われています。(RFCとは Request for Comments の略です。)
OSSの進化のために新しい機能を提案することも重要なOSS貢献の1つです。
ただ、今回の対象読者にとっては現時点ではあまり関係がないので詳細な説明は割愛します。

### 7. 他人のPRをレビューする

これはメンテナが行うことが多いですが、自分が実装した部分に関する修正PRが出た場合に、
メンテナからレビューを依頼されることもあります。
ただ、今回の対象読者にとっては現時点ではあまり関係がないので詳細な説明は割愛します。

### 8. お金を出す

OSS開発は、お金がかかります。例えば、ドキュメントを公開するだけでも、サーバー費用がかかります。
OSSを維持するために、お金が必要です。

Svelteの場合、[Open Collective](https://opencollective.com/svelte)で寄付を募っています。
現在の年間予算は約400万円です。Rich Harris氏がVercelに移籍してフルタイムのSvelteのコミッターになったとはいえ、
Vue.jsなど他のOSSと比較すると、開発体制は相対的に脆弱だと思います。
寄付が増えれば開発者を雇うことができ、それによってOSSを維持することができるので、寄付は重要な貢献方法の1つだと思います。

## まとめ

今回はOSSへの貢献方法を紹介しました。
最初にも書きましたが、今回紹介した知識に加えて **👊 頑張って取り組んで最後は度胸 👊** が大事だと思います。
この記事があなたのOSS貢献への第一歩に役立てば幸いです。

それではごきげんよう。🧜‍♀️