VSCode 插件 API 官方文档

VSCode 官方插件比方

VSCode 官方脚手架

VSCode 插件简介

VSCode 插件是 VSCode 为开发者供给的一种扩展其功用的手段,VSCode 的几乎每一个部分都能够通过插件来进行扩展。

详细有哪些才能能够看官方介绍

主要包含:

  • 通用才能
  • 主题
  • 声明性言语功用
  • 程序言语特性
  • 工作台扩展(比方:Webview)
  • 调试

VSCode 插件开发

运用官方脚手架创立项目

装置

npm install -g yo generator-code

运转

yo code

然后就呈现了如下界面:

? ==========================================================================
We're constantly looking for ways to make yo better! 
May we anonymously report usage statistics to improve the tool over time? 
More info: https://github.com/yeoman/insight & http://yeoman.io
========================================================================== Yes
     _-----_     ╭──────────────────────────╮
    |       |    │   Welcome to the Visual  │
    |--(o)--|    │   Studio Code Extension  │
   `---------   │        generator!        │
    ( _U`_ )    ╰──────────────────────────╯
    /___A___\   /
     |  ~  |     
   __'.___.'__   
    `  |  Y ` 
? What type of extension do you want to create? (Use arrow keys)
❯ New Extension (TypeScript) 
  New Extension (JavaScript) 
  New Color Theme 
  New Language Support 
  New Code Snippets 
  New Keymap 
  New Extension Pack 
  New Language Pack (Localization) 
  New Web Extension (TypeScript) 
  New Notebook Renderer (TypeScript)

能够根据自己的需求进行挑选,这儿我挑选了第一个,然后会提示输入插件称号、描述等信息,然后就会主动生成一个项目,如下图所示:

VSCode 插件开发-从零到WebView+React

这个工程创立出来是直接就能够运用的,按“F5”或许“运转->启动调试”,就能够运转起来插件了,第一次运转会进行编译,然后会拉起一个新的 VSCode 窗口,如下图所示:

VSCode 插件开发-从零到WebView+React

然后,按“Ctrl+Shift+P”或许“Command+Shift+P”,弹出如下指令窗,输入“Hello World”,如下图所示:

VSCode 插件开发-从零到WebView+React

最终,点击履行这个指令,就会弹出插件代码中写的弹窗,如下图所示:

VSCode 插件开发-从零到WebView+React

以上便是 VSCode 插件开发起步的过程。

Webview

Webview 功用是 VSCode 开放给开发者的一个 Web 页面功用,有了这个功用,咱们就能在 VSCode 中写前端页面,并且这些页面能够运用一些 API 与 VSCode 进行交互。

Webview API | Visual Studio Code Extension API

编写一个简略的页面

下面这个是官方给的比方,翻开一个写代码的页面:

import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
  console.log('Congratulations, your extension "my-vscode-extendsion" is now active!');
  let disposable = vscode.commands.registerCommand('my-vscode-extendsion.helloWorld', () => {
    vscode.window.showInformationMessage('Hello World from my-vscode-extendsion!');
    const panel = vscode.window.createWebviewPanel(
      'catCoding',
      'Cat Coding',
      vscode.ViewColumn.One,
      {
        retainContextWhenHidden: true, // 确保 Webview 所在页面进入后台时不被释放
        enableScripts: true, // 运转 JS 履行
      }
    );
    panel.webview.html = getWebviewContent();
  });
  context.subscriptions.push(disposable);
}
export function deactivate() { }
function getWebviewContent() {
  return `<!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Cat Coding</title>
      </head>
      <body>
        <img src="https://media.giphy.com/media/JIX9t2j0ZTN9S/giphy.gif"  />
      </body>
    </html>`;
}

作用如下:

VSCode 插件开发-从零到WebView+React

Webview 调试

