この広告は、90日以上更新していないブログに表示しています。
2023/1に出たばかりの本です。著者の伊藤康太さんは元Yahooのスペシャリスト認定制度の黒帯保持、有識者による一冊。タイトルは「Node.js入門」とありますがNode.js本体の話にとどまらずJavaScriptの文法の話、ExpressによるWebアプリにCLIツールにフロント/バックエンド両方の開発や運用...と、実質最新のフロントエンド・バックエンド全般を概観できる本となっています。384Pなのでそんなに分厚くはないですね。
Node.jsは仕事でもインストールはしてるしたまに使うこともあるのですが、ふんいきでなんとなく使ってる感はずっとあったので、これを機会に体系的に押さえなおそうとじっくり拝読しました。
同時接続数が大まかに10万人を超えると重くなる「C10K問題」に対し、上の特徴で対応。(ただし近年は他のWebサーバーも問題なくなっている)
2000年代後半のJS復権とともにプラグインやパッケージ管理が必要になってくる→Node.jsが持っていたnpmが解決。沢山のファイルを完成版では1つのファイルにまとめてバンドル、minifyで最小化するタスクランナーが必要。初期はGruntやgulpなど。SPAフレームワーク群にも必要。→これらのバックにNode.jsが。
最初は歴史を踏まえてNode.jsの役割を語っています。個別には知ってはいた話もあるのですが体系的に解説しているのでありがたい。改めてNode.js登場が2006年頃のJavaScript復権や、その後のフロントエンドの隆盛に大きな役割を果たしたのだなあと思います。
Node Package Managerは最近は略称でなく正式名称がnpmぽいというのは初めて知りました。
なお本書では解説の意図があってコードはJavaScriptになっていますが、複数人が関わるJavaScriptプロジェクトを始める時はもう最初からTypeScriptを推奨となっています。本も出揃ってきましたし最近はTSが整ってきた感がありますね。
あまり意識していなかったのですが、ブラウザ上で動作するJavaScriptとNode.js上で動作するバックエンドのJavaScriptは微妙に違うとのこと。本書でしっかり押さえておかねば...

