📖

Zennで本を作ってみた感想と本作りで得た知見

2022/07/05に公開

Zenn で本を作ってみました

Zenn で本(Book)を作ってみたいと長々思っていたのですが、最近になってようやく1つ目の本(以下のリンクの本)を作成して公開できました。幸運なことに多くの人に読んでもらい、いくつかのトレンドで上位になることもできました。

https://zenn.dev/estra/books/js-async-promise-chain-event-loop

今回は本を書いてみた感想やその過程で得た知見について書いてみたいと思います。実は、上の本の最後のあとがきとして書いたのですが、もう少し書いてみたいことがあり、あとがきにいくつか知見を加えた上で記事として公開してみたいと思います。あとがきをすでに読んだくれた方は本作りの知見の方にジャンプしてもらえるといいかと思います。

あとがきから

本を作ってみた感想

Zenn で本を作るのは初めてなので色々な反省点があります。

「理解度 60 ~ 70% 程度で先に書き始めてしまう」というのが自分のスタイルなのですが、これによって学習や理解が飛躍的に進むというのが大きなメリットである一方で、勘違いや間違いなどが後から見つかるケースが非常に多く、頻繁に内容を修正する羽目になります(理解度が 60 ~ 70% だと思っていたのが実際には 30% ぐらいだったみたいなことがあります😅)。

この本についても、最初から完全な理解に基づいた上でしっかり構成を考えて作ったわけではなく、以前に書いた「学習ロードマップ」の記事から逆算して重要度や誤解しやすいポイントからなんとなくのストーリーラインを作ってライブ感で作成したというのが実情です(本を書くこと自体が学習プロセスのアウトプットとして組み込まれているので、そういうやり方をしたという理由もあります)。

なので正直に言えば、作成プロセスの時点から「本」というよりは「記事の集合」あるいは「かなり長い記事をチャプターに断片化したもの」として捉えてしまった方が良いです。非連続的にチャプターを書いた結果、先のチャプターの内容で後のチャプターの知識を前提としてしまっている場合も中にはありました。

とは言え、そのおかげでかなり大胆に書くことができたとも思っています。良い面・悪い面あると思いますが、たぶん分かりきっていたらこういう本は書けなかったでしょう。「解釈」の話とかはまさにそうで、かなり大胆にしている自覚があります。「勘違いを正す」ときの知見が結構重要だと個人的に思っているところもあって、「分りつつある推移的な状態」でボトムアップに作った部分が多いです。実際、アウトプットしていく過程で得られた疑問や矛盾点などが大量にあったので、これを解決していくことが非同期処理を理解する上で非常に重要なキーとなりました。

最初想定していたものからかなり離れているのですが、自分の中ではそのおかげで面白いものが作れたなとは思っています。

また、Zenn では本として公開した後も継続的に編集ができるので、完成度が低い状態でもとりあえず公開することで衆目にさらされながら執筆を進めることができたのが非常に良かったと感じています。公開した記事に内容を追記していくような気軽さで書き進めることができたので心理的なハードルもかなり低くすみました。

こういった手法は「イテレーティブ」と呼ばれるものに近いそうですが、執筆を進めている途中でもコメントや感想がもらえるのでモチベーションがあがり筆が進みました。

https://typescriptbook.jp/writing/pdr/0002-iterative-writing-process

スクラップやツイッターなどで感想をくれた方々に感謝しています。皆さんのおかげで完成できました。ありがとうございました。

「非同期処理」について

内容に関する真面目な話をしますと、肝心の「非同期処理」は JavaScript の初学者が確実につまずくポイントとなっています。ECMAScript の非同期機能に目が行くのは当然で、fetch()setTimeout() などの Web API が Promise や async/await によって見逃されてしまい、非同期 API と非同期のシンタックスの話がごっちゃになるようになっています。

