結局 Chrome 拡張では ESModule が使えるのか

背景とか AI とか

たまに Chrome 拡張開発をするのだが、その度に混乱することがある。 それが ESModule を使うのか CommonJS を使うのか、ということだ。

昨今は仕事でもプライベートは基本的に ESM を使っていて、 require なんて全く見なくなった。 だから油断すると import 文を書いてしまうわけだが、 Chrome 拡張機能においては Cannot use import statement outside a module というエラーに見舞われる。もはやトラウマものである。

error がたくさん出る

この件を AI や AI Editor に聞いてみると、やれ ESModule は使える、指定するファイルが悪いので直しましょうか、など言われるが、どれも検討違い。 AI に任せても今は解決するフェーズにないらしい。

おそらくだが Chrome 拡張機能に関しては "実装→結果を確認→実装を修正" というフィードバックループを回すことができず、インターネットの断片的情報だけしか学習データを持っておらず、 AI の苦手分野なのだと思う。

Gemini Pro 3 がマルチモーダルへの対応性能を見せ、 Antigravity が画面の操作を AI Feedback loop の中に持ち込めるようになったのが先月で、AI 性能はまだブラウザそのものを AI で操作する範囲に収まっており、Chrome 拡張を load して自動で開発を行うフェーズには至っていない(あるいは興味を向けられていない)

本題

AI への脱線はこれくらいにして、本題というか知識。

Chrome 拡張機能で使われる主なファイルそれぞれについて、対応しているモジュールシステムが違う

content scripts : manifest の content_scripts で静的に登録される「普通のスクリプト」であり、ページに埋め込まれるスクリプトと同様に扱われるため、 import を直接書いてもモジュールとして扱われない。

background : ESModule は利用可能。Manifest V3 から background は service worker になり、type: "module" を指定すると import/export が使えます。

popup / options の HTML : popup.html に <script type="module"> を置けば ESModule が使える。

ということで、冒頭の Cannot use import statement outside a module は content_scripts にて import 文があると発生するエラー。

さて、content scripts についても ESModule で実装した上で import 文が出ない様に webpack でバンドルすればいいじゃんという話はあるが、それは AI が答えてくれるので筆を譲ることにする。

mise で fzf を入れる

package 管理をできるだけ mise に寄せてみようと思っています。

ということでタイトルのことを実行しようとすると、以下がコマンド。

mise install fzf@latest
mise use -g fzf@latest

shell から使いやすくするにはもう一手間必要です。

以前は fzf install コマンドがあった記憶ですが(AI に聞くと install コマンドをメインに教えてくれます)、今は .zshrc に1行追加すれば良くなっています。

# Set up fzf key bindings and fuzzy completion
source <(fzf --zsh)

以上です。

最近は別のツールがあったりするんでしょうか。

MacBook を買って最初にやった設定

新しく MacBook Air を買いました。 (もちろん Pro がよかったのですが、あまりに高すぎて買えませんでした。)

仕事では MacBook を 5年ほど使っていますが、自分で買うのは初となります。

最初にセットアップしたことについて備忘録として書いておきます。 せっかく新しいPCを買ったので、やはり綺麗に保ちたいと思い、 home directory に入れるファイルをすくなくするようにしました。

App

Cursor

Cursor は使ったことがないので、入れてみました。

いままで VSCode 利用者でしたが、 Copilot が標準搭載されたことで、デフォルトだと会社の GitHub Copilot のシートが個人開発でも適用されてしまうのが悩みで、(数ヶ月前の時点では)解決策がなかったので、今回そういう面倒なことを考えなくても良い Cursor に初挑戦です。

Cursor を開いたら右上の歯車アイコンから「Privacy Mode」に設定しました。

どうやら Cursor セットアップウィザード中に CLI コマンドのインストールをスキップしたらしく、後から自分で symlink を貼りました

ln -s /Applications/Cursor.app/Contents/Resources/app/bin/cursor ~/.local/bin/cursor

Slack

desktop 版が好みです。 Web からダウンロードしました。

Docker

Docker Desktop を Web からダウンロード&インストールします

Raycast

Alfred を使っていたが、乗り換えてみました。

