mcpField
N
n8n-code-nodes-official

n8n-code-nodes-official

github.com/n8n-io开发5582.1k 次安装2 周前更新
代码仓库

关于 n8n-code-nodes-official

为使用 n8n 的 Agent 提供 Code 节点选择与编写指导,适用于需要自定义数据处理的工作流。它优先推荐表达式和 Edit Fields,并说明跨数据源聚合等适合使用 Code 节点的场景。

主要功能

  1. 01按决策顺序选择表达式或 Code
  2. 02使用 Edit Fields 箭头函数处理数据
  3. 03为多数据源聚合使用 Code 节点
  4. 04了解 JavaScript Code 节点的运行模式
  5. 05优先使用原生 Crypto 和 XML 节点

适用场景

  1. 01转换少量字段而避免额外 Code 节点
  2. 02汇总多个上游数据源
  3. 03解析 XML 后提取字段

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/n8n-io/skills --skill n8n-code-nodes-official

安装后在 Claude Code 中输入/n8n-code-nodes-official确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
ARROW_FUNCTIONS_IN_EDIT_FIELDS.md
DECISION_TREE.md
JAVASCRIPT_PATTERNS.md

详细介绍

n8n Code 节点

Code 节点功能强大,但往往不是正确的工具。它相当于在 ORM 足以解决问题时直接使用原始 SQL:确实存在适合它的实际场景,但只要 Code 节点处理了表达式也能完成的逻辑,工作流就会变得更难阅读、调试和维护。性能差距也确实存在:Code 在沙盒 JS 运行时中运行,而表达式和 Edit Fields 则在进程内运行;对于等效逻辑,Code 的每次调用开销可能高出数百倍(据说约为 2ms 对 600ms)。对于热点路径和大量项目,这种差距会不断累积。

强默认选择

  1. Code 节点是最后的选择。 决策顺序:表达式({{...}})→ Edit Fields 中的箭头函数 → Code 节点。前两种方式可以处理大多数“转换这些数据”任务。多源聚合、外部库,以及下文记录的少数特定模式,才值得使用 Code。

  2. 默认使用 JavaScript。 除非用户明确要求使用 Python(“这里用 Python”“我们团队使用 Python”,或粘贴了 Python 代码),否则就写 JS。n8n 的其他所有地方(表达式、Edit Fields)都使用 JS,而且 JS 有经过筛选的库允许列表(lodash、crypto、luxon)。

决策树

Need custom logic?
├── Is it a transformation of one or two fields?
│   └── Expression: {{ $json.foo.toUpperCase() }} or {{ $json.items.map(item => item.name).join(', ') }}
│       Most "just transform this" cases land here.
│
├── Is it multi-line, but pure data shaping (map, filter, reduce, conditional)?
│   └── Edit Fields with arrow function expression. See references/ARROW_FUNCTIONS_IN_EDIT_FIELDS.md
│
├── Does it need full statements, multiple data sources, or external libs?
│   ├── Are you SURE the above two don't work?
│   │   └── Re-read the parent. The bar is high.
│   └── Yes, genuinely needs it
│       └── Code node. See references/JAVASCRIPT_PATTERNS.md
│
└── Is it actually two separate transformations stitched together?
    └── Use two nodes (Edit Fields → Edit Fields, or Edit Fields → IF). Composability beats one big Code block.

有关完整决策逻辑及每个分支的示例,请参阅 references/DECISION_TREE.md。

人们容易忽略表达式能做什么

常见的、让人想用 Code 节点的场景,其实应该用表达式:

// ❌ Code node
return { name: $input.first().json.name.toUpperCase() }

// ✅ Expression in Edit Fields, "name" field
{{ $json.name.toUpperCase() }}
// ❌ Code node
const items = $input.first().json.items
return { tags: items.map(item => item.tag).filter(tag => tag).join(', ') }

// ✅ Expression
{{ $json.items.map(item => item.tag).filter(tag => tag).join(', ') }}
// ❌ Code node
const date = new Date($input.first().json.created_at)
return { formatted: date.toISOString().slice(0, 10) }

// ✅ Expression with n8n's date extension
{{ $json.created_at.toDateTime().format('yyyy-MM-dd') }}

有关表达式能实现什么的更多信息,请参阅 n8n-expressions-official 技能。

Edit Fields 中的箭头函数能做什么

Edit Fields 通过表达式赋值。内联箭头函数可以让你在不使用 Code 节点的情况下,完成大多数多行逻辑:

