Next.js: 在静态导出时向页面传递额外的道具?

Next.js: pass additional props to the page during static export?

我正在尝试静态导出 next.js 应用程序。 docs 表示页面对象只有 2 个值:pagequery。有没有办法将额外的道具传递给页面?

我尝试为此使用 query,但 next 的路由器似乎不知道路由的 query 对象。因此它没有用。

换句话说,我在构建时有一个博客文章列表,我如何将它们内联到页面(页面组件)?

我猜 react-static 有一个 routeInfo.json 是为每条路线预取的。 next.js.

中有没有类似的东西

UPD 4 月 4 日 20 至少在next.js 9.3里面有getStaticPropsgetStaticPaths

(complete example)

const IndexPage: NextPage<{ names: string[] }> = (props) => {
  return (
    <main>
      <section>
        {props.names.map((name) => (
          <div key={name}>
            <Link href={`/users/${name}`}>
              <a>{name}</a>
            </Link>
          </div>
        ))}
      </section>
    </main>
  );
};

export const getStaticProps: GetStaticProps = async () => {
  const data: User[] = readJsonSync("./data.json");

  return {
    props: {
      names: data.map((user) => user.name),
    },
  };
};

export default IndexPage;

UPD 12 月 4 日 19

getStaticProps 有一个 RFC 解决了这个问题:https://github.com/zeit/next.js/issues/9524


这是我最后得到的结果。

_app.js:

import React from "react";
import App, { Container } from "next/app";

import fs from "fs";
import { resolve, join } from "path";

export default class extends App {
  static async getInitialProps({ Component, ctx }) {
    const { req, asPath } = ctx;
    let pageProps = {};

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx);
    }

    let p;
    if (req) {
      p = JSON.parse(
        fs.readFileSync(resolve(join("data", asPath, "route.json"))).toString()
      );
    } else {
      p = await (await fetch(`/data${asPath}/route.json`)).json();
    }

    return { pageProps: { ...pageProps, ...p } };
  }

  render() {
    const { Component, pageProps } = this.props;
    return (
      <Container>
        <Component {...pageProps} />
      </Container>
    );
  }
}

在next.config.js中:

const fetch = require("isomorphic-unfetch");
const fs = require("fs");
const path = require("path");
const fse = require("fs-extra");
const withBundleAnalyzer = require("@next/bundle-analyzer")({
  enabled: false
});

module.exports = withBundleAnalyzer({
  webpack(config) {
    config.node = { fs: "empty", path: "empty" };
    return config;
  },
  async exportPathMap() {
    const response = await fetch(
      "https://jsonplaceholder.typicode.com/posts?_page=1"
    );
    const postList = await response.json();
    fs.writeFileSync(
      path.resolve(`data/route.json`),
      JSON.stringify({ postList }, null, 2)
    );
    for (let i = 0; i < postList.length; ++i) {
      const id = postList[i].id;
      const response = await fetch(
        `https://jsonplaceholder.typicode.com/posts/${id}`
      );
      const post = await response.json();
      const fn = path.resolve(`data/post/${id}/route.json`);

      await fse.outputFile(fn, JSON.stringify(post, null, 2));
    }

    const pages = postList.reduce(
      (pages, post) =>
        Object.assign({}, pages, {
          [`/post/${post.id}`]: {
            page: "/post"
          }
        }),
      {}
    );

    return Object.assign({}, pages, {
      "/": { page: "/" }
    });
  }
});