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); } }
复现步骤
- 执行
npm i安装所有依赖 - 运行
npm run build-prod生成dist文件夹 - 启动
npm run build-dev - 在无痕浏览器中访问
localhost:3000,输入城市名(如London)后提交
补充说明
错误提示显示接口请求返回的是HTML文档而非预期的JSON数据,猜测webpack-dev-server没有代理Express的接口请求,导致所有路由都返回静态HTML文件。
内容的提问来源于stack exchange,提问作者Rohan Asif
相关产品推荐
相关产品推荐

