场景导入:为什么你必须学会自定义节点?
在 N8N大学 的社区里,我见过太多同学被“标准化”节点折磨得死去活来。你是不是也遇到过这种情况:业务逻辑稍微复杂一点,现有的 HTTP Request 或者 Code 节点就显得捉襟见肘?拼凑十几个节点不仅让工作流丑陋不堪,维护起来更是噩梦。
笔者曾经为了对接一个内部老旧的 ERP 系统,硬是用 JavaScript 节点写了 500 行代码,每次修改都要小心翼翼。这就是为什么要开发自定义节点——它不是为了炫技,而是为了把复杂的逻辑封装成一个可复用的“黑盒”。当你掌握了自定义节点开发,n8n 对你来说就不再是一个工具,而是一个平台。
准备工作:磨刀不误砍柴工
在开始写代码之前,我们需要准备好“兵器”。别担心,门槛并不高:
- Node.js 环境:建议安装最新的 LTS 版本(v16 或更高),这是运行开发脚手架的基础。
- 代码编辑器:VS Code 是首选,配合 ESLint 插件能帮你规避很多低级语法错误。
- n8n CLI 工具:n8n 官方提供了一个脚手架工具,能一键生成项目结构。通过
npm install -g n8n-nodes-dev安装。 - 一个 n8n 实例:本地开发最好使用 Docker 启动一个纯净的 n8n 环境,避免污染现有的生产环境。
核心实操:从 Hello World 到实战节点
笔者将带你通过 3 个步骤,构建一个简单的“大小写转换”节点(虽然简单,但涵盖了核心原理)。
第一步:初始化项目结构
打开终端,输入以下命令初始化项目:
n8n-nodes-dev init
系统会提示你输入节点名称(例如 n8n-nodes-community-my-transform)。初始化完成后,你会得到一个标准的 TypeScript 项目结构。其中,nodes 目录存放节点逻辑,credentials 目录存放凭据(如果需要鉴权的话)。
第二步:定义节点描述符 (Node Descriptor)
这是最关键的一步。你需要告诉 n8n 这个节点长什么样。打开 nodes/MyTransform/MyTransform.node.ts(具体路径视项目名而定),你会看到一个 interface 和一个类。
在类的 description 属性中,我们需要定义:
- displayName:节点在 UI 上显示的名字。
- name:节点的唯一标识符(代码中使用)。
- inputs 和 outputs:定义输入输出流,通常是
['main']。 - properties:这是 UI 的核心。我们需要在这里定义一个下拉菜单(选择转大写或小写)和一个输入字段(要转换的文本)。
笔者建议新手先照着官方文档的结构抄一遍,不要急着创新。重点是理解 fields 中的 typeOptions 和 default 值的作用。
第三步:编写执行逻辑 (Execute Method)
UI 搞定后,就要写后端逻辑了。找到类中的 execute() 方法。这里接收两个参数:workflowData 和 options。
我们需要遍历传入的 items(n8n 的数据流是基于 item 的):
for (const item of items) {
const text = item.json.inputField; // 获取用户输入
const mode = item.json.mode; // 获取模式(大写/小写)
let resultText;
if (mode === 'upper') {
resultText = text.toUpperCase();
} else {
resultText = text.toLowerCase();
}
// 将结果挂载到 item.json 上
item.json.result = resultText;
}
记得最后返回 return [items],这是 n8n 数据流转的标准格式。
避坑指南:笔者的血泪教训
开发过程中,你大概率会遇到以下两个坑,提前做好心理准备:
1. 依赖地狱(Dependency Hell)
在自定义节点中,你只能使用 n8n 核心库已经安装的依赖(如 lodash, axios)。如果你想引入第三方库(比如 moment.js),必须在 package.json 中将其写入 peerDependencies,否则编译时会报错,甚至导致 n8n 主程序崩溃。笔者建议:除非必要,尽量使用原生 JS API。
2. 类型定义的陷阱
TypeScript 是强类型语言,但 n8n 的数据结构是动态的。很多时候,item.json 的属性在编译期是未知的。如果你在代码中直接访问 item.json.nonExistProp,TS 不会报错,但运行时可能得到 undefined。解决方案是使用 interface 显式定义你的数据结构,或者在访问属性时使用可选链操作符 ?.()。
调试与发布:本地测试与上线
写完代码后,如何让 n8n 识别?
- 本地链接:在项目根目录运行
npm run link。这会创建一个软链接到全局的 n8n 目录。 - 重启 n8n:如果是 Docker 环境,需要重启容器。如果是本地启动,通常 n8n 会自动热重载,如果没有,手动
Ctrl+C后重新启动。 - 测试:进入 n8n UI,搜索你的节点名称,拖拽出来,配置参数,运行。如果报错,查看控制台日志(Docker logs),通常错误信息非常直白。
当你本地测试无误后,可以将代码发布到 npm,或者提交到 n8n 的官方节点仓库(n8n-nodes-base),让更多人使用你的成果。
FAQ 问答
Q: 自定义节点开发需要很高的编程水平吗?
A: 不需要。如果你能读懂 JavaScript/TypeScript 的基础语法,理解 n8n 的数据结构(Item/JSON),就能上手。N8N大学 的建议是从修改现有节点开始,而不是从零开始。
Q: 自定义节点会影响 n8n 的性能吗?
A: 这取决于你写的代码。如果你在循环中执行昂贵的计算或阻塞的 I/O 操作,肯定会拖慢工作流。记住,n8n 是异步的,尽量避免同步阻塞操作。
Q: 我开发的节点可以商用吗?
A: 可以。n8n 是开源的(Fair-code 许可证)。你可以将自定义节点作为私有仓库维护,或者开源出去。只要遵守 n8n 的许可证协议即可。
总结与资源
开发自定义节点是进阶 n8n 高手的必经之路。它让你突破了标准节点的限制,真正实现了“工具适应业务,而非业务适应工具”。就像 N8N大学 一直强调的:低代码不是不写代码,而是更聪明地写代码。
如果你想深入学习,以下资源或许能帮到你:
- n8n 官方文档 - Nodes Development
- n8n GitHub 仓库中的 nodes-base 源码(最好的学习教材)
- N8N大学 社区论坛 - 专门的开发讨论版块
动手写你的第一个节点吧,报错不可怕,那是代码在跟你对话。