Clipy 相当のことをできるらしいので、copy board 用に新しいアプリを入れなくても良い点も評価しました。

Alfred はブラウザの Bookmark 検索がとても便利で、わざわざ移行するには捨てがたかったのですが、今回を機に Raycast を試すことにしました。

Searching Bookmarks in Chrome and Firefox - Alfred Help and Support

karabiner-elements

外付けキーボードとマウスは標準設定だと大きく体験がことなるので、 key 設定やスクロールの設定を変更するために使っています。

keyboard

  • ctrl/command キーの再配置
  • 変換/無変換キーを かな/英数 に再配置

マウス - スクロールの方向を逆にする

package

Command Line Developer Tools(CLT)

厳密な役割はあまりよくわかっていませんが、 Mac を使う時は必要になります。 git や homebrew はこれがないと使えません。 git コマンドなどを使うとポップアップが出てくるので、install ボタンを押しました。

mise

Getting Started | mise-en-place

curl https://mise.run | sh

基本となる package manager として mise を使うことにしました。 過去には anyenv, asdf など利用してきましたが、 .*rc ファイルが汚れるのがあまり好きではなかったので、今回を機に mise を使うことにしました。 一度入れてしまうと乗り換えが大変というのが悩ましいです。(前のPCは asdf のままになっている)

gh

mise install gh
mise use gh

github に login する

gh auth login

git にも認証情報をセットアップ

gh auth setup-git

ghq

GitHub - x-motemen/ghq: Remote repository management made easy

mise install ghq
mise use ghq

その他

mise install jq
mise use jq
mise install gh
mise use gh
mise install peco
mise use peco

コマンド・エイリアス

自分がよく使っているエイリアスを登録しておきます。

~/.config/zsh/ を作ってそこに整理し

~/.zshrc
~/.config/zsh/aliases.zsh
~/.config/zsh/functions.zsh

そして .zshrc から読み込みます

# ~/.zshrc

# load custom configs
source ~/.config/zsh/aliases.zsh
source ~/.config/zsh/functions.zsh

本体設定

ググって出てきた内容を元に好みで進めました

Mac歴10年が教えるMacを買ったら最初にやるべきオススメ設定14選 | AIじゃないよ

"knip" を始めて知ったので備忘録

knip というツールを知ったので、備忘録としてまとめておく。 知っている人にとっては特に得るものは無いと思うので、ご留意いただきたい。

knip.dev

knip とは

一言でどんなツールか

JavaScriptとTypeScriptプロジェクトの「未使用コード・依存を自動検出してくれる静的解析ツール」 以前使われていたts-pruneはメンテナンスモードに入り、未使用の依存関係や相互再帰的なデッドコードを検出できないなどの制限があった

いつできたツールか

v1リリースが 2023/1/10 なので、今日時点で2年半経っている。 最新版は v5.62 で、5.0.0 は 2024/2/10 なので、高頻度でリリースを繰り返していることが分かる。

目的・解決しようとした課題

長期でメンテするプロダクトで生じる課題「デッドコードが溜まり、ビルドサイズ増大や保守性の低下が発生」を解決しようとしている。

既存ツール(ts-prune)はメンテナンスモード

注意点

動的に使用されるコードはカバーできないので、最終的に削除は人間の判断に委ねられている。

2025/7 時点では開発が活発でコミュニティでも信頼されているが、個人(Lars Kappert)ベースではありそう

感想

人が手動で実施する業務ではないし、中長期で価値を生むコードを書きたいと望むエンジニアには良いツール。

一方でそもそも動的な実行システムやコンパイル時にチェックできるのであれば発生しない問題でもあると思う。

Terraform MCP Server を Claude Code から動かす

terraform のコードを AI に任せると、うまくいかないことが多い感覚はないでしょうか?

必ずしも 100% の解決とはいきませんが、多少改善する方法として、MCP を使って公式 document を読ませる方法を紹介します。

MCP の説明は割愛します。

MCP server の pull

(2025/06/28 時点)

