【n8n教程】:从零上手自定义节点开发(规划 → 编写 → 测试 → 部署)
面向已经会一点 JavaScript/TypeScript、用过 n8n 的同学,带你按官方文档的节奏,一步步把“自定义节点”真正跑起来。
1. 自定义节点到底能做什么?
n8n 自带了大量节点,但在实际项目里你经常会遇到:
- 某个内部系统只提供 HTTP API,没有现成节点
- 想把一大段「重复的 Code / Function 节点」封装成一个可复用积木
- 想把自己封装好的能力(例如 AI、内部服务)分享成一个 npm 包
这时候,“自定义节点”就是官方推荐的方式:
你可以像官方节点一样,在左侧节点面板里搜索到它,拖拽、配置、连线即可。
2. 官方推荐的整体流程
官方“Creating Nodes”文档把整个过程拆成五步:规划 → 构建 → 测试 → 部署 → 维护/分享。
| 步骤 | 对应官方文档 | 你要做的事情(简化版) |
|---|---|---|
| 规划 (Plan) | Plan a node | 选好节点类型、构建风格、UI 参数、文件结构 |
| 构建 (Build) | Build a node | 写 TypeScript / 声明式配置,实现节点逻辑 |
| 测试 (Test) | Test a node | 在本地 n8n 手动跑 + 用 linter 自动检查 |
| 部署 (Deploy) | Deploy a node | 本地私有安装,或发布为社区节点,供云端使用 |
| 概览 (Overview) | Creating nodes | 总体说明、参考链接、UI 元素 & 文件结构参考 |
n8n 的节点开发属于前端 TypeScript + 后端 HTTP/业务逻辑的结合,但官方已经把接口与约定封装得比较好,照着套路走即可。
n8n 工作流编辑界面长什么样?
下面这类界面就是你开发节点后要用到的工作流编辑器:左侧选节点,中间拖线,右侧配置参数。

