n8n 中自开发组件

在 n8n 中自开发组件(自定义节点)是一个强大的功能,可以让您扩展平台的能力。以下是完整的开发指南:

1. 开发环境准备

安装 n8n CLI

bash复制代码

复制代码
npm install -g @n8n/n8n
# 或
npm install -g n8n

创建自定义节点项目

bash复制代码

复制代码
# 创建项目目录
mkdir n8n-nodes-custom
cd n8n-nodes-custom

# 初始化项目
npm init -y

2. 项目结构

复制代码

复制代码
n8n-nodes-custom/
├── nodes/           # 自定义节点目录
│   ├── MyCustomNode/
│   │   ├── MyCustomNode.node.ts
│   │   └── MyCustomNode.node.json
├── package.json
├── tsconfig.json
└── webpack.config.js

3. 基础配置文件

package.json

json复制代码

复制代码
{
  "name": "n8n-nodes-custom",
  "version": "1.0.0",
  "description": "Custom n8n nodes",
  "main": "index.js",
  "scripts": {
    "build": "webpack --mode=production",
    "dev": "webpack --watch --mode=development"
  },
  "dependencies": {
    "n8n-workflow": "^0.28.0"
  },
  "devDependencies": {
    "@types/node": "^16.0.0",
    "ts-loader": "^9.2.6",
    "typescript": "^4.5.5",
    "webpack": "^5.68.0",
    "webpack-cli": "^4.9.2"
  }
}

tsconfig.json

json复制代码

复制代码
{
  "compilerOptions": {
    "target": "es2020",
    "lib": ["es2020"],
    "module": "commonjs",
    "moduleResolution": "node",
    "declaration": true,
    "outDir": "./dist",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["nodes/**/*"]
}

4. 创建自定义节点

节点定义文件 (MyCustomNode.node.json)

json复制代码

复制代码
{
  "node": {
    "version": 1,
    "name": "myCustomNode",
    "displayName": "My Custom Node",
    "description": "A custom node example",
    "defaults": {
      "name": "My Custom Node"
    },
    "inputs": ["main"],
    "outputs": ["main"],
    "properties": [
      {
        "displayName": "Resource",
        "name": "resource",
        "type": "options",
        "noDataExpression": true,
        "options": [
          {
            "name": "User",
            "value": "user"
          }
        ],
        "default": "user"
      },
      {
        "displayName": "Operation",
        "name": "operation",
        "type": "options",
        "noDataExpression": true,
        "options": [
          {
            "name": "Get",
            "value": "get"
          }
        ],
        "default": "get"
      },
      {
        "displayName": "User ID",
        "name": "userId",
        "type": "string",
        "default": "",
        "required": true,
        "displayOptions": {
          "show": {
            "resource": ["user"],
            "operation": ["get"]
          }
        }
      }
    ]
  }
}

节点逻辑文件 (MyCustomNode.node.ts)

typescript复制代码

复制代码
import {
  IExecuteFunctions,
  INodeExecutionData,
  INodeType,
  INodeTypeDescription,
} from 'n8n-workflow';

export class MyCustomNode implements INodeType {
  description: INodeTypeDescription = {
    displayName: 'My Custom Node',
    name: 'myCustomNode',
    icon: 'fa:user',
    group: ['transform'],
    version: 1,
    description: 'A custom node example',
    defaults: {
      name: 'My Custom Node',
      color: '#FF6B6B',
    },
    inputs: ['main'],
    outputs: ['main'],
    properties: [
      {
        displayName: 'Resource',
        name: 'resource',
        type: 'options',
        options: [
          {
            name: 'User',
            value: 'user',
          },
        ],
        default: 'user',
        required: true,
        description: 'The resource to operate on',
      },
      {
        displayName: 'Operation',
        name: 'operation',
        type: 'options',
        options: [
          {
            name: 'Get',
            value: 'get',
          },
        ],
        default: 'get',
        required: true,
      },
      {
        displayName: 'User ID',
        name: 'userId',
        type: 'string',
        default: '',
        required: true,
        displayOptions: {
          show: {
            resource: ['user'],
            operation: ['get'],
          },
        },
        description: 'The ID of the user',
      },
    ],
  };

  async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
    const items = this.getInputData();
    const returnData: INodeExecutionData[] = [];

    const resource = this.getNodeParameter('resource', 0) as string;
    const operation = this.getNodeParameter('operation', 0) as string;

    for (let i = 0; i < items.length; i++) {
      try {
        if (resource === 'user' && operation === 'get') {
          const userId = this.getNodeParameter('userId', i) as string;
          
          // 这里实现你的业务逻辑
          const userData = {
            id: userId,
            name: `User ${userId}`,
            email: `user${userId}@example.com`,
            timestamp: new Date().toISOString(),
          };

          returnData.push({
            json: userData,
            pairedItem: {
              item: i,
            },
          });
        }
      } catch (error) {
        if (this.continueOnFail()) {
          returnData.push({
            json: {
              error: error.message,
            },
            pairedItem: {
              item: i,
            },
          });
          continue;
        }
        throw error;
      }
    }

    return [returnData];
  }
}