「非同期処理」という用語によって非同期 API とコールバックや Promise などの話でひとくくりに認識されてしまうので、かなり厄介であるこの罠に気づけません。他の言語での経験があれば一概にそうとはいえませんが、逆に API について当たり前の事実にされていることで JavaScript を最初に触る学習者が見落としてしまう事象について認識されずらいところがあると思います。

公式のドキュメントでさえもそうで、Node だけでなく Deno でも、「そもそも API とは何か」みたいな基本的な説明が一切ありません。「みんなもうわかってるよね?」という前提があるのかもしれませんが、これはかなりの障壁であるなと感じました。というのも、API が分かっていないと非同期処理をやる意味そのものが分かりません。

更に、「環境」に注目する必要があることに気づくのが非常に難しいです。学習を進めれば必然的にそこに注目しなくてはいけないことが分かるのですが、かなり時間がかかります。自分はたまたまブラウザからではなく、Node や Deno 環境でコマンドラインでのスクリプト実行から本格的に学習を始めるというやり方で、複数の環境を最初から前提にできたこともあり、環境の相違点や共通点、環境に埋め込まれたコンポーネント群について比較的早めに意識できた方ではあると思います(結構特殊かもしれません)。

そういう訳で、かなり重要であるにも関わらず欠落している、あるいは見落とされがちな話題や認識そのものがいくつかあることに気づきました。

コマンドラインから始める JavaScript

上で言ったことは「学習の結果」として分かった話です。少し話はそれますが、以下の記事が面白く、実はこの本の考え方として一部触発されている部分があります。

非同期処理の実行順序を理解するためにローカルテストするなら「コマンドラインからの方が無駄なものが削ぎ落とされるはずだ」という見込みと実際の体験から Deno をメイン実行環境にしました(自分は実際に Deno を使って非同期処理をテストして学習しました)。それに、Deno があることで Node を相対的に見ることができますし、その逆もできますからランタイム環境を理解する上でも結構良い判断でした。

後は、Chrome などのブラウザ環境よりもランタイム環境を基礎として考えた方がレンダリングの機構が無いためイベントループについても分かりやすくなることはこの本で紹介した通りです。V8 エンジンでローカルテストするとか色々な都合も良いですし。

コマンドライン一般の知識が必要だったとしても(おそらく非同期処理を学習する人はその時点で0からのプログラミング初学者でもないと思うので)、ランタイム環境でコマンドライン実行した方が良いなと思った次第です。

更に、Deno では JavaScript → TypeScript への移行が容易であり、型定義の恩恵を受けつつ JS を書くことも可能です。Node だと色々なパッケージをローカルインストールしたりする必要があるので、それ自体が TypeScript のハードルになります。

Deno では設定なしで TypeScript が使えるのですが、TypeScript からではなく JavaScript から解説しているのにも一定の理由があります。もちろん TypeScript がまだ自分に難しいというのもありますが、JavaScript の基礎を固めつつ段階的な型付けを行う方が Deno の思想的にもマッチしているのではないかと思っており、また TypeScript を見据えつつ Deno で JavaScript を学習することが今後は一般的になるのではないか、あるいはそうなったら面白いなとも思っています。私見では TypeScript は JavaScript に型情報の操作機能が加わった言語であると認識しており、型情報の操作によって扱うデータに対する具象性を帯びるため、あくまで JavaScript を基礎とした学習の後から型注釈が付いてくるようにしたほうが分かりやすいだろうなと感じています。

というか、TypeScript の強みそのものが、具体的な型情報の操作を行わない JavaScript から段階的に型情報を加えていけるように移行ができる点にあるだろうなと初学者の視点でも思っています。

JSに習熟していった先の発展的な進化として TypeScript を使うと、JSに型システムを導入することができます。型がないから駄目だ、みたいなことを言う人も多かったですが、TypeScript は動的型から静的型にシームレスに移行できる言語で、はじめての静的型言語の学習コスト的にも、適切です。
(プログラミング初心者のための JavaScript と Node.js の歴史、それを踏まえた勉強方法より引用)

他の静的型付け言語での経験などがある場合は別だと思いますが、初手で TypeScript から入ると環境構築や型に関する情報量が膨れ上がるため挫折しがちです(個人的な経験です😅)。JS の操作に加えて型の操作やそれに伴うコンパイルエラーなども付随するので当たり前と言えば当たり前なんですが。個人的には JavaScript の操作を完全に前提知識として説明を省いて TypeScript の型操作のみにスポットをあてた解説書籍などが欲しいなと思っています。

本を作った動機

非同期処理についての話に戻すと、自分が非同期処理についての学習を始めた際には、上で語ったような「非同期処理の学習において重要であるが欠落している話題」について断片的な情報しか得られない場合が多く、「なぜ非同期処理をするのか、どういう仕組みで、なぜそういう実行順序になるのかについて、環境に関わらず一般的に理解する」というような1つのストーリーで詳細に解説しているものを見つけることができませんでした。上で挙げたようなトラップについて実際には自分もかなり引っかかったので、こういったトラップについて早期に気づけるようなドキュメントもあったらいいなと考えてこの本を作り始めました。

最初は1つの記事として公開していたのですが、書いている内にこれは本にできるなと思い、ロードマップの記事のフィードバックからも色々と考えてみました。

その結果、非同期処理について学んでみたけど分からないという人が過去の自分も含めてかなり多いと考えたので、大きな目的として「学習者にとって簡単すぎず仕様に近すぎない抽象度で1つのストーリーとして理解したい」人達のために「なぜ分からないかが分かる」ように書いたのがこの一冊です。そもそも理解するための前提として必要な知識や、誤解しやすいポイントが何なのかを分かることを大事にしてます。そういう訳で、執筆対象とするモデルを「一応学習してみたけど分かっていなかった過去の自分」にして書いています。

過去の時点で自分が知りたかったことを書いているとはいえ、自分と同じように非同期処理を理解しようと悪戦苦闘している方々のお役に立てれば幸いです。


以上が「あとがき」からの内容となります。
作成した本である『イベントループとプロミスチェーンで学ぶJavaScriptの非同期処理』への感想や疑問点、間違いの指摘などあれば次のスクラップで受け付けていますので、ぜひコメントをください。

https://zenn.dev/estra/scraps/20dc6c4a1b64f8

本作りの知見

ここからはこの記事での追記(本題)となります。

本を作る過程で、本作りに関しての知見やアイデアをいくつか獲得できたので公開してみたいと思います。散文的に書いていますが、いくつかの事項が役に立つかもしれませんので読んでいただけるとありがたいです。

本作りのプロセス

自分の場合、Zenn で学習プロセス上のアウトプットとして記事を公開しているという側面が強いのですが、その一環で本を作る前から非同期処理や Deno についての記事をいくつか書いていました。

特に「非同期処理の学習ロードマップ」の記事は思った以上に反響があり、そこから導線となって Book の方を見てくれた方々も多かったと思います(記事から内容を期待して見てくれた方もいたと思います)。

更に、mizchi さんの以下の記事にもロードマップの記事を引用していただいたのでその影響も大きかったと思っています。

https://zenn.dev/mizchi/articles/understanding-promise-by-ts-eventloop

とはいえ、学習ロードマップの内容は自分の学習体験から「こういう道筋で学習した結果、こういう罠があるので、こういうことに気をつけると良いですよ」というあくまで俯瞰的な知見だったため、アウトプットの精度としては低いものであったと感じていました。

実は「学習ロードマップ」という言葉も自分の中では割と大言壮語で、あとになって追記した内容がかなり多く修正しました。そのため、更新された知見に基づいてそれなりに具体的なアウトプットを公開した方が良いだろうとも思い、Promise チェーンの作り方についての記事を書き始めたわけです。

最初は Book ではなくて、単なる記事として書き始めて公開したのですが、思った以上に長くなってしまい、これは本にできるかもしれないと気づいてから途中で本として再構成して公開しました(もともと自分の記事は読了に40分~50分程度かかるものが多いのですが、その時点でずば抜けて長くなってしまったので)。