另外,咱们能够调出开发者页面对页面进行调试,按“Ctrl+Shift+P”或许“Command+Shift+P”,弹出如下指令窗,输入“Open Webview Developer Tools” 能够翻开 Webview 的控制台。如下图所示:

VSCode 插件开发-从零到WebView+React

数据交互

插件 -> Webview

插件中的代码:

panel.webview.postMessage({text: 'I\'m VSCode extension'});

Webview 中的代码:

window.addEventListener('message', (e) => {
  document.getElementById('test').innerHTML = e.data.text;
});

Webview -> 插件

Webview 中的代码:

const vscode = acquireVsCodeApi();
vscode.postMessage({
  text: "I'm Webview"
});

插件中的代码:

panel.webview.onDidReceiveMessage(data => {
  console.log(data.text);
});

完好代码

import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
  console.log('Congratulations, your extension "my-vscode-extendsion" is now active!');
  let disposable = vscode.commands.registerCommand('my-vscode-extendsion.helloWorld', () => {
    vscode.window.showInformationMessage('Hello World from my-vscode-extendsion!');
    const panel = vscode.window.createWebviewPanel(
      'catCoding',
      'Cat Coding',
      vscode.ViewColumn.One,
      {
        retainContextWhenHidden: true, // 确保 Webview 所在页面进入后台时不被释放
        enableScripts: true, // 运转 JS 履行
      }
    );
    panel.webview.html = getWebviewContent();
    panel.webview.postMessage({ text: 'I\'m VSCode extension' });
    panel.webview.onDidReceiveMessage(data => {
      console.log(data.text);
    });
  });
  context.subscriptions.push(disposable);
}
export function deactivate() { }
function getWebviewContent() {
  return `<!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Cat Coding</title>
      </head>
      <body>
	    <p id="test"></p>
        <script>
          window.addEventListener('message', e => {
            document.getElementById('test').innerHTML = e.data.text;
          });
          const vscode = acquireVsCodeApi();
          vscode.postMessage({
            text: "I'm Webview"
          });
        </script>
      </body>
    </html>`;
}

运转作用如下图所示:

VSCode 插件开发-从零到WebView+React

编写一个 React 页面

从上面的比方咱们能够看出来,我想要在 Webview 环境中写个界面是非常难受的,由于 getWebviewContent 返回的是一个字符串,写个简略页面还行,要是功用复杂点儿,不上个 React 或许 Vue 还真是不习惯,也不方便。

这儿我挑选运用传统的 Webpack + React(tsx),接下来咱们需求装置一堆东西。

装置react依靠

pnpm i react react-dom -S

装置react类型依靠

pnpm i @types/react @types/react-dom -D

创立index.html

先在 src 下创立一个 view 文件夹,再创立 index.html,内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>webview-react</title>
</head>
<body>
  <div id="root"></div>
</body>
</html>

创立App.tsx

import React from 'react';
function App() {
  return (
    <h2>Webview-react</h2>
  );
}
export default App;

创立index.tsx

import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
const root = document.getElementById('root');
if (root) {
  createRoot(root).render(<App />);
}

修正tsconfig.json装备

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "ES2020",
    "lib": [
      "ES2020",
      "DOM",
      "DOM.Iterable"
    ],
    "sourceMap": true,
    "rootDir": "src",
    "strict": true,
    "jsx": "react-jsx", // react18 用 react-jsx,18之前的版本用 react
    "esModuleInterop": true
  },
  "exclude": ["src/test"]
}

Webpack依靠装置及装备

依靠装置:

pnpm i webpack webpack-cli -D
pnpm i babel-loader @babel/core @babel/preset-react @babel/preset-typescript -D
pnpm i html-webpack-plugin -D
pnpm i webpack-dev-server webpack-merge -D

插件项目创立的时分有一个 webpack.config.js,不过咱们不去修正和运用它,另起一些装备文件。

