You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

内联JS可正常运行,如何让外部app.js在IPFS/Pinata环境下工作?

问题与解决方案:IPFS/Pinata部署后外部JS无法加载导致功能失效

问题背景

开发基于IPFS和Pinata的网站,原内联JS版本在本地/公共网关正常运行,但Pinata禁止使用内联JS,遂将JS代码提取至同目录的app.js文件。上传IPFS后,HTML页面可正常显示,但按钮点击功能完全失效,调用JS文件时持续返回400/500错误,尝试多种路径均无法解决。

调用JS的代码:

<script type="text/javascript" src="app.js"></script>

现有代码

HTML代码

<!DOCTYPE html>
<html>
<head>
    <title>LootCache</title>
    <script type="text/javascript" src="app.js"></script>

    <style>
        body {
            background-color: black;
            margin: 0;
            padding: 0;
        }

        .container {
            max-width: 100%;
            margin: 0 auto;
            border: 5px solid gold;
            padding: 10px;
            box-sizing: border-box;
            display: flex;
            flex-direction: column;
            align-items: center;
            height: 100vh;
            overflow: auto;
        }

        h1 {
            font-size: 50px;
            font-weight: bold;
            color: gold;
            margin: 10px 0;
            display: flex;
            align-items: center;
        }

        .input-container {
            background-color: white;
            padding: 10px;
            margin: 10px 0;
            border-radius: 5px;
            display: flex;
            flex-direction: column;
            align-items: center;
            width: 100%;
            box-sizing: border-box;
            max-width: 800px;
        }

        input[type=text] {
            width: 100%;
            padding: 10px;
            border: none;
            border-radius: 5px;
            box-sizing: border-box;
            font-size: 16px;
            margin-bottom: 10px;
        }

        button {
            background-color: gold;
            color: black;
            border: none;
            border-radius: 5px;
            padding: 10px;
            font-size: 16px;
            cursor: pointer;
        }

        .response {
            color: gold;
            font-size: 20px;
            margin-top: 10px;
            word-wrap: break-word;
            text-align: center;
        }

        img {
            display: block;
            max-height: calc(100vh - 300px);
            margin: 10px auto;
            object-fit: contain;
            max-width: 100%;
            height: auto;
        }
    </style>
</head>
<body>
    <div class="container">
        <img src="https://ipfs.io/ipfs/QmXjtBuhfDRZfTXZjF2dpJ4mSnmjj5RPow4qMY5X6ZQ6QU?filename=LootCache-1.png" alt="LootCache">
        <h1></h1>
        <div class="input-container">
            <label for="ethAddress">Enter Ethereum Address (No ENS):</label>
            <input type="text" id="ethAddress" name="ethAddress" placeholder="0x...">
            <button id="checkBalanceBtn">Check Your Stash!</button>
        </div>
        <div class="response" id="response"></div>
    </div>
</body>
</html>

JS代码(app.js)

window.onload = function() {
async function getBalance(address) {
    const response = await fetch(`https://mainnet.infura.io/v3/fb3bba54ae0449c28400a4e28fb61e6c?module=account&action=balance&address=${address}`);
    const data = await response.json();
    return data.result;
}

function displayAddress() {
    var address = document.getElementById("ethAddress").value;
    var provider = new Web3.providers.HttpProvider("https://mainnet.infura.io/v3/fb3bba54ae0449c28400a4e28fb61e6c");
    var web3 = new Web3(provider);
    web3.eth.getBalance(address, function(error, balance) {
        if (error) {
            document.getElementById("response").innerHTML = "Error: " + error.message;
        } else {
            var balanceInEther = web3.utils.fromWei(balance, "ether");
            var formattedBalance = parseFloat(balanceInEther).toFixed(4);
            document.getElementById("response").innerHTML = "Address: " + address + "<br>Balance: " + formattedBalance + " ETH";
        }
    });
}
}

核心问题与修复步骤

1. 函数作用域问题(直接导致按钮失效)

displayAddress函数被包裹在window.onload的回调内部,全局作用域无法访问该函数,按钮点击时找不到对应的处理逻辑。

修复方法:在window.onload内部直接绑定按钮的点击事件,无需依赖全局函数:

window.onload = function() {
    async function getBalance(address) {
        const response = await fetch(`https://mainnet.infura.io/v3/fb3bba54ae0449c28400a4e28fb61e6c?module=account&action=balance&address=${address}`);
        const data = await response.json();
        return data.result;
    }

    function displayAddress() {
        var address = document.getElementById("ethAddress").value;
        var provider = new Web3.providers.HttpProvider("https://mainnet.infura.io/v3/fb3bba54ae0449c28400a4e28fb61e6c");
        var web3 = new Web3(provider);
        web3.eth.getBalance(address, function(error, balance) {
            if (error) {
                document.getElementById("response").innerHTML = "Error: " + error.message;
            } else {
                var balanceInEther = web3.utils.fromWei(balance, "ether");
                var formattedBalance = parseFloat(balanceInEther).toFixed(4);
                document.getElementById("response").innerHTML = "Address: " + address + "<br>Balance: " + formattedBalance + " ETH";
            }
        });
    }

    // 绑定按钮点击事件
    document.getElementById("checkBalanceBtn").addEventListener("click", displayAddress);
}

2. 缺失Web3依赖

代码中使用了Web3对象,但HTML未引入Web3库,导致JS执行报错。

修复方法:在HTML的<head>中添加Web3的CDN引用,放在app.js之前:

<script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script>
<script type="text/javascript" src="app.js"></script>

3. IPFS上传与路径问题

  • 必须将index.html和app.js放在同一文件夹中整体上传至IPFS,而非单独上传文件。IPFS的相对路径依赖于同一目录的CID,单独上传会导致文件CID不同,相对路径失效。
  • 验证JS文件可访问性:打开页面后,在浏览器控制台的Network标签查看app.js的请求状态,若显示404,说明路径错误,需确认上传的目录结构是否正确。

4. 网关与CORS排查

若仍有错误,打开浏览器控制台的Console标签查看具体报错信息:

  • 若提示Web3 is not defined:确认Web3库已正确加载。
  • 若提示404:检查IPFS网关的JS文件路径是否正确。
  • 若提示CORS错误:确认Infura接口允许跨域请求(Infura默认支持,若问题持续可换用其他公共网关)。

内容的提问来源于stack exchange,提问作者F0urL34f

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 12:39:54