Next.js文档自定义App、Document,getInitialProps翻译

getInitialProps

getInitialProps在页面中启用服务端渲染并允许你进行初始数据注入,也就是发送在服务器已经注入了数据的页面。这有利于SEO。

getInitialProps会禁用自动静态优化
  • getInitialProps是一个可以作为静态方法添加到任意页面的异步方法,看下面例子:
import fetch from 'isomorphic-unfetch'

function Page({ stars }) {
    return <div>Next stars: {stars}</div>
}

Page.getInitialProps = async ctx => {
    const res = await getch('https://api.github.com/repos/zeit/next.js')
    const json = await res.json()

    return { stars: json.stargazers_count }
}

export default Page

或者使用类组件:

import React from 'react'
import fetch from 'isomorphic-unfetch'

class Page extends React.Component {
    static async getInitialProps(ctx) {
        const res = await fetch('https://api.github.com/repos/zeit/next.js')
        const json = await res.json()

        return { stars: json.stargazers_count }
    }

    render() {
        return <div>Next stars: {this.props.stars}</div>
    }
}

export default Page

getInitialProps用于异步获取一些数据,然后注入props.

服务端渲染时,将getInitialProps获取的数据序列化,和JSON.stringify做的一样。确保getInitialProps返回的对象是一个纯对象,没有使用Date, MapSet.

初始页面的加载只会在服务器运行。getInitialProps只会在客户端通过next/linknext/router导航到其他路由时执行。

Context对象

getInitialProps只接收一个参数contextcontext对象中有如下属性:

  • pathname -当前路由,是pages文件加下页面的路径
  • query -URL的请求字符串部分,解析为对象
  • asPath -浏览器中显示的真实路径(包括query)的字符串格式
  • req -HTTP请求对象(只服务端)
  • res -HTTP响应对象(只服务端)
  • err -若在渲染过程中遇到错误,返回Error对象

注意

  • getInitialProps不能使用在子组件中,只能在每个页面的default export中使用
  • 若在getInitialProps中使用只在服务端用的模块,确保正确的import,否则会拖慢你的app

===

自定义App

Next.js使用App组件来初始化页面。可以重写App来覆盖Next.js自带的App,控制页面初始化。允许你做这些事情:

  • 在页面改变时保持布局
  • 导航页面时保持状态
  • 使用componentDidCatch来自定义错误处理
  • 将其他数据注入页面
    pages文件夹下创建_app.js文件来覆盖原有的App
function MyApp({ Component, pageProps }) {
    return <Component {...pageProps} />
}

// 这个方法使得每一个页面都由服务器渲染,禁用了自动静态优化功能,所以只有应用中每个单独页面都有阻塞数据的请求时才可以注释掉此方法。
//
// MyApp.getInitialProps = async (appContext) => {
//     const appProps = await App.getInitialProps(appContext)

//     return { ...appProps }
// }

export default MyApp

Component的prop是当前活动的page,所以当切换路由时,Component会切换为新的page。因此,发送给Component的props都会被page接收。

pageProps是一个包含预加载页面props的对象,如果页面不使用getInitialProps,它就是一个空对象。

在你的`App`中添加一个自定义`getInitialProps`方法会禁用掉自动静态优化。

===

自定义Document

Next.js跳过了周围文档标记的定义,所以用自定义Document来扩展应用的<html><body>标签。

自定义Document也可以包含getInitialProps方法来表示异步的服务器渲染数据请求。

pages文件夹下创建_document.js来覆盖默认的Document文件,自定义Document如下

import Document, { Html, Head, Main, NextScript } from 'next/document'

class MyDocument extends Document {
    static async getInitialProps(ctx) {
        const initialProps = await Document.getInitialProps(ctx)
        return { ...initialProps}
    }

    render() {
        return (
            <Html>
                <Head />
                <body>
                    <Main />
                    <NextScript />
                </body>
            </Html>
        )
    }
}

要正确渲染页面,<Html>,<Head />,<Main /><NextScript>是必须的。

ctx对象就相当于getInitialProps中接收到的对象,再加上一个:

  • renderPageFunction 一个回调函数,同步执行React渲染逻辑。为了支持服务器渲染wrappers(如Aphrodite的renderStatic),对这个函数进行decorate是很有用的。

注意

  • Document只在服务器中渲染,事件处理如onClcikwon‘t work
  • <Main />之外的React组件不会被浏览器初始化,不要在其中添加应用的逻辑。如果在页面中有共用的组件(如菜单或者工具栏),使用App组件代替。
  • 客户端转换时不会调用DocumentgetInitialProps方法,页面静态优化时也不会调用。

定制renderPage

注意,之所以要定制`renderPage`,是因为在css-in-js库中,需要包裹应用才能正确使用服务端渲染。(简单地说,就是规定)

可选对象作为参数来进一步定制

import Document from 'next/document'