webpack.base.js 公共装备:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  entry: path.join(__dirname, './src/view/index.tsx'), // 进口文件
  output: {
    filename: 'static/js/[name].js',
    path: path.join(__dirname, './dist'),
    clean: true,
    publicPath: '/',
  },
  module: {
    rules: [
      {
        test: /.(ts|tsx)$/, // 匹配.ts, tsx文件
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              '@babel/preset-react',
              '@babel/preset-typescript'
            ]
          }
        }
      }
    ]
  },
  resolve: {
    extensions: ['.js', '.tsx', '.ts'],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, './src/view/index.html'),
      inject: true, // 主动注入静态资源
    }),
  ],
};

webpack.dev.js 开发环境装备:

const path = require('path');
const { merge } = require('webpack-merge');
const baseConfig = require('./webpack.base.js');
module.exports = merge(baseConfig, {
  mode: 'development',
  devtool: 'source-map',
  devServer: {
    port: 3000,
    compress: false,
    hot: true,
    historyApiFallback: true,
    static: {
      directory: path.join(__dirname, './src/view/public'),
    }
  },
});

webpack.prod.js 生成环境装备:

const { merge } = require('webpack-merge');
const baseConfig = require('./webpack.base.js');
module.exports = merge(baseConfig, {
  mode: 'production',
});

extension.ts

import * as vscode from 'vscode';
import path from 'node:path';
export function activate(context: vscode.ExtensionContext) {
  console.log('Congratulations, your extension "my-vscode-extendsion" is now active!');
  let disposable = vscode.commands.registerCommand('my-vscode-extendsion.helloWorld', () => {
    vscode.window.showInformationMessage('Hello World from my-vscode-extendsion!');
    const panel = vscode.window.createWebviewPanel(
      'React',
      'React App',
      vscode.ViewColumn.One,
      {
        retainContextWhenHidden: true, // 确保 Webview 所在页面进入后台时不被释放
        enableScripts: true, // 运转 JS 履行
      }
    );
    const isProduction = context.extensionMode === vscode.ExtensionMode.Production;
    let srcUrl = '';
    if (isProduction) {
      const filePath = vscode.Uri.file(
        path.join(context.extensionPath, 'dist', 'static/js/main.js')
      );
      srcUrl = panel.webview.asWebviewUri(filePath).toString();
    } else {
      srcUrl = 'http://localhost:3000/static/js/main.js';
    }
    panel.webview.html = getWebviewContent(srcUrl);
    const updateWebview = () => {
      panel.webview.html = getWebviewContent(srcUrl);
    };
    updateWebview();
    const interval = setInterval(updateWebview, 1000);
    panel.onDidDispose(
      () => {
        clearInterval(interval);
      },
      null,
      context.subscriptions,
    );
  });
  context.subscriptions.push(disposable);
}
export function deactivate() { }
function getWebviewContent(srcUri: string) {
  return `<!doctype html>
  <html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>webview-react</title>
    <script defer="defer" src="https://juejin.im/post/7157283214472511518/${srcUri}"></script>
  </head>
  <body>
    <div id="root"></div>
  </body>
  </html>`;
}

package.json 装备

"scripts": {
    "vscode:prepublish": "pnpm run build && pnpm run package",
    // ...
    "dev": "webpack-dev-server -c webpack.dev.js",
    "build": "webpack -c webpack.prod.js"
},

开发的时分 pnpm run dev 运转 webpack dev server,然后 F5 即可。

运转作用如下图所示:

VSCode 插件开发-从零到WebView+React

打包

首先是打包,插件打包成 vsix 格式。

装置 vsce

pnpm i vsce -g

打包生成 vsix 文件:

# pnpm 必须加 --no-dependencies
vsce package --no-dependencies

另外,打包之后最好装备一下 README.mdpackage.json 中的 repository 字段,以及一个 LICENSE 文件。

打包成功之后就能够直接装置运用了,装置方法如下图所示:

VSCode 插件开发-从零到WebView+React