国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Nextjs中文文檔

luckyw / 2156人閱讀

摘要:中文站點中文站當前翻譯版本為。注意將不能使用在子組件中。只能使用在頁面中。替換路由組件默認將新推入路由棧中。以防服務端渲染發生錯誤,建議事件寫在生命周期里。禁止文件路由默認情況,將會把下的所有文件匹配路由如渲染為如果你的項目使用

Next.js 是一個輕量級的 React 服務端渲染應用框架。

Next.js中文站點 http://nextjs.frontendx.cn

Next.js中文站Github https://github.com/raoenhui/next-site-cn

當前翻譯版本為 7.0.0-canary.8。

怎么使用

安裝

代碼自動分割

CSS

支持嵌入樣式

內嵌樣式

使用 CSS / Sass / Less / Stylus files

靜態文件服務(如圖像)

獲取數據以及組件生命周期

路由

用法

URL 對象

替換路由

組件支持點擊事件onClick

暴露href給子元素

禁止滾動到頁面頂部

命令式

攔截器 popstate

URL 對象用法

路由事件

淺層路由

高階組件

預加載頁面

用法

命令式 prefetch 寫法

自定義服務端路由

禁止文件路由

動態前綴

動態導入

1. 基礎支持 (同樣支持 SSR)

2. 自定義加載組件

3. 禁止使用 SSR

4. 同時加載多個模塊

自定義

自定義

自定義錯誤處理

渲染內置錯誤頁面

自定義配置

設置自定義構建目錄

禁止 etag 生成

配置 onDemandEntries

配置頁面后綴名解析擴展

配置構建 ID

自定義 webpack 配置

自定義 babel 配置

暴露配置到服務端和客戶端

啟動服務選擇 hostname

CDN 支持前綴

項目部署

瀏覽器支持

導出靜態頁面

使用

限制

多 zone

怎么定義一個 zone

怎么合并他們

技巧

FAQ

貢獻

作者

怎么使用

安裝

安裝它:

npm install --save next react react-dom

將下面腳本添加到 package.json 中:

{
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  }
}

下面, 文件系統是主要的 API. 每個.js 文件將變成一個路由,自動處理和渲染。

新建 ./pages/index.js 到你的項目中:

export default () => 
Welcome to next.js!

運行 npm run dev 命令并打開 http://localhost:3000。 如果你想使用其他端口,可運行 npm run dev -- -p <設置端口號>.

目前為止我們可以了解到:

自動打包編譯 (使用 webpack 和 babel)

熱加載

./pages作為服務端的渲染和索引

Static file serving. ./static/ is mapped to /static/ (given you create a ./static/ directory inside your project)

靜態文件服務. ./static/ 映射到 /static/ (可以 創建一個靜態目錄 在你的項目中)

這里有個簡單的案例,可以下載看看 sample app - nextgram

代碼自動分割

每個頁面只會導入import中綁定以及被用到的代碼. 也就是說并不會加載不需要的代碼!

import cowsay from "cowsay-browser"

export default () =>
  
    {cowsay.say({ text: "hi there!" })}
  

CSS

支持嵌入樣式


Examples
  • Basic css

我們綁定 styled-jsx 來生成獨立作用域的 CSS. 目標是支持 "shadow CSS",但是 不支持獨立模塊作用域的 JS.

export default () =>
  
Hello world

scoped!

想查看更多案例可以點擊 styled-jsx documentation查看.

內嵌樣式


Examples

  • Styled components
  • Styletron
  • Glamor
  • Glamorous
  • Cxs
  • Aphrodite
  • Fela

有些情況可以使用 CSS 內嵌 JS 寫法。如下所示:

export default () => 

hi there

更復雜的內嵌樣式解決方案,特別是服務端渲染的時樣式更改。我們可以通過包裹自定義 Document,來添加樣式,案例如下:custom

使用 CSS / Sass / Less / Stylus files

支持用.css, .scss, .less or .styl,需要配置默認文件 next.config.js,具體可查看下面鏈接

@zeit/next-css

@zeit/next-sass

@zeit/next-less

@zeit/next-stylus

靜態文件服務(如圖像)

在根目錄下新建文件夾叫static。代碼可以通過/static/來引入相關的靜態資源。

export default () => 

_注意:不要自定義靜態文件夾的名字,只能叫static ,因為只有這個名字 Next.js 才會把它當作靜態資源。

生成


Examples

我們設置一個內置組件來裝載到頁面中。

import Head from "next/head"

export default () =>
  
My page title

Hello world!

我們定義key屬性來避免重復的標簽,保證只渲染一次,如下所示:

import Head from "next/head"
export default () => (
  
My page title

Hello world!

)

只有第二個才被渲染。

注意:在卸載組件時,的內容將被清除。請確保每個頁面都在其定義了所需要的內容,而不是假設其他頁面已經加過了

獲取數據以及組件生命周期


Examples
  • Data fetch

如果你需要一個有狀態、生命周期或有初始數據的 React 組件(而不是上面的無狀態函數),如下所示:

import React from "react"

export default class extends React.Component {
  static async getInitialProps({ req }) {
    const userAgent = req ? req.headers["user-agent"] : navigator.userAgent
    return { userAgent }
  }

  render() {
    return (
      
Hello World {this.props.userAgent}
) } }

相信你注意到,當頁面渲染時加載數據,我們使用了一個異步方法getInitialProps。它能異步獲取 JS 普通對象,并綁定在props