3. 环境准备(一步步来)
要跟着本教程动手,建议你先准备好:
- 基础技能
- 会一点 JavaScript/TypeScript(函数、对象、Promise 等)
- 会用 npm(
npm init、npm install、npm publish基本命令) - 会用 git
- 开发环境
- Node.js(建议 18+)
- 一个代码编辑器(VS Code 即可)
- git 命令行
- 本地 n8n 实例
- 最简单:
npx n8n直接启动(默认 http://localhost:5678) - 或用 Docker 自建(方便挂载自定义节点目录):
官方与社区节点安装文档都建议把 n8n 数据目录挂载到容器的/home/node/.n8n,例如:
- 最简单:
docker run -it --rm \
--name n8n \
-p 5678:5678 \
-e N8N_COMMUNITY_PACKAGES_ENABLED=true \
-v ~/n8n-data:/home/node/.n8n \
docker.n8n.io/n8nio/n8n
其中 N8N_COMMUNITY_PACKAGES_ENABLED=true 是加载社区/自定义节点所必需的环境变量。
4. 第一步:规划你的节点(Plan a node)
这一阶段只动脑,不动手写代码,目标是把以下四件事想清楚。
4.1 选择节点类型
常见的有两大类:
- 普通节点(Regular node)
- 有输入,有输出
- 例如 HTTP Request、Edit Fields (Set)、Code
- 用于“处理数据、调用服务”
- 触发器节点(Trigger node)
- 负责“什么时候启动工作流”
- 例如 Cron、Webhook、Gmail Trigger
- 触发器节点通常没有上游输入,而是自己推送数据给后面的节点
新手建议:先从“普通节点”开始。
例如:封装一个“调用公开 HTTP API”并返回 JSON 的节点。
4.2 选择构建风格:声明式 vs 代码式
官方文档目前主推两种“节点构建风格”:
- 声明式(Declarative-style node)
- 用配置对象描述:
- 这个节点有哪些参数(UI 字段)
- 请求怎么发(URL、Method、Query、Body)
- 响应如何映射到 item
- 优点:不需要写太多
execute()里的业务代码,更接近“配置一个 HTTP 集成” - 适合:绝大多数“包装 REST API”型节点
- 用配置对象描述:
- 代码式(Code-style / imperative)
- 主要在
execute方法里写 TypeScript 逻辑:- 读参数
- 发 HTTP 请求、处理数组、做循环/条件
- 组织并返回输出数据
- 优点:灵活,不限于 HTTP,复杂逻辑都能写
- 适合:复杂业务规则、需要多次调用 API、或处理本地文件等
- 主要在
初学建议:先做一个“声明式 HTTP 节点”,体验打通全流程。
4.3 设计 UI:用户在右侧面板看到什么?
n8n 的节点 UI 本质上是“一个配置结构”,内部渲染成表单。
常见字段类型:
- 文本输入:string
- 数字:number
- 选择框:options(下拉,radio 等)
- 开关:boolean
- 集合 / 表格:collection(例如“额外 header”、“查询参数列表”)
你需要想清楚:
- 用户最常改的参数有哪些?尽量放到上面,减少“点击更多选项”。
- 哪些可以给合理默认值?例如
Method = GET。 - 哪些用下拉选项比自由输入更安全?比如 HTTP 方法、模式等。
一个简单示例:封装猫咪语录 API 的节点
- 节点名称:
Cat Fact - 必选参数:
limit(返回条数,数字,默认 1)
- 可选参数:
onlyText(布尔,默认 true,表示只输出文本字段)
4.4 设计节点代码的文件结构
一个最小的自定义节点包,大致目录结构如下:
my-n8n-cat-node/
├─ package.json # 声明 n8n 节点、依赖、名字等
├─ tsconfig.json # TypeScript 配置(可复用官方模板)
├─ nodes/
│ └─ CatFact.node.ts # 具体节点实现文件
└─ credentials/ # 若需要鉴权(本例不需要,可为空)
在 package.json 里,需要有一个 n8n 字段,告诉 n8n:
- 这个包里有哪些
nodes - 有哪些
credentials(如果有)
5. 第二步:编写你的第一个声明式 HTTP 节点(实战示例)
下面以“调用公开猫咪语录 API:https://catfact.ninja/fact”为例,写一个最小可用的节点骨架。
注意:代码是结构示意,重点是帮助你理解,不是完整生产代码。
5.1 初始化项目
在你本机某个目录下:
mkdir my-n8n-cat-node
cd my-n8n-cat-node
npm init -y
随后:
- 安装 TypeScript、n8n 节点类型依赖(可以参考官方“Build a node”页面里的
devDependencies) - 添加
tsconfig.json(可直接照官方模板)
5.2 配置 package.json 中的 n8n 字段
在 package.json 中增加类似配置(示例):
{
"name": "my-n8n-cat-node",
"version": "0.1.0",
"main": "dist/nodes/index.js",
"n8n": {
"nodes": [
"dist/nodes/CatFact.node.js"
],
"credentials": []
},
"scripts": {
"build": "tsc",
"lint": "eslint ."
}
}
要点:
n8n.nodes数组里列出编译后的节点文件路径(通常在dist下)- 开发时用 TypeScript (
.ts),构建后输出 JS (.js)
5.3 编写 CatFact.node.ts(简化版结构)
nodes/CatFact.node.ts 示例结构(删掉了一些高级配置,只保留最关键部分,帮助你看清“形状”):
import type {
INodeType,
INodeTypeDescription,
IExecuteFunctions,
} from 'n8n-workflow';
export class CatFact implements INodeType {
description: INodeTypeDescription = {
displayName: 'Cat Fact',
name: 'catFact',
group: ['transform'],
version: 1,
description: 'Get random cat facts from catfact.ninja',
defaults: {
name: 'Cat Fact',
},
inputs: ['main'],
outputs: ['main'],
properties: [
{
displayName: 'Limit',
name: 'limit',
type: 'number',
typeOptions: {
minValue: 1,
maxValue: 10,
},
default: 1,
description: 'How many facts to fetch',
},
{
displayName: 'Only Text',
name: 'onlyText',
type: 'boolean',
default: true,
description: 'Return only fact text field',
},
],
};
async execute(this: IExecuteFunctions) {
const items = this.getInputData();
const returnData = [];
const limit = this.getNodeParameter('limit', 0) as number;
const onlyText = this.getNodeParameter('onlyText', 0) as boolean;
// 简单写法:只看第一条输入 item,执行一次请求
const response = await this.helpers.request({
method: 'GET',
uri: 'https://catfact.ninja/facts',
qs: { limit },
json: true,
});
const facts = response?.data || [];
for (const fact of facts) {
if (onlyText) {
returnData.push({ json: { fact: fact.fact } });
} else {
returnData.push({ json: fact });
}
}
return [returnData];
}
}
这里混合了“声明式 UI”(properties)和“代码式 execute”,是最常见的模式:
UI 用配置描述,逻辑用 TypeScript 写。
完整的类型定义(
INodeTypeDescription各字段含义、UI 元素种类)可以在官方 “Build a declarative-style node” 文档与参考章节里查到。
6. 第三步:在本地 n8n 中测试节点(Test a node)
官方文档推荐两种测试方式都用上:手动测试 + linter 自动检查。
6.1 把节点安装到本地 n8n 实例
常见方式(以 Docker、自定义包为例):
- 先构建 TypeScript
npm run build
- 把整个包放到 n8n 数据目录的
custom下,例如:
cd ~/n8n-data
mkdir -p custom
cd custom
# 假设你已经在别处写好包,可以用 npm 安装或直接拷贝
npm i /path/to/my-n8n-cat-node
- 确保 n8n 容器启动时挂载了该目录,并设置了
-v ~/n8n-data:/home/node/.n8n
-e N8N_COMMUNITY_PACKAGES_ENABLED=true
- 重启 n8n
- Docker:
docker stop n8n && <之前的 docker run 命令> - Docker Compose:
docker compose restart
- Docker:
n8n 只会在启动时扫描 custom 目录里的包,所以每次装新节点后必须重启。
6.2 在编辑器里手动测试节点
- 打开本地 n8n(默认 http://localhost:5678)
- 新建一个空工作流
- 添加节点:
- 先拖一个 Manual Trigger(手动触发) 节点
- 再在左侧搜索刚才安装的
Cat Fact节点,拖到画布上 - 用连线把 Manual Trigger 连到
Cat Fact节点
- 选中
Cat Fact,在右侧参数面板里设置:Limit = 3Only Text = true
- 点击顶部“执行工作流”(或单独执行节点),观察输出数据
6.3 用 linter 自动测试
官方提供了节点 linter,用于检查:
- 是否使用了推荐的参数命名/描述规范
- 是否有常见错误(例如未处理错误、未返回新数组等)
基本使用方式:
- 在
package.json里添加一个lint脚本(官方模板里通常已给出) - 在项目根目录运行:
npm run lint
- 根据输出逐条修复
具体 linter 的安装命令与配置请以官方 “Test a node” 文档为准;教程里保持概念即可,避免跟版本耦合过死。
7. 第四步:部署与分享节点(Deploy a node)
当你在本地反复测试、linter 通过后,就可以考虑“给别人用”了。
7.1 仅自己用:私有节点
如果只是团队内部 / 自己用,有两个简单方式:
- 复制包到每个 n8n 实例的
custom目录- 缺点:多个实例要手动同步更新版本
- 在私有 npm 仓库发布包
- 运维只需要在
~/n8n-data/custom里npm i my-n8n-cat-node@latest然后重启即可
- 运维只需要在
这种方式在自托管 n8n 中很常见,适合企业内网集成。
7.2 分享给社区:发布为社区节点
如果希望别人能在 n8n 云端(hosted)直接安装你的节点,需要:
- 把节点打包并发布到 npm(公开包)
- 按照官方要求提交到 n8n 的“社区节点仓库”
- 通过审核后,就会出现在 n8n 后台的“社区节点”列表中,
云端环境也可以像装插件一样一键安装使用
官方也明确:在云端想用自定义节点,只能通过“社区节点”的方式安装,不能像本地那样直接挂个 custom 目录。
8. 实战案例:导入一个完整工作流 JSON(可以直接跑)
最后给一个完整可执行工作流 JSON 作为实战练习,让你熟悉:
- 工作流 JSON 的基本结构(
nodes、connections等) - 如何把 JSON 导入到 n8n
- 如何在其中替换成你自己的自定义节点
8.1 工作流功能说明:一键发送一条短信
示例来自一个公开的 n8n 工作流数据集中:
它做的事情非常简单:
- 用 Manual Trigger 手动触发
- 调用 Plivo 短信节点,向指定手机号发一条 “Hello world!” 短信
注意:要真正发送短信,你需要一个 Plivo 账号和有效的手机号码,这里只是展示结构与导入方法。
8.2 完整工作流 JSON 代码
你可以直接复制下面这段 JSON,在 n8n 中导入并运行(记得先配置 Plivo 凭据)。
{
"name": "",
"nodes": [
{
"name": "On clicking 'execute'",
"type": "n8n-nodes-base.manualTrigger",
"position": [250, 300],
"parameters": {},
"typeVersion": 1
},
{
"name": "Plivo",
"type": "n8n-nodes-base.plivo",
"position": [500, 300],
"parameters": {
"to": "+14156667778",
"from": "+14156667777",
"message": "Hello world!"
},
"credentials": {
"plivoApi": ""
},
"typeVersion": 1
}
],
"active": false,
"settings": {},
"connections": {
"On clicking 'execute'": {
"main": [
[
{
"node": "Plivo",
"type": "main",
"index": 0
}
]
]
}
}
}
这个 JSON 的几个关键点:
nodes数组里有两个节点:- 手动触发:
n8n-nodes-base.manualTrigger - Plivo SMS 节点:
n8n-nodes-base.plivo
- 手动触发:
connections描述了连线关系:- 当 Manual Trigger 执行成功后,把数据传给 Plivo 节点
active: false表示导入后默认不自动激活,需要手动点“激活工作流”才会定时/触发执行
这一结构与官方的“导出/导入工作流”文档描述是一致的:
n8n 会把工作流保存为 JSON,其中 nodes、connections、name 等是导入时的关键字段。
8.3 如何在 n8n 中导入这个工作流
- 打开 n8n,进入 “Workflows” 页面
- 点击右上角 “Import” / “导入”
- 选择 “从剪贴板导入”(Import from clipboard)
- 把上面的 JSON 粘贴进去,点击确认
- 进入刚导入的工作流:
- 双击
Plivo节点 - 在
Credentials下拉里选择你已经配置好的 Plivo 凭据 - 把
to、from改成你自己的测试号码
- 双击
- 点击顶部的 “执行工作流”(或点击触发器节点上的执行按钮)
如果一切配置正确,你会收到一条 “Hello world!” 短信。
8.4 如何把示例工作流改成“使用你自己的自定义节点”
练习题:现在你已经有了 Cat Fact 节点,可以试试这样改造:
- 在上面的工作流里:
- 删除
Plivo节点 - 改为添加你的
Cat Fact节点
- 删除
- 连线:
Manual Trigger→Cat Fact
- 执行:
- 观察
Cat Fact输出的 JSON 数据
- 观察
进一步挑战:
- 在
Cat Fact后面再加一个官方的 Edit Fields (Set) 节点,把fact字段改名为message,为后续短信/通知做准备。 - 再接一个 HTTP Request 或聊天机器人节点,把猫语录发给自己。
这就是一个完整闭环:
规划节点 → 编写节点 → 测试节点 → 部署节点 → 在真实工作流中使用它。
9. 总结与下一步建议
通过这篇教程,你已经掌握了:
- 从 0 规划一个自定义节点:选类型、选构建风格、设计 UI、确定文件结构
- 用 TypeScript 写出一个最小节点骨架:定义
description+ 实现execute - 在本地 n8n 中安装 & 测试节点:挂载
custom目录、启用社区包、手动执行 - 了解如何部署和分享节点:私有安装 vs 社区节点
- 通过完整 JSON 工作流练习导入/执行:熟悉工作流 JSON 结构与导入流程
下一步可以做什么?
- 给你的节点加上 Credentials 支持(例如绑定某个 SaaS API)
- 尝试做一个 Trigger 节点(例如轮询某个接口有无新数据)
- 学习官方更多示例和规范(命名风格、错误处理、分页处理等)
- 浏览社区工作流/节点仓库,看看别人是怎么设计的
1149

被折叠的 条评论
为什么被折叠?



