本文带你从 0 到 1,动手写出、部署并运行一个完全运行在以太坊区块链上的“问候”示例;你会看到如何使用 Web3.js、Truffle、Ganache 让前端与智能合约无缝交互。通过实践学习 DApp 开发流程、Web3.js API、Solidity 合约迁移部署 等核心知识,快速迈入 Web3 世界。
1. 基础术语与概念速览
- 区块链:只能追加、不可篡改的分布式账本。
- 以太坊:支持智能合约的开放区块链平台。
- 智能合约:运行在去中心化网络上的自执行代码,通常用 Solidity 编写。
- DApp:去中心化应用 = 前端 + 钱包 + 智能合约,具备无停机、透明、开源等特点。
- Web3.js:使用 HTTP/IPC/WebSocket 与节点通信的 JavaScript 库集合,是开发 以太坊 DApp 开发 的必备工具包。
2. Web3.js 如何工作
Web3.js 本质上是把 JavaScript 调用翻译成 JSON-RPC 请求:
前端 ↔ Web3.js ↔ Provider ↔ 以太坊节点常见 Provider:HttpProvider、WebsocketProvider、IpcProvider。
Web3.js 提供了五大包:
web3.eth:与区块链和智能合约交互web3.bzz:Swarm 去中心化存储web3.shh:Whisper 消息广播web3.utils:常用工具,如单位换算、十六进制转换web3.*.net:获取网络 ID、节点数量等元数据
👉 一次性掌握所有 Web3 核心生态知识点,点击直达完整资料页!
3. 环境搭建(macOS、Windows、Linux 通杀)
| 工具 | 作用 | 安装命令 |
|---|---|---|
| Node.js | 运行 JavaScript、构建前端 | brew install node |
| Truffle | 以太坊开发框架,合约编译与部署 | npm install -g truffle |
| Ganache | 本地区块链,一键启动多个测试账户 | 官网安装 GUI 版 或 npm install -g ganache-cli |
| solc | Solidity 编译器 | npm install -g solc |
说明:Ganache GUI 适合可视化调试,CLI 更轻量,二选一即可。
4. 初始化项目
mkdir dapp-demo && cd dapp-demo
truffle init运行后,Truffle 会生成:
contracts/存放 Solidity 文件migrations/部署脚本truffle-config.js网络与编译配置
5. 编写智能合约 Greeting.sol
保存为 contracts/Greeting.sol:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Greeting {
string public greeting = "hello";
function sayHello() external view returns (string memory) {
return greeting;
}
function updateGreeting(string calldata _greeting) external {
greeting = _greeting;
}
}- 提供两个函数:
sayHello()读取问候语,updateGreeting()更新问候语。
6. 编写迁移脚本
创建 migrations/2_greeting_migration.js:
const Greeting = artifacts.require("Greeting");
module.exports = deployer => deployer.deploy(Greeting);7. 编译 & 部署到本地链
- 启动 Ganache(快速启动即可)。
- 取消
truffle-config.js中development网络的注释,并确保端口对应 Ganache 的 RPC Server(默认 7545)。 命令行执行:
truffle compile truffle migrate --network development控制台会返回合约地址:如
0x123...,记住它!
8. 前端联调:让页面直接与链对话
8.1 新建前端文件夹并安装依赖
mkdir client && cd client
npm init -y
npm install web3@latest jquery lite-server --save-dev
mkdir src contracts8.2 复制合约 ABI
- 从
../build/contracts/Greeting.json复制同文件名文件至client/contracts/(包含 ABI 和地址映射)。
8.3 封装工具函数 src/utils.js
// 获取 Web3 实例
const getWeb3 = () =>
new Promise((resolve, reject) => {
window.addEventListener("load", async () => {
try {
const web3 = new Web3("http://127.0.0.1:7545"); // Ganache RPC端口
resolve(web3);
} catch (error) {
reject(error);
}
});
});
// 获取合约对象
const getContract = async (web3) => {
const data = await $.getJSON("./contracts/Greeting.json");
const netId = await web3.eth.net.getId();
const deployedNetwork = data.networks[netId];
return new web3.eth.Contract(
data.abi,
deployedNetwork && deployedNetwork.address
);
};8.4 页面入口 client/index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8"/>
<title>DApp Demo</title>
</head>
<body>
<h2 id="greeting-text">加载中 …</h2>
<form id="form">
<input id="input" type="text" placeholder="输入新问候语"/>
<button type="submit">更新</button>
</form>
<script src="node_modules/jquery/dist/jquery.min.js"></script>
<script src="node_modules/web3/dist/web3.min.js"></script>
<script type="module" src="src/index.js"></script>
</body>
</html>8.5 交互逻辑 src/index.js
import { getWeb3, getContract } from "./utils.js";
const displayGreeting = async (contract) => {
const text = await contract.methods.sayHello().call();
$("#greeting-text").text(text);
};
const updateGreeting = async (inputText, contract, accounts) => {
await contract.methods
.updateGreeting(inputText)
.send({ from: accounts[0], gas: 40000 });
await displayGreeting(contract);
};
const greetingApp = async () => {
const web3 = await getWeb3();
const accounts = await web3.eth.getAccounts();
const contract = await getContract(web3);
displayGreeting(contract);
$("#form").on("submit", async (e) => {
e.preventDefault();
const inputText = $("#input").val();
updateGreeting(inputText, contract, accounts);
});
};
greetingApp();Tip: ⚡ 记得在 client\package.json 中添加脚本:
"scripts": {
"start": "lite-server"
}9. 启动 DApp
- 在项目根目录另开一个终端:
cd client && npm start - 浏览器自动打开
http://localhost:3000。 - 页面先读取链上默认问候语 “hello”,输入新词点击“更新”即可上链。每笔交易都能同步到 Ganache 的区块里。
👉 想进一步部署到主网或测试网?这里提供一站式区块链部署攻略!
常见问题 FAQ
Q1:为什么刷新页面后交易更新马上生效?
A:Web3.js 通过轮询节点,会立即读取最新区块状态,因此几乎实时可见。
Q2:报错 connection not open on send 如何解决?
A:大多数情况是 Ganache 没启动或端口被占用。确认 http://127.0.0.1:7545 正常返回 JSON:{"jsonrpc":"2.0","id":1,"result":"0x539"}。
Q3:如何切换 MetaMask 网络?
A:关闭本示例中的 Web3.js 实例,把页面 Provider 替换为 window.ethereum 即可让 MetaMask 接管权限;更新仅对用户签名的账户生效。
Q4:Gas Limit 选多少合适?
A:简单读写 40,000 Wei 足够。复杂逻辑先用 Remix 估算,再上调 10–20% 作为缓冲区。
Q5:我想把币值单位换算为 ETH,而不是 Wei?
A:使用 web3.utils.fromWei(ethValue) 一行搞定数值转换。
Q6:怎样让合约开源以便社区验证?
A:把源码与编译参数上传到 Etherscan、Blockscout 等区块浏览器的 Verify & Publish 通道,自动生成 ABI 及校验代码。
结语
恭喜,你已经完成了第一个 基于 Web3.js 的以太坊 DApp 的完整端到端体验:从合约编写、Truffle 部署,到前端联调。掌握了这些核心技能后,下一步可以挑战更复杂的 DeFi、NFT、DAO 项目。持续迭代、参与线上黑客松,让代码与创意在链上闪光!