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)
能够根据自己的需求进行挑选,这儿我挑选了第一个,然后会提示输入插件称号、描述等信息,然后就会主动生成一个项目,如下图所示:
这个工程创立出来是直接就能够运用的,按“F5”或许“运转->启动调试”,就能够运转起来插件了,第一次运转会进行编译,然后会拉起一个新的 VSCode 窗口,如下图所示:
然后,按“Ctrl+Shift+P”或许“Command+Shift+P”,弹出如下指令窗,输入“Hello World”,如下图所示:
最终,点击履行这个指令,就会弹出插件代码中写的弹窗,如下图所示:
以上便是 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>`;
}
作用如下:
Webview 调试
另外,咱们能够调出开发者页面对页面进行调试,按“Ctrl+Shift+P”或许“Command+Shift+P”,弹出如下指令窗,输入“Open Webview Developer Tools” 能够翻开 Webview 的控制台。如下图所示:
数据交互
插件 -> 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>`;
}
运转作用如下图所示:
编写一个 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
即可。
运转作用如下图所示:
打包
首先是打包,插件打包成 vsix
格式。
装置 vsce
:
pnpm i vsce -g
打包生成 vsix
文件:
# pnpm 必须加 --no-dependencies
vsce package --no-dependencies
另外,打包之后最好装备一下 README.md
、package.json
中的 repository
字段,以及一个 LICENSE
文件。
打包成功之后就能够直接装置运用了,装置方法如下图所示: