Tae

最近在寫 tae. 這是一個能抓取 Bang 並顯示網址的程式。

為什麼叫做 tae 呢?首先,因為 BanG Dream! 有一個叫 Hanazono Tae 的角色很可愛。再來,因為程式一開始是用 TypeScript 寫的。

那為什麼不用 TypeScript 了呢? Well, TypeScript 在抓取未定義的變數時,確實很好用;但說來說去,TypeScript 還是要用編譯器產生;而經手的編譯器越多,越容易出狀況。

這次的狀況是,我要用一個叫 open 的專案。結果卻出了狀況,說 open 不能用:

tae> npm run cli !g Google

> tae@1.0.0 cli
> node cli.js !g Google

tae\cli.js:2
const open = require("open");
             ^

Error [ERR_REQUIRE_ESM]: require() of ES Module tae\node_modules\open\index.js from tae\cli.js not supported.
Instead change the require of index.js in tae\cli.js to a dynamic import() which is available in all CommonJS modules.
    at Object.<anonymous> (tae\cli.js:2:14) {
  code: 'ERR_REQUIRE_ESM'
}

Node.js v19.3.0

那如果我從 tsconfig.json 修改 "module": "ES2015" 然後 "type": "module" 呢?又不成了:

PS tae> npm run cli !g Google

> tae@1.0.0 cli
> node cli.js !g Google

node:internal/errors:491
    ErrorCaptureStackTrace(err);
    ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'tae\build\modules\fs' imported from tae\build\BangList.js
    at new NodeError (node:internal/errors:400:5)
    at finalizeResolution (node:internal/modules/esm/resolve:260:11)
    at moduleResolve (node:internal/modules/esm/resolve:879:10)
    at defaultResolve (node:internal/modules/esm/resolve:1087:11)
    at nextResolve (node:internal/modules/esm/loader:161:28)
    at ESMLoader.resolve (node:internal/modules/esm/loader:834:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:415:18)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:77:40)
    at link (node:internal/modules/esm/module_job:76:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

Node.js v19.3.0

簡單來說,TypeScript 編譯時候忘記換副檔名了。結果 nodeJS 不接受 foo/bar 的路徑,非 foo/bar.js 要不可。程式就這樣報錯了。

沒辦法。這麼麻煩不如直接用原生 JavaScript 寫。


改用原生 JavaScript 寫之後就完成了嗎?想得美!像是 this 就卡了很久:

const main = (input = false) => {
    const foo = new Bar();
    const ajax = input ? foo.bar : foo.baz;
    ajax().then( ... );
}

結果卻發現 ajax 這個參數的 this 並不一定綁 Bar 實體。真惱人。沒法子,索性把請求清理的程式,分開來各自為政。

總之,真的很煩。