是否可以制作由 mjs 文件组成的 vscode 扩展?
因为我尝试仅使用 mjs 文件进行扩展,以便在不使用 TypeScript 的情况下拥有完整的 es6 功能。 但它不运行:
如果我使用
$ vsce package
进行扩展,它不会给出任何错误,但它会生成一个在安装时不起作用的扩展:我放入 package.json 中的贡献存在,但 vscode 显示一个错误弹出窗口,其中显示
激活扩展'my.ext'失败:必须使用导入来加载ES模块:c:sext xtension.mjs。
我尝试运行的每个命令都会出错
未找到命令“my.cmd”
如果我在调试器上运行扩展,并且标记了未捕获异常选项上的断点,它将在 /src/vs/workbench/api/node/extHostExtensionService.ts:88 处中断。
经过进一步搜索,我注意到当脚本尝试加载第一个 mjs 模块时,会生成此异常。
我可以做些什么来包含我的 mjs 库文件?
我认为这种行为也可能会影响 npm 模块与 mjs 文件的使用。
找到(某种)使用 esm 的方法:
这个想法是使用esm来处理es6导入并在导入的模块之间共享vscode对象
这看起来相当棘手,但是当我尝试
import * as vscode from "vscode"
我的 mjs 文件时,vscode 抱怨说 找不到模块 vscode。
所以我做了以下事情
var vscode; // will store vscode obj
export function IMPORTVSCODE(vscodeInstance){
vscode = vscodeInstance
}
例如
// init.js
const vscode = require("vscode")
const esm = require("esm")(module/*, options*/)
const main = esm("./main.mjs")
main.IMPORTVSCODE(vscode)
module.exports = main
// main.mjs
import * as other from "./other.mjs"
var vscode; // will store vscode obj
export function IMPORTVSCODE(vscodeInstance){
vscode = vscodeInstance
}
function activate(){
other.IMPORTVSCODE(vscode)
other.methodThatNeedsVscode()
}
// other.mjs
var vscode; // will store vscode obj
export function IMPORTVSCODE(vscodeInstance){
vscode = vscodeInstance
}
export function methodThatNeedsVscode(){
vscode // ...use vscode
}
我的扩展现在运行良好!
但我认为可以找到更好的想法,所以如果有人有一些最好的解决方案,请分享它们
是的,您可以使用纯 ESM(感谢上帝),即使您必须从 CJS 开始。诀窍是使用
await import
:
/**
* @param {import('vscode').ExtensionContext} context - The context.
*/
async function activate(context) {
(await import('./register-hello-world.mjs')).activate(context);
(await import('./register-hello-tensor.mjs')).activate(context);
}
module.exports.activate = activate;
注册-hello-world.mjs:
import {add} from '#customImport';
import {vscode} from '#vscode';
/**
* This method is called when your extension is activated, which
* happens the very first time the command is executed.
* @param {import('vscode').ExtensionContext} context - The context.
*/
export function activate(context) {
// 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('> register extension.helloWorld');
// 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
const disposable = vscode.commands.registerCommand('extension.helloWorld', () => {
vscode.window.showInformationMessage(`Hello World! add(10, 20) is ${add(10, 20)}`);
});
context.subscriptions.push(disposable);
}
现在您可能想知道 - 那是什么
import {vscode} from '#vscode';
?
你基本上可以像导入地图一样使用你的
package.json
:
{
"name": "vscode-extension-transformers",
"displayName": "vscode-extension-transformers",
"description": "Transformers.js example for VS Code",
"version": "1.0.0",
"publisher": "kungfooman",
"repository": "https://github.com/kungfooman/vscode-extension-transformers/",
"scripts": {
"watch": "echo Begone, watch build step! Embracing true ESM power!",
"vscode:prepublish": "echo Begone, prepublish build step! Embracing true ESM power!",
"lint": "eslint \"src/**/*.js\""
},
"engines": {
"vscode": "^1.74.0"
},
"categories": [
"Other"
],
"activationEvents": [],
"main": "./src/extension.js",
"contributes": {
"commands": [
{
"command": "extension.helloWorld",
"title": "Hello World"
},
{
"command": "extension.helloTensor",
"title": "Hello Tensor"
}
]
},
"devDependencies": {
"@types/node": "^16.18.34",
"@types/vscode": "^1.73.0",
"eslint": "^8.26.0"
},
"imports": {
"#customImport": "./src/customImport.mjs",
"#vscode": "./src/vscode.mjs"
},
"dependencies": {
"@xenova/transformers": "^2.6.1"
}
}
并且 ./src/vscode.mjs 必须看起来像这样:
import {createRequire} from 'node:module';
const require = createRequire(import.meta.url);
export const vscode = require('vscode');
Tada,问题已解决 - 享受 ESM 的乐趣。如果您使用 TypeScript,请立即放弃它:它只会通过 AST 转换等造成额外的麻烦。
代码太多?我在这里做了一个完整的测试仓库: