の続きでDenoでCDKを動かしていきます
要約
- CDK CLIをDenoで動かすのはダメでした。
- 問題を回避しても非対応なNode APIが使われているため現状Denoでは動かなそう
- 以下書いてあるのは試行錯誤のメモです
CDK CLIもDenoにしたい
現状の構成ではCDKコード(なんと言うのが正しいのか不明)はDenoでしたが、
CDK CLIはNodeで動作しています。
CDK CLIもCDKコードの移行と同じノリで動かせないか試してみます。
トライアンドエラーの記録
素朴なインポート
確認のため単純に https://esm.sh/aws-cdk@2.26.0 をブラウザで開いてみます
/* esm.sh - error */
throw new Error("[esm.sh] " + "Could not resolve \"aws-cdk\"");
export default null;
うーんエラーですね。
ライブラリじゃないからindex.js
とかがないからですかね?
cdkコマンドをたどってみる
では実体のcdk
コマンドの中身はどうなっているのか。
#!/usr/bin/env node
require('./cdk.js');
cdk.js
をrequireしているだけでした。
では https://esm.sh/aws-cdk@2.26.0/bin/cdk.js ではどうでしょうか
/* esm.sh - error */
throw new Error("[esm.sh] " + "esbuild: Do not know how to load path: esm-build-6d6e3a2749ffb4e9ef8c71f2514eb00cdd2b9cf3-8f306217/node_modules/aws-cdk/bin/cdk");
export default null;
内容が変わりましたがエラーのままですね。
bin/
の下は取れないとかあるのでしょうか。
実装をたどる
うーんじゃぁ aws-cdk/bin/cdk.js
の中身は?
import { cli } from '../lib';
cli();
カンタンな実装で安心しました。
ここでimportしている https://esm.sh/aws-cdk@2.26.0/lib はどうでしょう?
/* esm.sh - aws-cdk@2.26.0/lib */
export * from "https://esm.sh/v85/aws-cdk@2.26.0/es2022/lib.js";
export { default } from "https://esm.sh/v85/aws-cdk@2.26.0/es2022/lib.js";
おっ、いけました。じゃぁこれを使うよう作れば行けるかも?
// cdk.ts (自前)
import lib from "https://esm.sh/aws-cdk@2.26.0/lib";
lib.cli();
import以外ほぼ同じコードを書いて実行します。
$ deno run --allow-all cdk.ts
<略>
error: Import 'https://esm.sh/v85/fsevents@2.3.2/deno/fsevents.js' failed: 500 Internal Server Error
at https://esm.sh/v85/aws-cdk@2.26.0/deno/lib.js:2:1763
エラーですね…
fsevents
ってOptional DependencyでLinuxで必要なくなかったですか?
(試している環境はGitHub CodespacesのDevcontainer上のLinuxです)
Optional Dependencyを除外できるといいんだけどな…
esm.shのIssueに上がっていましたので既知の問題のようです。
fseventsをダマす
通常Linuxでは必要ないんだからimportが満足したらなんとかなるのでは?
うまく騙せる方法はないでしょうか。
調べてみたところDenoにはImport mapsという機能があり、import参照先を差し替えられるようです。
これは使えそうなので試してみます。
まず、差し替え先となるfsevents-stub.js
を空ファイルで作ります。
// fsevents-stub.js
そして、それに差し替えるimport mapファイルを作成します。
(バージョンベタ書きですぐ壊れそう…)
// importmap.json
{
"imports": {
"https://esm.sh/v85/fsevents@2.3.2/deno/fsevents.js": "./fsevents-stub.js"
}
}
import mapオプションを渡して実行します。
$ deno run --allow-all --import-map=importmap.json cdk.ts
<略>
Check file:///workspaces/cdk-deno/cdk.ts
error: TS2300 [ERROR]: Duplicate identifier 'URLSearchParams'.
declare class URLSearchParams {
~~~~~~~~~~~~~~~
at asset:///lib.deno.url.d.ts:8:15
'URLSearchParams' was also declared here.
interface URLSearchParams extends _URLSearchParams {}
~~~~~~~~~~~~~~~
at https://cdn.esm.sh/v85/@types/node@16.11.33/url.d.ts:822:19 and here.
var URLSearchParams:
~~~~~~~~~~~~~~~
at https://cdn.esm.sh/v85/@types/node@16.11.33/url.d.ts:843:13
TS2300 [ERROR]: Duplicate identifier 'URL'.
declare class URL {
~~~
at asset:///lib.deno.url.d.ts:155:15
'URL' was also declared here.
interface URL extends _URL {}
~~~
at https://cdn.esm.sh/v85/@types/node@16.11.33/url.d.ts:823:19 and here.
var URL:
~~~
at https://cdn.esm.sh/v85/@types/node@16.11.33/url.d.ts:833:13
Found 2 errors.
おっ進んだ!!
でもTypeScriptのエラーですね…
そもそも@types/node@16.11.33
にエラーがあるのかビミョウですが、
これなら型チェックすっ飛ばせばなんとかなるのでは…
そもそもCLIは型チェックしなくていいと思うし。
型チェックを省略
TypeScriptの型チェックを省略する--no-check
オプションをつけて実行してみます。
$ deno run --allow-all --import-map=importmap.json --no-check cdk.ts
error: Uncaught SyntaxError: The requested module '/v85/fsevents@2.3.2/deno/fsevents.js' does not provide an export named 'default'
at <anonymous> (https://esm.sh/v85/aws-cdk@2.26.0/deno/lib/index.js:2:332)
また進んだ!
今度は差し替えたニセモノのfsevents
の問題のようです。
エラーからするとdefault exportしたなにかしらがあれば通りそう…
さすがに空じゃマズかったか…
fseventsをダマす その2
ということで修正。
// fsevents-stub.js
export default class A {}
そして実行。
$ deno run --allow-all --import-map=importmap.json --no-check cdk.ts
error: Uncaught Error: Not implemented: See https://github.com/denoland/deno_std/issues/1436
throw new Error(message);
^
at <anonymous> (https://deno.land/std@0.141.0/node/_utils.ts:22:9)
おーまた進んだ!
けど今度はdenoが明示的に投げてるエラーです…
DenoのNode互換はまだまだ
エラーメッセージで出てきたIssueはnodeのos APIがまだ実装されていないものがある、というものでした。
CDK CLIはDenoがサポートしていないNode APIを呼び出してしまったのでしょう。
コールスタックが出ていないのでどこでなんのAPIの呼び出しでエラーになったのかわからないですね…
AWSのクレデンシャル取るためのホームディレクトリの取得あたりが怪しいか?
まぁ今回はここらで諦めます…
感想
今までさっくり動いて来たけど、流石にそうカンタンに全部は動きませんよね。
むしろこうでなくっちゃ(?)
メモリ消費量がハンパなく試してる途中もOOM Killerに(?)Denoが殺されたり
動いたとしてもいいことがほぼなさそうです。
(aws-sdkとかの依存が重すぎる?)
当面はnodeをインストールするくらいの手間は受け入れましょう…
Nodeの互換性が改善された日にはまた試してみます。