Closed37

Package Managersについて学ぶ

tkrytkry

Package Managersって何してるの

なんとなくわかってるつもりだけど改めて勉強したいのでやる
https://roadmap.sh/frontend に記載されてる記事を読む

tkrytkry

Modern JavaScript Explained For Dinosaursを読む

エコシステムの歴史を学べる記事
2017年までの内容らしい

tkrytkry

node.js以前

  • htmlにscriptタグを書く
  • すべてのjsファイルはグローバルで扱われる
  • バージョンの追従が大変

JavaScriptパッケージマネージャー(npm)の使用

  • 中央リポジトリからライブラリをダウンロードしてアップグレードするプロセスを自動化する仕組み
  • npmはnode.js(サーバ)専用に作成されたマネージャー
  • package.jsonだけ共有すればよい、node_moduelesを共有しなくていい
  • これだけだと、HTMLにパスを指定しないといけないのが大変
tkrytkry

モジュールバンドラーの登場(webpackなど)

経緯

  • JavaScriptは別のファイルからコードをインポートする方法がなかった
    • セキュリティ上の理由からファイルシステムにはアクセスできず、ブラウザのみで動作するため
  • CommonJSはサーバでJSエコシステムを定義することを目標としたプロジェクト
    • ファイル間でインポート、エクスポートできるようになった
    • node.jsはその実装
  • サーバーは↑でよかったが、ブラウザではrequireが動かないから同じことができない

登場

  • そのため、requireステートメントを見つけてそれを置き換え、単一のバンドルされたJSファイルを作るモジュールバンドラーが必要になった
  • 単一のJSなのでパフォーマンス的によかった
  • ビルドステップで色々なことができるようになって便利だった
tkrytkry

トランスパイラの登場(babel)

  • トランスパイルとは、ある言語を別の類似言語のコードに変換すること
  • ブラウザは新しい機能を追加するのが遅いのでトランスパイル可能な新しい言語が作成された
  • CSS
    • Sass, Less, Stylus
  • JS
    • TypeScript
    • CoffeScript
  • babelは次世代のJSをES5に変換するトランスパイラ

babel

  • @babel/core:主要部分
  • @babel/preset-env:どの新しいJS機能をトランスパイルするか定義する
  • babel-loader:webpackで動作できるようにするパッケージ
tkrytkry

タスクランナーの使用(npmスクリプト)

  • ビルドプロセスを自動化するもの
  • タスク
    • コードの縮小
    • イメージの最適化
    • テストの実行
tkrytkry

webpackのローダーという概念がよくわからない

tkrytkry

how-to-npm

  • 作業環境構築からモジュールの公開まで学べるらしい
  • 面白そう
tkrytkry

USAGEうまくいかない

  • globalにインストールしたくない
  • インストールしてもvolta?に干渉してかうまく動かなかった
  • git cloneして中身を眺めることにした
    • 日本語化もされてるらしい
tkrytkry

ざっと眺めてみた
npmにpublishする方法とか書いてあるっぽかった

tkrytkry

Meet PNPM: The Faster, More Performant NPM

  • pnpmについて簡潔に紹介する記事
  • 「Performant NPM」の略らしい
tkrytkry

PNPMとは何ですか?

PNPM の主な目的は、すべてのパッケージをグローバル (集中型) ストアに保持し、必要に応じてハード リンクを作成して他のプロジェクトでも使用することです。

NPM よりも PNPM を使用する利点

膨大なディスク容量を節約します。
パッケージのインストールにかかる時間が短縮されます。
mono リポジトリのサポートが組み込まれています。

tkrytkry

Getting Started | Yarn

yarnの基本を学ぶ

tkrytkry
  • v2.0以前のドキュメントらしい
  • 基本的なコマンドの使い方が書かれていた
tkrytkry

Intro

知らない機能がたくさんあるんだなぁ

  • 重点分野
    • 速度
    • 正確性
    • セキュリティ
    • 開発者体験
  • 機能
    • ワークスペース
    • オフラインキャッシュ
    • 並列インストール
    • 強化モード
    • 対話型コマンド
tkrytkry

インストールと使用方法

特に真新しいものはないけど、Corepackが必要らしい

tkrytkry

この記事の人の調査力凄すぎる...笑
時系列でとてもわかりやすかった

ざっくり要約

  • 重複削除(deduplication, 略してdedupe)
    • 単純に依存関係を全てインストールする問題に対処
    • 重複するものはhoistingしてnode_modulesの直下に置かれるようになった
  • 木構造が不変のアルゴリズムとlockファイル
    • node_modulesをインストール順やパッケージマネージャの順番に依存することなく再現可能になった
  • シンボリックリンク方式
    • 依存関係をシンボリックリンクで表現することでパフォーマンスを向上した
      • もともとnpmも検討してたけどnodeのバグを避けるために採用が見送られたっぽい
    • pnpmで採用
    • npmにも取り込まれる
  • yarn PnP
    • node_modulesを作らない方式
    • Module.loadをオーバーライドする(?)
  • npm v7でインストール順に依存しなくなった
tkrytkry