// In Edit Fields, "summary" field:
{{ (() => {
    const items = $json.items
    const total = items.reduce((sum, item) => sum + item.price, 0)
    const tax = total * 0.08
    return `Total: $${(total + tax).toFixed(2)}`
})() }}

当“逻辑稍微复杂,无法写成单行”时,就该使用它。有关模式和格式,请参阅 references/ARROW_FUNCTIONS_IN_EDIT_FIELDS.md。

适合使用 Code 节点的场景

确实存在适用场景。门槛高,但不是“绝对不能用”。以下情况都合理。放心使用代码,不必抱歉。

跨整个数据集进行多源聚合

当一个节点需要:

  • 同时从多个上游节点读取数据(例如,$('Source A').all()、$('Source B').all()、$('Source C').first().json)。
  • 一次性针对所有项目(而非逐项)计算统计数据或进行转换。
  • 使用中间数据结构(查找映射、累加器、比率)执行多步逻辑。

这是最常见的合理场景。示例:

  • 分析汇总:按组计算平均值、百分位评分、跨类别归一化。
  • 从一个来源构建查找表,再与另一个来源的行进行连接。
  • 根据两个参考数据集计算偏移量或比率,再应用于第三个数据集。
// Real-world shape: aggregate test results from one source,
// model metadata from another, category mapping from a third,
// and produce per-model-per-category averages.

const testResults = $('Get Test Results').all().map(item => item.json)
const models = $('Get Models').all().map(item => item.json)
const categoryMap = $('Get Category Map').first().json.testCategoryMap

const categoryByTestId = Object.fromEntries(
    categoryMap.map(mapping => [mapping.testId, mapping.category])
)

const result = models.map(model => {
    const modelTests = testResults.filter(test => test.modelId === model.id)
    const stats = modelTests.reduce((acc, test) => {
        const cat = categoryByTestId[test.testId]
        if (!cat) return acc
        acc[cat] ??= { scored: 0, available: 0, count: 0 }
        acc[cat].scored += test.pointsScored ?? 0
        acc[cat].available += test.pointsAvailable ?? 0
        acc[cat].count += 1
        return acc
    }, {})

    const averages = Object.fromEntries(
        Object.entries(stats).map(([category, stat]) => [
            category,
            { avg: stat.available > 0 ? stat.scored / stat.available : 0, n: stat.count }
        ])
    )

    return { modelId: model.id, modelName: model.modelName, ...averages }
})

return result.map(json => ({ json }))

从技术上说,表达式可以通过 $('Node Name').all() 跨项目读取数据,并内联执行归约;但对于结构如此复杂的情况(连接、分组汇总、嵌套聚合),最终会变成难以阅读且无法调试的单行巨型表达式。请使用 Code。

外部库

JS Code 可以通过 require 使用经过筛选的允许列表中的库(如 lodash),但表达式不行。

务必先检查是否有原生节点。 n8n 的原生节点比很多人想象的更多。对于原生节点已经能处理的事情仍使用 Code,是一个反复出现的错误。接下来的两个小节会介绍具体容易踩的坑。

加密操作:使用 Crypto 节点,而非 Code

HMAC、签名、哈希、加密:n8n 有原生 Crypto 节点(n8n-nodes-base.crypto)。 请使用它。它可以处理 SHA256、MD5、HMAC、加密/解密和随机数生成,无需编写 JavaScript。

// WRONG (recurring AI slip):
const crypto = require('crypto')
const hash = crypto.createHash('sha256').update(buf).digest('hex').slice(0, 12)

// RIGHT: configure the Crypto node with operation: 'hash', type: 'SHA256'
//   then read $('Hash').item.json.<output> downstream.

使用 require('crypto') 的 Code 模式是最常见的“这需要 Code 节点”误判之一。其实不需要。Crypto 节点就能处理。

对二进制数据进行哈希,而不是对字符串进行哈希

不要仅仅因为需要对二进制数据(PDF、图像、文件缓冲区)进行哈希就使用 Code。Crypto 节点有一个 binaryPropertyName 参数。将它指向二进制属性键,它就会直接对缓冲区进行哈希。你不需要在用户代码中调用 this.helpers.getBinaryDataBuffer(...)。

// WRONG (recurring AI slip with binary):
const crypto = require('crypto')
const buf = await this.helpers.getBinaryDataBuffer($itemIndex, 'data')
const hash = crypto.createHash('sha256').update(buf).digest('hex')