あとがきでも書きましたが、最初から本としての構成をしっかりと練っていたり、非同期処理について「完全に理解」していたら、たぶん書けていなかったなと思っています。というのも、本の構成を緻密に練って壮大なものを作り上げようとすると心理障壁によって手が動かなかったり、書ききれずに途中での破綻が起きていただろうなと予想しているからです。また「既に分かりきってしまっている」ことで「分からないこと」や「なぜ分からないのか」という知見が時間と共に失われてしまうので、その情報を保全する意味でも分かりつつある状態で分からなかったことや今矛盾して理解していることを書きながら構成していくというプロセスが今の自分には必要だったからです(非同期処理の場合においてもこれがかなり重要だったと思っています)。無謀にも「非同期処理」というかなり大きなテーマで本を作れたのはこのプロセスのおかげだと考えています。自分でもよく書けたなと今更思っています(笑)。

実際、最初の内容は「Promise チェーンの書き方のアンチパターン」を書くだけのものであったのですが、本にする際には飛躍させるために意図的にまだ存在していないチャプターの内容である「イベントループ」をタイトルにつけて後から拡張しました。イベントループは相当に大きく重要な概念なのでいくらでも話をふくらませることができますし、そこから書いていく内に自然とわからないことや理解しきれていないことがどんどんでてきたのでそれを更にネタにして書き連ねていくというやり方で話をふくらませることができました。実際、Promise チェーンを起点にして非同期処理の解説をしていたのに、今では JavaScript や実行環境の深層(のあるレベルまで)に潜って解説するような本になりました。

この本を書き始めた時に自分の中では「非同期処理」の原理に関しての理解度が 70% ぐらいには到達しているだろうという前提で書き始めたのですが、実際に書いてみると致命的な勘違いをしていることが判明したものがいくつかあったので、実際は 40 % 程度の理解度で書き始めたものだったなと思っています。ほぼ書き終えた現時点では、80 % ぐらいかなと思っています(あくまで動作メカニズムについてですが)。

本の内容としては、最初から収録したいと思っていた内容のチャプターも入れましたが、意図していなかった面白い内容も入れることができたのはこのやり方のおかげだと思います。後から書いていくチャプターがどんどん面白くなっていき、元々の Promise チェーンの話よりも面白くなったと思っています。

記事から本に昇華させたというのは結果で、上のようなことも半分程度は分かりつつも大きくはケーススタディの結果として分かったことではあります。とはいえ、この書き方が自分(あるいは今回のケース)との相性がかなり良かったと今では思っています。もちろん、冒頭で書いたとおり、本というよりも「複数記事の集合」や「かなり長い記事が断片化されたもの」が実体に近いのは間違いないです。

実体はともかく、本から書き始めるのではなくて、長い記事や複数の記事書き始めて本へと昇華させるというプロセスが本をつくるための心理障壁を超えさせてくれますので、「これから本を書こうと思っているけど中々できない」という方がいればこの方法をとってみるのをおすすめします。

また、Zenn のサービスで記事を本のチャプターとして取り込めるようになったり、逆にチャプターを記事として公開できるようにする機能とか、あるいは複数記事の"スクラップ"などができると面白いかもしれないなとも感じました。

チャプターを記事にして公開してみる

実際、より多くの人に読んでもらえるために、チャプターとして書く予定のものをあえて記事として先行で公開してみるのも手だと思います(Zenn に怒られたらやめます😅)。

自分もチャプターとして収録する予定だったものを次の記事で公開してみたところ中々の反響を得ることができました。この記事から本を読んでもらえた方々もいたと思います。

https://zenn.dev/estra/articles/asyncawait-v8-converting

本の文脈に依存しすぎている場合は良くないですが、上の記事は独立性が比較的高かったので、記事にしても問題ないと判断して公開しています(ちなみに、先に記事として完成させてからチャプターに取り込んでいます)。