當服務渲染時,getInitialProps將會把數據序列化,就像JSON.stringify。所以確保getInitialProps返回的是一個普通 JS 對象,而不是Date, MapSet類型。

當頁面初次加載時,getInitialProps只會在服務端執行一次。getInitialProps只有在路由切換的時候(如Link組件跳轉或路由自定義跳轉)時,客戶端的才會被執行。

當頁面初始化加載時,getInitialProps只會加載在服務端。只有當路由跳轉(Link組件跳轉或 API 方法跳轉)時,客戶端才會執行getInitialProps

注意:getInitialProps將不能使用在子組件中。只能使用在pages頁面中。


只有服務端用到的模塊放在getInitialProps里,請確保正確的導入了它們,可參考import them properly。
否則會拖慢你的應用速度。


你也可以給無狀態組件定義getInitialProps

const Page = ({ stars }) =>
  
Next stars: {stars}
Page.getInitialProps = async ({ req }) => { const res = await fetch("https://api.github.com/repos/zeit/next.js") const json = await res.json() return { stars: json.stargazers_count } } export default Page

getInitialProps入參對象的屬性如下:

pathname - URL 的 path 部分

query - URL 的 query 部分,并被解析成對象

asPath - 顯示在瀏覽器中的實際路徑(包含查詢部分),為String類型

req - HTTP 請求對象 (只有服務器端有)

res - HTTP 返回對象 (只有服務器端有)

jsonPageRes - 獲取數據響應對象 (只有客戶端有)

err - 渲染過程中的任何錯誤

路由

用法


Examples

可以用 組件實現客戶端的路由切換。

// pages/index.js
import Link from "next/link"

export default () =>
  
Click{" "} here {" "} to read more
// pages/about.js
export default () => 

Welcome to About!

注意:可以使用使鏈接和預加載在后臺同時進行,來達到頁面的最佳性能。

客戶端路由行為與瀏覽器很相似:

組件獲取

如果組件定義了getInitialProps,數據獲取了。如果有錯誤情況將會渲染 _error.js

1和2都完成了,pushState執行,新組件被渲染。

如果需要注入pathname, queryasPath到你組件中,你可以使用withRouter。

URL 對象


Examples

組件接收 URL 對象,而且它會自動格式化生成 URL 字符串

// pages/index.js
import Link from "next/link"

export default () =>
  
Click{" "} here {" "} to read more

將生成 URL 字符串/about?name=Zeit,你可以使用任何在Node.js URL module documentation定義過的屬性。

替換路由

組件默認將新 url 推入路由棧中。你可以使用replace屬性來防止添加新輸入。

// pages/index.js
import Link from "next/link"

export default () =>
  
Click{" "} here {" "} to read more

組件支持點擊事件 onClick

支持每個組件所支持的onClick事件。如果你不提供標簽,只會處理onClick事件而href將不起作用。

// pages/index.js
import Link from "next/link"

export default () =>
  
Click{" "}

暴露 href 給子元素

如子元素是一個沒有 href 屬性的標簽,我們將會指定它以免用戶重復操作。然而有些時候,我們需要里面有標簽,但是Link組件不會被識別成超鏈接,結果不能將href傳遞給子元素。在這種場景下,你可以定義一個Link組件中的布爾屬性passHref,強制將href傳遞給子元素。

注意: 使用a之外的標簽而且沒有通過passHref的鏈接可能會使導航看上去正確,但是當搜索引擎爬行檢測時,將不會識別成鏈接(由于缺乏 href 屬性),這會對你網站的 SEO 產生負面影響。

import Link from "next/link"
import Unexpected_A from "third-library"

export default ({ href, name }) =>
  
    
      {name}
    
  

禁止滾動到頁面頂部

的默認行為就是滾到頁面頂部。當有 hash 定義時(#),頁面將會滾動到對應的 id 上,就像標簽一樣。為了預防滾動到頂部,可以給
scroll={false}屬性:

Disables scrolling
Changes with scrolling to top

命令式


Examples

你也可以用next/router實現客戶端路由切換

import Router from "next/router"

export default () =>
  
Click Router.push("/about")}>here to read more

攔截器 popstate

有些情況(比如使用custom router),你可能想監聽popstate,在路由跳轉前做一些動作。
比如,你可以操作 request 或強制 SSR 刷新

import Router from "next/router"

Router.beforePopState(({ url, as, options }) => {
  // I only want to allow these two routes!
  if (as !== "/" || as !== "/other") {
    // Have SSR render bad routes as a 404.
    window.location.href = as
    return false
  }

  return true
});

如果你在beforePopState中返回 false,Router將不會執行popstate事件。
例如Disabling File-System Routing。

以上Router對象的 API 如下:

route - 當前路由的String類型

pathname - 不包含查詢內容的當前路徑,為String類型

query - 查詢內容,被解析成Object類型. 默認為{}

asPath - 展現在瀏覽器上的實際路徑,包含查詢內容,為String類型

push(url, as=url) - 頁面渲染第一個參數 url 的頁面,瀏覽器欄顯示的是第二個參數 url

replace(url, as=url) - performs a replaceState call with the given url

beforePopState(cb=function) - 在路由器處理事件之前攔截.

pushreplace 函數的第二個參數as,是為了裝飾 URL 作用。如果你在服務器端設置了自定義路由將會起作用。

