Vue+Node项目部署Heroku调用API返回需启用JS错误排查
你看到的「未启用JavaScript」提示来自Vue打包后index.html内的<noscript>标签,本质是接口请求返回了完整的index.html内容而非预期JSON,是后端路由顺序、参数匹配、构建配置几个问题共同导致的,按以下步骤修复即可:
修复步骤
1. 调整Server.js路由顺序与逻辑
Express的中间件、路由严格按代码书写顺序从上到下匹配,你当前将静态资源中间件放在API路由之前,且未正确配置history模式兜底路由,同时存在参数名不匹配、文件路径风险、重复中间件问题,替换为以下代码即可:
const express = require('express') const cors = require('cors') const bodyParser = require('body-parser') const serveStatic = require("serve-static") const path = require('path') const fs = require('fs') const app = express() const _port = process.env.PORT || 80 // 全局中间件优先注册 app.use(cors()) app.use(bodyParser.json()) app.use(bodyParser.urlencoded({ extended: true })) // 所有API路由放在静态资源之前,优先匹配 app.get('/api', (req, res) => { res.json({ message: 'Welcome to the API.' }) }) app.get('/api/ddlGeneral', (req, res) => { // 改用绝对路径读取文件,避免生产环境启动目录变化导致读文件失败 const dbddlGeneral = fs.readFileSync(path.join(__dirname, './db/ddls.json')) const ddlArray = JSON.parse(dbddlGeneral) // 修复前后端参数名不匹配问题:前端传参名为categories,原代码误写为categorias let _categorias = req.query.categories // 增加空值、类型兼容,避免参数缺失时读取length抛错 if (!_categorias) return res.json([]) if (!Array.isArray(_categorias)) _categorias = [_categorias] let _newArrayDdl = [] for (let loopDdls = 0; loopDdls < ddlArray.length; loopDdls++) { const _ddl = ddlArray[loopDdls] for (let _loopCategoria = 0; _loopCategoria < _categorias.length; _loopCategoria++) { if(_categorias[_loopCategoria] == _ddl.categoria){ _newArrayDdl.push(ddlArray[loopDdls]) } } } res.json(_newArrayDdl) }) // API路由注册完成后再挂载静态资源 app.use(serveStatic(path.join(__dirname, "/dist"))) // 最后配置通配符兜底,适配Vue Router history模式,所有非API GET请求返回首页 app.get("*", (req, res) => { res.sendFile(path.join(__dirname, "/dist/index.html")) }) app.listen(_port, () => { console.log(`Server started on port ${_port}`) })
- 删除了重复注册的
cors中间件 - 移除了可能导致路由拦截的错误顺序配置
- 增加了参数异常兼容,避免接口抛错
2. 清理前端Axios无效配置
你在请求头中添加的Access-Control-Allow-*属于后端CORS响应头,前端写在请求头中完全无效,同时存在未使用的冗余变量,修正mixin-code.js代码如下:
import axios from 'axios' // 原代码中定义的_port为Node端环境变量,浏览器端无法读取且未使用,直接删除 const instance = axios.create({ baseURL: "/api", headers: { Accept: "application/json", }, }) export const mixinDdlGeneral = async (payload) => { return new Promise(async(resolve, reject) => { let Result try { Result = await instance.get('/ddlGeneral', { params: { categories: payload } }) } catch (error) { console.dir(error) return reject(JSON.stringify(error.response?.data || '请求失败')) } return resolve(JSON.stringify({ data: { queryddlsByCategory: Result.data } })) }) }
- 如果需要处理数组参数序列化格式,可自行安装
qs库增加paramsSerializer配置,不做强制要求,后端已做参数兼容。
3. 修正Heroku构建配置
Heroku默认生产环境安装依赖时不会安装devDependencies下的包,你需要做以下任意一项调整,保证postinstall阶段的npm run build能正常生成dist目录:
- 将
@vue/cli-service及Vue构建相关依赖从devDependencies移动到dependencies - 在Heroku项目后台配置环境变量
NPM_CONFIG_PRODUCTION=false,允许生产环境安装开发依赖
验证方式
部署完成后先直接访问你的Heroku域名/api,如果能正常返回{"message":"Welcome to the API."}的JSON内容,说明API路由已正常匹配,此时页面调用接口就不会再返回HTML内容,那个noscript相关的错误提示也会消失。
内容的提问来源于stack exchange,提问作者devFerzen
相关产品推荐
相关产品推荐

