Skip to content

Instantly share code, notes, and snippets.

@hatappo
Last active April 10, 2026 13:49
Show Gist options
  • Select an option

  • Save hatappo/5a90759beec091f983eead7dc83acfba to your computer and use it in GitHub Desktop.

Select an option

Save hatappo/5a90759beec091f983eead7dc83acfba to your computer and use it in GitHub Desktop.
Chrome Extension 開発の初期セットアップ手順メモ

Chrome Extension 開発の初期セットアップ手順メモ

このメモは、WXT + Svelte を使った Chrome Extension 開発の初期ベースラインを作るための手順を、日本語でまとめたものです。 特定プロジェクト固有の実装内容ではなく、開発を始める前段の共通セットアップに絞っています。

このベースラインで整うもの

  • WXT + Svelte の Chrome Extension 雛形
  • Node バージョンの固定
  • pnpm ベースの依存管理
  • Prettier による format 環境
  • ESLint による lint 環境
  • svelte-check による typecheck
  • vitest によるテスト基盤
  • VS Code 保存時の format / lint fix 設定

前提

  • macOS 想定
  • mise が使えること
  • pnpm が使えること
  • Chrome が使えること

Node は LTS 系に固定しておくのが無難です。 このメモでは mise.toml で以下のように 24 を固定します。

[tools]
node = "24"

1. リポジトリ作成

空ディレクトリを作って移動します。

mkdir my-chrome-extension
cd my-chrome-extension

Git を初期化します。

git init

2. Node バージョン固定

プロジェクトローカルで Node 24 を固定します。

mise use node@24

mise.toml が生成され、node = "24" が記録されます。

補足:

  • ローカルに奇数系 Node が入っていても、ツール互換性を考えると LTS 系に揃えた方が安定です
  • mise WARN gpg not found は環境によって出ることがありますが、この作業自体では致命的ではありません

3. WXT + Svelte 雛形生成

WXT の scaffold は wxt init を使います。

空ディレクトリなら、そのままルートに生成できます。

pnpm dlx wxt@latest init . --template svelte --pm pnpm

すでに docs/ などのファイルを置いていて、ルートが非空ディレクトリになっている場合は wxt init . が abort します。 その場合はいったん一時ディレクトリに生成してからコピーします。

pnpm dlx wxt@latest init tmp/wxt-starter --template svelte --pm pnpm
cp -R tmp/wxt-starter/. .

補足:

  • wxt init . は非空ディレクトリだと止まります
  • 一時ディレクトリ経由にすると、既存の docs/ やメモを残したまま scaffold を取り込めます
  • mv ではなく cp にしておくと、問題時に生成物を退避として残せます

4. 依存関係インストール

pnpm install

この時点では最低限の WXT / Svelte 雛形が入り、package.json には以下のような基本 script が入ります。

  • dev
  • build
  • zip
  • check
  • postinstall

5. .wxt の生成

最初に svelte-check を実行すると、./.wxt/tsconfig.json が未生成で失敗するケースがありました。 そのため、一度 wxt prepare を明示実行して型関連の生成物を作っておきます。

pnpm exec wxt prepare

6. 開発支援パッケージ追加

format / lint / test 基盤を整えるため、以下を追加します。

pnpm add -D eslint @eslint/js typescript-eslint eslint-plugin-svelte globals prettier prettier-plugin-svelte vitest

各パッケージの役割:

  • eslint: lint 本体
  • @eslint/js: ESLint 公式の基本ルール
  • typescript-eslint: TypeScript 向け parser / rule セット
  • eslint-plugin-svelte: Svelte ファイル向け lint
  • globals: browser / node / webextensions の globals 設定
  • prettier: format 本体
  • prettier-plugin-svelte: Svelte を Prettier で整形するためのプラグイン
  • vitest: テストランナー

7. format 方針

方針は以下です。

  • できるだけ Prettier のデフォルトを使う
  • Svelte 向け整形は prettier-plugin-svelte に寄せる
  • 明示設定は最小限にする
  • printWidth120
  • クォートは singleQuote: true

.prettierrc.json:

{
  "plugins": ["prettier-plugin-svelte"],
  "printWidth": 120,
  "singleQuote": true
}

.prettierignore:

.git
.wxt
coverage
dist
node_modules
tmp

8. lint 方針

方針は以下です。

  • ESLint の公式推奨をベースにする
  • TypeScript は型情報付き推奨ルールまで入れる
  • Svelte は eslint-plugin-svelte の flat config 推奨を使う
  • Prettier と競合する Svelte ルールは flat/prettier で抑える

eslint.config.js:

import js from '@eslint/js';
import { defineConfig } from 'eslint/config';
import svelte from 'eslint-plugin-svelte';
import globals from 'globals';
import tseslint from 'typescript-eslint';