URL 對象用法

pushreplace可接收的 URL 對象(組件的 URL 對象一樣)來生成 URL。

import Router from "next/router"

const handler = () =>
  Router.push({
    pathname: "/about",
    query: { name: "Zeit" }
  })

export default () =>
  
Click here to read more

也可以像組件一樣添加額外的參數。

路由事件

你可以監聽路由相關事件。
下面是事件支持列表:

routeChangeStart(url) - 路由開始切換時觸發

routeChangeComplete(url) - 完成路由切換時觸發

routeChangeError(err, url) - 路由切換報錯時觸發

beforeHistoryChange(url) - 瀏覽器 history 模式開始切換時觸發

hashChangeStart(url) - 開始切換 hash 值但是沒有切換頁面路由時觸發

hashChangeComplete(url) - 完成切換 hash 值但是沒有切換頁面路由時觸發

這里的url是指顯示在瀏覽器中的 url。如果你用了Router.push(url, as)(或類似的方法),那瀏覽器中的 url 將會顯示 as 的值。

下面是如何正確使用路由事件routeChangeStart的例子:

const handleRouteChange = url => {
  console.log("App is changing to: ", url)
}

Router.events.on("routeChangeStart", handleRouteChange)

如果你不想長期監聽該事件,你可以用off事件去取消監聽:

Router.events.off("routeChangeStart", handleRouteChange)

如果路由加載被取消(比如快速連續雙擊鏈接)

Router.events.on("routeChangeError", (err, url) => {
  if (err.cancelled) {
    console.log(`Route to ${url} was cancelled!`)
  }
})

淺層路由


Examples

淺層路由允許你改變 URL 但是不執行getInitialProps生命周期。你可以加載相同頁面的 URL,得到更新后的路由屬性pathnamequery,并不失去 state 狀態。

你可以給Router.pushRouter.replace方法加shallow: true參數。如下面的例子所示:

// Current URL is "/"
const href = "/?counter=10"
const as = href
Router.push(href, as, { shallow: true })

現在 URL 更新為/?counter=10。在組件里查看this.props.router.query你將會看到更新的 URL。

你可以在componentdidupdate鉤子函數中監聽 URL 的變化。

componentDidUpdate(prevProps) {
  const { pathname, query } = this.props.router
  // verify props have changed to avoid an infinite loop
  if (query.id !== prevProps.router.query.id) {
    // fetch data based on the new query
  }
}

注意:

淺層路由只作用于相同 URL 的參數改變,比如我們假定有個其他路由about,而你向下面代碼樣運行:

Router.push("/?counter=10", "/about?counter=10", { shallow: true })

那么這將會出現新頁面,即使我們加了淺層路由,但是它還是會卸載當前頁,會加載新的頁面并觸發新頁面的getInitialProps

高階組件


Examples

如果你想應用里每個組件都處理路由對象,你可以使用withRouter高階組件。下面是如何使用它:

import { withRouter } from "next/router"

const ActiveLink = ({ children, router, href }) => {
  const style = {
    marginRight: 10,
    color: router.pathname === href? "red" : "black"
  }

  const handleClick = (e) => {
    e.preventDefault()
    router.push(href)
  }

  return (
    
      {children}
    
  )
}

export default withRouter(ActiveLink)

上面路由對象的 API 可以參考next/router.

預加載頁面

?? 只有生產環境才有此功能 ??


Examples
  • Prefetching

Next.js 有允許你預加載頁面的 API。

用 Next.js 服務端渲染你的頁面,可以達到所有你應用里所有未來會跳轉的路徑即時響應,有效的應用 Next.js,可以通過預加載應用程序的功能,最大程度的初始化網站性能。查看更多.

Next.js 的預加載功能只預加載 JS 代碼。當頁面渲染時,你可能需要等待數據請求。

用法

你可以給添加 prefetch 屬性,Next.js 將會在后臺預加載這些頁面。

import Link from "next/link"

// example header component
export default () =>
  

命令式 prefetch 寫法

大多數預加載是通過處理的,但是我們還提供了命令式 API 用于更復雜的場景。

import { withRouter } from "next/router"

export default withRouter(({ router }) =>
  
)

路由實例只允許在應用程序的客戶端。以防服務端渲染發生錯誤,建議 prefetch 事件寫在componentDidMount()生命周期里。

import React from "react"
import { withRouter } from "next/router"

class MyLink extends React.Component {
  componentDidMount() {
    const { router } = this.props
    router.prefetch("/dynamic")
  }
  
  render() {
    const { router } = this.props
    return (
          
    )
  }
}

export default withRouter(MyLink)

自定義服務端路由


Examples

一般你使用next start命令來啟動 next 服務,你還可以編寫代碼來自定義路由,如使用路由正則等。

當使用自定義服務文件,如下面例子所示叫 server.js 時,確保你更新了 package.json 中的腳本。

{
  "scripts": {
    "dev": "node server.js",
    "build": "next build",
    "start": "NODE_ENV=production node server.js"
  }
}

下面這個例子使 /a 路由解析為./pages/b,以及/b 路由解析為./pages/a;

// This file doesn"t go through babel or webpack transformation.
// Make sure the syntax and sources this file requires are compatible with the current node version you are running
// See https://github.com/zeit/next.js/issues/1245 for discussions on Universal Webpack or universal Babel
const { createServer } = require("http")
const { parse } = require("url")
const next = require("next")

