add esbuild sample (#1042)

* add esbuild sample

* update

* remove duplicated samples
This commit is contained in:
Martin Aeschlimann
2024-06-03 17:18:25 +02:00
committed by GitHub
parent 057c02f46d
commit 7353cc77aa
18 changed files with 3236 additions and 19 deletions

View File

@ -164,6 +164,15 @@ const samples = [
{
description: 'webpack-sample',
path: 'webpack-sample',
excludeFromReadme: true
guide: null,
apis: [],
contributions: []
},
{
description: 'esbuild-sample',
path: 'esbuild-sample',
excludeFromReadme: true
guide: null,
apis: [],
contributions: []
@ -282,7 +291,6 @@ const samples = [
{ description: 'notebook-renderer-react-sample', excludeFromReadme: true, path: 'notebook-renderer-react-sample', guide: null, apis: [], contributions: [] },
{ description: 'proposed-api-sample', excludeFromReadme: true, path: 'proposed-api-sample', guide: null, apis: [], contributions: [] },
{ description: 'virtual-document-sample', excludeFromReadme: true, path: 'virtual-document-sample', guide: null, apis: [], contributions: [] },
{ description: 'webpack-sample', excludeFromReadme: true, path: 'webpack-sample', guide: null, apis: [], contributions: [] },
{ description: 'welcome-view-content-sample', excludeFromReadme: true, path: 'welcome-view-content-sample', guide: null, apis: [], contributions: [] },
{ description: 'document-paste', excludeFromReadme: true, path: 'document-paste', guide: null, apis: [], contributions: [] },
{ description: 'drop-on-document', excludeFromReadme: true, path: 'drop-on-document', guide: null, apis: [], contributions: [] },

View File

@ -3,5 +3,12 @@
"prettier.semi": true,
"prettier.printWidth": 92,
"prettier.singleQuote": true,
"prettier.useTabs": true
"prettier.useTabs": true,
"git.branchProtection": [
"main"
],
"git.branchProtectionPrompt": "alwaysCommitToNewBranch",
"git.branchRandomName.enable": true,
"githubPullRequests.assignCreated": "${user}",
"githubPullRequests.defaultMergeMethod": "squash"
}

View File

@ -51,7 +51,8 @@ You need to have [node](https://nodejs.org/en/) and [npm](https://nodejs.org/en/
| [Color Theme Sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/theme-sample) | [/api/extension-guides/color-theme](https://code.visualstudio.com/api/extension-guides/color-theme) | [contributes.themes](https://code.visualstudio.com/api/references/contribution-points#contributes.themes) |
| [Product Icon Theme Sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/product-icon-theme-sample) | [/api/extension-guides/product-icon-theme](https://code.visualstudio.com/api/extension-guides/product-icon-theme) | [contributes.productIconThemes](https://code.visualstudio.com/api/references/contribution-points#contributes.productIconThemes) |
| [Vim Sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/vim-sample) | N/A | [commands](https://code.visualstudio.com/api/references/vscode-api#commands)<br>[StatusBarItem](https://code.visualstudio.com/api/references/vscode-api#StatusBarItem)<br>[window.createStatusBarItem](https://code.visualstudio.com/api/references/vscode-api#window.createStatusBarItem)<br>[TextEditorCursorStyle](https://code.visualstudio.com/api/references/vscode-api#TextEditorCursorStyle)<br>[window.activeTextEditor](https://code.visualstudio.com/api/references/vscode-api#window.activeTextEditor)<br>[Position](https://code.visualstudio.com/api/references/vscode-api#Position)<br>[Range](https://code.visualstudio.com/api/references/vscode-api#Range)<br>[Selection](https://code.visualstudio.com/api/references/vscode-api#Selection)<br>[TextEditor](https://code.visualstudio.com/api/references/vscode-api#TextEditor)<br>[TextEditorRevealType](https://code.visualstudio.com/api/references/vscode-api#TextEditorRevealType)<br>[TextDocument](https://code.visualstudio.com/api/references/vscode-api#TextDocument) |
| [webpack-sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/webpack-sample) | N/A | |
| [webpack-sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/webpack-sample) | [api/working-with-extensions/bundling-extension](https://code.visualstudio.com/api/working-with-extensions/bundling-extension) | |
| [esbuild-sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/esbuild-sample) | [api/working-with-extensions/bundling-extension](https://code.visualstudio.com/api/working-with-extensions/bundling-extension) | |
| [Source Control Sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/source-control-sample) | [/api/extension-guides/scm-provider](https://code.visualstudio.com/api/extension-guides/scm-provider) | [workspace.workspaceFolders](https://code.visualstudio.com/api/references/vscode-api#workspace.workspaceFolders)<br>[SourceControl](https://code.visualstudio.com/api/references/vscode-api#SourceControl)<br>[SourceControlResourceGroup](https://code.visualstudio.com/api/references/vscode-api#SourceControlResourceGroup)<br>[scm.createSourceControl](https://code.visualstudio.com/api/references/vscode-api#scm.createSourceControl)<br>[TextDocumentContentProvider](https://code.visualstudio.com/api/references/vscode-api#TextDocumentContentProvider)<br>[contributes.menus](https://code.visualstudio.com/api/references/contribution-points#contributes.menus) |
| [Commenting API Sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/comment-sample) | N/A | |
| [Document Editing Sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/document-editing-sample) | N/A | [commands](https://code.visualstudio.com/api/references/vscode-api#commands) |

View File

@ -0,0 +1,20 @@
/**@type {import('eslint').Linter.Config} */
// eslint-disable-next-line no-undef
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
plugins: [
'@typescript-eslint',
],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
],
rules: {
'semi': [2, "always"],
'@typescript-eslint/no-unused-vars': 0,
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/explicit-module-boundary-types': 0,
'@typescript-eslint/no-non-null-assertion': 0,
}
};

View File

@ -0,0 +1,5 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": ["dbaeumer.vscode-eslint", "connor4312.esbuild-problem-matchers"]
}

21
esbuild-sample/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,21 @@
// A launch configuration that compiles the extension and then opens it inside a new window
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
{
"version": "0.2.0",
"configurations": [
{
"name": "Run Extension",
"type": "extensionHost",
"request": "launch",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
],
"preLaunchTask": "${defaultBuildTask}"
}
]
}

64
esbuild-sample/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,64 @@
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
{
"version": "2.0.0",
"tasks": [
{
"label": "watch",
"dependsOn": [
"npm: watch:tsc",
"npm: watch:esbuild"
],
"presentation": {
"reveal": "never"
},
"group": {
"kind": "build",
"isDefault": true
}
},
{
"type": "npm",
"script": "watch:esbuild",
"group": "build",
"problemMatcher": "$esbuild-watch",
"isBackground": true,
"label": "npm: watch:esbuild",
"presentation": {
"group": "watch",
"reveal": "never"
}
},
{
"type": "npm",
"script": "watch:tsc",
"group": "build",
"problemMatcher": "$tsc-watch",
"isBackground": true,
"label": "npm: watch:tsc",
"presentation": {
"group": "watch",
"reveal": "never"
}
},
{
"type": "npm",
"script": "watch-tests",
"problemMatcher": "$tsc-watch",
"isBackground": true,
"presentation": {
"reveal": "never",
"group": "watchers"
},
"group": "build"
},
{
"label": "tasks: watch-tests",
"dependsOn": [
"npm: watch",
"npm: watch-tests"
],
"problemMatcher": []
}
]
}

View File

@ -0,0 +1,8 @@
.vscode
node_modules
src/**
package-lock.json
tsconfig.json
esbuild.js
.eslintrc.js
**/*.map

50
esbuild-sample/README.md Normal file
View File

@ -0,0 +1,50 @@
# esbuild & Extensions
This is an extension that uses [esbuild](https://esbuild.github.io/) to bundle and minify its sources. Using a bundler will help to reduce the install- and startup-time of large extensions because instead of hundreds of files, a single file is produced.
## Configuration
The build script does the following:
- It creates a build context with esbuild. The context is configured to:
- Bundle the code at [`src/extension.ts`](./src/extension.ts) into a single file `dist/extension.js`.
- Minify the code if the `--production` flag was passed.
- Generate source maps unless the `--production` flag was passed.
- Exclude the 'vscode' module from the bundle (since it's provided by the VS Code runtime).
- Use the esbuildProblemMatcherPlugin plugin to report errors that prevented the bundler to complete. This plugin emits the errors in a format that is detected by the `esbuild` problem matcher with also needs to be installed as an extension.
- If the `--watch` flag was passed, it starts watching the source files for changes and rebuilds the bundle whenever a change is detected.
esbuild can work directly with TypeScript files. However, esbuild simply strips off all type declarations without doing any type checks.
Only syntax error are reported and can cause esbuild to fail.
For that reason, we separatly run the TypeScript compiler (`tsc`) to check the types, but without emmiting any code (flag `--noEmit`).
## Scripts
The `scripts`-section of the [`package.json`](./package.json)-file has entries for compiling and watching and creating a production target. esbuild in ran to produce a minified output file and `tsc`, the TypeScript compiler, is used for type checking.
```json
"scripts": {
"compile": "npm run check-types && node esbuild.js",
"check-types": "tsc --noEmit",
"watch": "npm-run-all -p watch:*",
"watch:esbuild": "node esbuild.js --watch",
"watch:tsc": "tsc --noEmit --watch --project tsconfig.json",
"vscode:prepublish": "npm run package",
"package": "npm run check-types && node esbuild.js --production"
}
```
### Launching and debugging
To run the extension use F5, as always. The launch configuration in [`.vscode/extensions.json`](./.vscode/extensions.json) will use build tasks defined in [`.vscode/launch.json`](./.vscode/launch.json) that will create a separate terminal for the `esbuild` and `tsc` watch tasks.
The `esbuild` task relies on esbuild problem matcher that is defined by the extension [`connor4312.esbuild-problem-matchers`](https://marketplace.visualstudio.com/items?itemName=connor4312.esbuild-problem-matchers). This extension needs to be installed for the launch to complete.
To not forget that, we add a [`.vscode/extension.json`](./.vscode/extension.json) file to the workspace that recommends [`connor4312.esbuild-problem-matchers`](https://marketplace.visualstudio.com/items?itemName=connor4312.esbuild-problem-matchers)

59
esbuild-sample/dist/extension.js vendored Normal file
View File

@ -0,0 +1,59 @@
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/extension.ts
var extension_exports = {};
__export(extension_exports, {
activate: () => activate,
deactivate: () => deactivate
});
module.exports = __toCommonJS(extension_exports);
var vscode = __toESM(require("vscode"));
// src/math.ts
function add(a, b) {
return a + b;
}
// src/extension.ts
function activate(context) {
console.log('Congratulations, your extension "esbuild-sample" is now active!');
let disposable = vscode.commands.registerCommand("esbuild-sample.helloWorld", () => {
vscode.window.showInformationMessage(`41 + 1 = ${add(41, 1)}`);
});
context.subscriptions.push(disposable);
}
function deactivate() {
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
activate,
deactivate
});
//# sourceMappingURL=extension.js.map

6
esbuild-sample/dist/extension.js.map vendored Normal file
View File

@ -0,0 +1,6 @@
{
"version": 3,
"sources": ["../src/extension.ts", "../src/math.ts"],
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,aAAwB;;;ACCjB,SAAS,IAAI,GAAW,GAAmB;AACjD,SAAO,IAAI;AACZ;;;ADAO,SAAS,SAAS,SAAkC;AAE1D,UAAQ,IAAI,iEAAiE;AAE7E,MAAI,aAAoB,gBAAS,gBAAgB,6BAA6B,MAAM;AACnF,IAAO,cAAO,uBAAuB,YAAY,IAAI,IAAI,CAAC,CAAC,EAAE;AAAA,EAC9D,CAAC;AAED,UAAQ,cAAc,KAAK,UAAU;AACtC;AAEO,SAAS,aAAa;AAAC;",
"names": []
}

56
esbuild-sample/esbuild.js Normal file
View File

@ -0,0 +1,56 @@
const esbuild = require("esbuild");
const production = process.argv.includes('--production');
const watch = process.argv.includes('--watch');
/**
* @type {import('esbuild').Plugin}
*/
const esbuildProblemMatcherPlugin = {
name: 'esbuild-problem-matcher',
setup(build) {
build.onStart(() => {
console.log('[watch] build started');
});
build.onEnd((result) => {
result.errors.forEach(({ text, location }) => {
console.error(`✘ [ERROR] ${text}`);
console.error(` ${location.file}:${location.line}:${location.column}:`);
});
console.log('[watch] build finished');
});
},
};
async function main() {
const ctx = await esbuild.context({
entryPoints: [
'src/extension.ts'
],
bundle: true,
format: 'cjs',
minify: production,
sourcemap: !production,
sourcesContent: false,
platform: 'node',
outfile: 'dist/extension.js',
external: ['vscode'],
logLevel: 'silent',
plugins: [
/* add to the end of plugins array */
esbuildProblemMatcherPlugin,
],
});
if (watch) {
await ctx.watch();
} else {
await ctx.rebuild();
await ctx.dispose();
}
}
main().catch(e => {
console.error(e);
process.exit(1);
});

2834
esbuild-sample/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,50 @@
{
"name": "esbuild-sample",
"displayName": "esbuild-sample",
"description": "",
"version": "0.0.1",
"publisher": "vscode-samples",
"private": true,
"repository": {
"type": "git",
"url": "https://github.com/Microsoft/vscode-extension-samples"
},
"engines": {
"vscode": "^1.74.0"
},
"categories": [
"Other"
],
"activationEvents": [],
"main": "./dist/extension.js",
"contributes": {
"commands": [
{
"command": "esbuild-sample.hello-esbuild",
"title": "Hello esbuild"
}
]
},
"scripts": {
"vscode:prepublish": "npm run package",
"compile": "npm run check-types && npm run lint && node esbuild.js",
"watch": "npm-run-all -p watch:*",
"watch:esbuild": "node esbuild.js --watch",
"watch:tsc": "tsc --noEmit --watch --project tsconfig.json",
"package": "npm run check-types && npm run lint && node esbuild.js --production",
"compile-tests": "tsc -p . --outDir out",
"check-types": "tsc --noEmit",
"lint": "eslint \"src/**/*.ts\""
},
"devDependencies": {
"@types/vscode": "^1.73.0",
"@types/mocha": "^10.0.6",
"@types/node": "18.x",
"@typescript-eslint/eslint-plugin": "^7.7.1",
"@typescript-eslint/parser": "^7.7.1",
"eslint": "^8.57.0",
"esbuild": "^0.20.2",
"npm-run-all": "^4.1.5",
"typescript": "^5.4.5"
}
}

View File

@ -0,0 +1,19 @@
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/
import * as vscode from 'vscode';
import { add } from './math';
export function activate(context: vscode.ExtensionContext) {
console.log('Congratulations, your extension "esbuild-sample" is now active!');
const disposable = vscode.commands.registerCommand('esbuild-sample.hello-esbuild', () => {
vscode.window.showInformationMessage(`41 + 1 = ${add(41, 1)}`);
});
context.subscriptions.push(disposable);
}
export function deactivate() {}

View File

@ -0,0 +1,12 @@
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/
export function add(a: number, b: number): number {
return a + b;
}
export function sub(a: number, b: number): number {
return a - b;
}

View File

@ -0,0 +1,12 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es2020",
"lib": ["es2020"],
"outDir": "out",
"sourceMap": true,
"strict": true,
"rootDir": "src"
},
"exclude": ["node_modules", ".vscode-test"]
}

View File

@ -1,6 +1,6 @@
# Webpack & Extensions
This is an extension that uses [https://webpack.js.org]() to bundle and minify its sources. Using webpack will help to reduce the install- and startup-time of large extensions because instead of hundreds of files, a single file is produced.
This is an extension that uses [https://webpack.js.org]() to bundle and minify its sources. Using webpack will help to reduce the install- and startup-time of large extensions because instead of hundreds of files, a single file is produced.
## Configuration
@ -11,18 +11,3 @@ Webpack is configured in the [`webpack.config.js`](./webpack.config.js)-file. Fi
The `scripts`-section of the [`package.json`](./package.json)-file has entries for webpack. Those compile TypeScript and produce the bundle as well as producing a minified production build. Note, that there is no dedicated TypeScript-script as webpack takes care of that.
## More
If you use `vscode-nls` to localize your extension that you likely also use `vscode-nls-dev` to create language bundles at build time. To support webpack, a loader has been added to vscode-nls-dev. Add the section below to the `modules/rules`-configuration.
```js
{
// vscode-nls-dev loader:
// * rewrite nls-calls
loader: 'vscode-nls-dev/lib/webpack-loader',
options: {
base: path.join(__dirname, 'src')
}
```
A good sample is the shared config built-in extensions use: https://github.com/Microsoft/vscode/blob/bf5b0585d2a8759541690b2c564b96cb604ff92e/extensions/shared.webpack.config.js#L29-L51