berry-typescript-project icon indicating copy to clipboard operation
berry-typescript-project copied to clipboard

TypeScript + Berry Project Playground

TypeScript + PnP + Workspace でプロジェクトを作ってみた。このREADMEは、その感触について書く。

使ってみた感想

  • npm とは完全に別系統に進化しつつある。互換があんまりない。
  • 今対応するのは時期尚早でアーリーアダプターだけでよい
  • pnp 対応でエコシステム全部見直す必要があり大変
  • workspaces 対応は素晴らしいので使っていきたい

pnp とは

https://classic.yarnpkg.com/en/docs/pnp/

node_modules にすべてのファイルを展開するのではなく、 .yarn/cache に zip ファイルを置く。なんやかんやあって hot cache で最大70% 速くなると↑ の記事には書いてある。その結果、 node_modules 内のパスで色々やる系のライブラリは色々と変更を迫られている。この記事もほぼ pnp 対応に費やされた。

大胆な変更だが、 npm 側にも tink というプロジェクトがあり、ほぼ同じような設計なので、npm でも似たような変更が予定されていた。ので、これ自体は yarn が勝手にやってるという感じでもない。

https://github.com/npm/tink

ただし、 npm 社は経営不安で大規模なレイオフを敢行するなどしており、tink は開発が止まっている。もはや npm tink を実装するエンジニアリソースがないのではないかと、個人的に疑っている。

初期化

mkdir newprj
cd newprj
yarn set berry
yarn init

jest

jest-pnp-resolver を使う

yarn add jest-pnp-resolver -D

module.exports = {
  resolver: require.resolve("jest-pnp-resolver"),
  transform: {
    "^.+\\.tsx?$": "ts-jest"
  },
  testRegex: "(/__tests__/.*)\\.test\\.tsx?$",
  moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node", "wasm"]
};

typescript + pnpify

vscode はデフォルトでは node_modules/@types/ の型を探索してしまうため、型定義ファイルが見つからない。これを pnpify で解決する。

yarn add @yarnpkg/pnpify
yarn pnpify --sdk # .vscode を書き換えられるので、コミットする必要がある

vscode で ts 拡張子のファイルを開き、右下の TypeScript のバージョン選択から、  Use workspace version: 3.7.5-pnpify を選択

これで VSCode 内で実行可能になった。

参考: https://yarnpkg.com/advanced/editor-sdks

pnp + webpack

pnp-webpack-plugin を使えば webpack も使える。

// webpack.config.js
const path = require("path");
const PnpWebpackPlugin = require(`pnp-webpack-plugin`);
module.exports = {
  resolve: {
    extensions: [".js", "json", ".ts", ".tsx", ".wasm"],
    plugins: [PnpWebpackPlugin]
  },
  resolveLoader: {
    plugins: [PnpWebpackPlugin.moduleLoader(module)]
  },
  entry: {
    main: path.join(__dirname, "packages/webapp/src/index")
  },
  output: {
    filename: "[name].js",
    path: path.join(__dirname, "dist")
  },
  module: {
    rules: [
      {
        test: /\.tsx?/,
        use: [
          {
            loader: "ts-loader",
            options: {
              transpileOnly: true
            }
          }
        ]
      }
    ]
  }
};

しかし一つ問題が発生した。packages/webapp を掘って、その下で yarn add webpack webpack-cli -D を行ったが、このディレクトリからの yarn webpack 実行時には webpack-cli が見つからず、 webpack の実行ができなかった。

おとなしくルートディレクトリにインストールした。

.gitignore

https://github.com/yarnpkg/berry/issues/454#issuecomment-530312089

.yarn/*
!.yarn/releases
!.yarn/plugins
.pnp.*
dist
node_modules

node_modules は発生しない…はずなのだが、webpack を使うと terser-webpack-pluginnode_modules/.cache を生成していた。これは単に無視していいと思う

workspaces

これに関しては yarn v1 よりはるかに素晴らしい。yarn v1 の workspaces はどの位置で yarn install を発行したかで頻繁に整合性が崩れていたが、 node_modules が生えずにルートディレクトリの.yarn/cache にちゃんとエイリアスが集約された。

packages/
  foo
  bar
  nested/
    nested-a
    package.json # "workspaces": ["packages/*"]
package.json # "workspaces": ["packages/*"]

この状態で foo から nested-a が import できた。(もとからできていたが、挙動が怪しかった)

ライブラリ作者の考えること

相対パスから node_modules を探索する系の処理を自前で書いてしまうと、基本的に berry では動かなくなる。