别再被官方节点限制了:为什么你需要自定义节点?
笔者在 N8N大学 这几年,见过太多学员卡在“官方节点不够用”的死胡同里。比如你想调用某个冷门的 API,或者需要一个特殊的字符串处理逻辑,官方节点库虽然丰富,但总有覆盖不到的角落。
自定义节点不是什么高深莫测的黑科技,它本质上就是用 JavaScript (TypeScript) 写一段逻辑,封装成 n8n 能识别的格式。一旦掌握,你的自动化工作流将拥有无限可能。今天,我们就抛开枯燥的文档,手把手带你从零开发一个实用的插件。
准备工作:磨刀不误砍柴工
在开始之前,请确保你的环境满足以下硬性条件:
- Node.js (v16 或更高版本):这是运行 JavaScript 的环境,必须安装。
- 代码编辑器:推荐 VS Code,它对 TypeScript 支持最好。
- n8n 官方 CLI 工具:这是开发自定义节点的脚手架工具。
- 一个 n8n 实例:用于测试插件。
如果环境还没搭好,建议先去 N8N大学 看看之前的环境搭建教程,避免在第一步就卡住。
核心实操:从零构建“随机笑话生成器”
为了演示,我们开发一个简单的插件:调用一个免费的笑话 API,随机返回一条笑话。这是一个典型的 HTTP 请求+数据清洗的实战场景。
步骤 1:初始化项目骨架
打开终端,进入你想要存放代码的目录,运行以下命令:
npx n8n-node-dev init-custom-node n8n-custom-joke
这行命令会自动创建一个名为 `n8n-custom-joke` 的文件夹,并生成标准的项目结构。进入目录并安装依赖:
cd n8n-custom-joke && npm install
步骤 2:编写核心逻辑 (修改 NodeDescription)
打开项目中的 `nodes/MyNode/MyNode.node.ts` 文件(你可以将其重命名为 JokeNode)。我们需要修改两个核心部分:**描述 (Description)** 和 **执行逻辑 (Execute)**。
首先定义节点的基本信息,这决定了它在 n8n 画布中的样子:
export class JokeNode implements INodeType {
description: INodeTypeDescription = {
displayName: '随机笑话',
name: 'jokeNode',
icon: 'file:joke.svg',
group: ['transform'],
version: 1,
description: '获取一个随机笑话',
defaults: {
name: '随机笑话',
color: '#00FF00',
},
inputs: ['main'],
outputs: ['main'],
properties: [
// 这里定义用户在界面上看到的参数
{
displayName: '类型',
name: 'type',
type: 'options',
options: [
{ name: '普通', value: 'general' },
{ name: '编程', value: 'programming' },
],
default: 'general',
description: '选择笑话的类型',
},
],
};
}
步骤 3:实现执行逻辑 (Execute 方法)
这是节点的“大脑”。我们需要在这里发起 HTTP 请求,并处理返回的数据。n8n 内置了 `this.httpRequest()` 方法,非常方便。
继续在 `JokeNode` 类中添加 `execute` 方法:
async execute(this: IExecuteFunctions) {
// 1. 获取用户选择的类型
const type = this.getNodeParameter('type', 0) as string;
// 2. 发起 HTTP 请求 (使用公有的 Joke API)
const responseData = await this.httpRequest({
method: 'GET',
url: `https://v2.jokeapi.dev/joke/${type}`,
headers: {
'Content-Type': 'application/json',
}
});
// 3. 数据清洗:API返回的对象比较深,我们只取笑话内容
let jokeText = '';
if (responseData.type === 'single') {
jokeText = responseData.joke;
} else {
jokeText = `${responseData.setup}nn${responseData.delivery}`;
}
// 4. 将结果放入输出流
return [
[
{
json: {
original: responseData,
cleanJoke: jokeText,
}
}
]
];
}
注意:这里我们返回了一个包含 `json` 对象的数组。这是 n8n 节点间传递数据的标准格式。
步骤 4:本地构建与安装
代码写好了,现在需要将其编译并打包。运行:
npm run build
构建完成后,你会在根目录下看到一个 `dist` 文件夹。进入该文件夹,运行打包命令:
npm run n8n:custom-node
这会生成一个 `.tgz` 文件(例如 `n8n-node-n8n-custom-joke-1.0.0.tgz`)。这就是我们要安装的插件包。
最后,进入你的 n8n 实例,点击左侧菜单的 **Settings** -> **Community Nodes** -> **Install**,上传或输入刚才生成的 `.tgz` 文件路径。安装成功后,你就能在节点面板中搜索并使用“随机笑话”节点了。
避坑指南:新手最容易踩的两个雷
在笔者指导过的无数案例中,以下两个问题出现频率最高:
- 版本不匹配导致的“节点加载失败”
n8n 版本更新很快,如果你的 n8n 实例版本过低(比如低于 1.0),可能无法识别新语法的插件。反之,如果你的插件依赖了 n8n 最新的核心库,但运行在旧版 n8n 上,也会报错。建议开发时查看 `package.json` 中的 `n8n` peerDependencies 版本。 - 数据格式错误
在 `execute` 方法返回数据时,必须严格遵循 `[{ json: { ... } }]` 这种结构。很多新手直接返回 `{ json: ... }` 或者纯 JSON 对象,导致 n8n 无法解析数据,画布上的节点虽然变绿了,但没有任何数据输出。记住,n8n 处理的是“行”数据,所以最外层是数组。
FAQ 问答
Q1: 自定义节点可以用 Python 写吗?
目前官方只支持 JavaScript/TypeScript。如果你想用 Python,可以通过 n8n 的 **SSH** 或 **HTTP Request** 节点去调用外部的 Python 脚本服务,但这属于“外部调用”,不是原生节点。
Q2: 开发好的节点能商用吗?
当然可以。n8n 自定义节点遵循 MIT 协议(或你选择的开源协议),你可以将其发布到 npm,或者私有化部署在企业内部使用。
Q3: 为什么我的节点在界面上显示不出来?
首先检查 `description` 中的 `name` 是否拼写正确。其次,如果是在开发模式下(`n8n-node-dev`),确保你的项目目录结构正确,且 n8n 实例已经开启了开发者模式。如果是打包安装,检查上传的 `.tgz` 文件是否完整。
总结与资源
开发 n8n 自定义节点是迈向高级玩家的必经之路。它让你不再受限于官方库,能够将任何业务逻辑无缝集成到自动化工作流中。今天这个“随机笑话”节点虽然简单,但它涵盖了定义、请求、处理、返回的完整流程,是绝佳的入门练手项目。
如果你在开发过程中遇到更复杂的逻辑,或者想了解如何调试节点,欢迎访问 N8N大学,我们有更深入的实战案例和源码解析等你来拿。动手试试吧,你会发现代码的世界比想象中更有趣!