※スマホ対応はしてません。

npm installがENOENTとか変な失敗をするとき、VS Codeを閉じると良いかも。

カテゴリー: 開発環境

Windows/WSL1 + Ubuntu + VS Code という組み合わせでやってるんですが、しばしば npm install が失敗します。

npm ERR! code ENOENT
npm ERR! syscall rename
npm ERR! path /mnt/c/Users/ginpei/xxx/node_modules/@typescript-eslint/typescript-estree/node_modules/semver
npm ERR! dest /mnt/c/Users/ginpei/xxx/node_modules/@typescript-eslint/typescript-estree/node_modules/.semver.DELETE
npm ERR! errno -2
npm ERR! enoent ENOENT: no such file or directory, rename '/mnt/c/Users/ginpei/xxx/node_modules/@typescript-eslint/typescript-estree/node_modules/semver' -> '/mnt/c/Users/ginpei/xxx/node_modules/@typescript-eslint/typescript-estree/node_modules/.semver.DELETE'
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoent 

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/ginpei/.npm/_logs/2020-09-30T18_57_36_471Z-debug.log

なんか一時ファイルっぽいし謎ですね。

原因はよくわかってないんですが、どこか(どこだっけ)で「VS Code のファイル監視が悪さをしている」ような話を聞いたことがあって、実際 VS Code を閉じた状態でこういうエラーに出くわしたことはないです。

というわけで VS Code を閉じてみてください。

  1. VS Code を閉じる
  2. VS Code 以外のターミナルから npm install
  3. 完了したら、VS Code を開く

[Windows] VS Code を閉じた状態でターミナルを利用する

VS Code 内のターミナルで実行しているのに VS Code を閉じるとそのまま npm install も終了してしまうので、他のターミナルが必要です。

  1. cmd.exe … Windows 標準の黒い画面。wsl コマンドとかで WSL を開く
  2. Windows Terminal … Microsoft 謹製のターミナルアプリ。複数タブ等、諸々便利でおすすめ
  3. tmux … Linux 内で動くターミナル多重化アプリ。一言で言うと「閉じても終了しないセッションを作る」ことができる

tmux が一番便利だけど CLI に慣れてないとつらいと思うので、一般には Windows Terminal をお勧めしておきます。いずれにしろ入れておいて損はないです。

おしまい

「VS Code のファイル監視が~」の件、ちゃんとした情報源があれば教えてください。

JestでregeneratorRuntime is not definedと言われたら、regenerator-runtimeを入れる

カテゴリー: JavaScript

たぶん TypeScript のときだけ。というか Babel 使ってるときだけ。

エラー