// RIGHT: Crypto node configured to hash binaryPropertyName='data', SHA256.
//   Then $('Crypto').item.json.<output> has the hash; chain a Set node for any field shaping.

剩下唯一合理的加密场景:需要使用 Crypto 节点未提供的非标准签名方案(例如自定义的 AWS 风格签名),并且 httpCustomAuth 凭据也不适用。这种情况很少见。请明确说明理由。

XML / SOAP / RSS 解析:使用 XML 节点,而不是 Code

n8n 有一个原生 XML 节点(n8n-nodes-base.xml),支持解析和字符串化操作。它已经可以将 XML 转换为 JSON。转换后,结果就是普通 JSON,使用带箭头函数表达式的 Edit Fields 即可完成字段提取、数组规范化(Array.isArray(...) ? ... : ...)以及查找链接(.find()),这些都是你可能会用 Code 来做的操作。

// WRONG (recurring AI slip):
// XML node already parsed → another Code node to extract a few fields:
const entry = $('Parse XML').item.json.feed.entry
const firstEntry = Array.isArray(entry) ? entry[0] : entry
return { json: { title: firstEntry.title, url: firstEntry.link.find(link => link.type === 'pdf').href } }

// RIGHT: Edit Fields with arrow function expressions:
//   title:  ={{ (() => { const entry = $('Parse XML').item.json.feed.entry; return Array.isArray(entry) ? entry[0].title : entry.title; })() }}
//   pdfUrl: ={{ $('Parse XML').item.json.feed.entry.link.find(link => link.type === 'pdf')?.href }}

如果字段提取逻辑确实太复杂,即使用多行箭头函数也无法用内联表达式处理,接下来应使用带有单个多行箭头函数的 Edit Fields,而不是 Code 节点。参见 references/ARROW_FUNCTIONS_IN_EDIT_FIELDS.md。

这些情况的共同点

合理的场景与作用范围有关:整个数据集、多个来源,或单条目工具无法处理的有状态结构。不合理的场景包括:Code 做了表达式就能完成的工作,或者原生节点已经能完成的工作。

快速判断:

  • “我能否把这个 Code 节点的工作描述为‘接收这一个条目并……’?” 如果可以,那就用错工具了。
  • “有没有原生节点能做这件事?” 先通过 search_nodes 搜索。Crypto、XML、JSON 解析、日期计算(Luxon)、HTTP 调用、文件 I/O、正则匹配:都有原生节点或表达式级支持。

JavaScript Code 节点详解

两种模式:

  • Run Once for All Items(默认,使用此模式): 使用 $input.all() 运行一次。如果需要逐条处理,只需在内部使用 for (const item of $input.all())。这是标准写法,几乎总是你需要的模式。
  • Run Once for Each Item: 每个条目运行一次,使用 $input.first()(或 $input.item)。

常见写法:

// Run Once for All Items
const items = $input.all()
const totals = items.map(item => ({
  ...item.json,
  total: item.json.qty * item.json.price,
}))
return totals.map(json => ({ json }))

返回值必须是 { json: ... } 对象组成的数组(或 { json: ..., binary: ... }),不能是原始 JSON。

有关二进制数据处理、错误模式和仅限 Code 节点的漏洞,请参见 references/JAVASCRIPT_PATTERNS.md。

参考文件

文件阅读时机
references/DECISION_TREE.md想要使用 Code 节点,并希望确认更简单的方法确实行不通时
references/ARROW_FUNCTIONS_IN_EDIT_FIELDS.md转换需要多行代码,但只是纯数据整形时
references/JAVASCRIPT_PATTERNS.md确实需要 Code 节点,且使用 JavaScript 时

反模式

反模式问题所在修复方法
Code 节点执行 return { x: $input.first().json.x.toUpperCase() }仅为一个表达式就使用整个节点替换为 Edit Fields 表达式
Code 节点为电子邮件正文构建 HTML 字符串Email 节点的正文栏支持表达式将表达式内联到 Email 节点中
Code 节点使用 new Date() 格式化日期不如 Luxon 清晰在表达式中使用 Luxon。参见 n8n-expressions-official
Set 节点 + Code 节点组合(Set 构建输入,Code 进行转换)两个节点做了本应由一个 Edit Fields 完成的事合并为一个带箭头函数的 Edit Fields
将凭据/令牌粘贴到 Code 节点文本中与文本字段一样会导致泄露使用凭据,不要使用 Code 节点

评论

支持 Markdown