Esbuild 调试 Golang 进程 和 NodeJs 通信 小白教程
背景
在 esbuild 中有很多同学,都进行了nodejs 插件的开发,但是具体怎么通过 nodejs 进程 通信到 golang 中呢?通过这篇文章能让你对 esbuild 插件源码有一个 200% 的了解。
Esbuild 隐藏的秘密
- 隐藏在 issue 中 esbuild 二次开发特性
- github.com/evanw/esbui…
- github.com/evanw/esbui…
重新编译方法 ·installForTests·
installForTests
是一个 可以重新编译 esbuild 函数,是作者特意留下来用于调试开发esbuild用的,下面这段代码 就是一个 使用的 示例
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)
...
}
buildBinary
该方法是 构建 esbuild 上卷 golang 的字节码,通过 nodejs childprocess 调用 go build 这里我们要留意该方法 buildBinary
中的 github/esbuild/scripts/esbuild.js
中 line 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' })
buildNeutralLib
该方法是 esbuild 自举 构建 nodejs -> npm/esbuild/lib/main.js
调用函数,esbuild 是不含有任何 npm run build
构建调用。我们这里有一些需要关注的代码。lib/shared/common.ts
这个代码大部分都会被构建于 npm/esbuild/lib/main.js
主包调用 nodejs 中逻辑中。
// 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
在 esbuild 主包中 install.js -> checkAndPreparePackage
-> validateBinaryVersion
函数中,可以替换golang go-build 构建结果 esbuild bin文件。
使用示例如下
{
"scripts": {
"build": "ESBUILD_BINARY_PATH=/Users/xxx/Desktop/github/esbuild/esbuild ts-node-dev ./build/index.ts"
},
}
如何附加调试 esbuild 进程,包含(vscode,goland)
- 下载esbuild 源码到本地
- 在任意目录,编写一个 测试 demo 示例 并 指定
installForTests
为 esbuild 指定导出,(参考 章节2 ),且确定增加了 gops 的编译参数-ldflags=-s -w
- 在 packjson 中指定,环境变量到 本地 github 下载源码目录。(参考 章节3 )
- 指定esbuild 构建模式为
watch: true
或者incremental: true
,保证 执行命令行后,golang的进程会挂起不会释放。 - 本地确认 golang 版本,确认已经
dlv
gotools 调试工具
- 安装教程 github.com/go-delve/de…
$ 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
上述结果的 第二个数字
即为 esbuild golang 进程中的 PID
填写到如下 json 当中
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Attach to Process",
"type": "go",
"request": "attach",
"mode": "local",
"processId": 72470
}
]
}
启动附加后,可以尝试 internal/bundler/bundler.go
中 func runOnLoadPlugins
中 设置断点, line 849 行左右。然后尝试修改 demo 中文件 进行欢乐的调试。
PS:vscode golang extension 扩展中已经自动帮你安装了 gops 附加工具,调试的时候自动启动,使用vsocde 同学可以自动忽略!不需要了解 gops 是何种工具,只要保证第5步 中 delve 成功安装即可
- Goland 附加调试
- 确保你已经通过 jetbrains 网站中,下载好了 Goland 源码,且通过 Goland 打开 esbuild 源码
- 打开
internal/bundler/bundler.go
文件,任意*.go 文件皆可。已 mac 为标准 按住 ctrl + option + f5, 第一次 Goland 会自动帮你下载 gops,然后就出现 当前机器下所有 golang 的进程小窗口,选择其中 esbuild 的 进行调试 - (参考链接) www.jetbrains.com/help/go/att…
- 启动附加后,可以尝试
internal/bundler/bundler.go
中func runOnLoadPlugins
中 设置断点, line 849 行左右。然后尝试修改 demo 中文件 进行欢乐的调试。
- 严格注意 go version 1.16.x 中 gops 附加会有严重bug 请确保当前
go version
并不是上述版本在进行上述尝试!
代办报建
本公司承接江浙沪报建代办施工许可证。
联系人:张经理,18321657689(微信同号)。
13条评论
好帖子!http://vhrr6.dataragroup.com
精华帖的节奏啊!http://i1dz.medipel.net
大神就是大神,这么经典!http://o2sz8v.jxjy618.com
大神就是大神,这么经典!http://muz20.sz-zccs.com
学习雷锋,好好回帖!http://www.jiagu1.com/fei/sy32urop3/
好无聊啊!http://75hj.ncrlzy.cn
顶一下,收藏了!http://zq8w.jinchenginternational.net
写得实在太好了,我唯一能做的就是默默顶贴!http://70kagl.lilincnc.cn
宇宙第一贴诞生了!http://q74.qcxcy.com
有品位!http://voycb.sucangyuan.com
谢谢楼主的分享!http://www.guangcexing.net/voddetail/VmkPgQbQE.html
态度决定一切,不错!http://pi5.jsjt888.com
好东西,学习学习!http://www.guangcexing.net/voddetail/qAZqHpXYvnHf.html
发表评论