2018 年 9 月 19 日 星期三
Next.js 7
發布者經過 26 個 Canary 版本發布和 340 萬次下載,我們很榮幸推出已準備好正式環境的 Next.js 7,其特色包括
- DX 改善:啟動速度提升 57%,重新編譯速度提升 42%
- 更佳的錯誤報告功能,搭配 react-error-overlay
- 升級的編譯管線:Webpack 4 和 Babel 7
- 標準化的動態導入
- 靜態 CDN 支援
- 更小的初始 HTML 載荷
- App 和 Pages 之間使用 React Context 進行 SSR
最後,我們很高興能在全新 Nextjs.org 上分享這個消息
DX 改善
Next.js 的主要目標之一是以最佳的開發者體驗,提供最佳的生產環境效能。此版本為建置和偵錯管線帶來許多重大改進
編譯速度
歸功於 Webpack 4、Babel 7 以及我們程式碼庫上的許多改進和最佳化,Next.js 現在在開發期間啟動速度提升了 57%。
歸功於我們新的增量編譯快取,您對程式碼所做的變更現在將加快 40% 的建置速度。
以下是我們收集的一些範例數據
6.0 | 7.0 | 差異 | |
---|---|---|---|
啟動時間 (基本應用程式) | 1947ms | 835ms | 57% 更快 |
程式碼變更 (基本應用程式) | 304ms | 178ms | 42% 更快 |
此外,在開發和建置時,由於 webpackbar,您現在將看到更佳的即時回饋

使用 React Error Overlay 改善錯誤報告
呈現準確且有幫助的錯誤訊息對於良好的開發和偵錯體驗至關重要。到目前為止,我們都會呈現錯誤訊息及其堆疊追蹤。接下來,我們將使用 react-error-overlay
來豐富堆疊追蹤,使其包含
- 伺服器和用戶端錯誤的精確錯誤位置
- 原始碼重點標示,以提供上下文
- 完整的豐富堆疊追蹤
這是我們錯誤訊息改進前後的比較

