【日報】yarn workspacesとnuxt / vuepressを組み合わせるとnohoist必須、あと台風

 9月2日の日報です。yarn workspaces + nuxt = しんどいバグという話です。

yarn workspaces あれこれ

 タグボトル内部の構造を修正し、yarn workspace導入しました。ところがバグっていたので修正しました

 ワークスペースを導入すると、複数プロジェクトで利用するモジュールを一括して1つの node_modules に入れられるというわけです。最高そうですね! ということで使ってみます。

 実際にやってみると、workspacesの導入そのものは簡単です。各 package.json にバージョンを持たせるとか、name とディレクトリ名を一致させておくとか(?)、ルートのプロジェクトをプライベートにするなどの細かい点はありますが、特に難しいことはありません。

 ただ、ワークスペースを導入してからnuxt内部の依存関係の解決が全く動かなくなりました。雑なコピペで nohoist 1導入したら、ついでにvuepressまで壊れました

Error: [BABEL] /builds/tagbottle/tagbottle.com/node_modules/vuepress/lib/app/clientEntry.js: Cannot find module '@babel/helper-module-imports'

 job失敗の詳細ログはここにあります。

 雑な修正以前は、 @nuxtjs/pwa が見つからないよーという別パターンのバグを踏んで無事終了しました。どうやら様々なものを相対パスで拾っているっぽいですが、なんだか困りますね。

 もちろんのこと動かないままでは困るので、見よう見まねで nohoist オプションを理解してみました。 記載場所はルートの package.json です。

"workspaces": {
  "packages": [
    "documents",
    "functions",
    "hosting"
  ],
  "nohoist": [
    "documents/vuepress",
    "documents/vuepress/**",
    "hosting/nuxt-edge",
    "hosting/nuxt-edge/**",
    "hosting/nuxt-i18n",
    "hosting/nuxt-i18n/**",
    "hosting/@nuxtjs/pwa",
    "hosting/@nuxtjs/pwa/**"
  ]
},

 公式ブログが詳しいのですが(というか他のドキュメントはなさげ) nohoist は2つのパターンを組み合わせて記述していきます。

  • documents/vuepress: documents プロジェクトが依存する vuepress モジュールを documents/node_modules に置いたままにします。ただし vuepress が依存するモジュール群は親ディレクトリで一括インストールします。
  • documents/vuepress/**: documents プロジェクトが依存する vuepress モジュールがさらに依存するモジュール群 (@babel とか) を documents/node_modules に置きます。

 ここでは、nuxt vuepress が怪しいということで、それぞれ名指しで除外しています2

 今回は露骨にワークスペース導入によりビルドエラーが出たので、nohoist を修正しては yarn.lock を削除し、 yarn install からの様子見でさらに記述を追加し… という作業をしています。ぶっちゃけこれは、原因がワークスペース周りにあると確信しているからこそ実行可能な作業です。いつの間にか壊してしまって「なんかおかしい、どこか壊れた…」レベルだと、これはなかなか厳しいことになると思います。yarn 周りで依存が壊れることってあんまりないので、そもそも「依存が壊れているのでは?」と考えつくまでのコストが高そう。

 今回は久しぶりにまともな先行例のない問題を踏んでどえらい目に遭いましたので、日報に記載しておきます。

今後の作業

  • issue 1つずつ消化してリファクタリング

 地道にいきます。あと台風が通過したら再び東京に行きます。


  1. nohoist = no hoist = 上に巻き取らない

  2. なぜだかよく分かりませんが、公式記事のサンプルでは上記のように対象プロジェクトを明示せず、ざっくり ** で消し飛ばす設定になっています。勿論それで動くんでしょうが、その記載だと何を意図して記述しているのかがサッパリ分からないので、今回は上記のように明示的な書き方をしてみました