本の中のチャプターとして公開していても1つのチャプター単体で面白かったり、興味深い内容であればトレンドに上がることで本に興味の無い人達にも読んでもらえる可能性や本に興味のある人達につながるかもしれないので、記事として公開してみるのも効果的な手だと思います。

イテレーティブ手法

あとがきの方にイテレーティブの手法に近いと書きましたが、実際には中枢となる Promise チェーンのアンチパターンの記事から本に昇華した時点で5割程度の完成度であった Promise チェーンの部分を本として公開してしまって、そこから全体のぼんやりとしたストーリーラインに基づいて必要と思われるチャプターを随時追加していくという形で書いていました。

イテレーティブな手法を採用する。この手法では、全体をざっくり書いた上で、次のステップを繰り返しながら、漸進的に全体の内容を充実させていく。
(0002-イテレーティブな執筆プロセス | TypeScript入門『サバイバルTypeScript』 より引用)

どこまで完成したら公開していいのかみたいなのは結構悩む所だと思いますが、「見てもらいたい」と自分が思えた時点ですでに公開してしまっていいと個人的には考えています。「まだ内容としては未完成ですが、公開してみました!」みたいな感じで自分も公開していました。

https://twitter.com/pd1xx/status/1515622947666677767?s=20&t=W7EWo8JyVN2Lv1qPzWIZgQ

本に閉じこもる

このようにイテレーティブに書くのはやりやすく、新しい記事を書くよりも、既存のものに追記していったりするほうが筆がのるのは本でも同じことでした。しかしながら、本を書き始めてからまったく新しい記事を書いていないことに気づいたのでリハビリとしてもこの記事を書いています笑。

というのも、新しい記事を書くよりも、どんどんこの本の完成度を上げていきたいという思いが強くなってしまって、本に閉じこもって追記修正や新しいチャプターを追加していった結果、50万文字超えてしまいました。文字数の感覚が若干おかしくなっているかもしれません。もちろん、文字数が多ければ良いというわけでもありませんし、見方によってはダラダラ書いているようにも感じられるかもしれませんが、その一方でアウトプットの役割としてはかなり強く働いてくれたなと思います(なので通常の本とは考え方が違うかもしれません)。

ただ、「非同期処理」のテーマに関しては今回のように言葉による説明やコードの例、コメントなどをひたすら尽くした方が結果的に理解しやすいだろうなとも思っています。このテーマでの解説では、理解するために必要な情報が相当に多いのに抜け落ちている情報があり、読み手が推論して補う必要があることから誤解を招いたり理解できないケースが多々あるからです(通常の書籍なら紙面的な都合によるもので抽象化したり、コードを少なくしたりする必要がありますから)。

個人的な話では、本に閉じこもることでその分野についての深堀りはものすごくできるのですが、新しい方向にはあまり進まないので、やはり記事とのバランスをとることも重要かなと感じています。

前提を共有して高度な話に進める

記事であれば、その記事単体でみて理解できるようにあまり知られていない単語や概念を簡単に説明する必要などが毎回でてきますが、自分の作った本のチャプターで解説した事項は後のチャプターで(なんなら先のチャプターでも)利用したり参照したりできます。

例えば、イベントループやコールスタック、実行コンテキストなどの高度な概念は一々説明するのはかなり大変なのですが、1つのチャプターで詳細に解説しておけば別のチャプターで参照するだけで話を進めることができます。複雑なものや高度な概念を積み上げて話をどんどん進めて行けるので筆がかなり進みます。また、概念だけでなく、自分の意見や考え方を前提として共有しつつ話を積み上げていくことができます。チャプターに独立させておくことであとからの修正や追記がかなり楽ですし、本の中で参照のネットワークもつくれます。記事ではなく本として構成することによって可能になった特性ですね。

とは言っても、これは別に「大発見」などではなくて、チャプターなどのページを持つメディアの元々の特性だと思います。