5. Webpack 配置

webpack.config.js

javascript复制代码

复制代码
const path = require('path');

module.exports = {
  target: 'node',
  entry: './nodes/MyCustomNode/MyCustomNode.node.ts',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'MyCustomNode.node.js',
    libraryTarget: 'commonjs2',
  },
  resolve: {
    extensions: ['.ts', '.js'],
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
    ],
  },
  externals: {
    'n8n-workflow': 'commonjs2 n8n-workflow',
  },
};

6. 构建和安装

构建节点

bash复制代码

复制代码
npm run build

在 n8n 中安装

  1. 将构建好的文件复制到 n8n 的 custom extensions 目录
  2. 或使用 npm 包方式安装

7. 高级功能示例

认证配置

typescript复制代码

复制代码
// 在 properties 数组中添加认证配置
{
  displayName: 'Authentication',
  name: 'authentication',
  type: 'options',
  options: [
    {
      name: 'API Key',
      value: 'apiKey',
    },
    {
      name: 'OAuth2',
      value: 'oauth2',
    },
  ],
  default: 'apiKey',
  required: true,
}

Webhook 支持

typescript复制代码

复制代码
// 添加 webhook 描述
webhooks: [
  {
    name: 'default',
    httpMethod: 'POST',
    responseMode: 'onReceived',
    path: 'webhook',
  },
],

8. 测试和调试

本地测试

bash复制代码

复制代码
# 启动 n8n 并加载自定义节点
n8n start --tunnel

调试技巧

  • 使用 console.log 输出调试信息
  • 检查 n8n 日志文件
  • 使用 try-catch 处理错误

9. 最佳实践

  1. 错误处理: 实现完整的错误处理机制
  2. 类型安全: 使用 TypeScript 确保类型安全
  3. 文档: 为节点提供清晰的文档说明
  4. 测试: 编写单元测试和集成测试
  5. 版本控制: 遵循语义化版本控制

这个指南涵盖了 n8n 自定义节点开发的主要方面。根据您的具体需求,可以进一步扩展和定制节点的功能。

相关推荐
双翌视觉1 天前
基于机器视觉对位技术实现精准的手机屏幕贴合
智能手机·软件工程
爱思德学术1 天前
中国计算机学会(CCF)推荐学术会议-C(软件工程/系统软件/程序设计语言):ICST 2026
软件测试·软件工程·软件验证
云知谷3 天前
【软件测试】《集成测试全攻略:Mock/Stub 原理 + Postman/JUnit/TestNG 实战》
c语言·开发语言·c++·软件工程·团队开发
码界奇点4 天前
Java设计模式精讲从基础到实战的常见模式解析
java·开发语言·设计模式·java-ee·软件工程
数字时代全景窗4 天前
从App时代到智能体时代,如何打破“三堵墙”
人工智能·软件工程
莫桑晚-为尚天6 天前
触控芯片核心:DRV与SENS信号解析
嵌入式硬件·硬件工程·软件工程
_清浅6 天前
软件工程(速成笔记)
软件工程
PcVue China6 天前
PcVue X 工控——工厂数字化转型与落地巡回研讨会圆满举行
人工智能·软件工程·scada·监控平台·工控网
雾江流8 天前
RikkaHub 1.6.11 | 开源的本地大型语言模型聚合应用,支持多种AI服务提供商
人工智能·语言模型·自然语言处理·软件工程