n8n-code-nodes について
n8n の Code ノードの選択と記述を案内するスキルです。単純な変換には式や Edit Fields を優先し、広いデータ範囲やライブラリが必要な場合に JavaScript を使う判断を支援します。
主な機能
- 01式、Edit Fields、Code の選択ガイド
- 02全アイテムを対象とする集約例
- 03JavaScript Code ノードの記述パターン
- 04一般的な処理での標準ノード活用指針
活用シーン
- 01データ変換に適したノードの選択
- 02複数ソースのデータ結合と集約
- 03標準ノードで独自コードを置き換えられるかの確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ n8n-io/ skills --skill n8n-code-nodesインストール後、Claude Code で/n8n-code-nodesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/ARROW_FUNCTIONS_IN_EDIT_FIELDS.mdDECISION_TREE.mdJAVASCRIPT_PATTERNS.md詳細
n8n コードノード
コードノードは強力ですが、選ぶべきではない場合も多くあります。ORM で済むのに生の SQL に切り替えるようなものです。実際に必要なケースはありますが、式で実現できるロジックをコードノードで処理すると、ワークフローの可読性、デバッグのしやすさ、保守性が損なわれます。パフォーマンスにも大きな差があります。コードはサンドボックス化された JS ランタイムで実行されますが、式と Edit Fields はプロセス内で実行されます。呼び出しごとのオーバーヘッドはコードのほうが数百倍高くなる場合があります(同等のロジックで、経験則では約 2ms 対約 600ms)。頻繁に実行される処理や大量のアイテムを扱う場合、この差は積み重なります。
基本方針
-
コードノードは最終手段です。 判断の順序は、式(
{{...}})→ Edit Fields 内のアロー関数 → コードノードです。最初の 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 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 スキルを参照してください。
Edit Fields 内のアロー関数でできること
Edit Fields は、式を使ってフィールドの値を設定します。インラインのアロー関数を使えば、コードノードを使わずに、複数行にわたるロジックの大半を記述できます。
// 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 を参照してください。
コードノードが適切な選択肢となる場合
実際に必要なケースはあります。基準は高く設定されていますが、「決して使わない」という意味ではありません。以下のケースは正当な用途です。ためらわずにコードを使ってください。
データセット全体にわたる複数ソースの集約
ノードで次の処理が必要な場合です。
- 複数の上流ノードを同時に読み取る(例:
$('Source A').all()、$('Source B').all()、$('Source C').first().json)。 - すべてのアイテムをまとめて(アイテムごとではなく)統計情報や変換を計算する。
- 中間データ構造(ルックアップマップ、アキュムレーター、比率)を使った複数ステップのロジックを適用する。
最も一般的な正当なケースです。例:
- 分析結果の集計:グループごとの平均、パーセンタイルスコア、カテゴリ間の正規化。
- あるソースからルックアップテーブルを作成し、別のソースの行と結合する。
- 2 つの参照データセット間でオフセットや比率を計算し、それを 3 つ目のデータセットに適用する。
// 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() を使ってアイテムをまたいでデータにアクセスし、インラインで reduce できます。しかし、これほど複雑な構造(結合、グループ化、ネストされた集約)を扱うと、結果は読みづらくデバッグもできない一行の巨大な式になります。コードノードを使ってください。
外部ライブラリ
JS コードでは厳選された許可リスト(lodash など)から require できますが、式ではできません。
まず、標準ノードがないか必ず確認してください。 n8n には、思われているより多くの標準ノードがあります。標準ノードでできることにコードノードを使ってしまうのは、よくある間違いです。次の 2 つの節では、特に注意すべきケースを説明します。
暗号処理にはコードではなく Crypto ノードを使う
HMAC、署名、ハッシュ化、暗号化には、n8n に標準の Crypto ノード(n8n-nodes-base.crypto)があります。 使ってください。JavaScript を書かずに、SHA256、MD5、HMAC、暗号化/復号、乱数生成に対応できます。
// 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') を使うコードのパターンは、「コードノードが必要」と誤って判断される最も一般的な例の 1 つです。必要ありません。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 に関して Code が有効なのは、Crypto ノードが対応していない非標準の署名方式(たとえば、カスタムの AWS 形式の署名)が必要で、かつ httpCustomAuth 認証情報も適合しない場合です。まれなケースです。理由を明確に説明してください。
XML/SOAP/RSS の解析:Code ではなく XML ノードを使う
n8n には、解析と文字列化の操作を備えたネイティブの XML ノード(n8n-nodes-base.xml)があります。 XML をすでに JSON に変換できます。変換後は通常の JSON なので、Edit Fields のアロー関数式で、Code を使いたくなるようなフィールドの抽出、配列の正規化(Array.isArray(...) ? ... : ...)、リンクの検索(.find())に対応できます。
// 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 }}
複数行のアロー関数を使ってもインライン式ではフィールド抽出ロジックが複雑すぎる場合は、次に試すのは Code ノードではなく、複数行のアロー関数を 1 つ使った Edit Fields です。references/ARROW_FUNCTIONS_IN_EDIT_FIELDS.md を参照してください。
これらに共通する点
有効なケースは、スコープに関するものです。データセット全体、複数のソース、または単一アイテム用ツールでは対応できないステートフルな構成が該当します。無効なケースは、式でできること、またはネイティブノードですでにできることを Code で行う場合です。
簡単な確認方法:
- 「この Code ノードの役割を『この 1 つのアイテムを受け取り、…する』と説明できますか?」 はいなら、ツールの選択が間違っています。
- 「これに対応するネイティブノードはありますか?」 まず
search_nodesで検索してください。Crypto、XML、JSON 解析、日付計算(Luxon)、HTTP 呼び出し、ファイル I/O、正規表現によるマッチングには、すべてネイティブノードまたは式レベルのサポートがあります。
JavaScript Code ノードの詳細
2 つのモードがあります。
- Run Once for All Items(デフォルト。これを使用):
$input.all()を使って 1 回実行します。アイテムごとのロジックが必要な場合は、内部でfor (const item of $input.all())を使用してください。これが標準的な形式で、ほとんどの場合に適しています。 - Run Once for Each Item:
$input.first()(または$input.item)を使って、アイテムごとに 1 回実行します。
一般的な形式:
// 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() } を実行する | 1 つの式のためにノード全体を使っている | Edit Fields の式に置き換える |
| Code ノードでメール本文用の HTML 文字列を組み立てる | Email ノードの本文フィールドでは式を使用できる | 式を Email ノードに直接記述する |
Code ノードで日付の書式設定に new Date() を使う | Luxon の明快さに劣る | 式で Luxon を使う。n8n-expressions を参照 |
| Set ノードと Code ノードの組み合わせ(Set で入力を作成し、Code で変換する) | 1 つの Edit Fields ノードで済む処理に 2 つのノードを使っている | アロー関数を使った 1 つの Edit Fields にまとめる |
| 認証情報やトークンを Code ノードのテキストに貼り付ける | テキストフィールドと同じ情報漏えいが起きる | Code ノードではなく、認証情報を使う |