const dev = process.env.NODE_ENV !== "production"
const app = next({ dev })
const handle = app.getRequestHandler()

app.prepare().then(() => {
  createServer((req, res) => {
    // Be sure to pass `true` as the second argument to `url.parse`.
    // This tells it to parse the query portion of the URL.
    const parsedUrl = parse(req.url, true)
    const { pathname, query } = parsedUrl

    if (pathname === "/a") {
      app.render(req, res, "/b", query)
    } else if (pathname === "/b") {
      app.render(req, res, "/a", query)
    } else {
      handle(req, res, parsedUrl)
    }
  }).listen(3000, err => {
    if (err) throw err
    console.log("> Ready on http://localhost:3000")
  })
})

next的 API 如下所示

next(opts: object)

opts 的屬性如下:

dev (boolean) 判斷 Next.js 應用是否在開發環境 - 默認false

dir (string) Next 項目路徑 - 默認"."

quiet (boolean) 是否隱藏包含服務端消息在內的錯誤信息 - 默認false

conf (object) 與next.config.js的對象相同 - 默認{}

生產環境的話,可以更改 package.json 里的start腳本為NODE_ENV=production node server.js

禁止文件路由

默認情況,Next將會把/pages下的所有文件匹配路由(如/pages/some-file.js 渲染為 site.com/some-file

如果你的項目使用自定義路由,那么有可能不同的路由會得到相同的內容,可以優化 SEO 和用戶體驗。

禁止路由鏈接到/pages下的文件,只需設置next.config.js文件如下所示:

// next.config.js
module.exports = {
  useFileSystemPublicRoutes: false
}

注意useFileSystemPublicRoutes只禁止服務端的文件路由;但是客戶端的還是禁止不了。

你如果想配置客戶端路由不能跳轉文件路由,可以參考Intercepting popstate

動態前綴

有時你需要設置動態前綴,可以在請求時設置assetPrefix改變前綴。

使用方法如下:

const next = require("next")
const micro = require("micro")

const dev = process.env.NODE_ENV !== "production"
const app = next({ dev })
const handleNextRequests = app.getRequestHandler()

app.prepare().then(() => {
  const server = micro((req, res) => {
    // Add assetPrefix support based on the hostname
    if (req.headers.host === "my-app.com") {
      app.setAssetPrefix("http://cdn.com/myapp")
    } else {
      app.setAssetPrefix("")
    }

    handleNextRequests(req, res)
  })

  server.listen(port, (err) => {
    if (err) {
      throw err
    }

    console.log(`> Ready on http://localhost:${port}`)
  })
})

動態導入


Examples

ext.js 支持 JavaScript 的 TC39 提議dynamic import proposal。你可以動態導入 JavaScript 模塊(如 React 組件)。

動態導入相當于把代碼分成各個塊管理。Next.js 服務端動態導入功能,你可以做很多炫酷事情。

下面介紹一些動態導入方式:

1. 基礎支持 (同樣支持 SSR)
import dynamic from "next/dynamic"

const DynamicComponent = dynamic(import("../components/hello"))

export default () =>
  

HOME PAGE is here!

2. 自定義加載組件
import dynamic from "next/dynamic"

const DynamicComponentWithCustomLoading = dynamic(
  import("../components/hello2"),
  {
    loading: () => 

...

} ) export default () =>

HOME PAGE is here!

3. 禁止使用 SSR
import dynamic from "next/dynamic"

const DynamicComponentWithNoSSR = dynamic(import("../components/hello3"), {
  ssr: false
})

export default () =>
  

HOME PAGE is here!

4. 同時加載多個模塊
import dynamic from "next/dynamic"

const HelloBundle = dynamic({
  modules: () => {
    const components = {
      Hello1: import("../components/hello1"),
      Hello2: import("../components/hello2")
    }

    return components
  },
  render: (props, { Hello1, Hello2 }) =>
    

{props.title}

}) export default () =>

自定義


Examples
  • Using _app.js for layout

  • Using _app.js to override componentDidCatch

組件來初始化頁面。你可以重寫它來控制頁面初始化,如下面的事:

當頁面變化時保持頁面布局

當路由變化時保持頁面狀態

使用componentDidCatch自定義處理錯誤

注入額外數據到頁面里 (如 GraphQL 查詢)

重寫的話,新建./pages/_app.js文件,重寫 App 模塊如下所示:

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

export default class MyApp extends App {
  static async getInitialProps ({ Component, router, ctx }) {
    let pageProps = {}

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

    return {pageProps}
  }

  render () {
    const {Component, pageProps} = this.props
    return 
      
    
  }
}

自定義


Examples
  • Styled components custom document

  • Google AMP

在服務端呈現

初始化服務端時添加文檔標記元素

通常實現服務端渲染會使用一些 css-in-js 庫,如styled-components, glamorous 或 emotion。styled-jsx是 Next.js 自帶默認使用的 css-in-js 庫

Next.js會自動定義文檔標記,比如,你從來不需要添加, 等。如果想自定義文檔標記,你可以新建./pages/_document.js,然后擴展Document類:

// _document is only rendered on the server side and not on the client side
// Event handlers like onClick can"t be added to this file

// ./pages/_document.js
import Document, { Head, Main, NextScript } from "next/document"

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

  render() {
    return (
      
        
          
        
        
          
) } }

