背景
在 esbuild 中有很多同学,都进行了nodejs 插件的开发,但是具体怎么通过 nodejs 进程 通信到 golang 中呢?通过这篇文章能让你对 esbuild 插件源码有一个 200% 的了解。
Esbuild 隐藏的秘密
- 隐藏在 issue 中 esbuild 二次开发特性
重新编译方法 ·installForTests·
installForTests示例
import {loadPlugin, resolvePlugin} from '../plugin'
import fs from 'fs';
import path from 'path';
// esbuild 源码中 目录 esbuild/scripts/esbuild.js
const esbuild = require('../../scripts/esbuild').installForTests()
// const esbuild = require('../../npm/esbuild/lib/main')
async function exec() {
let res = await esbuild.build({
entryPoints: ["src/index.tsx"],
outfile: "dist/main.js",
minify: false,
bundle: true,
// watch: true,
incremental: true,
sourcemap: true,
plugins: [loadPlugin, resolvePlugin]
});
}
installForTests
exports.installForTests = () => {
// Build the "esbuild" binary and library
const esbuildPath = exports.buildBinary()
buildNeutralLib(esbuildPath)
...
}
buildBinarybuildBinarygithub/esbuild/scripts/esbuild.jsline 298
// 目前代码 不支持 gops 附加调试
childProcess.execFileSync('go', ['build', '-gcflags="all=-N -l"', './cmd/esbuild'], { cwd: repoDir, stdio: 'ignore' })
// 注意!!! 建议修改如下 增加 '-ldflags=-s -w' 参数 来支持 gops 调试
childProcess.execFileSync('go', ['build', '-ldflags=-s -w', './cmd/esbuild'], { cwd: repoDir, stdio: 'ignore' })
buildNeutralLibnpm/esbuild/lib/main.jsnpm run buildlib/shared/common.tsnpm/esbuild/lib/main.js
// line 662 这里是 nodejs 发送 streambuffer unit8array 通过 ipc 到 golang 中 核心方法
// 这里的 Req 就是 每个 nodejs 调用 golang 中,参数类型
// sendRequest<protocol.RebuildRequest, protocol.BuildResponse> 发送重新构建 示例。
// 该方法 是一个 镜像方法 在golang 中 回调 nodejs 中有同样的实现。
let sendRequest = <Req, Res>(
refs: Refs | null,
value: Req,
callback: (error: string | null, response: Res | null) => void
): void => {
....
}
rebuild 参数如下,esbuild 命令类型 “command” 执行 task 时,esbuild 会有个 'id' key 来标识多线程中 构建结果。
export interface RebuildRequest {
command: "rebuild";
key: number;
//changefile: string[];
}
重定向 字节码文件的 环境变量 ESBUILD_BINARY_PATH
checkAndPreparePackagevalidateBinaryVersion
使用示例如下
{
"scripts": {
"build": "ESBUILD_BINARY_PATH=/Users/xxx/Desktop/github/esbuild/esbuild ts-node-dev ./build/index.ts"
},
}
如何附加调试 esbuild 进程,包含(vscode,goland)
installForTests-ldflags=-s -wwatch: trueincremental: truedlv
$ git clone https://github.com/go-delve/delve
$ cd delve
$ go install github.com/go-delve/delve/cmd/dlv
dlv
➜ ~ dlv
Delve is a source level debugger for Go programs.
Delve enables you to interact with your program by controlling the execution of the process,
evaluating variables, and providing information of thread / goroutine state, CPU register state and more.
The goal of this tool is to provide a simple yet powerful interface for debugging Go programs.
Pass flags to the program you are debugging using `--`, for example:
`dlv exec ./hello -- server --config conf/config.toml`
Usage:
dlv [command]
- vscode 中 创建 .vscode/launch.json 并且填写如下内容
$: ps -ef|grep esbuild
501 72470 72428 0 6:58下午 ttys000 0:00.09 /Users/xxx/Desktop/github/esbuild/esbuild --service=0.14.25 --ping
第二个数字PID
internal/bundler/bundler.gofunc runOnLoadPlugins
vscode golang extension 扩展中已经自动帮你安装了 gops 附加工具,调试的时候自动启动,使用vsocde 同学可以自动忽略!不需要了解 gops 是何种工具,只要保证第5步 中 delve 成功安装即可
- Goland 附加调试
internal/bundler/bundler.gointernal/bundler/bundler.gofunc runOnLoadPlugins
go version