摘要:中文站點中文站當前翻譯版本為。注意將不能使用在子組件中。只能使用在頁面中。替換路由組件默認將新推入路由棧中。以防服務端渲染發生錯誤,建議事件寫在生命周期里。禁止文件路由默認情況,將會把下的所有文件匹配路由如渲染為如果你的項目使用
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 () =>CSS 支持嵌入樣式{cowsay.say({ text: "hi there!" })}
Examples
我們綁定 styled-jsx 來生成獨立作用域的 CSS. 目標是支持 "shadow CSS",但是 不支持獨立模塊作用域的 JS.
export default () =>Hello worldscoped!
想查看更多案例可以點擊 styled-jsx documentation查看.
內嵌樣式
Examples
有些情況可以使用 CSS 內嵌 JS 寫法。如下所示:
export default () =>hi there
更復雜的內嵌樣式解決方案,特別是服務端渲染的時樣式更改。我們可以通過包裹自定義 Document,來添加樣式,案例如下:custom
支持用.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
如果你需要一個有狀態、生命周期或有初始數據的 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, Map 或 Set類型。
當頁面初次加載時,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, query 或 asPath到你組件中,你可以使用withRouter。
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事件而href將不起作用。
// pages/index.js import Link from "next/link" export default () =>Click{" "}
如子元素是一個沒有 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 () =>攔截器 popstateClick Router.push("/about")}>here to read more
有些情況(比如使用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) - 在路由器處理事件之前攔截.
push 和 replace 函數的第二個參數as,是為了裝飾 URL 作用。如果你在服務器端設置了自定義路由將會起作用。
push 或 replace可接收的 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,得到更新后的路由屬性pathname和query,并不失去 state 狀態。
你可以給Router.push 或 Router.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
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 }) =>setTimeout(() => router.push("/dynamic"), 100)}> A route transition will happen after 100ms {// but we can prefetch it! router.prefetch("/dynamic")})
路由實例只允許在應用程序的客戶端。以防服務端渲染發生錯誤,建議 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 () =>2. 自定義加載組件HOME PAGE is here!
import dynamic from "next/dynamic" const DynamicComponentWithCustomLoading = dynamic( import("../components/hello2"), { loading: () =>3. 禁止使用 SSR...
} ) export default () =>HOME PAGE is here!
import dynamic from "next/dynamic" const DynamicComponentWithNoSSR = dynamic(import("../components/hello3"), { ssr: false }) export default () =>4. 同時加載多個模塊HOME PAGE is here!
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 }) =>自定義}) export default () =>{props.title}
Examples
組件來初始化頁面。你可以重寫它來控制頁面初始化,如下面的事:
當頁面變化時保持頁面布局
當路由變化時保持頁面狀態
使用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
在服務端呈現
初始化服務端時添加文檔標記元素
通常實現服務端渲染會使用一些 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
可以使用些一些常見的模塊
@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
為了擴展方便我們使用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中。否則,使用files 或 now.files
添加部署白名單,并排除.next或自定義打包文件夾。
Next.js 支持 IE11 和所有的現代瀏覽器使用了@babel/preset-env。為了支持 IE11,Next.js 需要全局添加Promise的 polyfill。有時你的代碼或引入的其他 NPM 包的部分功能現代瀏覽器不支持,則需要用 polyfills 去實現。
ployflls 實現案例為polyfills。
導出靜態頁面
Examples
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 函數。
req和res只在服務端可用,不能通過getInitialProps。
所以你不能預構建 HTML 文件時動態渲染 HTML 頁面。如果你想動態渲染可以運行next start或其他自定義服務端 API。多 zone
Examples
一個 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
體積多大?
客戶端大小根據應用需求不一樣大小也不一樣。
是,因為它讓你的 SSR 開發更簡單。 不是,因為它規定了一定的目錄結構,使我們能做以下更高級的事: 服務端渲染 自動代碼分割 此外,Next.js 還提供兩個內置特性: 路由與懶加載組件: (通過引入 next/link) 修改的組件: (通過引入 next/head) 如果你想寫共用組件,可以嵌入 Next.js 應用和 React 應用中,推薦使用create-react-app。你可以更改import保持代碼清晰。
這個像 create-react-app?
是或不是.
怎么解決 CSS 嵌入 JS 問題?
Next.js 自帶styled-jsx庫支持 CSS 嵌入 JS。而且你可以選擇其他嵌入方法到你的項目中,可參考文檔as mentioned before。
可以參照這些 以及 這些
哪些語法會被轉換?怎么轉換它們?
我們遵循 V8 引擎的,如今 V8 引擎廣泛支持 ES6 語法以及async和await語法,所以我們支持轉換它們。但是 V8 引擎不支持修飾器語法,所以我們也不支持轉換這語法。
在客戶端,我們組件有個屬性as,可以裝飾改變獲取到的 URL。我怎么定義自定義路由?
我們通過請求處理來添加任意 URL 與任意組件之前的映射關系。
怎么獲取數據?
這由你決定。getInitialProps是一個異步函數async(也就是函數將會返回個Promise)。你可以在任意位置獲取數據。
我可以使用 GraphQL 嗎?
是的! 這里有個例子Apollo.
我可以使用 Redux 嗎?
是的! 這里有個例子
我可以在 Next 應用中使用我喜歡的 Javascript 庫或工具包嗎?
從我們第一次發版就已經提供很多例子,你可以查看這些例子。
PHP 的易用性也是個很好的靈感來源,我們覺得 Next.js 可以替代很多需要用 PHP 輸出 HTML 的場景。 與 PHP 不同的是,我們得利于 ES6 模塊系統,每個文件會輸出一個組件或方法,以便可以輕松的導入用于懶加載和測試 我們研究 React 的服務器渲染時并沒有花費很大的步驟,因為我們發現一個類似于 Next.js 的產品,React 作者 Jordan Walke 寫的react-page (現在已經廢棄)什么啟發我們做這個?
我們實現的大部分目標都是通過 Guillermo Rauch 的Web 應用的7原則來啟發出的。
可查看 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來實現React的服務端渲染,為了之后開發方便自己寫了個腳手架工具。 官方也有一個create-next-app的工具,但是只能簡單的安裝基礎的依賴,或者通過他們提供的某個例子來構建...
摘要:樣式在中寫樣式,一般可以歸為類,一類是基于文件的傳統方式包括,等,另一類則是。我們回到我們的代碼中,更改,代碼如下在標簽中,我們寫我們的,必須包含在中,否則會報錯。至此,的基礎概念已經介紹完了,更高級的用法,可以參考官方的例子。 本篇教程基于上一篇的基礎,主要講解服務端渲染,樣式以及部署相關的一些知識,若你沒有看過上一篇的內容,或者你看過又忘了,建議重新去看一遍。 順便說一句,Next...
摘要:是一個基于實現的服務端渲染框架,地址為。本文先從簡單地基礎概念開始,一步一步帶大家認識。本篇教程到此結束,后面會跟大家介紹的服務端渲染及以及部署相關的一下概念及示例代碼。 Next.js是一個基于React實現的服務端渲染框架,github地址為next.js。 使用Next.js實現服務端渲染是一件非常簡單的事,在這里,你完全可以不用自己去寫webpack等配置,Next.js全都幫...
摘要:前言實習了大半年,又臨近畢業,一直想做一個屬于自己的博客。于是就用和開發了一個服務端渲染的博客系統。其中后端管理使用開發前端頁面使用服務端渲染框架接口服務使用使用當接口發生時向我發送郵件通知項目地址是點我訪問項目地址,不要臉地求。 前言 實習了大半年,又臨近畢業,一直想做一個屬于自己的博客。于是就用Vue、React和Koa開發了一個服務端渲染的博客系統。其中: 后端管理使用Vue開...
閱讀 3521·2021-11-18 10:02
閱讀 952·2021-09-04 16:48
閱讀 2039·2019-08-30 15:55
閱讀 3540·2019-08-30 15:52
閱讀 1816·2019-08-30 14:08
閱讀 3557·2019-08-30 13:19
閱讀 1142·2019-08-27 10:53
閱讀 3122·2019-08-26 12:11