Node.js
Node.jsとは
Node.jsは ノンブロッキングI/O
という仕組みにより、「大量の小さな通信」の処 理を得意としており、チャットアプリや小規模なゲームのサーバープログラム開発言語として用いられることが増えている。
また、クライアントサイドと同じJavaScriptでサーバーサイドのプログラムを書けるため、新たにサーバーサイド言語を覚える必要がないという利点もある。
Moduleのキャッシング
キャッシュがパージされる瞬間については記載がないが、基本的にプロセスが死ぬまではキャッシュされ続ける様子。
Node.js の require はキャッシュされるよ
リファレンス
JavaScriptファイルは一般的に「モジュール」と呼ばれますが、正確にはそのファイルのエクスポート機能を利用している場合にモジュールとして扱われる。
JavaScriptにおいてモジュールとは、他のファイルに対して関数や変数、クラスなどをエクスポートして再利用可能にしたもの。
モジュールを使うことで、コードを機能ごとに分割して管理でき、可読性や保守性が向上する。
誤った使用法
トップレベルアクセス
Node.js
のモジュールはキャッシュされるため、どのモジュールのトップレベルでもALSにアクセスしないでください。
メソッドの結果をHttpContext.getOrFail()最上位レベルの変数に割り当てると、モジュールを最初にインポートしたリクエストへの参照が保持されます。
import { HttpContext } from '@adonisjs/core/http'
const ctx = HttpContext.getOrFail()
export default class UsersController {
async index() {
ctx.request
}
}
トップレベルアクセスの意味
トップレベル:ファイルの一番外側のスコープ(グローバルスコープに相当)
モジュールのトップレベルとは、export defaultやclass、functionの外側の場所。
ファイルをインポートした際、このトップレベルのコードは即時実行され、Node.jsのキャッシュ機能により、最初のリクエスト時の状態がキャッシュされ続けるという問題がある。
静的プロパティのアクセス
どのクラスの静的プロパティ (メソッドではない) も、モジュールがインポートされるとすぐに評価される。
import { HttpContext } from '@adonisjs/core/http'
import { BaseModel } from '@adonisjs/lucid'
export default class User extends BaseModel {
static connection = HttpContext.getOrFail().tenant.name
}
なぜ遅延インポートするのか
- 起動時のパフォーマンス向上
アプリケーションの起動時にすべてのコマンドを一度に読み込むと、不要なコマンドも含めてメモリを使ってしまい、時間がかかる。
() => import(...)
を使うことで、実際にコマンドが必要になったタイミングで読み込むため、起動時の負荷を減らします。 - メモリ使用量の最適化 一度にすべてをロードしないことで、メモリを無駄遣いせず、必要なときだけ対象を読み込みます。
- 動的なロードが可能 JavaScriptやTypeScriptではimportを関数として使うことで、必要なときにそのモジュールを非同期で読み込むことができる。。 このため、メモリ使用効率が高くなると同時に、特定の状況でのみ利用するコマンドを動的に呼び出せるようになる。
export default defineConfig({
commands: [
() => import('@adonisjs/core/commands'),
() => import('@adonisjs/lucid/commands'),
() => import('@adonisjs/bouncer/commands'),
],
});
Tips
Node.jsのTipsまとめ。
Node.jsのREPL環境をカスタマイズする
npm 便利スクリプト
Browserslistの更新を要求された場合
Node stream api
Streamのメリットは大きな容量のファイルを読み取り・書き込み・加工する際にちょっとずつ処理することで最大メモリ使用量を抑えることがメリット。
nodeのversion上げ方
AsyncLocalStorage
AsyncLocalStorageとusingで快適に構造化ロギングしたい話