🐣

VSCode拡張機能の作り方(入門)

2024/08/25に公開

はじめに

モブプロをする際に、VSCode上で交代までのセッション時間を見れるようにしたいと思い、以下のようなモブプロ用のタイマーを作成し、公開してみました。
VSCodeで、semba.mob-programming-timerと検索すると出てきます。
https://marketplace.visualstudio.com/items?itemName=semba.mob-programming-timer
今後VSCode拡張機能を作成する人の参考になればと思い、その時に得られた知見をまとめてみました。

環境構築

  • 以下のコマンドから、対話形式で環境を作ります。

    $ npm install -g yo generator-code
    $ yo code
    

    TypeScriptで作る際に、実際に選んだ選択肢は以下の通りです。
    対話形式の質問一覧

    選択肢のある質問は以下の2つでした。
    どのタイプの拡張機能を作りたいか
    パッケージマネージャーで何を使うか

  • 上記選択により、以下のようなファイル構成が作成されます。

    .
    ├── CHANGELOG.md
    ├── README.md
    ├── package-lock.json
    ├── package.json
    ├── src
    │   ├── extension.ts
    │   └── test
    │       └── extension.test.ts
    ├── tsconfig.json
    ├── vsc-extension-quickstart.md
    └── webpack.config.js
    

初期テンプレートで動く処理

src/extension.tsがメインの処理を記述するファイルになります。
TypeScriptを選択し、プロジェクト名を「sample-extension」で作成した場合は、以下の初期状態になります。

src/extension.ts
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';

// This method is called when your extension is activated
// Your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {

  // Use the console to output diagnostic information (console.log) and errors (console.error)
  // This line of code will only be executed once when your extension is activated
  console.log('Congratulations, your extension "samle-extention" is now active!');

  // The command has been defined in the package.json file
  // Now provide the implementation of the command with registerCommand
  // The commandId parameter must match the command field in package.json
  let disposable = vscode.commands.registerCommand('samle-extention.helloWorld', () => {
    // The code you place here will be executed every time your command is executed
    // Display a message box to the user
    vscode.window.showInformationMessage('Hello World from Sample Extension!');
  });

  context.subscriptions.push(disposable);
}

// This method is called when your extension is deactivated
export function deactivate() {}

こちらの初期テンプレートで動く処理は、以下のようなものになります。

  1. Hello Worldをコマンドパレットで呼び出す
    alt text
  2. Hello World from Sample Extension!というメッセージが表示される
    alt text

各関数やメソッドについて、簡単に説明すると以下の通りです。

  • activate関数:拡張機能がアクティベートされた時に呼び出される
  • vscode.commands.registerCommand:コマンドID(samle-extention.helloWorld)をハンドラ関数にバインドして、コマンドとして登録する(参考
  • context.subscriptions.push:拡張機能がディアクティベートされた時に、登録したコマンドを解除して、メモリリークを避けることができます。この処理をしなくても機能としては動きますが、メモリリークを避けるためにしておくのが無難です。
    こちらの公式Stack Overflowが参考になります。
  • vscode.window.showInformationMessage:ユーザーに情報メッセージを表示する
  • deactivate関数:拡張機能がディアクティベートされた時に呼び出される

デバッグ方法

  • 実行デバッグの開始で、別ウィンドウのVScodeが起動されるので、コマンドパレットから登録されたコマンドを呼び出すなどして、動作確認できるようになります。
  • コード変更後に、デバッグウィンドウからCommand + rでリロードすることで、変更が反映されます。
  • 初期テンプレートのHellow Worldコマンドを呼び出せることを確認したら、以下の情報を参考に自分の作りたい機能を実装していくことになります。

設定の記述

package.jsonに、開発する上で必要な拡張機能の設定を記述します。
必須の設定は、主に以下の二つです。

  • contributes.commands:コマンドパレットで呼び出せるコマンド
    • Hello Worldというコマンド名で、samle-extention.helloWorldというコマンドIDを呼び出す例は以下になります。
      alt text
      "contributes": {
        "commands": [
          {
            "command": "samle-extention.helloWorld",
            "title": "Hello World"
          }
        ]
      },
      
  • activationEvents:拡張機能がアクティベートされるタイミング
    • VSCodeを起動したタイミングで、アクティベートされる例は以下になります。
      "activationEvents": ["*"]
      
    • samle-extention.helloWorldというコマンドが呼び出されたタイミングで、アクティベートされる例は以下になります。
      "activationEvents": ["onCommand:samle-extention.helloWorld"]
      
    • その他、指定可能なアクティベートイベント一覧はこちらにまとめられています。

リリース方法

手順については、公式のこちらにまとめられています。概要は以下のとおりです。

  1. Azure DevOpsアカウントを作成
  2. パーソナルアクセストークンを取得
  3. パブリッシャーIDを確認して、package.jsonpublisherに記述
  4. ターミナルでvsce login <パブリッシャーID>を実行後、パーソナルアクセストークンを入力してログイン
  5. ターミナルでvsce publishを実行

その他、リリース時に気をつける点は以下の通りです。

  • activationEvents*にすると、パフォーマンスに影響が出る可能性があるため、以下のような警告が出ます。できるだけ、必要なイベントのみを指定するようにしましょう。
    alt text
  • GIFをREADMEに貼り付けた場合、以下のようなエラーが出ます。
    alt text
    解決方法としては、リポジトリをpublicにして、以下のようにpackage.jsonにリポジトリのURLを設定します。動画を貼ることで、ユーザーに使い方をわかりやすく伝えることができます。
    package.json
    "repository": {
      "type": "git",
      "url": "<リポジトリのURL>"
    },
    

更新方法

package.jsonversionを新しいバージョンに変更し、vsce publishを実行することで、更新されます。
publishしてから、拡張機能のマーケットプレイスに反映されるまでには、数分かかりました。

package.json
{
  "version": "新しいバージョン",
}

まとめ

拡張機能を作ることで、自分だけでなく他の開発者の作業効率も向上させられます。
普段の開発で困っていることや欲しい機能があれば、ぜひ作ってみましょう。

Discussion