Next.js: 在静态导出时向页面传递额外的道具?
Next.js: pass additional props to the page during static export?
我正在尝试静态导出 next.js 应用程序。 docs 表示页面对象只有 2 个值:page
和 query
。有没有办法将额外的道具传递给页面?
我尝试为此使用 query
,但 next 的路由器似乎不知道路由的 query
对象。因此它没有用。
换句话说,我在构建时有一个博客文章列表,我如何将它们内联到页面(页面组件)?
我猜 react-static
有一个 routeInfo.json
是为每条路线预取的。 next.js.
中有没有类似的东西
UPD 4 月 4 日 20
至少在next.js 9.3里面有getStaticProps
和getStaticPaths
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: "/" }
});
}
});
我正在尝试静态导出 next.js 应用程序。 docs 表示页面对象只有 2 个值:page
和 query
。有没有办法将额外的道具传递给页面?
我尝试为此使用 query
,但 next 的路由器似乎不知道路由的 query
对象。因此它没有用。
换句话说,我在构建时有一个博客文章列表,我如何将它们内联到页面(页面组件)?
我猜 react-static
有一个 routeInfo.json
是为每条路线预取的。 next.js.
UPD 4 月 4 日 20
至少在next.js 9.3里面有getStaticProps
和getStaticPaths
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: "/" }
});
}
});