此外,react-error-overlay
讓您只需點擊特定的程式碼區塊,即可輕鬆開啟文字編輯器。
Webpack 4
自首次發布以來,Next.js 一直由 webpack 提供支援,用於捆綁您的程式碼並重複使用豐富的插件和擴充功能生態系統。我們很高興宣布 Next.js 現在由最新的 webpack 4 提供支援,它帶來了許多改進和錯誤修復。
其中我們獲得了
- 支援
.mjs
原始碼檔案 - 程式碼分割改進
- 更佳的 tree-shaking(移除未使用程式碼)支援
另一個新功能是 WebAssembly 支援,Next.js 甚至可以伺服器端渲染 WebAssembly,這是一個 範例。
注意:此升級完全向後相容。但是,如果您透過 next.config.js 使用自訂 webpack 加載器或插件,您可能需要升級它們。
CSS 導入
透過 webpack 4,引入了一種從捆綁包中提取 CSS 的新方法,稱為 mini-extract-css-plugin。
@zeit/next-css
、 @zeit/next-less
、 @zeit/next-sass
和 @zeit/next-stylus
現在由 mini-extract-css-plugin
提供支援。
這些 Next.js 插件的新版本解決了 20 個與 CSS 導入相關的現有問題;例如,現在支援在動態 import()
中導入 CSS
import './my-dynamic-component.css';
export default function MyDynamicComponent() {
return <h1>My dynamic component</h1>;
}
import dynamic from 'next/dynamic'
const MyDynamicComponent = dynamic(import('../components/my-dynamic-component'))
export default function Index() {
return () {
<div>
<MyDynamicComponent/>
</div>
}
}
一個主要的改進是您不再需要在 pages/_document.js
中添加以下內容
<link rel="stylesheet" href="/_next/static/style.css" />
相反地,Next.js 會自動注入 CSS 檔案。在生產環境中,Next.js 也會自動將內容雜湊添加到 CSS URL,以便在發生變更時,確保您的終端使用者永遠不會取得過時的檔案版本,並能夠引入不可變的永久快取。
簡而言之,在您的 Next.js 專案中支援導入 .css
檔案,您只需在您的 next.config.js
中註冊 withCSS 插件即可
const withCSS = require('@zeit/next-css');
module.exports = withCSS({
/* my next config */
});
標準化的動態導入
自版本 3 以來,Next.js 就透過 next/dynamic
支援動態導入。
作為這項技術的早期採用者,我們必須編寫自己的解決方案來處理 import()
。
結果,Next.js 開始與 webpack 後來為其引入的支援產生分歧,並且缺少某些功能。
因此,Next.js 不支援 webpack 自那時以來引入的一些 import()
功能。
例如,手動命名和捆綁某些檔案在一起是不可能的
import(/* webpackChunkName: 'my-chunk' */ '../lib/my-library');
另一個例子是使用 import()
而不將其包裝在 next/dynamic
模組中。
從 Next.js 7 開始,我們不再修改預設的 import()
行為。這表示您可以立即獲得完整的 import()
支援。
此變更也完全向後相容。使用動態組件仍然像這樣簡單
import dynamic from 'next/dynamic';
const MyComponent = dynamic(import('../components/my-component'));
export default function Index() {
return (
<div>
<MyComponent />
</div>
);
}
此範例的作用是為 my-component
建立一個新的 JavaScript 檔案,並且僅在 <MyComponent />
渲染時才載入它。
最重要的是,如果它沒有被渲染,則 <script>
標籤不會包含在初始 HTML 文件載荷中。
為了進一步簡化我們的程式碼庫並利用出色的 React 生態系統,在 Next.js 7 中,next/dynamic
被重寫以在幕後使用 react-loadable
(進行了一些小的修改)。這也為動態組件引入了兩個很棒的新功能
- 使用
next/dynamic
上的timeout
選項設定逾時 - 載入組件延遲,使用
next/dynamic
上的delay
選項。此延遲允許您的載入組件在渲染載入狀態之前等待 x 時間,例如,如果導入速度非常快。
Babel 7
Next.js 6 在 Babel 7 仍處於 beta 階段時引入了它。從那時起,Babel 7 的穩定版本已經發布,而 Next.js 7 現在正在使用這個版本。
如需完整的變更列表,您可以參考 Babel 的 發行說明。
一些主要功能包括
- Typescript 支援,對於 Next.js,您可以使用
@zeit/next-typescript
- Fragment 語法
<>
支援 babel.config.js
支援overrides
屬性,用於僅將預設/插件應用於檔案或目錄的子集
如果您在您的 Next.js 專案中沒有自訂 Babel 設定,則不會有重大變更。
但是,如果您有自訂 Babel 設定,則必須將各自的自訂插件/預設升級到其最新版本。
如果您是從 Next.js 6 以下的版本升級,您可以執行出色的 babel-upgrade
工具。
除了升級到 Babel 7 之外,當 NODE_ENV
設定為 test
時,Next.js Babel 預設集 (next/babel
) 現在預設將 modules
選項設定為 commonjs
。
此設定選項通常是在 Next.js 專案中建立自訂 .babelrc
的唯一原因
{
"env": {
"development": {
"presets": ["next/babel"]
},
"production": {
"presets": ["next/babel"]
},
"test": {
"presets": [["next/babel", { "preset-env": { "modules": "commonjs" } }]]
}
}
}
使用 Next.js 7,這變成了
{
"presets": ["next/babel"]
}
此時,可以移除 .babelrc
,因為當沒有 Babel 設定時,Next.js 將自動使用 next/babel
。
更小的初始 HTML 載荷
由於 Next.js 預先渲染 HTML,它會將頁面包裝成預設結構,包含 <html>
、<head>
、<body>
和渲染頁面所需的 JavaScript 檔案。
此初始載荷先前約為 1.62kB。在 Next.js 7 中,我們最佳化了初始 HTML 載荷,現在為 1.5kB,減少了 7.4%,使您的頁面更精簡。
6.0 | 7.0 | 差異 | |
---|---|---|---|
文件大小(伺服器端渲染) | 1.62kb | 1.50kb | 7.4% 更小 |
我們縮小尺寸的主要方式是
- 移除了
__next-error
div - 內聯腳本已縮小,在未來的版本中,它們將被完全移除
- 當
__NEXT_DATA__
屬性未使用時,編譯移除未使用的屬性,例如nextExport
和assetPrefix
屬性。
靜態 CDN 支援
在 Next.js 5 中,我們引入了 assetPrefix
支援,這是一種讓 Next.js 自動從特定位置(通常是 CDN)載入資產的方法。如果您的 CDN 支援代理,此選項非常有效,您可以請求像這樣的 URL
https://cdn.example.com/_next/static/<buildid>/pages/index.js
通常,CDN 會檢查其快取中是否具有該檔案,否則會直接從來源請求。
代理資產正是 Edge Network 的運作方式。
但是,某些解決方案需要將目錄直接預先上傳到 CDN 中。這樣做的問題在於,Next.js 的 URL 結構與 .next
資料夾內的資料夾結構不符。例如我們之前的範例
https://cdn.example.com/_next/static/<buildid>/pages/index.js
// mapped to:
.next/page/index.js
在 Next.js 7 中,我們已更改 .next
的目錄結構以符合 URL 結構
https://cdn.example.com/_next/static/<buildid>/pages/index.js
// mapped to:
.next/static/<buildid>/pages/index.js
雖然我們確實建議使用代理類型的 CDN,但這種新結構允許不同類型的 CDN 使用者將 .next
目錄上傳到他們的 CDN。
Styled JSX v3
我們很高興推出 styled-jsx 3,Next.js 中預設包含的 CSS-in-JS 解決方案現在已為 React Suspense 做好準備。
經常不清楚的一件事是如何在子組件不屬於當前組件範圍的情況下,為子組件設定樣式,例如,如果您包含一個子組件,該子組件僅在父組件內部使用時才需要特定的樣式
const ChildComponent = () => (
<div>
<p>some text</p>
</div>
);
export default function Index() {
return (
<div>
<ChildComponent />
<style jsx>{`
p {
color: black;
}
`}</style>
</div>
);
}
上面的程式碼嘗試選取 p
標籤不起作用,因為 styled-jsx 樣式的作用範圍限定於目前組件,它們不會洩漏到子組件中。一種解決方法是使用 :global
方法,從 p
標籤中移除前綴。但是,這引入了一個新問題,即樣式確實會洩漏到整個頁面。
在 styled-jsx 3 中,此問題已透過引入新的 API css.resolve
解決,它將為給定的 styled-jsx 字串產生 className
和 <style>
標籤(styles
屬性)
import css from 'styled-jsx/css';
const ChildComponent = ({ className }) => (
<div>
<p className={className}>some text</p>
</div>
);
const { className, styles } = css.resolve`
p {
color: black;
}
`;
export default function Index() {
return (
<div>
<ChildComponent className={className} />
{styles}
</div>
);
}
這個新的 API 允許透明地將自訂樣式傳遞到子組件。
由於這是 styled-jsx 的主要版本,因此有一個重大變更,如果您正在使用 styles-jsx/css
,它可以改善捆綁包大小。在 styled-jsx 2 中,我們會產生外部樣式的「scoped」和「global」版本,即使僅使用「scoped」版本,我們仍然會包含這些外部樣式的「global」版本。
在 styled-jsx 3 中,全域樣式必須使用 css.global
而不是 css
標記,以便 styled-jsx 可以最佳化捆綁包大小。
如需所有變更,請參考 發行說明。
App 和 Pages 之間使用 React Context 進行 SSR
從 Next.js 7 開始,我們現在支援 pages/_app.js
和頁面組件之間的新 React context API。
以前在伺服器端頁面之間無法使用 React context。原因在於 webpack 保留了內部模組快取,而不是使用 require.cache
,我們編寫了一個自訂 webpack 插件來變更此行為,以便在頁面之間共享模組實例。
這樣做不僅允許使用新的 React context,還可以減少在頁面之間共享程式碼時 Next.js 的記憶體佔用量。
6.0 | 7.0 | 差異 | |
---|---|---|---|
記憶體使用量 | 57.5MB | 48.1MB | -16% 記憶體 |
nextjs.org
隨著 Next.js 7 的發布,我們也推出了完全重新設計的 nextjs.org。
部落格
您目前正在閱讀的部落格文章已經是 nextjs.org 上新部落格區塊的一部分。這個部落格將成為與 Next.js 相關的溝通新家,例如,新版本公告。

獲取靈感
隨著使用 Next.js 的應用程式數量持續增長,我們需要一種方式在一個概覽中展示所有這些精美的應用程式。歡迎來到全新的 /showcase
頁面

這個新的範例展示允許我們持續新增使用 Next.js 建置的新應用程式。
我們邀請您訪問 /showcase
以獲取靈感,或提交您使用 Next.js 建置的應用程式!
社群
自首次發布以來,Next.js 已被應用於從財富 500 強公司到個人部落格的各種領域。我們非常高興看到 Next.js 的採用率不斷成長。
- 目前,有超過 12,500 個公開索引的網域正在使用 Next.js。
- 我們有超過 500 位貢獻者至少提交過 1 次 commit。
- 在 GitHub 上,該專案已被標註星號超過 29,000 次。
- 自首次發布以來,已提交近 2200 個 pull request。
Next.js 社群擁有近 2000 名成員。 加入我們!