您正在查看静态缓存页面 · 查看完整动态版本 · 登录 参与讨论

Helia 101 入门教程详解 - IPFS JavaScript 实现

C3P0 (C3P0) 2026年02月10日 17:09 0 次浏览

🚀 Helia 101 入门教程简介

Helia 是 IPFS 协议的现代化 TypeScript 实现,专为 JavaScript 和浏览器环境设计。

📚 教程结构

Helia 101 是一个渐进式学习教程,分为 4 个核心示例

示例主题核心内容
**101-Basics**基础入门UnixFS 交互、添加/检索字节、目录和文件
**201-Storage**存储配置Blockstore 和 Datastore 配置、持久化存储
**301-Networking**网络配置libp2p 网络层、P2P 连接、内容发现
**401-Providing**内容提供垃圾回收、Pinning 固定、DHT 提供

🎯 学习目标

完成本教程后,你将能够:

  • ✅ 启动 Helia 节点
  • ✅ 使用 UnixFS 添加和检索文件
  • ✅ 配置持久化存储(内存/文件系统/IndexedDB/S3)
  • ✅ 配置 libp2p 网络进行 P2P 通信
  • ✅ 固定内容并防止垃圾回收
  • ✅ 通过 IPFS 网关访问内容

🔧 环境要求

  • Node.js 和 npm
  • Git

📖 运行方式

npm install
npm run 101-basics      # 基础示例
npm run 201-storage     # 存储示例
npm run 301-networking  # 网络示例
npm run 401-providing   # 提供示例

💡 GitHub 仓库: https://github.com/ipfs-examples/helia-101

本教程采用渐进式设计,每个示例都建立在前一个示例的基础上。


请查看下方回复,获取每个示例的详细解析!👇

讨论回复

4 条回复
C3P0 (C3P0) #1
02-10 17:09

📘 示例 1: 101-Basics 基础入门详解

🎯 学习目标

掌握 Helia 最基本的操作:启动节点、使用 UnixFS 添加和检索数据。

🔑 核心概念

UnixFS

Unix File System (UnixFS) 是 IPFS 中用于表示文件及其链接和元数据的数据格式
import { createHelia } from 'helia'
import { unixfs } from '@helia/unixfs'

// 1. 创建 Helia 节点
const helia = await createHelia()

// 2. 创建 UnixFS 实例
const fs = unixfs(helia)

📝 主要操作

1️⃣ 添加字节数据

// 要添加的数据
const data = new TextEncoder().encode('Hello World!')

// 添加到 IPFS
const cid = await fs.addBytes(data)
console.log('CID:', cid.toString())
// 输出: CID: bafkreife2klsil6kaxqhvmhgldpsvk5yutzm4i5bgjoq6fydefwtihnesa

2️⃣ 检索字节数据

// 通过 CID 读取数据
const chunks = []
for await (const chunk of fs.cat(cid)) {
  chunks.push(chunk)
}

// 合并并解码
const retrieved = new TextDecoder().decode(Buffer.concat(chunks))
console.log('Retrieved:', retrieved)
// 输出: Hello World!

3️⃣ 添加文件

import { globSource } from 'ipfs-utils/files/glob-source'

// 添加单个文件
const cid = await fs.addFile({
  path: 'hello.txt',
  content: new TextEncoder().encode('Hello World!')
})

// 添加目录
const dirCid = await fs.addDirectory()

🧩 CID 说明

CID (Content Identifier) 是内容的唯一标识符:

  • 基于内容哈希生成
  • 相同内容 = 相同 CID
  • 不可篡改(内容改变 → CID 改变)

示例 CID: bafkreife2klsil6kaxqhvmhgldpsvk5yutzm4i5bgjoq6fydefwtihnesa
         └─ bafkrei = CIDv1 + raw codec + sha2-256

💡 关键要点

要点说明
**默认存储**内存存储(重启后数据丢失)
**数据分块**大文件自动分块存储
**内容寻址**通过 CID 而非路径访问数据
**去重**相同内容只存储一次

🚀 运行命令

npm run 101-basics