鉤子getInitialProps接收到的參數ctx對象都是一樣的

回調函數renderPage是會執行 React 渲染邏輯的函數(同步),這種做法有助于此函數支持一些類似于 Aphrodite 的 renderStatic 等一些服務器端渲染容器。

注意:

外的 React 組件將不會渲染到瀏覽器中,所以那添加應用邏輯代碼。如果你頁面需要公共組件(菜單或工具欄),可以參照上面說的App組件代替。

自定義錯誤處理

404和500錯誤客戶端和服務端都會通過error.js組件處理。如果你想改寫它,則新建_error.js在文件夾中:

import React from "react"

export default class Error extends React.Component {
  static getInitialProps({ res, err }) {
    const statusCode = res ? res.statusCode : err ? err.statusCode : null;
    return { statusCode }
  }

  render() {
    return (
      

{this.props.statusCode ? `An error ${this.props.statusCode} occurred on server` : "An error occurred on client"}

) } }

渲染內置錯誤頁面

如果你想渲染內置錯誤頁面,你可以使用next/error

import React from "react"
import Error from "next/error"
import fetch from "isomorphic-unfetch"

export default class Page extends React.Component {
  static async getInitialProps() {
    const res = await fetch("https://api.github.com/repos/zeit/next.js")
    const statusCode = res.statusCode > 200 ? res.statusCode : false
    const json = await res.json()

    return { statusCode, stars: json.stargazers_count }
  }

  render() {
    if (this.props.statusCode) {
      return 
    }

    return (
      
Next stars: {this.props.stars}
) } }
如果你自定義了個錯誤頁面,你可以引入自己的錯誤頁面來代替next/error

自定義配置

如果你想自定義 Next.js 的高級配置,可以在根目錄下新建next.config.js文件(與pages/package.json一起)

注意:next.config.js是一個 Node.js 模塊,不是一個 JSON 文件,可以用于 Next 啟動服務已經構建階段,但是不作用于瀏覽器端。

// next.config.js
module.exports = {
  /* config options here */
}

或使用一個函數:

module.exports = (phase, {defaultConfig}) => {
  //
  // https://github.com/zeit/
  return {
    /* config options here */
  }
}

phase是配置文件被加載時的當前內容。你可看到所有的 phases 常量:constants
這些常量可以通過next/constants引入:

const {PHASE_DEVELOPMENT_SERVER} = require("next/constants")
module.exports = (phase, {defaultConfig}) => {
  if(phase === PHASE_DEVELOPMENT_SERVER) {
    return {
      /* development only config options here */
    }
  }

  return {
    /* config options for all phases except development here */
  }
}

設置自定義構建目錄

你可以自定義一個構建目錄,如新建build文件夾來代替.next 文件夾成為構建目錄。如果沒有配置構建目錄,構建時將會自動新建.next文件夾

// next.config.js
module.exports = {
  distDir: "build"
}

禁止 etag 生成

你可以禁止 etag 生成根據你的緩存策略。如果沒有配置,Next 將會生成 etags 到每個頁面中。

// next.config.js
module.exports = {
  generateEtags: false
}

配置 onDemandEntries

Next 暴露一些選項來給你控制服務器部署以及緩存頁面:

module.exports = {
  onDemandEntries: {
    // period (in ms) where the server will keep pages in the buffer
    maxInactiveAge: 25 * 1000,
    // number of pages that should be kept simultaneously without being disposed
    pagesBufferLength: 2,
  }
}

這個只是在開發環境才有的功能。如果你在生成環境中想緩存 SSR 頁面,請查看SSR-caching

配置頁面后綴名解析擴展

如 typescript 模塊@zeit/next-typescript,需要支持解析后綴名為.ts的文件。pageExtensions 允許你擴展后綴名來解析各種 pages 下的文件。

// next.config.js
module.exports = {
  pageExtensions: ["jsx", "js"]
}

配置構建 ID

Next.js 使用構建時生成的常量來標識你的應用服務是哪個版本。在每臺服務器上運行構建命令時,可能會導致多服務器部署出現問題。為了保持同一個構建 ID,可以配置generateBuildId函數:

// next.config.js
module.exports = {
  generateBuildId: async () => {
    // For example get the latest git commit hash here
    return "my-build-id"
  }
}

自定義 webpack 配置


Examples
  • Custom webpack bundle analyzer

可以使用些一些常見的模塊

@zeit/next-css

@zeit/next-sass

@zeit/next-less

@zeit/next-preact

@zeit/next-typescript

注意: webpack方法將被執行兩次,一次在服務端一次在客戶端。你可以用isServer屬性區分客戶端和服務端來配置

多配置可以組合在一起,如:

const withTypescript = require("@zeit/next-typescript")
const withSass = require("@zeit/next-sass")

module.exports = withTypescript(withSass({
  webpack(config, options) {
    // Further custom configuration here
    return config
  }
}))

為了擴展webpack使用,可以在next.config.js定義函數。

// next.config.js is not transformed by Babel. So you can only use javascript features supported by your version of Node.js.

module.exports = {
  webpack: (config, { buildId, dev, isServer, defaultLoaders }) => {
    // Perform customizations to webpack config
    // Important: return the modified config
    return config
  },
  webpackDevMiddleware: config => {
    // Perform customizations to webpack dev middleware config
    // Important: return the modified config
    return config
  }
}