it() がエラーになっちゃった。

    ReferenceError: regeneratorRuntime is not defined

      30 |       });
      31 |
    > 32 |       it("can read to own item", async () => {
         |         ^

詳細な再現条件は確認してないけど(内部で)ジェネレーター関数が利用されているとこうなるっぽい。

解決策

ポリフィルを入れて、

$ npm install -D regenerator-runtime

どこかで一度だけ import します。

import "regenerator-runtime/runtime";

たぶん setupFilesAfterEnv 設定で指定したスクリプトに書くことになるでしょう。

関連:

babel-polyfill ?

古い情報だと babel-polyfill を入れろというのがあるんだけど、このパッケージはもう非推奨 deprecated になってるので、regenerator-runtime の方を使ってください。

🚨 As of Babel 7.4.0, this package has been deprecated in favor of directly including core-js/stable (to polyfill ECMAScript features) and regenerator-runtime/runtime (needed to use transpiled generator functions):

🚨 Babel 7.4.0 ではこのパッケージは非推奨となりました。core-js/stable(ECMAScript 機能を代替する)や regenerator-runtime/runtime(トランスパイルされたジェネレーター関数の利用に必要)を直接含めてください。

core-js/stable の方は今回の件については不要です。

おしまい

フレームワークなしの自力でやると細かいところで引っかかるものですね。FW すごい。

参考

Cannot find module ‘firebase-admin’ from ‘index.cjs.js’と言われたらそのfirebase-adminをインストールする

カテゴリー: JavaScript

Firebase Firestore の試験書くのに @firebase/testing という npm パッケージがあるんだけど、どうやら先月2020年8月に deprecated になり新しい @firebase/rules-unit-testing というものに置き換えられたようです。

エラー

さっそく手元のコードを置き換えたところ、同じコードでエラーになってしまいました。

こちらがコード。かつて @firebase/testing 利用の頃はそのまま動いてました。

import { initializeAdminApp } from "@firebase/rules-unit-testing";
import "babel-polyfill";

it("is ok", async () => {
  const admin = initializeAdminApp({ projectId: "my-project" });

  try {
    const doc = admin.firestore().collection("items").doc("item-1");
    await doc.set({ name: "Item 1" });
    const ss = await doc.get();
    expect(ss.data()?.name).toBe("Item 1");
  } finally {
    await admin.delete();
  }
});

で、エラーです。

Cannot find module 'firebase-admin' from 'index.cjs.js'

      3 |
      4 | it("is ok", async () => {
    > 5 |   const admin = initializeAdminApp({ projectId: "my-project" });
        |                 ^

firebase-admin って何だよ index.cjs.js ってどこだよ。

解決策

勘で試したところ firebase-admin は npm パッケージで、それをインストールすれば解決しました。そっか。

$ npm install -D firebase-admin

クライアント側で使わないので dependencies じゃなくて devDependencies へインストールしておきます。

コードは変更なし

特に変えてないけどちゃんと動いてるっぽいです。

おしまい

node_modules/@firebase/rules-unit-testing/package.json を開くと件の firebase-admin は案の定 peerDependencies に含まれていました。

ずっとクライアント側の実装でばかり使っていたので firebase-admin は使ったことがなく気付かなかったけど、思いついて良かった。

問題を整理すると解決に繋がることが多いですね。勘も必要だけども。

参考

Module xxx in the setupFilesAfterEnv option was not foundと言われたら<rootDir>を足す。

カテゴリー: JavaScript

ここまでのあらすじ

Jest で試験前に import "@testing-library/jest-dom/extend-expect"; とかそういう準備をするじゃないですか、そういうのをやるために準備用ファイルを読み込むため setupFilesAfterEnv オプション使ったらエラーになりました。

エラー

package.json で setupFilesAfterEnv オプション付けました。

{
  "jest": {
    "setupFilesAfterEnv": [
      "src/setupTests.ts"
    ]
  }

そしたらこんなエラーに。

● Validation Error:

  Module src/setupTests.ts in the setupFilesAfterEnv option was not found.
         <rootDir> is: /mnt/c/Users/ginpei/projects/my-project

  Configuration Documentation:
  https://jestjs.io/docs/configuration.html

解決策:<rootDir> を足す

ファイルパスの最初に <rootDir> を足します。

{
  "jest": {
    "setupFilesAfterEnv": [
      "<rootDir>/src/setupTests.ts"
    ]
  }

これで動くようになりました。

ドキュメント

を読んだらまさにそう書いてありました。(翻訳されてないや。)


If you want a path to be relative to the root directory of your project, please include <rootDir> inside a path’s string, like "<rootDir>/a-configs-folder".

もしパスをあなたのプロジェクトのルートディレクトリーに対し相対的なものにしたい場合、パス文字列の中に <rootDir> を含めてください。例:"<rootDir>/a-configs-folder"

おしまい

ドキュメント読もうね案件でした。

こういう、一度設定したらもう触らない系の話はすぐ忘れちゃう。

参考

Puppeteerのpage._clientの代わりにcreateCDPSession()を使おう。

カテゴリー: JavaScript

全然 Puppeteer よくわかってないけどメモ書いておきます。

先にまとめ

といってもこれが全てだけど。

  • page._client は非公開 API なので避ける
  • await page.target().createCDPSession() で client オブジェクト取れる
  • CDP = Chrome DevTools Protocol

例

Before:

await page._client.send('Emulation.clearDeviceMetricsOverride')

After:

const client = await page.target().createCDPSession();
await client.send('Emulation.clearDeviceMetricsOverride')

おしまい

人のコード見てて page._client って何かなとか調べてるうちに DefinitelyTyped の 2018 年の issue を見つけました。なんで閉じないんだろ?

もっかい言うけど Puppeteer 素人です。CDP も知らない。

参考