Yarn PnP

  • ざっくりはわかったけどよくわからないのでドキュメントも眺める
  • あんまりよくわからなかったかも...

メリット

  • node_modulesが不要になる
  • .pnp.cjsがNode.js loader fileになる(?)らしい
    • loaderはモジュールの読み込み方法をカスタマイズするための機能(GPT曰く?)
  • ディスク上のすべてのプロジェクトで同じパッケージ成果物を利用
    • キャッシュパスを介して参照するので複雑さが軽減(?)
  • hostingが完全になる(?)
  • セマンティックなエラーメッセージ
    • これは嬉しそう
tkrytkry

Yarn PnP試してみる

  • voltaで管理してるので、corepackyarnを入れた
  • initする
yarn init -2
// 2って何?
  • ディレクトリにファイルが作成される
    • package.json
    • yarn.lock
    • .yarnrc.yml
    • .pnp.cjs
      • これはgit対象外
      • 中身を覗くと色々処理の書いてあるただのjsファイル
tkrytkry
  • -というダミーのnpmパッケージを入れてみる
  • RAW_RUNTIME_STATEに差分あり

  • RAW_RUNTIME_STATEは下記で使われている
function $$SETUP_STATE(hydrateRuntimeState, basePath) {
  return hydrateRuntimeState(JSON.parse(RAW_RUNTIME_STATE), {basePath: basePath || __dirname});
}
  • 最終的にはdefaultApiというexportされてるインスタンスで使われてる
  • これがModule.loadをpatchしているという話(?)なのかな
    • ここら辺はよくわからんので諦める
tkrytkry

Corepackとは

  • パッケージマネージャのバージョンを定義できるNode.jsのツール
  • yarnとpnpmで推奨してる
  • 実験段階で、オプトインなのでcorepack enableが必要
  • voltaは現在統合されていない
    • あれ、普通にvoltaでcorepackインストールしたけど、何かあるのかな
tkrytkry

corepackとvolta、みたいな組み合わせの記事ちらほらあるけどやったほうがいいんだろうか

tkrytkry

package.jsonにenginesでnodeのバージョンを指定できるらしい
enginescorepackだけでvoltaの代わりにならないんだろうか

tkrytkry

Workspace機能について

monorepoのときに選択肢として聞くけど、何ができるかわかってないので簡単に確認しておく

tkrytkry

npm workspace

Getting started with workspaces

試しにやってみた

.
├── lib
│   └── index.js
├── node_modules
│   ├── abbrev
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── lib
│   │   │   └── index.js
│   │   └── package.json
│   ├── test-a -> ../packages/test-a
│   └── test-b -> ../packages/test-b
├── package-lock.json
├── package.json
└── packages
    ├── test-a
    │   ├── index.js
    │   └── package.json
    └── test-b
        └── package.json

This set of features makes up for a much more streamlined workflow handling linked packages from the local file system. Automating the linking process as part of npm install and avoiding manually having to use npm link in order to add references to packages that should be symlinked into the current node_modules folder.

次の一連の機能により、ローカルファイルシステムからリンクされたパッケージを扱う際のワークフローが大幅に簡素化されます。npm installの一部としてリンクプロセスを自動化し、手動でnpm linkを使用して現在のnode_modulesフォルダにシンボリックリンクを追加する必要がなくなります。(GPT翻訳)

  • node_modulesの中はリンクになってる
  • abbrevtest-aでインストールしたものだけど、一番上のnode_modulesに実態がある
// ./lib/index.js
const moduleA = require('a')
console.log(moduleA) // -> a

確かに普通にモジュールとして呼べるようになってる

tkrytkry

yarn v1 workspace

npm workspaceと同じっぽかった(どっちが先かはわからないけど)

yarn v4 workspace

いつ使うか

  • yarnはworkspace機能をドックフーディングして運用してる
  • babelやjestも使ってる

宣言方法

v1でもできるって書いてあったな

{
  "workspaces": [
    "packages/*"
  ]
}

相互依存

workspace:プロトコルでいい感じにできるらしい

{
  "dependencies": {
    "@my-org/utils": "workspace:^"
  }
}
tkrytkry

pnpm workspace

  • pnpm-workspace.yamlファイルで独立して定義する

workspace protocol

link-workspace-packagesがtrueに設定されている場合、利用可能なパッケージが宣言された範囲と一致していれば、pnpmはワークスペースからパッケージをリンクします。例えば、barの依存関係に"foo": "^1.0.0"が含まれており、foo@1.0.0がワークスペース内に存在する場合、foo@1.0.0がbarにリンクされます。しかし、barの依存関係に"foo": "2.0.0"が含まれており、foo@2.0.0がワークスペース内に存在しない場合は、foo@2.0.0がレジストリからインストールされます。この動作により、多少の不確実性が生じます。

  • ワークスペースのライブラリのバージョンと、ルートプロジェクトのライブラリのバージョンが違う時、勝手にレジストリからインストールされるらしい
  • workspace:を使えば、ワークスペースからの依存に指定できる

Usage examples

モダンなUIフレームワークメタフレームワーク、だいたいpnpmやんけ...
https://pnpm.io/workspaces#usage-examples

このスクラップは2024/08/17にクローズされました