likes
comments
collection
share

getServerSideProps vs getInitialProps getStaticProps in Next.js

作者站长头像
站长
· 阅读数 38

这三个函数结合了两个主题,组件道具和预渲染。

Props可以用来向组件传递值,你可以在这里找到更多的信息。 因为在Next.js中,页面也是组件,所以我们也可以向它们传递值这三个 ***"getXProps"***函数分别代表了向页面传递道具的不同方法。

我们将通过一个例子来详细探讨这些方法,但简而言之,就是 getInitialProps使用服务器端渲染,但已经被 getServerSideProps所取代,后者使用相同的方法,而 getStaticProps使用静态网站生成。

预渲染是在我们向客户端发送之前为我们的Web应用制作HTML。在像React这样的常规JavaScript网络应用中,我们从一个基本的HTML占位符页面开始,然后用JavaScript来渲染其他的HTML。

Next.js提供了两种不同的技术,允许它为你的网络应用预渲染HTML,尽可能少地将JavaScript发送到客户端以帮助提高性能。这两种技术是服务器端渲染(SSR)和静态网站生成(SSG)。

如果你还不熟悉Next.js,它是一个伟大的框架,在React的基础上进行了扩展,并提供了一些非常有用的附加功能,你可以在这里阅读更多关于它的信息。

getInitialProps

getInitialProps是用来启用服务器端渲染的,或者说是页面的SSR。有了SSR,当HTML需要被提供给客户端时,它就在服务器上生成。 在第一次加载时,它将在服务器上运行,而在随后的每次运行中,它将在客户端运行。这对于获取你期望经常变化的数据很有用,比如社交媒体页面上的最新帖子。

const Initial = ({ cat }) => {
    return (
        <div>
            <h1>Random Cat:</h1>
            <Image src={cat} layout="fixed" width="250" height="250"></Image>
        </div>
    );
};

Initial.getInitialProps = async (ctx) => {
    const { data } = await axios.get('https://cataas.com/cat?json=true');
    return { cat: 'https://cataas.com' + data.url + '?type=sq' };
};

export default Initial;

在这个例子中,我们使用getInitialProps来执行一个获取请求。如果你不熟悉在Next.js或vanilla React中进行API请求,我建议你查看我们的这个页面作为介绍

强烈建议使用另外两个函数中的一个,而不是这个,如果你需要直接平行,那就是getServerSideProps。

你可能注意到在这里我们使用了Next.js中的Image组件,而不仅仅是一个img元素。这有一些好处,你可以在这里找到

getServerSideProps

像getInitialProps。 getServerSideProps将在服务器上运行。然而,与getInitialProps不同,它总是在服务器上运行。

getInitialProps被弃用,而不是这个函数,主要原因是让你对代码的运行地点有更大的控制。 getServerSideProps保证在服务器上运行,你甚至可以使用服务器端的代码,比如fs模块加载文件作为道具传递。

下面是上面的例子,改写为使用 getServerSideProps:

const ServerSide = ({ cat }) => {
    return (
        <div>
            <h1>Random Cat:</h1>
            <Image src={cat} layout="fixed" width="250" height="250"></Image>
        </div>
    );
};

export async function getServerSideProps() {
    const { data } = await axios.get('https://cataas.com/cat?json=true');
    return {
        props: { cat: 'https://cataas.com' + data.url + '?type=sq' }, // will be passed to the page component as props
    };
}

export default ServerSide;

getStaticProps

getStaticProps是与前面两个函数略有不同。 在静态生成中,我们尽量在你构建应用时为网站生成尽可能多的HTML。这意味着如果数据要经常变化,你就不能使用这个函数,因为它在你部署应用后不会改变。

这使得它对像博客文章这样内容不会改变的东西很有用。你从中获得的好处是性能;在客户端或服务器端不需要获取或评估任何东西;服务器只是提供页面的原始HTML。就像 读取服务器端程序你也可以在你的应用程序中只使用服务器端的代码。

你可以将其与Next.js中的动态路由相结合。如果你的页面是一个动态路由,比如说 site.com/blog-posts/[postId].jsx,任何时候你访问一个路径,如 blog-posts/7,它就会被路由到同一个页面,Next.js就会把这个值传递给可通过 router.query on useRouter().

然而,对于静态网站,我们需要已经生成了每一个HTML文件,这样我们就可以直接提供HTML文件,那么当你有一个动态路径时,这又是如何工作的呢?

这就是getStaticPaths解决的问题。你可以使用任何你想要的方法来生成所有你希望Next.js建立静态页面的可能路径。这可能是你拥有的所有博客文章的路径和它们的ID。

下面是一个使用getStaticProps和getStaticPaths从文本文件本地加载博客文章的例子。

import fs from 'fs'; //This will get removed on the client
import path from 'path';

const Static = ({ blogPost }) => {
    return <div>{blogPost}</div>;
};

export async function getStaticProps({ params }) {
    //We get the filename as a parameter from the context object

    //fs is server side only, but this code only runs on the server
    const blogPost = fs.readFileSync(
        path.join(
            process.cwd(),
            'src/pages/examples/blog-posts',
            params.staticBlogPostId + '.txt'
        ),
        'utf8'
    );

    return {
        props: { blogPost }, // will be passed to the page component as props
    };
}

export async function getStaticPaths() {
    //I have a folder containing blog posts in text files
    const paths = fs
        .readdirSync(path.join(process.cwd(), 'src/pages/examples/blog-posts'))
        .map((fileName) => fileName.split('.')[0]); //Just a quick map to remove the .txt from the filenames
    console.log(paths); //[ 'manchester-holiday', 'new-beginnings', 'new-job' ]

    return {
        paths: paths.map((fileName) => {
            return { params: { staticBlogPostId: fileName } };
        }),
        fallback: false, //Means anything else will 404
    };
}

export default Static;

实际的组件很小,只是输出接收到的文本,但预渲染是更有趣的部分:

  • 在getStaticPaths中,我们得到一个目录中的文件列表;在这种情况下,我们所有的博客文章。
  • 我们的getStaticProps函数被用来为我们的每篇博文生成页面,只需从文本文件中加载博文即可。
  • 文件的内容作为道具被传递给页面。
  • 所有这些都发生在服务器上;从客户的角度来看,你只是得到了一个包含博客内容的HTML页面。

tl;dr:

  • 不要使用getInitialProps,它已经被getServerSideProps所取代,但要考虑是否可以使用getStaticProps。
  • getStaticProps用于静态网站生成,当你知道你在构建时要获取什么数据时就使用它,例如一篇博客文章,性能非常快,而且有利于SEO。
  • getServerSideProps用于服务器端渲染,当你有可能经常变化的数据时使用,例如天气API,但性能可能比SSG略差。

就这样吧!希望这有意义,而且这些例子足以启发你在你自己的项目中使用这些东西。我希望看到你用预渲染优化你的网站的任何聪明方法,所以欢迎在下面的评论中分享它们如果有什么不明白的地方,或者你有什么问题,或者你只是喜欢这篇文章,也可以随时评论。

转载自:https://juejin.cn/post/7176273607638106173
评论
请登录