webpack的第二個參數是個對象,你可以自定義配置它,對象屬性如下所示:

buildId - 字符串類型,構建的唯一標示

dev - Boolean型,判斷你是否在開發環境下

isServer - Boolean 型,為true使用在服務端, 為false使用在客戶端.

defaultLoaders - 對象型 ,內部加載器, 你可以如下配置

babel - 對象型,配置babel-loader.

hotSelfAccept - 對象型, hot-self-accept-loader配置選項.這個加載器只能用于高階案例。如 @zeit/next-typescript添加頂層 typescript 頁面。

defaultLoaders.babel使用案例如下:

// Example next.config.js for adding a loader that depends on babel-loader
// This source was taken from the @zeit/next-mdx plugin source: 
// https://github.com/zeit/next-plugins/blob/master/packages/next-mdx
module.exports = {
  webpack: (config, {}) => {
    config.module.rules.push({
      test: /.mdx/,
      use: [
        options.defaultLoaders.babel,
        {
          loader: "@mdx-js/loader",
          options: pluginOptions.options
        }
      ]
    })

    return config
  }
}

自定義 babel 配置


Examples
  • Custom babel configuration

為了擴展方便我們使用babel,可以在應用根目錄新建.babelrc文件,該文件可配置。

如果有該文件,我們將會考慮數據源,因此也需要定義 next 項目需要的東西,也就是 next/babel預設。

這種設計方案將會使你不詫異于我們可以定制 babel 配置。

下面是.babelrc文件案例:

{
  "presets": ["next/babel"],
  "plugins": []
}

next/babel預設可處理各種 React 應用所需要的情況。包括:

preset-env

preset-react

plugin-proposal-class-properties

plugin-proposal-object-rest-spread

plugin-transform-runtime

styled-jsx

presets / plugins 不允許添加到.babelrc中,然而你可以配置next/babel預設:

{
  "presets": [
    ["next/babel", {
      "preset-env": {},
      "transform-runtime": {},
      "styled-jsx": {},
      "class-properties": {}
    }]
  ],
  "plugins": []
}

"preset-env"模塊選項應該保持為 false,否則 webpack 代碼分割將被禁用。

暴露配置到服務端和客戶端

next/config模塊使你應用運行時可以讀取些存儲在next.config.js的配置項。serverRuntimeConfig屬性只在服務器端可用,publicRuntimeConfig屬性在服務端和客戶端可用。

// next.config.js
module.exports = {
  serverRuntimeConfig: { // Will only be available on the server side
    mySecret: "secret"
  },
  publicRuntimeConfig: { // Will be available on both server and client
    staticFolder: "/static",
    mySecret: process.env.MY_SECRET // Pass through env variables
  }
}
// pages/index.js
import getConfig from "next/config"
// Only holds serverRuntimeConfig and publicRuntimeConfig from next.config.js nothing else.
const {serverRuntimeConfig, publicRuntimeConfig} = getConfig()

console.log(serverRuntimeConfig.mySecret) // Will only be available on the server side
console.log(publicRuntimeConfig.staticFolder) // Will be available on both server and client

export default () => 

啟動服務選擇 hostname

啟動開發環境服務可以設置不同的 hostname,你可以在啟動命令后面加上--hostname 主機名-H 主機名。它將會啟動一個 TCP 服務器來監聽連接所提供的主機。

CDN 支持前綴

建立一個 CDN,你能配置assetPrefix選項,去配置你的 CDN 源。

const isProd = process.env.NODE_ENV === "production"
module.exports = {
  // You may only need to add assetPrefix in the production.
  assetPrefix: isProd ? "https://cdn.mydomain.com" : ""
}

注意:Next.js 運行時將會自動添加前綴,但是對于/static是沒有效果的,如果你想這些靜態資源也能使用 CDN,你需要自己添加前綴。有一個方法可以判斷你的環境來加前綴,如 in this example。

項目部署

部署中,你可以先構建打包生成環境代碼,再啟動服務。因此,構建和啟動分為下面兩條命令:

next build
next start

例如,使用now去部署package.json配置文件如下:

{
  "name": "my-app",
  "dependencies": {
    "next": "latest"
  },
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  }
}

然后就可以直接運行now了。

Next.js 也有其他托管解決方案。請查考 wiki 章節"Deployment" 。

注意:NODE_ENV可以通過next命令配置,如果沒有配置,會最大渲染,如果你使用編程式寫法的話programmatically,你需要手動設置NODE_ENV=production

注意:推薦將.next或自定義打包文件夾custom dist folder放入.gitignore.npmignore中。否則,使用filesnow.files
添加部署白名單,并排除.next或自定義打包文件夾。

瀏覽器支持

Next.js 支持 IE11 和所有的現代瀏覽器使用了@babel/preset-env。為了支持 IE11,Next.js 需要全局添加Promise的 polyfill。有時你的代碼或引入的其他 NPM 包的部分功能現代瀏覽器不支持,則需要用 polyfills 去實現。

ployflls 實現案例為polyfills。

導出靜態頁面


Examples
  • Static export

next export可以輸出一個 Next.js 應用作為靜態資源應用而不依靠 Node.js 服務。
這個輸出的應用幾乎支持 Next.js 的所有功能,包括動態路由,預獲取,預加載以及動態導入。