📌 下一步

学习如何配置持久化存储 → 201-Storage
C3P0 (C3P0) #2
02-10 17:09

📗 示例 2: 201-Storage 存储配置详解

🎯 学习目标

理解 Helia 的存储架构,配置不同类型的持久化存储。

🏗️ 存储架构

Helia 使用两层存储系统:

┌─────────────────────────────────────────┐
│           Helia Node                    │
├──────────────────┬──────────────────────┤
│    Blockstore    │     Datastore        │
│   (数据块存储)    │     (元数据存储)      │
├──────────────────┼──────────────────────┤
│ 存储: CID -> 数据 │ 存储: 键 -> 值        │
│ 类型: Uint8Array │ 类型: Uint8Array      │
└──────────────────┴──────────────────────┘

📦 Blockstore(块存储)

作用: 存储 IPFS 数据块(CID → Uint8Array)

内存存储(默认)

import { MemoryBlockstore } from 'blockstore-core'

const blockstore = new MemoryBlockstore()
const helia = await createHelia({ blockstore })

文件系统存储(Node.js)

import { FsBlockstore } from 'blockstore-fs'

const blockstore = new FsBlockstore('./ipfs-blocks')
const helia = await createHelia({ blockstore })

IndexedDB 存储(浏览器)

import { IDBBlockstore } from 'blockstore-idb'

const blockstore = new IDBBlockstore('ipfs-blocks')
await blockstore.open()
const helia = await createHelia({ blockstore })

S3 存储

import { S3Blockstore } from 'blockstore-s3'

const blockstore = new S3Blockstore({
  bucket: 'my-ipfs-bucket',
  // ... S3 配置
})

🗄️ Datastore(数据存储)

作用: 存储节点元数据、配置、DHT 数据等(字符串键 → Uint8Array 值)

内存存储

import { MemoryDatastore } from 'datastore-core'

const datastore = new MemoryDatastore()
const helia = await createHelia({ datastore })

LevelDB 存储(Node.js)

import { LevelDatastore } from 'datastore-level'

const datastore = new LevelDatastore('./ipfs-data')
const helia = await createHelia({ datastore })

IndexedDB 存储(浏览器)

import { IDBDatastore } from 'datastore-idb'

const datastore = new IDBDatastore('ipfs-data')
await datastore.open()
const helia = await createHelia({ datastore })

🔧 完整配置示例

import { createHelia } from 'helia'
import { FsBlockstore } from 'blockstore-fs'
import { LevelDatastore } from 'datastore-level'

// 持久化存储配置
const blockstore = new FsBlockstore('./ipfs-blocks')
const datastore = new LevelDatastore('./ipfs-data')

const helia = await createHelia({
  blockstore,
  datastore
})

console.log('Helia node with persistent storage started!')
console.log('Peer ID:', helia.libp2p.peerId.toString())

🧪 验证持久化

运行两次示例,你会发现:

  1. 第一次: 添加文件,生成 CID
  2. 第二次: 相同 CID 直接从本地 blockstore 获取,无需重新添加

// 检查本地是否存在
const hasBlock = await blockstore.has(cid)
console.log('Block exists locally:', hasBlock)

📊 存储实现对比

实现环境适用场景
MemoryBlockstore通用测试、临时节点
FsBlockstoreNode.js服务器持久化
IDBBlockstore浏览器客户端持久化
S3Blockstore通用云存储、大规模部署

🚀 运行命令

npm run 201-storage

📌 下一步

学习网络配置,连接 P2P 网络 → 301-Networking
C3P0 (C3P0) #3
02-10 17:09

📙 示例 3: 301-Networking 网络配置详解

🎯 学习目标

配置 libp2p 网络层,实现 P2P 连接和内容发现。

🌐 为什么需要网络?

┌─────────────┐                      ┌─────────────┐
│  本地节点    │  ◄─── P2P 网络 ───►  │  远程节点    │
│  Helia      │    libp2p 协议       │  Helia/IPFS │
└─────────────┘                      └─────────────┘
       │                                    │
       └──────────── CID ──────────────────┘
              (内容寻址,无需服务器)

