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

Webpack+Express应用出现JSON解析错误,请求技术支援

问题:Webpack-dev-server启动后Express接口返回HTML而非JSON

我开发了一个调用geonames、weatherbit、pixabay三个API的Node.js+Express应用,搭配body-parser和cors中间件。通过Webpack编译后启动webpack-dev-server时出现问题:提交城市名后,控制台报错SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON",错误位于app.js第130和64行。我推测服务器仅返回静态HTML,未执行Express的接口逻辑,请求协助解决。

Server.js代码

// Setup empty JS object to act as endpoint for all routes
cityData = {};
weatherData = {};
picturesData = {};

// Require Express to run server and routes
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');

// Start up an instance of app
const app = express();

/* Middleware*/
//Here we are configuring express to use body-parser as middle-ware.
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

// Cors for cross origin allowance
app.use(cors())
// Initialize the main project folder
app.use(express.static('../website/client'));

app.get("/all", function sendData(req, res) {
    res.send(cityData);
})

app.get("/allWeather", function sendWeather(req, res) {
    res.send(weatherData);
})

app.get("/allPictures", function sendPictures(req, res) {
    res.send(picturesData);
})


app.post("/addWeather", (req, res) => {
    weatherData['temp'] = req.body.temp;
    res.send(weatherData);
})

app.post("/addPicture", (req, res) => {
    picturesData['pic'] = req.body.pic;
    res.send(picturesData);
})

// Setup Server
app.listen(3000, () => {
    console.log("App listening on port 3000")
    console.log("Go to http://localhost:3000")
})

App.js代码

const geoURL = "http://api.geonames.org/searchJSON?";
const geoUsername = `rohanasif1990`;
const weatherURL = "https://api.weatherbit.io/v2.0/forecast/daily?"
const weatherKey = "20028a8267a24bba9a807362767bc4a7"
const pixabayKey = "30776478-ff0b8818f9bba72161ebb1731"
const pixabayURL = "https://pixabay.com/api?"

const present = new Date();

const submitBtn = document.getElementById("submitBtn");

submitBtn.addEventListener("click", (e) => {
    e.preventDefault();
    const city = document.getElementById("city").value;
    const departure = document.getElementById("date").value;
    const [depart_date, depart_time] = departure.split("T")
    const [depart_year, depart_month, depart_day] = depart_date.split("-")
    const [depart_hour, depart_minute] = depart_time.split(":")

    const future = new Date(depart_year, depart_month - 1, depart_day, depart_hour, depart_minute);

    console.log(future);
    console.log(present);
    if (city !== "" || departTime !== "") {

        document.getElementById("time").innerHTML = `Departure in ${(future - present) / 3600000 / 24} days`
        getCity(geoURL, city, geoUsername)
            .then(function (data) {
                return getWeather(weatherURL, weatherKey, data["geonames"][0]['lat'], data["geonames"][0]['lng'])
            }).then(weatherData => {
                return postWeatherData("/addWeather", { temp: weatherData['data'][0]['temp'] })
            }).then(function () {
                return receiveWeatherData()
            }).catch(function (error) {
                console.log(error);
                alert("Please enter a valid city and a valid time");
            })
        getPictures(city, pixabayURL, pixabayKey)
            .then(function (picsData) {
                return postPictureData("/addPicture", { pic: picsData['hits'][0]["webformatURL"] })
            })
            .then(function () {
                return receivePictureData()
            }).catch(function (error) {
                console.log(error);
                alert("No pictures found")
            })
    }
})

const getCity = async (geoURL, city, geoUsername) => {
    const res = await fetch(`${geoURL}q=${city}&username=${geoUsername}`);
    try {
        const cityData = await res.json();
        return cityData;
    }
    catch (error) {
        console.log("error", error);
    }
}


const postWeatherData = async (url = "", data = {}) => {
    const response = await fetch(url, {
        method: "POST",
        credentials: "same-origin",
        headers: {
            "Content-Type": "application/json",
        },
        body: JSON.stringify({
            temp: data.temp
        })
    });

    try {
        const newData = await response.json();
        return newData;
    }
    catch (error) {
        console.log(error);
    }
}

const receiveWeatherData = async () => {
    const request = await fetch("/allWeather");
    try {
        const allData = await request.json()
        document.getElementById("temp").innerHTML = "TEMPERATURE: " + allData['temp'];
    }
    catch (error) {
        console.log("error", error)
    }
}

const getWeather = async (weatherURL, weatherKey, lat, lon) => {
    const res = await fetch(`${weatherURL}&lat=${lat}&lon=${lon}&key=${weatherKey}`);
    try {
        const weatherData = await res.json();
        return weatherData;
    }
    catch (error) {
        console.log("error", error);
    }
}

const getPictures = async (city, pixabayURL, pixabayKey) => {
    const query = city.split(" ").join("+");
    const res = await fetch(`${pixabayURL}key=${pixabayKey}&q=${query}`);
    try {
        const picsData = await res.json();
        return picsData;
    }
    catch (error) {
        console.log("error", error)
    }
}

const receivePictureData = async () => {
    const request = await fetch("/allPictures");
    try {
        const allData = await request.json()
        document.getElementById("city-pic").src = allData['pic'];
    }
    catch (error) {
        console.log("error", error)
    }
}

const postPictureData = async (url = "", data = {}) => {
    const response = await fetch(url, {
        method: "POST",
        credentials: "same-origin",
        headers: {
            "Content-Type": "application/json",
        },
        body: JSON.stringify({
            pic: data.pic
        })
    });

    try {
        const newData = await response.json();
        return newData;
    }
    catch (error) {
        console.log(error);
    }
}

复现步骤

  1. 执行npm i安装所有依赖
  2. 运行npm run build-prod生成dist文件夹
  3. 启动npm run build-dev
  4. 在无痕浏览器中访问localhost:3000,输入城市名(如London)后提交

补充说明

错误提示显示接口请求返回的是HTML文档而非预期的JSON数据,猜测webpack-dev-server没有代理Express的接口请求,导致所有路由都返回静态HTML文件。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 19:40:59