next export將把所有有可能渲染出的 HTML 都生成。這是基于映射對象的pathname關鍵字關聯到頁面對象。這個映射叫做exportPathMap

頁面對象有2個屬性:

page - 字符串類型,頁面生成目錄

query - 對象類型,當預渲染時,query對象將會傳入頁面的生命周期getInitialProps中。默認為{}

使用

通常開發 Next.js 應用你將會運行:

next build
next export

next export命令默認不需要任何配置,將會自動生成默認exportPathMap生成pages目錄下的路由你頁面。

如果你想動態配置路由,可以在next.config.js中添加異步函數exportPathMap

// next.config.js
module.exports = {
  exportPathMap: async function (defaultPathMap) {
    return {
      "/": { page: "/" },
      "/about": { page: "/about" },
      "/readme.md": { page: "/readme" },
      "/p/hello-nextjs": { page: "/post", query: { title: "hello-nextjs" } },
      "/p/learn-nextjs": { page: "/post", query: { title: "learn-nextjs" } },
      "/p/deploy-nextjs": { page: "/post", query: { title: "deploy-nextjs" } }
    }
  }
}
注意:如果 path 的結尾是目錄名,則將導出/dir-name/index.html,但是如果結尾有擴展名,將會導出對應的文件,如上/readme.md。如果你使用.html以外的擴展名解析文件時,你需要設置 header 的Content-Type頭為"text/html".

輸入下面命令:

next build
next export

你可以在package.json添加一個 NPM 腳本,如下所示:

{
  "scripts": {
    "build": "next build",
    "export": "npm run build && next export"
  }
}

接著只用執行一次下面命令:

npm run export

然后你將會有一個靜態頁面應用在out 目錄下。

你也可以自定義輸出目錄。可以運行next export -h命令查看幫助。

現在你可以部署out目錄到任意靜態資源服務器上。注意如果部署 GitHub Pages 需要加個額外的步驟,文檔如下

例如,訪問out目錄并用下面命令部署應用ZEIT Now.

now

限制

使用next export,我們創建了個靜態 HTML 應用。構建時將會運行頁面里生命周期getInitialProps 函數。

reqres只在服務端可用,不能通過getInitialProps

所以你不能預構建 HTML 文件時動態渲染 HTML 頁面。如果你想動態渲染可以運行next start或其他自定義服務端 API。

多 zone


Examples
  • With Zones

一個 zone 時一個多帶帶的 Next.js 應用。如果你有很多 zone,你可以合并成一個應用。

例如,你如下有兩個 zone:

https://docs.my-app.com 服務于路由 /docs/**

https://ui.my-app.com 服務于所有頁面

有多 zone 應用技術支持,你可以將幾個應用合并到一個,而且可以自定義 URL 路徑,使你能同時多帶帶開發各個應用。

與 microservices 觀念類似, 只是應用于前端應用.

怎么定義一個 zone

zone 沒有多帶帶的 API 文檔。你需要做下面事即可:

確保你的應用里只有需要的頁面 (例如, https://ui.my-app.com 不包含 /docs/**)

確保你的應用有個前綴assetPrefix。(你也可以定義動態前綴dynamically)

怎么合并他們

你能使用 HTTP 代理合并 zone

你能使用代理micro proxy來作為你的本地代理服務。它允許你定義路由規則如下:

{
  "rules": [
    {"pathname": "/docs**", "method":["GET", "POST", "OPTIONS"], "dest": "https://docs.my-app.com"},
    {"pathname": "/**", "dest": "https://ui.my-app.com"}
  ]
}

生產環境部署,如果你使用了ZEIT now,可以它的使用path alias 功能。否則,你可以設置你已使用的代理服務編寫上面規則來路由 HTML 頁面

技巧

設置301重定向

只處理服務器端模塊

構建項目 React-Material-UI-Next-Express-Mongoose-Mongodb

構建一個 SaaS 產品 React-Material-UI-Next-MobX-Express-Mongoose-MongoDB-TypeScript

問答


這個產品可以用于生產環境嗎?

https://zeit.co 都是一直用 Next.js 寫的。

它的開發體驗和終端用戶體驗都很好,所以我們決定開源出來給大家共享。



體積多大?

客戶端大小根據應用需求不一樣大小也不一樣。

一個最簡單 Next 應該用 gzip 壓縮后大約65kb



這個像 create-react-app?

是或不是.

是,因為它讓你的 SSR 開發更簡單。

不是,因為它規定了一定的目錄結構,使我們能做以下更高級的事:

服務端渲染

自動代碼分割

此外,Next.js 還提供兩個內置特性:

路由與懶加載組件: (通過引入 next/link)

修改的組件: (通過引入 next/head)

如果你想寫共用組件,可以嵌入 Next.js 應用和 React 應用中,推薦使用create-react-app。你可以更改import保持代碼清晰。



怎么解決 CSS 嵌入 JS 問題?

Next.js 自帶styled-jsx庫支持 CSS 嵌入 JS。而且你可以選擇其他嵌入方法到你的項目中,可參考文檔as mentioned before。


哪些語法會被轉換?怎么轉換它們?

我們遵循 V8 引擎的,如今 V8 引擎廣泛支持 ES6 語法以及asyncawait語法,所以我們支持轉換它們。但是 V8 引擎不支持修飾器語法,所以我們也不支持轉換這語法。

可以參照這些 以及 這些



為什么使用新路由?

Next.js 的特別之處如下所示:

路由不需要被提前知道

路由總是被懶加載

頂層組件可以定義生命周期getInitialProps來阻止路由加載(當服務端渲染或路由懶加載時)

因此,我們可以介紹一個非常簡單的路由方法,它由下面兩部分組成:

每個頂層組件都將會收到一個url對象,來檢查 url 或修改歷史記錄

組件用于包裝如()標簽的元素容器,來執行客戶端轉換。

我們使用了些有趣的場景來測試路由的靈活性,例如,可查看nextgram。



我怎么定義自定義路由?

我們通過請求處理來添加任意 URL 與任意組件之前的映射關系。

在客戶端,我們組件有個屬性as,可以裝飾改變獲取到的 URL。



怎么獲取數據?

這由你決定。getInitialProps是一個異步函數async(也就是函數將會返回個Promise)。你可以在任意位置獲取數據。


我可以使用 GraphQL 嗎?

是的! 這里有個例子Apollo.


我可以使用 Redux 嗎?

是的! 這里有個例子


我可以在 Next 應用中使用我喜歡的 Javascript 庫或工具包嗎?

從我們第一次發版就已經提供很多例子,你可以查看這些例子。


什么啟發我們做這個?

我們實現的大部分目標都是通過 Guillermo Rauch 的Web 應用的7原則來啟發出的。

PHP 的易用性也是個很好的靈感來源,我們覺得 Next.js 可以替代很多需要用 PHP 輸出 HTML 的場景。

與 PHP 不同的是,我們得利于 ES6 模塊系統,每個文件會輸出一個組件或方法,以便可以輕松的導入用于懶加載和測試

我們研究 React 的服務器渲染時并沒有花費很大的步驟,因為我們發現一個類似于 Next.js 的產品,React 作者 Jordan Walke 寫的react-page (現在已經廢棄)


貢獻

可查看 contributing.md

作者

Arunoda Susiripala (@arunoda) – ZEIT

Tim Neutkens (@timneutkens) – ZEIT

Naoyuki Kanezawa (@nkzawa) – ZEIT

Tony Kovanen (@tonykovanen) – ZEIT

Guillermo Rauch (@rauchg) – ZEIT

Dan Zajdband (@impronunciable) – Knight-Mozilla / Coral Project

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/97685.html

相關文章

  • nextjs踩坑

    摘要:踩坑幾乎一整年沒咋寫文章,主要是懶,加上工作也挺忙。遇到一些坑,也有一些收獲這里記錄一下。個人習慣使用啟動服務。總結說了上面那么多,其實官方文檔里都有相關例子,就當我的個人踩坑記錄吧。 Next.js踩坑 幾乎一整年沒咋寫文章,主要是懶,加上工作也挺忙。但是想趁著年底發一篇,希望明年更勤奮一點。其實不是沒東西寫,就是想深入一個東西還是很困難的,要查各種資料,最終還是懶就是了。 next...

    JayChen 評論0 收藏0
  • 這是一個快速構建nextjs應用的工具

    摘要:官方也有一個的工具,但是只能簡單的安裝基礎的依賴,或者通過他們提供的某個例子來構建自己的項目。由于目前還在開發階段只支持上面這些的配置也是平常我用的比較多的配置。 因為公司的業務需求現在開發都用nextjs來實現React的服務端渲染,為了之后開發方便自己寫了個腳手架工具。 官方也有一個create-next-app的工具,但是只能簡單的安裝基礎的依賴,或者通過他們提供的某個例子來構建...

    scola666 評論0 收藏0
  • Next.js之基礎概念(二)

    摘要:樣式在中寫樣式,一般可以歸為類,一類是基于文件的傳統方式包括,等,另一類則是。我們回到我們的代碼中,更改,代碼如下在標簽中,我們寫我們的,必須包含在中,否則會報錯。至此,的基礎概念已經介紹完了,更高級的用法,可以參考官方的例子。 本篇教程基于上一篇的基礎,主要講解服務端渲染,樣式以及部署相關的一些知識,若你沒有看過上一篇的內容,或者你看過又忘了,建議重新去看一遍。 順便說一句,Next...

    DirtyMind 評論0 收藏0
  • Next.js之基礎概念

    摘要:是一個基于實現的服務端渲染框架,地址為。本文先從簡單地基礎概念開始,一步一步帶大家認識。本篇教程到此結束,后面會跟大家介紹的服務端渲染及以及部署相關的一下概念及示例代碼。 Next.js是一個基于React實現的服務端渲染框架,github地址為next.js。 使用Next.js實現服務端渲染是一件非常簡單的事,在這里,你完全可以不用自己去寫webpack等配置,Next.js全都幫...

    2bdenny 評論0 收藏0
  • 使用Vue、React和Koa開發個人博客

    摘要:前言實習了大半年,又臨近畢業,一直想做一個屬于自己的博客。于是就用和開發了一個服務端渲染的博客系統。其中后端管理使用開發前端頁面使用服務端渲染框架接口服務使用使用當接口發生時向我發送郵件通知項目地址是點我訪問項目地址,不要臉地求。 前言 實習了大半年,又臨近畢業,一直想做一個屬于自己的博客。于是就用Vue、React和Koa開發了一個服務端渲染的博客系統。其中: 后端管理使用Vue開...

    pf_miles 評論0 收藏0

發表評論

0條評論

luckyw

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<