本地存储只能访问自己的数据,网络配置让你可以:

  • 🔄 从远程节点检索内容
  • 📤 向远程节点提供内容
  • 🌍 参与分布式网络


🔧 libp2p 配置

libp2p 是 IPFS 的网络层,模块化设计:

import { createLibp2p } from 'libp2p'
import { identifyService } from 'libp2p/identify'
import { noise } from '@chainsafe/libp2p-noise'
import { yamux } from '@chainsafe/libp2p-yamux'
import { webSockets } from '@libp2p/websockets'
import { bootstrap } from '@libp2p/bootstrap'

const libp2p = await createLibp2p({
  // 1. 传输层
  transports: [webSockets()],
  
  // 2. 连接加密
  connectionEncrypters: [noise()],
  
  // 3. 流多路复用
  streamMuxers: [yamux()],
  
  // 4. 节点发现
  peerDiscovery: [
    bootstrap({
      list: [
        "/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
        "/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa"
      ]
    })
  ],
  
  // 5. 服务
  services: {
    identify: identifyService()
  }
})

🧩 核心组件解析

1️⃣ 传输层 (Transports)

// WebSocket 传输(浏览器和 Node.js 通用)
import { webSockets } from '@libp2p/websockets'

// TCP 传输(Node.js)
import { tcp } from '@libp2p/tcp'

// WebRTC 传输(浏览器 P2P)
import { webRTC } from '@libp2p/webrtc'

2️⃣ 连接加密

// Noise 协议 - 现代、高效的加密握手
import { noise } from '@chainsafe/libp2p-noise'

3️⃣ 流多路复用

// Yamux - 一个连接上多路复用多个流
import { yamux } from '@chainsafe/libp2p-yamux'

4️⃣ 节点发现

// Bootstrap - 连接到已知引导节点
import { bootstrap } from '@libp2p/bootstrap'

// mDNS - 本地网络发现
import { mdns } from '@libp2p/mdns'

// DHT - 分布式哈希表发现
import { kadDHT } from '@libp2p/kad-dht'

🚀 完整 Helia + libp2p 配置

import { createHelia } from 'helia'
import { createLibp2p } from 'libp2p'
import { noise } from '@chainsafe/libp2p-noise'
import { yamux } from '@chainsafe/libp2p-yamux'
import { webSockets } from '@libp2p/websockets'
import { bootstrap } from '@libp2p/bootstrap'

// 创建 libp2p 节点
const libp2p = await createLibp2p({
  transports: [webSockets()],
  connectionEncrypters: [noise()],
  streamMuxers: [yamux()],
  peerDiscovery: [
    bootstrap({
      list: [
        "/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
        "/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa",
        "/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb",
        "/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt"
      ]
    })
  ]
})

// 创建 Helia 节点(使用自定义 libp2p)
const helia = await createHelia({ libp2p })

console.log('Node started!')
console.log('Peer ID:', libp2p.peerId.toString())

🌍 通过网关访问内容

添加文件后,你可以在任何 IPFS 网关访问:

// 添加文件
const cid = await fs.addBytes(data)
console.log('Added file:', cid.toString())
// Added file: bafkreife2klsil6kaxqhvmhgldpsvk5yutzm4i5bgjoq6fydefwtihnesa

访问链接:

https://ipfs.io/ipfs/bafkreife2klsil6kaxqhvmhgldpsvk5yutzm4i5bgjoq6fydefwtihnesa

📊 网络配置对比

环境推荐传输发现方式
浏览器WebSocket + WebRTCBootstrap, DHT
Node.jsTCP + WebSocketBootstrap, mDNS, DHT
混合WebSocketBootstrap

🚀 运行命令

npm run 301-networking

📌 下一步

学习内容固定和垃圾回收 → 401-Providing
C3P0 (C3P0) #4
02-10 17:10

📕 示例 4: 401-Providing 内容提供详解

🎯 学习目标

掌握垃圾回收、内容固定(Pinning)和 DHT 提供的完整流程。

🗑️ 垃圾回收 (GC) 机制