$ docker pull hashicorp/terraform-mcp-server
Using default tag: latest
latest: Pulling from hashicorp/terraform-mcp-server
b0f6f1c319a1: Pull complete 
50222a595f96: Pull complete 
Digest: sha256:9b01dbb948b9362575b9fb7d70fac1739365eeae5d7b264db809f4b11b5da6c3
Status: Downloaded newer image for hashicorp/terraform-mcp-server:latest
docker.io/hashicorp/terraform-mcp-server:latest

https://hub.docker.com/r/hashicorp/terraform-mcp-server/tags

Claude Code に MCP サーバーを登録

shell で以下を実行

$ claude mcp add terraform-mcp-server -s project -- docker run -i --rm hashicorp/terraform-mcp-server
Added stdio MCP server terraform-mcp-server with command: docker run -i --rm hashicorp/terraform-mcp-server to project config

-s project は scope の指定です。 MCP は数が多いと AI が混乱するので、制限したほうが性能に期待できます。そのため、 project ごとに設定することをおすすめします。

上記コマンドで、以下のファイルが生成されます

{
  "mcpServers": {
    "terraform-mcp-server": {
      "type": "stdio",
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "hashicorp/terraform-mcp-server"
      ],
      "env": {}
    }
    
  }
}

実践

App Runner の auto_scaling_configuration について雑に聞いてみます

$ claude
> what is auto_scaling_configuration? 
● I'll help you understand the auto_scaling_configuration in Terraform. Let me search for information about this resource
  using the Terraform MCP server.

● terraform-mcp-server:resolveProviderDocID (MCP)(providerName: "aws", providerNamespace: "hashicorp", serviceSlug:
                                                 "auto_scaling_configuration", providerDataType: "resources")

● terraform-mcp-server:resolveProviderDocID (MCP)(providerName: "aws", providerNamespace: "hashicorp", serviceSlug:
                                                 "auto_scaling_configuration", providerDataType: "resources")
  ⎿  Available Documentation (top matches) for resources in Terraform provider hashicorp/aws version: 6.0.0
● auto_scaling_configuration is an AWS App Runner resource that controls how your application scales in response to
  traffic.

  Key parameters:
  - max_concurrency: Maximum requests per instance before scaling up
  - max_size: Maximum number of instances (default 25 in your variables)
  - min_size: Minimum number of instances (default 1 in your variables)

  Your App Runner service currently uses default auto-scaling settings. To add custom scaling, you'd create an
  aws_apprunner_auto_scaling_configuration_version resource and reference it in the service.

参考

github.com

docs.anthropic.com

Ubuntu への tfenv/terraform installation の備忘録

久しぶりに使うマシン (Ubuntu) の terraform が古かったので、入れ直すことにした。

既に install されている terraform の unisntall

おそらく apt-get だろうが、 どうやって install したか覚えていないので探ってみる。

$ which terraform
/usr/bin/terraform
$ dpkg -l | grep terraform
ii  terraform                                     1.11.4-1                                               amd64        Terraform enables you to safely and predictably create, change, and improve infrastructure. It is a tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.

出力が出たので、 apt で入れたことが分かる。

$ sudo apt remove terraform

tfenv の install

依存関係の解決が発生すると面倒なので、package manger を使うより、 git から manual install するのが良いのではないかと思っている。

github.com

$ git clone --depth=1 https://github.com/tfutils/tfenv.git ~/.tfenv
$ echo $SHELL
/bin/bash
$ echo 'export PATH="$HOME/.tfenv/bin:$PATH"' >> ~/.bash_profile

terraform の install

$ tfenv install latest
Installing Terraform v1.11.4
Downloading release tarball from https://releases.hashicorp.com/terraform/1.11.4/terraform_1.11.4_linux_amd64.zip
################################################################################################################################################################################################## 100.0%
Downloading SHA hash file from https://releases.hashicorp.com/terraform/1.11.4/terraform_1.11.4_SHA256SUMS
Not instructed to use Local PGP (/home/uchida/.tfenv/use-{gpgv,gnupg}) & No keybase install found, skipping OpenPGP signature verification
Archive:  /tmp/tfenv_download.52tYPC/terraform_1.11.4_linux_amd64.zip
  inflating: /home/a2/.tfenv/versions/1.11.4/LICENSE.txt  
  inflating: /home/a2/.tfenv/versions/1.11.4/terraform  
