pnpm
は、npm
やyarn
よりも基本的に高速かつ小さいサイズでライブラリをインストールしてくれるnode.jsのパッケージマネージャーです。
当然のことながら、pnpmのことを知っている人の多くは可能であればpnpmを使いたいと思っているでしょう。
ですが、pnpmの欠点として、pnpmに対応していないライブラリが多く存在するという点がありました。
特に有名なのがstorybook
です。
昨今のチーム開発において、storybookは準必須といっても過言ではないライブラリであり、特にデザイナーと仕事をするのであれば必須かもしれないライブラリでしょう。そのstorybookはpnpmに対応していませんでした。
おそらく、storybookとpnpmを両立できないために、pnpmを使用してこなかったという方はそこそこいるんじゃ無いでしょうか。
本記事では、その問題を解消してみようと思います。
どうすれば解決するのか
環境
- node: 18.12.1
- @storybook/addon-actions: 6.5.14
- @storybook/addon-essentials: 6.5.14
- @storybook/addon-interactions: 6.5.14
- @storybook/addon-links: 6.5.14
- @storybook/builder-webpack5: 6.5.14
- @storybook/manager-webpack5: 6.5.14
- @storybook/react: 6.5.14
- @storybook/testing-library: 0.0.13
- storybook-css-modules: 1.0.8
- babel-loader: 8.3.0
- sass-loader: 13.2.0
解決方法
ざっくり言うと、loaderの参照をrequire.resolve
で囲みました。
参考例として、css moduleとsassを使用しているNext.jsのプロジェクトの 設定ファイルを記載します。
module.exports = {
"stories": [
"../**/*.stories.mdx",
"../**/*.stories.@(js|jsx|ts|tsx)"
],
"addons": [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-interactions",
],
"framework": "@storybook/react",
"core": {
"builder": "@storybook/builder-webpack5"
},
webpackFinal: async (baseConfig) => {
baseConfig.module.rules.push({
test: /\.scss$/,
use: [
require.resolve("style-loader"),
{
loader: require.resolve("css-loader"),
options: {
importLoaders: 1,
modules: {
localIdentName: "[local]___[hash:base64:2]",
},
},
},
require.resolve("sass-loader"),
],
});
return { ...baseConfig };
},
}
require.resolveは、対象のライブラリの絶対パスを返す関数です。
これを用いて正しい参照先を渡してあげることで、loaderを読み込めるようにしています。
そもそもなんでstorybookで使えないの?
昔から色々頑張れば使えなくもなかったらしいのですが、よく検索にヒットする解決策がおま環酷かったので事実上使えないに等しかったと記憶しています。
使えなかった理由は、Webpackでした。
解決策から逆算した推論なのですが、おそらく昔のwebpack4などではpnpm使用時にこれらの参照をうまいこと解決できていなかったのだと思われます。
確かに、pnpmとyarn等の違いってimport時の重複排除等なので、その辺は納得できる理由のような気がしなくもないです。
あまり詳しい実装までは調査の手が回らなかったのですが、調べた感じwebpack5である程度その辺りが改善されたらしく、require.resolveによる解決がうまく働くようになったらしいです。
個人的には、webpackもそろそろ次の世代に世代交代感が出ているので、アドオン等ではなく公式でesbuildに対応してくれるといいんですけども……
記事の作成には、こちらのissueを参考にしました
https://github.com/webpack/webpack/issues/5087