Book の特性と構成の仕方

抽象的な話はこれぐらいにして、より具体的な知見としてチャプターの構成手段についても説明したいと思います。

本を構成する上で、最初は 1.epasync-begin.md のようにファイル名の頭に数字とドットをつけてそのままチャプターの順序になるようにしていました。

元のチャプター管理方法
1.epasync-begin.md
2.epasync-event-loop.md
3.epasync-promise-constructor-executor-func.md
4.epasync-callback-is-sync-or-async.md
# ...

書いている途中に追加したい内容や補足したい内容ができくることがあったのですが、この方法だと後からそういった追加のチャプターを挿入できないことに気づいて次のようなハイブリッドな方法に切り替えました。

まずは、ファイル名を 数字. ではなく 数字- のように変更します。これで数字による自動チャプター順序をやめます。

メインチャプターのファイル名
1-epasync-begin.md
2-epasync-event-loop.md
3-epasync-promise-constructor-executor-func.md
4-epasync-callback-is-sync-or-async.md
# ...

実際にはファイル名を変更しなくても config.yamlchapters セクションを記載することで変更できますが、紛らわしいのですべての名前を一部変更することにしました。

https://zenn.dev/zenn/articles/zenn-cli-guide#ファイル名(チャプター番号.slug.md)で並び順を管理することも

そして、サブチャプターのような位置づけで途中から挿入するチャプターはアルファベットの小文字を頭につけるように作成します。

後から追加したサブチャプターのファイル名
a-epasync-promise-basic-concept.md
b-epasync-callstack-execution-context.md
c-epasync-what-event-loop.md
d-epasync-task-microtask-queues.md
# ...

実際の内容としてはサブチャプターではないのですが、最初に書いていたメインストリームからは外れて自由に挿入できるようにある程度独立性のある内容などを書いています。このフォーマットで公開できるか分からない理解度の低い内容なども作成しています。例えば、『TypeScript における Promise の型注釈(j-epasync-ts-promise-type-annotation.md)』というチャプターが終盤にあるのですが、かなり前からあったチャプターではあるものの作成時点では理解度と完成度が低すぎたため、最近になったようやく公開できたものでした。

実際、自分が書いた本である『イベントループとプロミスチェーンで学ぶ非同期処理』の第1章のチャプターはこれらのサブチャプターの群から構成されています。第2章の Promise チェーンに関するチャプターを最初に書いていたため、公開最初の順序からはかなり変わっています

また、途中から以下のような章立てを行って章ごとのチャプターを設けることで、読みはじめる部分や読み終える部分を分割して情報粒度のコントロールを行いました。以下の章チャプターによってその章に含まれるチャプターへのリンクを管理しやすく、読者も読みやすくなったと思います。

章分けのチャプターのファイル名
sec-01-epasync.md
sec-02-epasync.md
sec-03-epasync.md

章チャプターは以下の画像のようにその章に含まれるチャプターへのリンクとその章の説明を記載しています。

章ごとのチャプター管理

まとめると結局、config.yamlchapters セクションで以下のように管理することにしました。管理する際に分かりやすいよう # 記号でタイトルをコメントとして実際に記載しています。ファイル名やチャプター名を変更する際には VS code などで一括置換します(チャプター名を被る言葉が文中にでてくることを防ぐために(『』 で囲んでいます)。

