大家好,我是 N8N大学 的主编。在自动化领域摸爬滚打 8 年,我见过太多人被 n8n 丰富的官方节点淹没,却在遇到特殊业务逻辑时束手无策。今天,我们要做一件硬核的事:不再依赖现成节点,而是亲手打造属于你的“瑞士军刀”。
很多人觉得写代码难,但 n8n 的自定义节点其实是一层温柔的“糖衣”。它允许你用纯 JavaScript(或 TypeScript)编写逻辑,却能封装成标准节点在画布上拖拽使用。这篇实战指南,笔者将带你从零构建一个简单的“文本加密节点”,彻底打通 n8n 自动化的最后一公里。
准备工作:磨刀不误砍柴工
在开始编写代码之前,我们需要搭建一个本地开发环境。虽然 n8n 提供了云端版本,但自定义节点的开发和调试必须在本地进行。
你需要准备以下硬性条件:
- Node.js (v16.x 或更高版本):这是运行 n8n 的基础环境。
- npm 或 yarn:用于依赖包管理。
- 一个代码编辑器:推荐 VS Code,对 TypeScript 支持最好。
- n8n 本地实例:如果你还没安装,建议使用 Docker 启动,方便管理。
笔者提示: 如果你的 n8n 是通过 npm 全局安装的,建议使用
npx n8n启动,或者通过 Docker 挂载本地目录来加载自定义节点。这是新手最容易卡住的地方。
核心实操:创建你的第一个节点
我们将创建一个名为 N8nCustomNodes 的文件夹,并在其中构建一个简单的节点。该节点的功能是接收输入文本,并使用简单的凯撒密码(位移加密)进行处理。
步骤 1:初始化项目结构
n8n 的自定义节点本质上是一个标准的 npm 包。打开终端,执行以下命令初始化项目:
mkdir n8n-custom-nodes
cd n8n-custom-nodes
npm init -y
接下来,安装 n8n 节点开发的核心依赖:
npm install n8n-core n8n-workflow n8n-node-dev
安装完成后,打开 package.json 文件,我们需要修改两个关键字段:
- main: 设置为
dist/EncryptNode.js(编译后的输出路径)。 - scripts: 添加
"build": "tsc"和"dev": "n8n-node-dev"。
步骤 2:编写节点描述文件 (credentials.ts)
虽然我们的加密节点不需要外部 API 密钥,但为了演示完整流程,我们先配置节点的基本信息。在项目根目录下创建 src 文件夹,并新建 EncryptNode.ts。
首先引入必要的类型:
import {
IExecuteFunctions,
INodeExecutionData,
INodeType,
INodeTypeDescription,
} from 'n8n-workflow';
定义节点类并描述元数据。这是 n8n 画布识别你的节点的“身份证”:
export class EncryptNode implements INodeType {
description: INodeTypeDescription = {
displayName: '文本加密器',
name: 'encryptNode',
icon: 'fa:lock',
group: ['transform'],
version: 1,
description: '使用凯撒密码对文本进行简单加密',
defaults: {
name: '文本加密器',
color: '#00FF00',
},
inputs: ['main'],
outputs: ['main'],
properties: [
// 这里定义用户在节点面板中能看到的参数设置
{
displayName: '偏移量 (Shift)',
name: 'shift',
type: 'number',
default: 3,
description: '字符在字母表中移动的位数',
},
{
displayName: '字段名',
name: 'fieldName',
type: 'string',
default: 'encryptedText',
description: '输出结果的字段名称',
},
],
};
}
步骤 3:编写执行逻辑 (execute 方法)
这是节点的“心脏”。我们需要实现 execute() 方法,处理输入数据并返回结果。在同一个文件中继续添加代码:
async execute(this: IExecuteFunctions) {
const items = this.getInputData();
const returnData: INodeExecutionData[] = [];
// 遍历每一个输入项
for (let i = 0; i = 65 && code <= 90 ? 65 : 97;
resultText += String.fromCharCode(((code - base + shift) % 26) + base);
} else {
resultText += char;
}
}
// 组装输出数据
const newItem: INodeExecutionData = {
json: {
...items[i].json,
[fieldName]: resultText,
},
};
returnData.push(newItem);
}
return returnData;
}
步骤 4:编译与加载
代码写好了,现在需要编译 TypeScript 为 JavaScript。在终端运行:
npm run build
编译成功后,你会看到 dist 文件夹生成了 EncryptNode.js。最后一步是告诉 n8n 去哪里找这个节点。启动 n8n 时,通过环境变量指定自定义节点路径:
N8N_CUSTOM_EXTENSIONS=/path/to/your/n8n-custom-nodes npm start
或者使用 Docker 挂载卷:
docker run -it --rm
-v ~/.n8n:/root/.n8n
-v /path/to/your/n8n-custom-nodes:/home/node/.n8n/custom
n8nio/n8n
打开 n8n 画布,搜索“文本加密器”,你会发现它已经静静躺在节点列表中了!
避坑指南:实战中的拦路虎
在开发过程中,笔者踩过不少坑,这里分享两个最常见的问题:
1. 模块解析报错 (Module not found)
在使用 import 导入 n8n 的核心库时,TypeScript 编译器可能会报错。这是因为 tsconfig.json 配置不正确。
解决方案: 确保你的项目根目录下存在 tsconfig.json,并包含以下配置:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"moduleResolution": "node",
"esModuleInterop": true
}
}
2. 节点在画布中不显示
如果你编译了代码,指定了路径,但 n8n 依然找不到你的节点,通常是因为路径挂载错误或缓存问题。
解决方案:
- 检查 Docker 挂载路径是否正确(容器内的路径通常是
/home/node/.n8n/custom)。 - 如果是通过 npm 启动,确保环境变量
N8N_CUSTOM_EXTENSIONS指向的是包含package.json的根目录。 - 重启 n8n 服务(修改代码后通常需要重启才能生效)。
FAQ:你可能还想问这些
Q1: 自定义节点可以用 Python 写吗?
A: 目前 n8n 的官方支持仅限于 Node.js (JavaScript/TypeScript)。虽然可以通过 HTTP Request 节点调用 Python API,但无法直接编写 Python 节点。
Q2: 开发好的节点可以发布到社区吗?
A: 当然可以!n8n 鼓励开源。你可以将节点发布为 npm 包,其他用户只需安装即可使用。N8N大学 后续也会推出如何打包发布的教程。
Q3: 自定义节点能访问 n8n 的全局数据吗?
A: 可以。通过 this.getWorkflowStaticData('global') 或 this.getWorkflowStaticData('node'),你可以让节点具备记忆能力,存储跨执行的数据。
总结与资源
通过这篇实战教程,我们从零开始构建了一个具备实际功能的 n8n 自定义节点。这不仅仅是写代码,更是将你的业务逻辑封装成可复用资产的开始。当你掌握了自定义节点开发,n8n 对你而言就不再是一个工具,而是一个平台。
扩展资源:
我是 N8N大学 的主编,如果你在开发过程中遇到任何问题,欢迎在社区留言。保持好奇,持续构建!