我已经尝试了数周时间,以使Nuxt.js + Express(使用create-nuxt-app
)与第三方API一起使用。无论我尝试什么,都没有,绝对没有任何效果。我的服务器端没有控制台语句被触发,只有前端语句被触发。另外,我最近开始获取Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
,并且没有在代码中的任何位置设置标头。
我要做的就是获取用户输入,将其传递到后端以避免CORS问题,从第三方API取回数据,然后显示它。这很简单。它一直在互联网上发生,所以为什么我不能使它工作?
下面是上述过程中涉及的所有文件。
pages / index.vue:
<template>
<div class="container">
<img src="@/assets/images/OscarPark.jpg" alt="Oscar in the park" title="I love the park!" />
<br />
<form>
<label for="title">Book Title:</label>
<input v-model="titleFromUser" type="text" name="title" class="title" />
<button @click.prevent="submit" class="submit">Find a Book!</button>
</form>
</div>
</template>
<script>
import { mapState } from 'vuex';
export default {
components: {},
data() {
return {
titleFromUser: '',
};
},
computed: mapState(['newTitles']),
methods: {
submit() {
this.$store.dispatch('FETCH_BOOK_TITLES', this.titleFromUser);
this.titleFromUser = '';
},
},
};
</script>
<style lang="scss">
.container {
margin: 0 auto;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
img {
transform: rotate(90deg); // this fixes a glitch that causes image to rotate needlessly
padding-top: $underHeaderGap; // these 2 padding lines help to fix the placement of the image caused by the needless rotation
padding-left: $underHeaderGap * 5;
margin-bottom: $underHeaderGap * 5;
height: $imgHeight;
}
}
</style>
store / index.js:
import consola from 'consola';
export const state = () => ({
newTitles: [],
});
export const mutations = {
SET_NEW_TITLES(state, newTitles) {
state.newTitles = newTitles;
},
};
export const actions = {
async FETCH_BOOK_TITLES({ commit }, titleFromUser) {
try {
consola.ready({
message: `'FETCH_BOOK_TITLES': titleFromUser: ${titleFromUser}`,
badge: true,
});
const { data } = await this.$axios.$post('/title', { titleFromUser });
consola.ready({
message: `data returned from api: ${data}`,
badge: true,
});
commit('SET_NEW_TITLES', data);
} catch (error) {
consola.error({
message: `FETCH_BOOK_TITLES: Something went wrong: ${error}`,
badge: true,
});
throw new Error(error);
}
},
};
server / index.js:
const express = require('express');
const cors = require('cors');
const consola = require('consola');
const axios = require('axios');
const { Nuxt, Builder } = require('nuxt');
const app = express();
const jsonParser = express.json();
const titleRouter = require('../api/title/index');
// Import and Set Nuxt.js options
const config = require('../nuxt.config.js');
config.dev = process.env.NODE_ENV !== 'production';
async function start() {
// Init Nuxt.js
const nuxt = new Nuxt(config);
const { host, port } = nuxt.options.server;
// Give app ability to parse json
app.use(jsonParser);
// Give app ability to get past CORS issues
app.use(cors());
// Give nuxt middleware to express
app.use(nuxt.render);
// Build only in dev mode
if (config.dev) {
const builder = new Builder(nuxt);
await builder.build();
} else {
await nuxt.ready();
}
app.use('/title', titleRouter);
app.get('/title', (req, res) => {
consola.ready({
message: `res.json in title endpoint-server: ${res.json()}`,
badge: true,
});
consola.ready({
message: `req.json in title endpoint-server: ${req.json()}`,
badge: true,
});
const recommendationsURL = `https://tastedive.com/api/similar?q=and+then+there+were+none&type=books&info=1&k=${process.env.TASTE_DIVE_API_KEY}`;
axios
.get(recommendationsURL, (req, res) => {
consola.ready({
message: `from server/index.js: ${res.json()}`,
badge: true,
});
})
.catch((error) => {
consola.error({
message: `error from axios server ${error} `,
badge: true,
});
});
});
// Listen to the server
app.listen(port, host, () => {
consola.ready({
message: `Server listening on http://${host}:${port}`,
badge: true,
});
});
}
start();
api / title / index.js:
const consola = require('consola');
const express = require('express');
const app = express();
const titleRouter = express.Router();
titleRouter.use((req, res, next) => {
Object.setPrototypeOf(req, app.request);
Object.setPrototypeOf(res, app.response);
req.res = res;
res.req = req;
next();
});
titleRouter.get('/title', (req, res) => {
res
.json()
.then((data) => {
consola.ready({
message: `~api/title get title is ${data}`,
badge: true,
});
})
.catch((error) => {
consola.error({
message: `~api/title get Something went wrong: ${error}`,
badge: true,
});
throw new Error(error);
});
});
titleRouter.post('/title', (req, res) => {
res
.json()
.then((data) => {
consola.ready({
message: `~api/title post title is ${data}`,
badge: true,
});
})
.catch((error) => {
consola.error({
message: `~api/title post Something went wrong: ${error}`,
badge: true,
});
throw new Error(error);
});
});
module.exports = titleRouter;
nuxt.config.js:
require('dotenv').config();
module.exports = {
mode: 'universal',
/*
** Headers of the page
*/
head: {
title: "Oscar's Book Recommendations",
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{
hid: 'description',
name: 'description',
content: process.env.npm_package_description || '',
},
],
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
},
/*
** Customize the progress-bar color
*/
loading: { color: '#fff' },
/*
** Plugins to load before mounting the App
*/
plugins: [],
/*
** Nuxt.js dev-modules
*/
buildModules: [
// Doc: https://github.com/nuxt-community/eslint-module
'@nuxtjs/eslint-module',
'@nuxtjs/dotenv',
'@nuxtjs/style-resources',
],
/*
** Nuxt.js modules
*/
modules: [
// Doc: https://axios.nuxtjs.org/usage
'@nuxtjs/axios',
'@nuxtjs/pwa',
'@nuxtjs/auth',
],
/*
** Axios module configuration
** See https://axios.nuxtjs.org/options
*/
axios: {
https: true,
baseURL: process.env.BASE_URL || 'http://localhost:3000',
},
/*
** Build configuration
*/
build: {
watch: ['api/title'],
/*
** You can extend webpack config here
*/
extend(config, ctx) {},
},
pageTransition: {
name: 'fade',
mode: 'out-in',
},
env: {
TASTE_DIVE_API_KEY: process.env.TASTE_DIVE_API_KEY,
},
serverMiddleware: ['~api/title'],
styleResources: {
scss: ['~assets/styles/main.scss'],
},
};
有人看到我不是吗?为什么数据不传递到服务器?为什么在我没有在代码中的任何位置设置标题时,告诉我在发送标题后无法设置标题?这怎么了?
我将非常感谢任何人的投入和帮助。谢谢。
好,所以碰巧我有一个server/index.js
和一个带有nuxt.config.js
条目的serverMiddleware
。努克斯(Nuxt)的创建者之一塞巴斯蒂安·肖邦(Sebastien Chopin)看到了我关于此问题的推文,并指出我可以在server/index.js
中使用serverMiddleware
文件或nuxt.config.js
,但不能同时使用。作为最初通过创建服务器文件来学习Express的人,我可以很容易地看到这将如何引起人们的困惑。
[最后,我决定使用Nuxt方法,并在serverMiddleware
中使用了nuxt.config.js
。当您设置Nuxt项目并选择从一开始就集成Express时,与传统的服务器文件相比,这是使用Express的首选方式。