Object型は中に何でも持てるが、JSONは文字列、数値、配列、boolean、null、JSON Objectしか持てないのに注意。関数を持ったObjectをJSONに変換して戻すと一部消えたりする。Array.prototype.myFunction = .. のように定義するとできる。class構文はシンタックスシュガー。classを使う設計は避けた方がよい。thisの指す先が変わる挙動の話。アロー関数で解決する。const c = [...a]; のように既存の配列やオブジェクトを展開するSpread構文をよく使う。元のオブジェクトとは違う新しい参照を持ったオブジェクトを作れる。(中にまたオブジェクトを持っていたら挙動が違う。const [first, second, ...foo] = のようにオブジェクトからまとめて取れる分割代入も便利。Reactで出てくる。forループ、不要ならfor...of が便利。アロー関数は省略しまくるとconst doubleFunc = a = > a* 2; のように書けますが、本書の作者さんは()や{}やreturn文はむやみに省略しない派とのこと。僕もバックエンドが主なのでコードやコメントは冗長でもいいから他人や未来の自分向けにちゃんと書く派なので同意見なのですが、このへん世の中の流れや言語ごとの文化圏によって違いがありますね。
ここで分割代入のコード例でconsole.log(foo); した結果が20,40,50になっていたのですが、30,40,50の間違いかな? と思いました。
export.(関数や変数) = .... で別ファイルからはrequire('./sample'); のようにして読み込む。module.exports = ....と書く方法もあるが、exportの方がおすすめ。*.js か*.cjs がデフォルト。*.mjs という拡張子を使う。export const hoge = 1 のようにしてエクスポート。import {hoge} from './hoge.mjs'; のように拡張子まで書く。import * as も可能。export default という変数名未指定でも使える記法もあるが、本書では混在させない方法をオススメ。importしてthen で処理を書き、呼び出された時点で初めて読み込まれるDynamic imports機能もあるが、現状はバンドルでファイル名を減らす方が効果は高い。typeプロパティでどちらかに固定できる。アプリ開発はまだCommonJS、ライブラリなら両方に。require('node:fs'); のようにnode:接頭辞で区別することもある。今後は増えていく予定。"private": true; と書いておくと公開されないので安心。 時々遭遇することのある*.cjsや*.mjsってそういうことだったのか...!と改めて整理になる章でした。今後はもうECMAScript modulesでシュッと統一、となれば良いのですが、CommonJSもまだまだ使われているとのこと。このへんJS文化圏はいつも発展の途中だなと。
yarnは速いが結局npm本体も進化してるので結局npmのままで良いというような話も聞きましたが、他にもパッケージマネージャーでpnpmがあるのですね。いやはや広い世界です。
Calblack, Promise, async/await, EventEmitter/Stream の4種。可能ならasync/await, ストリーム処理のみEventEmitter/Streamに統一するのが本書お勧めの設計パターン。Callback: readFile(ファイル名, コールバック関数); 方式;Promise:const PromiseFn = new Promise((resolve, reject) => { (正常時はresolve,失敗時はrejectを返すよう実装) });then,catchで受ける。async/await:シンタックスシュガーで同期的コードのように書ける。最推奨。async function someFn() = { await Promiseを返す式 };const someArrowFn = async () => { await Promiseを返す式 };.then((data) => {}) や.catch((err) => {}) でエラーハンドリングできる。Promiseと組み合わせて並行処理も実はシンプルに書ける。ストリーム処理のEventEmitter/Stream:
EventEmitterクラスを拡張したクラスを定義、newして作り、.on('{イベント名}', {入れる処理}); でリスナーを設定.emit('{イベント名}', {引数}); でイベントを発生。細切れの非同期イベントに対応できる。try-catchではエラーが捕捉できないのでエラー用イベントの定義が必要。AsyncIterator : async/awaitとストリーム処理を一緒に扱える
for await (変数名 of iteratableな対象) { のようにして、大量データを少しづつ処理する非同期処理を同期コード的に書ける。try-catchかasync/awaitでラップするの1通り。非同期処理はそれぞれ違う、となる。 JavaScriptの入門書などでもたびたび登場するこのあたり、本格的に使い込まないとなかなか身につかずよく忘れてしまうのですが、本書では改めて整理されています。こうして一覧化されると改めてasync/awaitがだいぶ見やすくなったのだなあと分かります。
ファイル処理やHTTPサーバーなどコード例も登場するのですが、バックエンドの他の言語に比べるとやはりかなり独特なところがありますね...注意が必要そうです。
コラムにはNode.jsの進歩を加速させたio.jsや、async/awaitと名前が同じでややこしいけどそれより前に同じ問題を解決しようとしたasync.jsの話なども載っています。JavaScript周りはこういう四方山話が豊富なのでこういうのもありがたいですね。
Node.jsのパワーを活かして、ローカル上のMarkdownファイルを読み込んでHTMLに変換してファイルで出力するコマンドラインツールを作っていく章。難易度的にもちょうどよい題材かと思います。
>npm init -y でpackage.jsonを作る。fs.readFileSync(....) で可能。CLIツールなので同期処理で良い。process.argv で取れる。配列の0,1,の先の2番目~が引数。lib/ の下に分割したり。ファイルパスは絶対パス注意。marked({入力文字列}); と関数を呼ぶだけ。>npm install。package.jsonの中でルールを書いたりお勧め設定を読み込んだり。> ./node_modules/.bin/eslint *.js とコマンドが長いので、package.jsonのscriptsプロパティにショートハンドを書いて便利に。./node_modules/.bin/ のパスを解決してくれる。>npm run で実行。assert.strictEqual()やオブジェクトの中まで見てくれるassert.deepStrictEqual()などができる。>npm run test でなく> npm test で可能。 他言語の経験はあるのでこの章は割とスラスラ読めてだいぶイメージが湧きました。npmに公開されているJS製CLIツールのモジュールも、根本的にはこんな感じで開発されているのですね。
コラムで日時処理は昔はmoment.jsがあったが今日ではDays.jsやdate-fnsがお勧め...とあり、こういうこぼれ話も役に立ちます。
ちょっと分からなかったのはファイル分割でlibの下に切り出されたファイルでした。exportsしたい関数の外側で変数を宣言してるのですが、こういう変数は関数の中で定義するのがふつうじゃないでしょうか..JSやNode.js界隈だとお作法が違うのかな?
指定されたURLへのアクセスでレスポンスやHTMLを返す、NoSQLのRedisからユーザーデータを返す、エラーハンドリングやテストもしていこう...という実戦的な章。
appに入れたらapp.get({パス}, {ミドルウェア関数}, {ミドルウェア関数}...) でルーティング。app.listen({ポート番号}, {コールバック関数}); で立ち上がる。req,resを取り、複数動かす場合は第3引数のnext をnext()で呼べばよい。app.use({全ルート適用のミドルウェア関数}); のようにして共通ロギングなども可能。app.use((err, req,res, next)=> {500を返すとか}); のようにして全体のエラーをハンドリング。
process.env.XXXで環境変数が使える。EventEmiitterを継承しているので一度だけ実行されるイベントハンドリングの.onceで起動処理のハンドラー関数を書けばよい。romise.allを使用して初期のuserデータを保存。ハンドラー内部でエラーが起きるとキャッチできないので、明確にtry-catchで処理する。ページングが必要な場合はURLパラメーターのoffsetに載せるのが一般的。Redisを呼ぶ関数の引数で使える。
Webサーバー側でHTMLを生成して返したい場合は、テンプレートエンジンとしてはejsが有名。
app.set('view engine', 'ejs'); と書いて認識される。res.render({xxx.ejsの絶対パス}, {セットする値の集合}); のように書く。慣例的にapp_name/view/xxx.ejs の場所に書き、中身はHTML。<% ~ %> でJSが書けてそこに変数をセット。純粋なjsファイルなどはapp_name/public/jsfuncs.js に配置することが多い。ルーティングではここを/static として設定、EJSの中のHTMLの<script>タグ内でも static/jsfuncs.js のように書く。
express-generatorという初期コードを生成してくれるライブラリがあるが、ファイル構成の考え方が若干古い。本書のスタイルではserver.jsという単一ファイルにルーティングをまとめる方法を推奨。
DBなどを指すミドルウェアとは別の意味のミドルウェアは、PHPのLaravelフレームワークでもルーティング周りに出てくるので、へーと思いました。共通処理だけを指す訳ではなくNode.jsの文脈だとパスに対応して動く関数全体を指すのでしょうか?などとWikipediaを見たら
また別の意味として、Django、Laravel、ASP.NET CoreなどWebフレームワークの一部において、HttpリクエストからControllerに至るまで、およびControllerからHttpレスポンスを返すまでの共通処理を層状に追加する概念である。
とありました。なるほどなるほど。他の言語でのフレームワーク類を知っていればだいたい対応するところがあるので、この6章前半は他言語の方も理解できていくのではないでしょうか。
難しいと思ったのはところどころにasyncがついた非同期の関数が入ることですね。ハンドラー内部のエラーはキャッチできないそうですが、あれEventEmiitterの解説と違うような...(混乱中)
本書の例ではファイル構成は以下のようになるかと思います。
app_name/+-public/ +- index.js//HTML内で使うJS関数+ handlers/ +- user.js// ルーティングで/userに来たときのハンドラー関数 +- user.test.js// ハンドラー関数に対応したテストコード+ views/ +- user.ejs// ルーティングで/userに来たときのレスポンスで返す画面 +- index.ejs// デフォルトのレスポンスで返す画面+ server.js// app.jsなどでも。Webサーバー起動、ルーティング、DB起動、初期データ投入など+ config.js// 明言されていないが設定ファイルもルート直下のここ?+package.json// いつもの+package-lock.json// いつもの
Generator関数===が真にならないSymbolErrorを渡して、ハンドラーの関数を呼んでcatchに来ることで確認したりexpectが何回呼ばれたかで判定するテストも書ける。これが重要になる場合も。getUsers等の関数は引数req、戻り値が結果になっている。res追加、これにステータスコードや検索結果を加える方法もあるが、依存が発生して後々大変になる話Jestは様々な機能があって便利そうですが、モック周りも入ってくると本格的になってきてテストコードを書くのもけっこう難しそう...!と思いました。ちゃんと入門しないといけなさそうですね。
作者の方が様々な現場で試行錯誤して得られたのであろう、様々なテクニックも入っていて参考になります。このへんやはりNode.js開発で標準で唯一定まっている方法はないのですね。
pid=1として起動する。Ndode.jsはpid=1として動作するよう設計されていない。結果としてCtrl+Cで止まってくれない。> docker run に--init をつける方法がある。沢山CPUを積んだマルチコアだとそれ用のモジュールがあったりするのか...なんて話は全く知りませんでした。浅い情報だとこのへん載ってないことも多いのでありがたいです。シングルプロセス・シングルスレッドならではの注意点がありそうです。
なかなか長い充実の7章は、フロントエンドをReact、バックエンドをExpressで動くAPIサーバーとして、両方を同じリポジトリで実装していきます。
workspacesプロパティで管理したいパッケージを記述。今回はpackages/* とし、packages/frontend, backendの2つを管理。それぞれの下にまたpackage.jsonがある。Reactによるフロントエンドの開発
> npx create-react-app packages/frontend でファイル一式が生成。src/App.js がトップのReactコンポーネントで、モジュールはECMAScript modules 形式。handleSubmit関数をコンポーネントの中に実装。素のJSのaddEventListener関数を使う方法だと、DOM要素がなくなったら消えてしまう。...usersのSpread構文がよく出てくる。React開発の応用
proxyオプションが内蔵されている。packaje.jsonにバックエンド側のポート番号(本書ではhttp://localhost:8000)を指定、fetchのコードでは/apiのようにドメインの後からだけの記述に。server.jsとして書いた基本コード内に記述。useEffect({実行する関数}, []); ただし空配列にしてもReact v18~では2回実行されるので注意。Client Side Routing
<Router><Routes>~</Routes></Router>要素内にパスと呼び出す子供のコンポーネントを書いていく。<a>要素で書くとブラウザの読み込みが発生、CSSなどのリソースをネットワークからもう一度取ってきてしまう。用意されている<Link to="">~</Link>を使うほうがよい。フロントエンド部分のデプロイ
> npm run build -w package/frontend で本番用のものができる。frontend/内に格納。GETリクエストは/でなく/* でindex.htmlを返すようにしておく。frontend/package.json 内に設定してコマンドで起動。本書の構成ではフロントエンド部分もNode.jsのサーバーで動かして、バックエンドもとはポート番号で分ける構成でやっています。2つあって慣れないうちはちょっと混乱しそうですね。
*.test.jsにGET /api/hoge が来たらこれを返すよ...というのを書き、その後にテスト本体も書く。src/Users.hook.jsとしている。それぞれをテストしやすくできる。この7章がなかなか長く本格的なのですが、React Hooks含めた最新のReactでの基本的な開発諸々~デプロイ~テストまで、様々な知見が詰まっていて非常に充実しています。フロントとバックは別リポジトリで別々に開発するのが普通かと思ってたんですが、今はモノレポの手法もあるんですねー。コラムにもいろんなお役立ち情報があってありがたいです。
> npm outdated で各パッケージがどれだけ古いか分かる。>npm auditで脆弱性チェック。>npm audit fix ですべて解決されるわけではないので注意。この8章は短いのですが実際の運用時の知見が詰まっています。ユーザー情報をキャッシュとして単に変数に入れておくと次のリクエストでアクセスできちゃったりするんですね。このへんかなり独特だなと思いました。他言語のバックエンド実装と同じ雰囲気でやっていると罠に嵌りそうです。

国産の本なので翻訳本特有のとっつきにくさもなく、文章も読みやすかったです。後書きによると作者さんもNode.jsを様々な案件で使い、慣れない頃は勉強会をやったり毎週泣きながらNode.js自体のソースを読んだり(ヒエッ...笑)したそうですが、そうした長年の経験に基づいた知見、独自の意見などもしっかり詰まっています。自分的には断片ごとには知っていたようなことも載っていたのですが、そうした断片が体系的に繋がり、知らなかったことが補完され、最近のアップデート分が上書き更新され、体系的に改めて整理できた感がありました。ちょうど勉強会でフロントエンド関連の話題をやろうと思っていたのでよいタイミングで読むことができました。
Node.js自体にモダンJavaScriptにReactにExpressにDBアクセスにユニットテストに運用とテーマ一式全部載せ、オールラウンドで詰まったおトクな本です。現役フロントエンドエンジニアの方もこれから挑戦する方も、バックエンドの方も、十分に役に立つことと思います。
本書から過去に遡っていくと...安心のオライリー本『ハンズオンNode.js』が2020/11。500ページ以上のしっかりした本です。
初心者向けの様々な超入門本を出している掌田津耶乃さんの『Node.js超入門[第3版]』が2020/7。その前の第2版が2018年で僕も読んだような...まあエンジニアが仕事で使うにはちょっと浅いシリーズですね。バックエンドのFWはExpress、DBアクセスにsequelizeが出てきます。
同じ超入門シリーズで『Node.jsフレームワーク超入門』が2022/5で新しい本。バックエンドでExpress、TypeScript夜のORMにPrisma、TypeORM。他にFWでSails.js、Adonis.js、NestJS、Meteorという珍しいテーマもあります。この辺をつまみ食いするにはよいかもしれません。
『Node.jsデザインパターン 第2版』が2019/5。こちらもがっつりしたオライリー本、Node,js v11.9を対象にガッツリと内部に踏み込んだ中級者以上向けの本。
『入門Node.jsプログラミング』も2019/9。こちらも同じく海外本、基本は分かっている中級者以上向けに様々なプロジェクトと共に解説していく本。
『サーバサイドJavaScript Node.js入門 (アスキー書籍)』は遡って2014年、うーんNode.jsが徐々に市民権を得てきた頃の唯一の本ですね。さすがに今となっては古いですね。(僕も前に読もうと思ってやめたことがあります...)
Node.js自体を扱った本というのは意外と少なかった感がありますが最近揃ってきました。超入門シリーズよりもっと深い本、かつ海外本特有のとっつきにくさがない国産本、そしてエンジニアが仕事で使うレベルの各種テーマを総合的に網羅した最新の本...という立ち位置でも、本書『実践Node.js入門 ―基礎・開発・運用』はちょうど良い位置にフィットするのではないでしょうか。
仕事で使うレベルのTypeScript自体の一冊というと2022/4に出たブルーベリー本こと『プロを目指す人のためのTypeScript入門 安全なコードの書き方から高度な型の使い方まで』がド定番、もしくは2020/3のオライリー本の『プログラミングTypeScript ―スケールするJavaScriptアプリケーション開発』の2冊が有名。
そして最近は2023/2の『フロントエンド開発のためのセキュリティ入門 知らなかったでは済まされない脆弱性対策の必須知識』、2023/4に出る『フロントエンド開発のためのテスト入門 今からでも知っておきたい自動テスト戦略の必須知識』と今まではなかった個別テーマの本も出てきました。
JavaScript自体の本というと2020/4の『JavaScript Primer 迷わないための入門書』が現場のエンジニアからも推奨されていましたが、その後オライリーのサイ本『JavaScript 第7版』が2021/12に出たり、前の版も評価の高かったJavaScript本格入門が2023/2に『改訂3版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで』と遂にアップデートされました。
一昔前まではフロントエンドは変化が早いから本が出ない!なんて言われていましたが、こうしてみると商業書籍もだいぶ陣容が揃ってきましたね。2023年現在では、学ぶ環境が成熟してきたといえるでしょうか。
id:iwasiman引退した元TRPGゲーマー。COBOLでもなくPL/Iの金融系レガシー紙駆動開発から脱出→国産メーカー系総合ITベンダーのITエンジニア。所謂SIerのSEだけど仕事はほぼソフトウェアエンジニア/ソフトウェアアーキテクトとして、Web開発でコードを書いたり技術を追ったり時々イベントに行ったり、楽しいエンジニアリングを目指しています。Views are my own.
お気軽にどうぞ~
リンク集:https://lit.link/iwasiman
AIイラスト関連の活動はこちら↓
https://www.chichi-pui.com/users/iwasiman/
https://pixiv.me/iwasiman
引用をストックしました
引用するにはまずログインしてください
引用をストックできませんでした。再度お試しください
限定公開記事のため引用できません。