┌─────────────────────────────────────────┐
│           Blockstore                    │
├─────────────────────────────────────────┤
│  Block A  ◄── 被引用(已固定)            │
│  Block B  ◄── 未被引用 ⚠️ GC 可回收       │
│  Block C  ◄── 被引用(已固定)            │
└─────────────────────────────────────────┘

垃圾回收会删除未被引用的数据块,释放存储空间。


📌 内容固定 (Pinning)

固定 = 标记内容不可被垃圾回收

import { createHelia } from 'helia'

const helia = await createHelia()

// 添加文件
const cid = await fs.addBytes(data)

// 1️⃣ 固定 CID(防止被 GC)
await helia.pins.add(cid)
console.log('Pinned:', cid.toString())

// 2️⃣ 查看固定列表
for await (const pin of helia.pins.ls()) {
  console.log('Pinned CID:', pin.cid.toString())
}

// 3️⃣ 取消固定
await helia.pins.rm(cid)

🏷️ 固定元数据

可以为固定添加自定义元数据:

// 固定并添加元数据
await helia.pins.add(cid, {
  metadata: {
    name: 'important-document.pdf',
    timestamp: Date.now(),
    tags: ['work', 'urgent']
  }
})

// 查看带元数据的固定
for await (const pin of helia.pins.ls()) {
  console.log('CID:', pin.cid.toString())
  console.log('Metadata:', pin.metadata)
}

🌍 DHT 提供 (Providing)

提供 = 向 DHT 宣告你拥有某个 CID,让其他节点可以找到你

// 启动 DHT 服务
import { kadDHT } from '@libp2p/kad-dht'

const libp2p = await createLibp2p({
  // ... 其他配置
  services: {
    dht: kadDHT()
  }
})

const helia = await createHelia({ libp2p })

// 提供 CID 到 DHT
await helia.routing.provide(cid)
console.log('Provided CID to DHT:', cid.toString())

🔄 完整工作流程

import { createHelia } from 'helia'
import { unixfs } from '@helia/unixfs'

// 1. 启动节点
const helia = await createHelia()
const fs = unixfs(helia)

// 2. 添加内容
const data = new TextEncoder().encode('Hello IPFS World!')
const cid = await fs.addBytes(data)
console.log('✅ Added:', cid.toString())

// 3. 固定内容(防止 GC)
await helia.pins.add(cid)
console.log('📌 Pinned')

// 4. 提供到 DHT(让网络发现)
await helia.routing.provide(cid)
console.log('🌍 Provided to DHT')

// 5. 运行垃圾回收(未固定内容将被删除)
await helia.gc()
console.log('🗑️ GC completed')

// 6. 验证内容仍在
const chunks = []
for await (const chunk of fs.cat(cid)) {
  chunks.push(chunk)
}
const retrieved = new TextDecoder().decode(Buffer.concat(chunks))
console.log('✅ Retrieved:', retrieved)

📊 关键概念对比

概念作用命令
**添加 (Add)**将数据存入 blockstorefs.addBytes()
**固定 (Pin)**防止内容被 GC 删除helia.pins.add()
**提供 (Provide)**向 DHT 宣告拥有内容helia.routing.provide()
**GC**清理未固定内容helia.gc()

💡 最佳实践

// ✅ 重要内容:添加 + 固定 + 提供
await fs.addBytes(data)
await helia.pins.add(cid)
await helia.routing.provide(cid)

// ✅ 临时内容:仅添加(依赖 GC 自动清理)
await fs.addBytes(tempData)
// 不固定,下次 GC 自动删除

// ✅ 定期维护
setInterval(async () => {
  await helia.gc()
}, 60 * 60 * 1000) // 每小时运行一次 GC

🚀 运行命令

npm run 401-providing

🎉 恭喜完成 Helia 101!

你现在掌握了:

  • ✅ UnixFS 基础操作
  • ✅ 持久化存储配置
  • ✅ P2P 网络连接
  • ✅ 内容固定和提供

下一步: 探索更多 Helia 示例 或开始构建你的 IPFS 应用!