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

Vite React项目运行Node脚本报错如何解决?

核心结论

Vite 搭建的纯前端React项目无法直接运行presto-client这类仅适配Node.js环境的依赖,修改模块导入写法无法解决根本问题。

报错的核心原因是环境能力不匹配:

  • 浏览器不存在Node.js专属的全局API与内置模块,包括__dirname、require、net、tls、fs等。presto-client底层依赖Node原生网络模块建立TCP连接发起查询,这类底层能力被浏览器安全沙箱严格限制,前端代码无法直接调用。
  • 你碰到的两个报错都是上述原因导致:__dirname is not defined是依赖内部调用了Node专属的路径全局变量,浏览器无对应实现;换回require的CommonJS写法后报未定义,是因为浏览器原生不支持CommonJS模块加载规则。
可行实现方案

Presto查询逻辑必须运行在Node.js上下文,前端只负责发起HTTP请求拿结果,不要把Node专属依赖放到src前端源码目录中,避免Vite打包时处理这类文件触发报错。根据使用场景可以选以下两种实现方式:

方案1:Vite服务端中间件(本地开发快速验证)

开发阶段不需要单独搭建后端服务,直接在vite.config.js中配置自定义服务端中间件,把Presto查询逻辑放到Vite的Node.js运行上下文中即可:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { Client } from 'presto-client'

// Presto客户端初始化逻辑跑在Node侧,不会被打包到前端代码
const prestoClient = new Client({
  host: 'lga-xxx-adhoc.xxx.com',
  ssl: {
    rejectUnauthorized: true,
  },
  // 补全其余原有配置
})

export default defineConfig({
  plugins: [react()],
  server: {
    middleware: [
      {
        name: 'presto-query-proxy',
        configureServer(server) {
          // 定义前端调用的查询接口
          server.middlewares.use('/api/presto-query', async (req, res) => {
            // 实际使用时补充POST body解析、参数校验逻辑
            const sql = new URL(req.url, 'http://localhost').searchParams.get('sql')
            if (!sql) {
              res.statusCode = 400
              res.end(JSON.stringify({ code: -1, msg: '缺少查询SQL参数' }))
              return
            }
            try {
              const queryResult = await new Promise((resolve, reject) => {
                prestoClient.execute({
                  query: sql,
                  // 补全其余原有execute配置
                  success: resolve,
                  error: reject
                })
              })
              res.setHeader('Content-Type', 'application/json')
              res.end(JSON.stringify({ code: 0, data: queryResult }))
            } catch (err) {
              res.statusCode = 500
              res.end(JSON.stringify({ code: -1, msg: err.message }))
            }
          })
        }
      }
    ]
  }
})

前端侧删除原来直接导入src/lib/presto.js的逻辑,改成调用本地接口:

// src/App.jsx
import { useState } from 'react'

function App() {
  const [data, setData] = useState([])
  const [loading, setLoading] = useState(false)

  const handleQuery = async () => {
    setLoading(true)
    try {
      // 替换成实际业务需要执行的SQL
      const sql = 'SELECT * FROM your_target_table LIMIT 100'
      const res = await fetch(`/api/presto-query?sql=${encodeURIComponent(sql)}`)
      const result = await res.json()
      if (result.code === 0) {
        setData(result.data)
      }
    } catch (err) {
      console.error('查询失败', err)
    } finally {
      setLoading(false)
    }
  }

  // 补全页面渲染逻辑
  return <button onClick={handleQuery} disabled={loading}>执行查询</button>
}

export default App

注意:该方案仅适用于本地开发调试,不能直接把Vite开发服务器作为生产服务对外暴露。

方案2:独立BFF层(生产环境推荐)

正式上线的场景建议搭建独立的BFF(服务于前端的后端)层,Express、Koa、NestJS或者Serverless函数都可以实现,核心逻辑和上述中间件一致:

  • BFF服务侧安装presto-client,封装Presto查询接口
  • 前端仅保留HTTP请求逻辑,不引入任何Node专属依赖
  • 可在BFF层统一实现权限校验、SQL合法性拦截、查询超时控制、结果格式化等逻辑,避免Presto服务地址、认证信息直接暴露在前端代码中引发安全问题。
避坑提醒
  • 不要尝试通过Vite的polyfill配置给浏览器模拟__dirname、require等变量,presto-client依赖的Node原生网络模块无法在浏览器环境被模拟,强行配置只会触发更多运行时错误。
  • 禁止将Presto连接地址、账号密码等敏感信息写在前端代码中,所有用户都可以通过浏览器开发者工具获取这类信息,存在极大的数据安全风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 15:27:15