在NextJS中如何将数据从server.js传递到_app.js?



在我的NextJS项目中,我使用koa作为server.js文件中的web框架,我想做的如下,

  1. 做一些外部api调用来生成一些自定义数据在server.js每个请求,
  2. 然后将生成的数据传递给_app.js,使数据可以通过props或context被所有页面共享。

我的问题是我们如何将server.js中生成的数据传递给_app.js或页面?

下面是一些代码示例,

//////////////////////////////////////////////////
// server.js
import Koa from "koa";
import Router from "koa-router";
const verified_names = {};
const handle = app.getRequestHandler();  // NextJS use this to handle each request
app.prepare().then(async () => {
const server = new Koa();
const router = new Router();
...
// in verifyNameFunc, if name is verified, will set verified_names[name] = some_data
router.get("/verify_name", verifyNameFunc);
router.get("(.*)", async (ctx) => {
// custom logic starts here: if name is not verified, redirect to /verify_name
const name = ctx.query.name;
if (verified_names[name] === undefined) {
ctx.redirect(`/verify_name?name=${name}`);
}
// HERE: do some external api calls and generate some data
var custom_data = custom_logic(verified_names[name]);
// I think here starts rendering the pages (i.e. enters the execution of `_app.js` and pages)
// QUESTION: how to pass the above `custom_data` to _app.js or pages?
await handle(ctx.req, ctx.res);  
}
});
server.use(router.routes());
server.listen(...);

});
//////////////////////////////////////////////////
// _app.js
class MyApp extends App {
...
}
MyApp.getInitialProps = async ({ ctx }) => {
// Can we get the `custom_data` from server.js here?
...
};

我想把custom_logic放在server.js里面的原因是,

  • 如果name未被验证,则会发生重定向,verifyNameFunc会将一些数据设置到verified_names中。

我不确定这个重定向是否也可以移动到_app.js?

如果需要,您可以使用getInitialProps并在__app.tsx中进行重定向。

https://nextjs.org/docs/api-reference/data-fetching/getInitialProps

也很容易检查一个名字是否在__app.tsx中被验证,然后基于此渲染一个不同的孩子。我不认为你需要一个完整的自定义服务器。

还可以看看https://nextjs.org/blog/next-10-2#routing-based-on-headers-and-query-string-parameters。

这只是解决方案之一:创建一个单独的js文件(模块),其中您将导出两个函数setData()getData(),如下所示:

//////////////////////////////////////////////////
// ./lib/data-manager.js
let promiseResolver = undefined;
const promise = new Promise((resolve) => {
promiseResolver = resolve;
})
export function setData(data) { promiseResolver(data); }
export function async getData() { return promise; }
//////////////////////////////////////////////////
// server.js
import { setData } from "../lib/data-manager"
import Koa from "koa";
import Router from "koa-router";
const verified_names = {};
const handle = app.getRequestHandler();  // NextJS use this to handle each request
app.prepare().then(async () => {
const server = new Koa();
const router = new Router();
...
// in verifyNameFunc, if name is verified, will set verified_names[name] = some_data
router.get("/verify_name", verifyNameFunc);
router.get("(.*)", async (ctx) => {
// custom logic starts here: if name is not verified, redirect to /verify_name
const name = ctx.query.name;
if (verified_names[name] === undefined) {
ctx.redirect(`/verify_name?name=${name}`);
}
// HERE: do some external api calls and generate some data
var custom_data = custom_logic(verified_names[name]);
setData(custom_data); // <-- saving data
// I think here starts rendering the pages (i.e. enters the execution of `_app.js` and pages)
// QUESTION: how to pass the above `custom_data` to _app.js or pages?
await handle(ctx.req, ctx.res);  
}
});
server.use(router.routes());
server.listen(...);

});
//////////////////////////////////////////////////
// _app.js
import { getData } from "../lib/data-manager"
class MyApp extends App {
...
}
MyApp.getInitialProps = async ({ ctx }) => {
const custom_data = await getData();  // <-- getting data
};

请记住,getInitialProps允许在页面中进行服务器端呈现,并允许您进行初始数据填充,这意味着发送带有已经从服务器填充的数据的页面(参见https://nextjs.org/docs/api-reference/data-fetching/getInitialProps)。但是,正如向您推荐的那样,也许您根本不需要自定义服务器