跳轉到

Weather Node 程式解說

這章專門解釋你現在手上的範例專案,如何從官方 Example 骨架變成一個真的 OpenMeteoWeather node。

對照專案

這章對照的是這個專案:

/Users/tungyu6/Documents/project/n8n-community-node-lab/n8n-nodes-demo-example

最重要的程式檔是:

  • /Users/tungyu6/Documents/project/n8n-community-node-lab/n8n-nodes-demo-example/nodes/OpenMeteoWeather/OpenMeteoWeather.node.ts

想一想

很多人在學 node 開發時,只看得懂「這段程式可以跑」,但不知道「這段程式為什麼要這樣寫」。如果你只把 community node 當成一個黑盒子,那你永遠會停在會複製、會改一點字串,卻不太知道哪些地方能改、哪些地方不能亂動。真正的進步是在於,你開始看懂一個 node 的三層結構:描述層、參數層、執行層。

描述層決定使用者在 n8n 看到什麼,參數層決定使用者可以填什麼,執行層決定節點真正做什麼事。這三層如果混在一起看,很容易亂;但如果分開看,你就會發現一個 node 其實很有秩序。這章就是要幫你建立這種秩序感。

1. 先看 class 名稱

現在這個 node 的 class 是:

export class OpenMeteoWeather implements INodeType

這代表: - 它是一個 n8n node 類別 - n8n 會靠這個 class 載入 node

如果你只改顯示名稱、不改 class 與檔名,專案還是可以工作;但長期來看會很亂。所以我這次把它正式命名成 OpenMeteoWeather

2. description 區塊在做什麼

description 是 node 的 UI 定義。

你在 n8n 面板裡看到的這些資訊,都來自這裡:

  • displayName
  • name
  • icon
  • group
  • description
  • defaults
  • inputs
  • outputs
  • properties

這次改了哪些重點

displayName

displayName: 'Open-Meteo Weather'

這是使用者在面板裡看到的節點名稱。

name

name: 'openMeteoWeather'

這是 node 的內部名稱,通常用 camelCase。

icon

icon: { light: 'file:openMeteoWeather.svg', dark: 'file:openMeteoWeather.dark.svg' }

這表示這個 node 在亮色與暗色主題下各用哪個圖示。

group

group: ['transform']

這表示它比較像資料處理節點,而不是 trigger。

3. properties 在做什麼

properties 決定使用者可以輸入哪些參數。

這次我們做了四個欄位:

1. Latitude

{
  displayName: 'Latitude',
  name: 'latitude',
  type: 'number',
  default: 25.04
}

2. Longitude

{
  displayName: 'Longitude',
  name: 'longitude',
  type: 'number',
  default: 121.56
}

3. Timezone

{
  displayName: 'Timezone',
  name: 'timezone',
  type: 'string',
  default: 'Asia/Taipei'
}

4. Include Units

{
  displayName: 'Include Units',
  name: 'includeUnits',
  type: 'boolean',
  default: true
}

這四個欄位就構成了 node 的輸入介面。

4. execute() 才是真正的工作區

execute() 是 node 執行時的核心。

這裡分成三步:

第一步:拿使用者輸入

const latitude = this.getNodeParameter('latitude', itemIndex) as number;
const longitude = this.getNodeParameter('longitude', itemIndex) as number;
const timezone = this.getNodeParameter('timezone', itemIndex) as string;

意思是: - 從 node UI 拿參數值 - 每個 item 都可以拿到自己的值

第二步:打 API

const response = await this.helpers.httpRequest({...})

這裡我們直接呼叫:

https://api.open-meteo.com/v1/forecast

並帶上: - latitude - longitude - timezone - current 欄位清單

第三步:整理輸出

returnData.push({
  json: {
    query: {...},
    location: {...},
    current: response.current ?? {},
    units: includeUnits ? response.current_units ?? {} : undefined,
  },
  pairedItem: itemIndex,
});

這代表: - 不直接把原始 API 全丟出去 - 先整理成比較好接後續 workflow 的格式

這是 node 開發很重要的觀念。你不是只是 API 代理器,而是在做「適合 n8n 使用者」的輸出。

5. 錯誤處理為什麼還要保留

這段:

if (this.continueOnFail()) { ... } else { ... }

是 n8n node 常見的錯誤處理模式。

目的: - 如果 workflow 設了 continue on fail,就不要整個炸掉 - 否則就丟出帶 itemIndex 的錯誤

這一段雖然看起來不花俏,但它是 node 品質的重要部分。很多初學者做的 node 只會成功,不會好好失敗,這在正式環境很危險。

6. package.json 裡哪一段對這個 node 最重要

最重要的是:

"n8n": {
  "nodes": [
    "dist/nodes/OpenMeteoWeather/OpenMeteoWeather.node.js"
  ]
}

這一段告訴 n8n: - build 後的 node 在哪裡

如果這裡沒改,檔案雖然重命名了,n8n 還是會去找舊的 Example 路徑。

7. OpenMeteoWeather.node.json 是做什麼

這個 JSON 檔不是主邏輯,它比較像 metadata。

這次我們把它改成: - node 識別為 openMeteoWeather - category 改成比較像資料與工具類 - 文件連到 Open-Meteo 官方 docs

這樣使用者在 n8n 裡打開 docs 時,比較不會看到假連結。

8. 為什麼這個範例值得學

因為它剛好卡在一個非常好的難度:

  • 不是空骨架
  • 也不是太複雜
  • 有真 API
  • 沒有 credential 負擔
  • 有參數、有請求、有輸出、有錯誤處理

這很適合當你第一個真正讀懂的 node。

9. 下一步最值得怎麼改

如果你要把這個 weather node 再往前推,我建議:

  1. Operation 現在只有查目前天氣,之後可以再加 forecast。

  2. 加更友善的欄位 例如:

  3. 城市名稱
  4. 單位切換

  5. 加 credential 練習 雖然 Open-Meteo 不需要,但你可以練設計 credential 架構。

  6. 改 package 名稱 如果之後真的要公開分享,可以把 demo 專案改成更正式名字。