const sharedGlobals = {
  ...globals.browser,
  ...globals.node,
  ...globals.webextensions,
};

export default defineConfig(
  {
    ignores: ['.wxt/**', 'coverage/**', 'dist/**', 'eslint.config.js', 'node_modules/**', 'tmp/**'],
  },
  js.configs.recommended,
  ...tseslint.configs.recommendedTypeChecked,
  ...svelte.configs['flat/recommended'],
  ...svelte.configs['flat/prettier'],
  {
    files: ['**/*.{js,mjs,cjs,ts,mts,cts}'],
    languageOptions: {
      globals: sharedGlobals,
      parserOptions: {
        projectService: true,
      },
    },
  },
  {
    files: ['**/*.svelte', '**/*.svelte.{js,ts}'],
    languageOptions: {
      globals: sharedGlobals,
      parserOptions: {
        extraFileExtensions: ['.svelte'],
        parser: tseslint.parser,
        projectService: true,
      },
    },
  },
);

補足:

  • .svelte に TypeScript を含む場合、parser: tseslint.parser を明示しないと ESLint が落ちるケースがありました
  • recommendedTypeChecked を使うなら projectService: true を合わせるのが前提です

9. npm scripts 整備

元の checktypecheck へ変更し、以下を追加します。

{
  "scripts": {
    "dev": "wxt",
    "dev:firefox": "wxt -b firefox",
    "build": "wxt build",
    "build:firefox": "wxt build -b firefox",
    "zip": "wxt zip",
    "zip:firefox": "wxt zip -b firefox",
    "format": "prettier . --write",
    "format:check": "prettier . --check",
    "lint": "eslint .",
    "lint:fix": "eslint . --fix",
    "typecheck": "svelte-check --tsconfig ./tsconfig.json",
    "test": "vitest run",
    "verify": "pnpm format:check && pnpm lint && pnpm typecheck && pnpm test",
    "fix": "pnpm format && pnpm lint:fix && pnpm typecheck && pnpm test",
    "postinstall": "wxt prepare"
  }
}

使い分け:

  • pnpm format: format 実行
  • pnpm format:check: format 差分の有無だけ確認
  • pnpm lint: lint 確認
  • pnpm lint:fix: 自動修正つき lint
  • pnpm typecheck: Svelte / TypeScript の型確認
  • pnpm test: テスト実行
  • pnpm verify: CI 的な一括確認
  • pnpm fix: 手元でまとめて整える

10. テスト基盤

最初は疎通確認だけのテストを 1 本置きます。

tests/smoke.test.ts:

import { describe, expect, it } from 'vitest';

describe('smoke', () => {
  it('runs the test suite', () => {
    expect(true).toBe(true);
  });
});

目的:

  • vitest 自体が動くことを先に確認する
  • 本体ロジック未実装でも test コマンドを成立させる

11. VS Code 設定

保存時に format と ESLint fix をかけます。

.vscode/settings.json:

{
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit"
  },
  "eslint.validate": ["javascript", "typescript", "svelte"],
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[json]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[markdown]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[svelte]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }
}

推奨拡張:

.vscode/extensions.json

{
  "recommendations": ["svelte.svelte-vscode", "dbaeumer.vscode-eslint", "esbenp.prettier-vscode"]
}

.vscode/settings.json を Git 管理するために .gitignore も以下のようにします。

.vscode/*
!.vscode/extensions.json
!.vscode/settings.json

12. 動作確認

以下を実行して、format / lint / typecheck / test が通ることを確認します。

pnpm verify

期待値:

  • format:check が通る
  • lint が通る
  • svelte-check が 0 errors / 0 warnings
  • vitest の smoke test が通る

13. 拡張の見た目確認

この時点では WXT のスターター popup が表示できれば OK です。

pnpm dev

その後 Chrome で以下を実施します。

  1. chrome://extensions を開く
  2. 右上のデベロッパーモードをオン
  3. 「パッケージ化されていない拡張機能を読み込む」を選ぶ
  4. .output/chrome-mv3 を指定する

この時点では WXT + Svelte のスターター UI が見えれば正常です。 まだアプリ固有の処理は未実装で問題ありません。

14. この時点での主要ファイル

  • mise.toml
  • package.json
  • pnpm-lock.yaml
  • .prettierrc.json
  • .prettierignore
  • eslint.config.js
  • .vscode/extensions.json
  • .vscode/settings.json
  • tests/smoke.test.ts
  • wxt.config.ts
  • src/entrypoints/popup/*

15. 次の実装候補

このベースラインの次にやると自然なのは以下です。

  1. スターター UI の撤去
  2. popup を実アプリ向けの骨組みに変更
  3. ファイル読み込みやアプリ固有ロジックの追加
  4. ドメインロジックのテスト追加
  5. build / zip / CI の整備
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment