在将React单页应用接入ENS与Ethereum Name Service体系时,核心并不是把DNS记录删掉,而是让应用能识别链上名称、并把用户访问的伪域名解析到真实资源位置。ENS本身只负责把类似 myapp.eth 的名称映射到以太坊地址、文本内容或IPFS哈希,网页文件仍需托管在IPFS或普通HTTPS服务上。

一、理解ENS解析与React路由的关系
很多团队误以为配置了ENS就能像DNS一样直接打开网站,其实浏览器不会原生用ENS解析HTTP请求。用户通常通过支持ENS的浏览器(如Brave)或网关(如 eth.link 的替代服务)访问 myapp.eth,网关会把名称换成对应的IPFSCID或地址再回源。因此React应用内部的 BrowserRouter 依然按正常路径工作,不需要为 .eth 后缀做特殊路由。
但如果你的应用需要根据当前访问的ENS名称展示不同租户内容,就需要在入口处读取 window.location.host,判断是否为 .eth 结尾,再调用解析接口拿到背后的哈希或地址。下面代码展示了如何用 ethers 读取名称对应的内容哈希:
import { ethers } from 'ethers';
async function resolveEnsContent(appName) {
const provider = new ethers.providers.JsonRpcProvider('https://ipipp.com/rpc');
// 解析器合约返回contenthash
const resolver = await provider.getResolver(appName);
if (!resolver) {
throw new Error('未找到解析器');
}
const contentHash = await resolver.getContentHash();
return contentHash;
}
这段代码返回的 contentHash 可能是 IPFS 的 CIDv0 或 CIDv1,需要转换成网关可访问的 URL。注意 getResolver 在名称未配置时会返回 null,必须在运行时做空值保护,否则白屏。
从架构看,ENS只是命名层,React是表现层,二者通过解析结果松耦合。把命名逻辑做成独立 Hook,可以避免业务组件直接依赖链上SDK,方便后续替换成其他去中心化命名系统。
二、构建与部署流程改造
传统React项目用 npm run build 生成静态文件后上传到Nginx或对象存储。迁移到ENS生态时,通常把 build 目录推到IPFS,再把IPFS哈希写到ENS的content字段。这样用户访问 myapp.eth 实际拿到的是IPFS上的文件,具备抗审查特性。
以下脚本演示如何用命令行把构建产物发布到IPFS并输出哈希:
# 构建React应用 npm run build # 使用ipfs-cli添加目录,获取根CID ipfs add -r build | tail -n 1 # 假设输出为 QmTestCID,更新ENS内容 npx ens-updater setContent myapp.eth ipfs QmTestCID --private-key $PK
在CI中可以把上述步骤写成流水线,每次发版自动更新ENS记录。但要小心:IPFS网关普遍有缓存,新内容可能延迟生效,建议在HTML里写版本号并配合Service Worker做强制更新。
另外,若团队暂时不敢完全去中心化,也可采用混合方案:ENS指向一个始终在线的HTTPS地址,仅把登录态或钱包绑定信息用ENS名称做身份校验。这样迁移成本最低,又能体验链上身份优势。
三、运行时解析组件与异常处理
为方便复用,我们封装一个React Hook,在应用启动时尝试解析当前 host 对应的ENS内容,失败则降级到预设地址。这样即使网关故障,页面也能用兜底配置运行。
import { useEffect, useState } from 'react';
import { ethers } from 'ethers';
export function useEnsFallback(defaultHost) {
const [target, setTarget] = useState(defaultHost);
useEffect(() => {
const host = window.location.host;
if (host.endsWith('.eth')) {
const provider = new ethers.providers.Web3Provider(window.ethereum);
provider.getResolver(host).then(async (r) => {
if (r) {
const hash = await r.getContentHash();
if (hash) setTarget('https://ipfs.io/ipfs/' + hash);
}
}).catch(() => {});
}
}, []);
return target;
}
该Hook不阻塞首屏,先渲染默认内容,解析成功后再切换资源域。实践中要注意,部分钱包注入的 window.ethereum 在纯访问场景下不存在,必须判断 undefined,否则会抛错中断渲染。
常见报错包括:解析器返回空内容、CIDv1未被网关支持、跨域限制导致字体加载失败。建议在控制台打印解析中间值,并准备一个状态页说明当前是中心化模式还是ENS模式,降低用户困惑。
四、迁移后的验证与监控
上线后用多种入口验证:普通浏览器加网关后缀、原生ENS浏览器、移动端钱包内置浏览器。记录各端首屏时间与解析成功率。若发现某网关不稳定,可在Hook里维护一个网关列表做轮询。
监控上,可以把解析耗时上报到自有分析服务,当ENS记录被误改时能快速发现流量跌落。整体来看,React迁移到ENS并非重写框架,而是增加一层名称解析与资源定位适配,掌握边界就能平稳过渡。
ReactENSEthereum_Name_Service修改时间:2026-08-12 00:33:29