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 自定义节点开发的主要方面。根据您的具体需求,可以进一步扩展和定制节点的功能。

相关推荐
程序员游老板21 小时前
基于SpringBoot3+vue3的爱心陪诊平台
java·spring boot·毕业设计·软件工程·课程设计·信息与通信
粟悟饭&龟波功1 天前
【软考系统架构设计师】七、系统架构设计基础
系统架构·软件工程
雾江流1 天前
小喵播放器 1.1.2| 一款支持视频超分的播放器,支持网页视频以及B站番剧
软件工程
ones~1 天前
软件体系架构(三)
学习·架构·软件工程
HLJ洛神千羽1 天前
J2EE技术及应用实验及报告(黑龙江大学)
java-ee·软件工程
程序员游老板2 天前
基于SpringBoot3_vue3_MybatisPlus_Mysql_Maven的社区养老系统/养老院管理系统
java·spring boot·mysql·毕业设计·软件工程·信息与通信·毕设
hans汉斯2 天前
【软件工程与应用】平移置换搬迁系统设计与实现
数据库·人工智能·系统架构·软件工程·汉斯出版社·软件工程与应用
粟悟饭&龟波功2 天前
【软考系统架构设计师】六、软件工程
系统架构·软件工程
郝学胜-神的一滴2 天前
Linux线程编程:从原理到实践
linux·服务器·开发语言·c++·程序人生·设计模式·软件工程
αSIM0V3 天前
人机交互期末复习
人机交互·软件工程