admin 管理员组

文章数量: 1086019

I'm wondering if the following scenario is possible with serverless (deployed on Vercel) Next JS:

I have a route /product/[id].tsx when you send a request with the header Accept: text/html, I would like it to go through the normal Next JS flow with a React page. But, when a request is given with Accept: application/json, I would like it to return the JSON representation.

I have acplished it by using some custom middleware I wrote for Express (see below), but I would also like to deploy it on Vercel, and Vercel is not designed to work with a custom Express implementation.

So the question is, is it possible to do this in a serverless environment? Could one of the Next JS React pages return pure JSON, or could you return React from a Next JS Api route? Or is there another way to acplish this?

server.ts

import express, { Request, Response } from "express";
import next from 'next'
import { parse } from 'url'

const port = parseInt(process.env.PORT || "3000", 10);
const dev = process.env.NODE_ENV !== "production";

async function run(): Promise<void> {
  const app = express();
  const nextApp = next({ dev })
  const nextHandler = nextApp.getRequestHandler()
  await nextApp.prepare()

  app.use((req, res) => {
    res.format({
      "text/html": async (req, res) => {
        const parsedUrl = parse(req.url!, true)
        await this.handler(req, res, parsedUrl)
      },
      "application/json": async (req, res) => {
        res.json({
          "dummy": "data"
        })
      }
    })
  });

  app.listen(port, () => {
    console.log(
      `> Server listening at http://localhost:${port} as ${
        dev ? "development" : process.env.NODE_ENV
      }`
    );
  });
}

run()

I'm wondering if the following scenario is possible with serverless (deployed on Vercel) Next JS:

I have a route /product/[id].tsx when you send a request with the header Accept: text/html, I would like it to go through the normal Next JS flow with a React page. But, when a request is given with Accept: application/json, I would like it to return the JSON representation.

I have acplished it by using some custom middleware I wrote for Express (see below), but I would also like to deploy it on Vercel, and Vercel is not designed to work with a custom Express implementation.

So the question is, is it possible to do this in a serverless environment? Could one of the Next JS React pages return pure JSON, or could you return React from a Next JS Api route? Or is there another way to acplish this?

server.ts

import express, { Request, Response } from "express";
import next from 'next'
import { parse } from 'url'

const port = parseInt(process.env.PORT || "3000", 10);
const dev = process.env.NODE_ENV !== "production";

async function run(): Promise<void> {
  const app = express();
  const nextApp = next({ dev })
  const nextHandler = nextApp.getRequestHandler()
  await nextApp.prepare()

  app.use((req, res) => {
    res.format({
      "text/html": async (req, res) => {
        const parsedUrl = parse(req.url!, true)
        await this.handler(req, res, parsedUrl)
      },
      "application/json": async (req, res) => {
        res.json({
          "dummy": "data"
        })
      }
    })
  });

  app.listen(port, () => {
    console.log(
      `> Server listening at http://localhost:${port} as ${
        dev ? "development" : process.env.NODE_ENV
      }`
    );
  });
}

run()
Share Improve this question asked Jul 10, 2020 at 18:20 jaxoncreedjaxoncreed 1,1282 gold badges14 silver badges25 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 8

Thanks to @timneutkens (Lead engineer for NextJS) on Twitter we have our answer. It is possible. You use getServerSideProps and perform everything you want to the res object there. Just be sure to end it with .end so it skips the react rendering phase.

I've made a sample repo for the code here: https://github./jaxoncreed/nextjs-content-type-test

And here's the page that matters:

import Head from 'next/head'

export default function Home() {
  return (
    <div className="container">
      <Head>
        <title>Create Next App</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main>
        <h1>Test App</h1>
      </main>

      
    </div>
  )
}

export async function getServerSideProps({ req, res }) {
  if (req.headers.accept === "application/json") {
    res.setHeader('Content-Type', 'application/json')
    res.write(JSON.stringify({ "dummy": "data" }))
    res.end()
  }
  return {
    props: {}, // will be passed to the page ponent as props
  }
}

本文标签: javascriptDifferent ContentTypes on the same route with Serverless Next JSStack Overflow