チャプター管理
chapters:
  - 1-epasync-begin # 『はじめに』
  - sec-01-epasync # 『第1章 - API を提供する環境と実行メカニズム』
  - f-epasync-asynchronous-apis # 『非同期 API と環境』
  - f-epasync-synchronus-apis # 『同期 API とブロッキング』
  - 2-epasync-event-loop # 『イベントループの概要と注意点』
  - d-epasync-task-microtask-queues # 『タスクキューとマイクロタスクキュー』
  - e-epasync-v8-engine # 『V8エンジン』
  - b-epasync-callstack-execution-context # 『コールスタックと実行コンテキスト』
  - c-epasync-what-event-loop # 『それぞれのイベントループ』
  - sec-02-epasync # 『第2章 - Promise インスタンスと連鎖』
  - a-epasync-promise-basic-concept # 『Promise の基本概念』
  - 3-epasync-promise-constructor-executor-func # 『Promise コンストラクタ』と Executor 関数』
  - 4-epasync-callback-is-sync-or-async # 『コールバック関数の同期実行と非同期実行』
  - g-epasync-resolve-reject # 『resolve 関数と reject 関数の使い方』
  - 5-epasync-multiple-promises # 『複数の Promise を走らせる』
  - 6-epasync-then-always-return-new-promise # 『then メソッドは常に新しい 』Promise を返す』
  - 7-epasync-pass-value-to-the-next-chain # 『Promise chain で値を繋ぐ』
  - 8-epasync-return-promise-in-then-callback # 『then メソッドのコールバックで Promise インスタンスを返す』
  - 9-epasync-dont-nest-promise-chain # 『Promise chain はネストさせない』
  - 10-epasync-dont-use-side-effect # 『コールバックで副作用となる非同期処理』
  - 11-epasync-omit-return-by-arrow-shortcut # 『アロー関数で return を省略』する』
  - h-epasync-catch-finally # 『catch メソッドと finally メソッド』
  - 12-epasync-wrapping-macrotask # 『古い非同期APIをPromiseでラップする』
  - 13-epasync-loop-is-nested # 『イベントループは内部にネストしたループがある』
  - sec-03-epasync # 『第3章 - async 関数と await 式の挙動』
  - 14-epasync-chain-to-async-await # 『Promise chain から async 関数へ』
  - 15-epasync-v8-converting # 『V8 エンジンによる async/await の内部変換』
  - 16-epasync-top-level-async # 『Top-level await』
  - sec-04-epasync # 『第4章 - 制御と型注釈』
  - 17-epasync-static-method # 『Promise の静的メソッドと並列化』
  - 18-epasync-await-position # 『await 式の配置による制御』
  - 19-epasync-async-loop # 『反復処理の制御』
  - k-epasync-iterator-generator # 『イテレータとイテラブルとジェネレータ関数』
  - j-epasync-ts-promise-type-annotation # 『TypeScript における Promise の型注釈』
  - y-epasync-conclusion # 『総括 - 非同期処理のまとめ』
  - x-epasync-epilogue # 『あとがき』
  - z-epasync-reference # 『参考文献』

また、config.yamlchapters セクションに記載しないファイルはチャプターから除外されたものとして見なされるので、除外チャプターとして本自体の管理ファイルを設けてそこにインデックスを作成して管理していました。

zenn本の管理ノート

セクションの関係性や todo などもこのノートに記載して管理しています。

こんな感じでチャプター名を付けて config.yamlchapters セクションに記載することで、フォルダツリー上で見やすい上に、さらに柔軟に管理できるようになります。

今後の展望

本に閉じこもることができてしまうと、新しい方向にあまり進めなくなってしまうので、新規記事と本での深堀りのバランスをとりつつも新しい本がつくれるようにアウトプットのワークフローを改善していきたいなと思います。あとは実際に作るアウトプットを増やしたいですね。

謝辞

アウトプットとして書き始めた本ですが、あくまで多くの参考資料や偉大な先人たちの知見によって生み出すことができた本であると思っています。

参考にさせていただいた記事や動画などの作成者の方々に深く感謝致します。

執筆途中で誤植の報告や感想などを頂いた方々にも改めて感謝致します。

また、Zenn というサービスのおかげで今までの自分ではやらなかったような大変面白い体験ができたと思っています。皆さんのおかげで執筆を進めることができ、完成できました。

ここまで読んでいただき誠にありがとうございました。

(😎 また感想などいただけると励みになります)

何かあれば Twitter かコメント欄にお願いします❗️

GitHubで編集を提案

Discussion