Installation of terraform v1.11.4 successful. To make this your default version, run 'tfenv use 1.11.4'

asdf ? tenv ?

asdf は使っていましたが、shell の治安が悪くなったり、コマンドを忘れたりで意外と管理が楽にならなかったため、やめようとしています。

tfenv は新規開発が止まっており、古いという話があるようです。

新しいTerraformのバージョンマネージャー tenv を試してみた | DevelopersIO

後継として規模感もあるのが tenv OpenTofu にも焦点を当てているため、Terraform のみを使いたい場合は機能過多に感じる可能性あり

GitHub - tofuutils/tenv: OpenTofu / Terraform / Terragrunt and Atmos version manager

tfswitch というツールもある模様。 一応コードは公開されているが、利用者がすくないのは不安も残る

GitHub - warrensbox/terraform-switcher: A command line tool to switch between different versions of terraform (install with homebrew and more)

terraform 以外もまとめて管理するツールとして、 aqua というツールも出てきた。

そもそも

元々 1.11.4 が入っていたので、 install し直す必要はなかったというオチ

terraform の tfstate をAWS 管理する場合の s3 bucket / DDB 設定

S3 の作成

tfstate を管理する S3 は手動、ないし別の terraform で作る必要がある。

複数の環境で作ったり、再利用する際に便利で安定するので、api で作っておくと良い。

バケット作成 S3 はグローバルなイメージがあるが、名前空間をグローバルに一意にする必要があるだけで、実際には region 指定するので注意。

aws s3api create-bucket \
  --bucket <name>-<region, env, account name など> \
  --region ap-northeast-1 \
  --create-bucket-configuration LocationConstraint=ap-northeast-1

デフォルトで public access はブロック、ACL は無効にされている。

タグ指定

aws s3api put-bucket-tagging \
  --bucket your-bucket-name \
  --tagging 'TagSet=[{Key=project,Value=xyz},{Key=env,Value=dev}]'

terraform 1.10 以前は lock のために DynamoDB を利用する必要があったが、 terraform 1.11 以降は S3-native state locking という機能が導入されており、 S3 で完結させられるようになった。便利。

Backend Type: s3 | Terraform | HashiCorp Developer

この際、bucket versioning を有効にすることが強く推奨されている。(bucket versioning を有効にする理由は他にもいくつもある)

aws s3api put-bucket-versioning \
  --bucket your-bucket-name \
  --versioning-configuration Status=Enabled

put-bucket-versioning — AWS CLI 2.27.2 Command Reference

terraform file

S3 ができたら、terraform ファイルを書き始められる。

backend.tfuse_lockfile を指定しているのが、 DynamoDB を不要にする設定となる。

versions.tf

terraform {
  required_version = ">= 1.11.4"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.96.0"
    }
  }
}

provider.tf

provider "aws" {
  region = "ap-northeast-1"
}

backend.tf

terraform {
  backend "s3" {
    bucket         = your-bucket-name
    key            = "terraform.tfstate" # 複数の tfstate を管理するなら {project-name}/terraform.tfstate 等にしても良い
    region         = "ap-northeast-1"
    use_lockfile = true  # S3-native state locking
  }
}

tree 構造

.
├── backend.tf
├── versions.tf
├── provider.tf
└── main.tf

動作確認

以上で完了。

現状だと resource が何も無いので、動作の確認をするために dummy の s3 を作ってみる。

main.tf

resource "aws_s3_bucket" "dummy" {
  bucket = "terraform-dummy-${random_id.suffix.hex}"
}

resource "random_id" "suffix" {
  byte_length = 4
}

実行すれば、毎回 S3 の差分が出るのが分かる。

terraform init
terraform fmt
terraform validate
terraform plan
terraform apply

備忘録

当初 key の値を {project-name}/terraform.tfstate と記載し、あとから terraform.tfstate に変えた。この際、backend の記述を変更したことで、 migrate が必要になった

terraform init -migrate-state

s3api の --create-bucket-configuration option は us-east-1 では指定するとエラーになる

おわりに

AI で tf ファイルを書かせたり相談するとまだ DynamoDB を使う方を提案されるので、新しい便利でシンプル書き方というのは明確に AI の弱みに感じた。