class MyDocument extends Document {
    static async getInitialProps(ctx) {
        const originalRenderPage = ctx.renderPage

        // ctx.renderPage = function() {
        //     ctx.renderPage({
        //         enhanceApp: App => App,
        //         enhanceComponent: Component => Component,
        //     })
        // }

        // ctx.renderPage把自己包裹在一个匿名函数中,这tm什么操作???
        // 这tm就是上面说的,规定,你不包一下,就不能服务端渲染
        ctx.renderPage = () =>
            originalRenderPage({
                // 用于包裹整个react树
                enhanceApp: App => App,
                // 用于以每页为单位包装
                enhanceComponent: Component => Component,
            })

        // 执行父类的`getInitialProps`方法,现在它包含了定制的`renderPage`
        const initialProps = await Document.getInitialProps(ctx)

        return initialProps
    }
}

export default MyDocument

===

原文地址:https://www.cnblogs.com/wydumn/p/12178670.html

时间: 2024-10-27 07:12:46

Next.js文档自定义App、Document,getInitialProps翻译的相关文章

JQuery之JQuery的版本 JQuery入门 属性获取 JQuery就绪函数 JS文档就绪函数和JQuery文档就绪函数的区别 JS对象和JQuery对象的区别 关于$的使用 多个JS库的冲突解决方案

JQuery的版本 JQuery入门 属性获取 JQuery就绪函数 JS文档就绪函数和JQuery文档就绪函数的区别 JS对象和JQuery对象的区别 关于$的使用 多个JS库的冲突解决方案 JQuery的版本 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>jQuery的版本</title> <

使用node.js 文档里的方法写一个web服务器

刚刚看了node.js文档里的一个小例子,就是用 node.js 写一个web服务器的小例子 上代码 (*^▽^*) //helloworld.js// 使用node.js写一个服务器 const http=require('http'); const hostname='127.0.0.1' const port=3000; const server = http.createServer((req,res)=>{ res.statusCode=200; res.setHeader('Cont

JS文档和Demo自动化生成工具 - SmartDoc发布

曾几何时,当你码神附体,一路披荆斩棘的完成代码后,带着“一码在手,天下我有”的傲然环顾之时,却发现单元测试.API文档.Demo实例陆续向你砸来,顿时有木有一种冰水挑战后的感觉.而这时你应该:哟哟,快使用SmartDoc: SmartDoc, 一个基于NodeJS的自动化文档生成工具,她拥有明眸的双眼(yuidoc引擎),华丽的外衣(bootstrap 3风格),灵巧的双手(demo生成,codemirror代码编辑,jasmine接口兼容);拥有她,相信你一定会仰天长啸:"小伙伴们再也不用担心

js文档碎片

今天看视频发现个有意思的东西,叫做文档碎片?文档碎片是什么呢?先卖个关子. 平常我们在向文档中插入节点的时候可能创建了节点就马上插入父元素,因此浏览器会一直渲染.插入的数量少可能还没影响,可是当插入的节点成千上万的时候,会发现浏览器卡顿了......如何解决这种问题呢?这里我们就要用到文档碎片了.在创建节点之后我们可以先把节点append在文档碎片上,在将所有的节点append之后再将文档碎片append在父元素上,理论上会快一些.经测试,有些时候要快一点^_^...... 1.普通插入 <in

有关文档碎片(document fragment)的使用方法

通常情况下改动.删除或者添加DOM元素. 更新DOM会导致浏览器又一次绘制屏幕,也会导 致reflow,这样会带来巨大的开销.我们通常解决这的办法尽量降低更新DOM.这也就意 味着将DOM的改变分批处理.并在"活动"文档树之外运行这些更新. 当须要创建一个相对照较大的子树.应该在子树全然创建之后再将子树加入到DOM树中. 这时採用文档碎片技术来容纳全部的节点. //反样例 //在创建时马上加入节点 var p,t; p = document.createElement('p'); t

学习笔记:javascript 文档对象(document)

1.documnet函数 方法 描述 close() 关闭用 document.open() 方法打开的输出流,并显示选定的数据. getElementById() 返回对拥有指定 id 的第一个对象的引用. getElementsByName() 返回带有指定名称的对象集合. getElementsByTagName() 返回带有指定标签名的对象集合. open() 打开一个流,以收集来自任何 document.write() 或 document.writeln() 方法的输出. write

immutable.js文档

immutable.js是一款用于生成不可变量的工具.在react的reducer中可以发挥一些用处,尝试翻译一下官方文档. --开始 npm install immutable NPM直接安装 --上手小栗子 var Immutable = require('immutable'); var map1 = Immutable.Map({a:1, b:2, c:3}); var map2 = map1.set('b', 50); map1.get('b'); // 2 map2.get('b')

js 文档加载完成之后执行 备用

1 //文档加载完成之后执行 2 (function(){ 3 var _globeCallback; 4 window.$$ = function(callback){ 5 _globeCallback = callback; 6 }; 7 function documentReady(){ 8 _globeCallback(); 9 } 10 //document ready --mobile -webkit 11 var listenerDocumentReady = function()

有关文档碎片(document fragment)的用法

通常情况下修改.删除或者增加DOM元素.更新DOM会导致浏览器重新绘制屏幕,也会导 致reflow,这样会带来巨大的开销.我们通常解决这的办法尽量减少更新DOM,这也就意 味着将DOM的改变分批处理,并在"活动"文档树之外执行这些更新. 当需要创建一个相对比较大的子树,应该在子树完全创建之后再将子树添加到DOM树中, 这时采用文档碎片技术来容纳所有的节点. //反例子 //在创建时立即添加节点 var p,t; p = document.createElement('p'); t =