2018 年 2 月 5 日 星期一
Next.js 5:通用 Webpack、CSS 導入、外掛程式與區域
作者:我們非常高興向全世界介紹 Next.js 5.0。它已立即在 npm 上提供。若要升級,請執行
npm i next@latest react@latest react-dom@latest
除了升級 Next.js 之外,我們也升級了對等相依性
react
和react-dom
Next.js 是一個用於通用、伺服器端渲染(或靜態預先渲染)React.js 應用程式的工具組。開始開發任何規模的應用程式都非常容易,只需執行 next
即可。(閱讀更多。)
每次發布新版本時,我們都致力於保留向後相容性、提供簡單的升級路徑,並且僅在絕對必要時才進行 API 變更。Next.js 5.0 也不例外。
然而,在底層,Next.js 經歷了徹底的轉型,以實現強大的新用例和可擴展性。我們首先讓 Next.js 為伺服器和用戶端程式碼共享通用的 Webpack 管線。
通用 Webpack 和 Next 外掛程式
Next.js 利用現有的強大工具,如 Webpack、Babel 和 Uglify,以非常簡單的介面呈現給終端使用者:next
(用於開發)、next build
(用於準備生產環境)和 next start
(用於伺服)或 next export
(用於預先渲染為靜態檔案)。
我們早期做出的決定之一是為這些工具的配置方式提供非常強大的擴展點。我們不僅僅想要易於使用,還希望能夠靈活地擴展工具組,無論您想要如何擴展。
例如,您可以透過在您的 next.config.js
中設定 webpack
屬性來擴展 Next.js webpack 配置。
由於 webpack 在生產環境和開發環境中的執行方式不同,我們當時決定將其設為一個函數,用於裝飾我們的預設 webpack 配置
module.exports = {
webpack(config, { dev }) {
// modify it!
return config;
},
};
可選的
next.config.js
檔案範例
然而,Webpack 只會在用戶端(瀏覽器)套件上執行,您將錯過在伺服器端渲染中使用這個出色工具鏈的可能性。
我們很高興地宣布,我們已經廣泛地重構了我們的程式碼庫,以使 Webpack 通用地工作。
從您的角度來看,所有變更都只是一個額外的 isServer
屬性被傳遞到上面的裝飾器函數。然而,新的語義意味著廣泛的 Webpack 加載器生態系統現在可供您使用。
CSS、LESS、SASS、SCSS 和 CSS Modules
我們最受歡迎的功能之一是能夠導入 CSS 檔案並利用 Webpack 加載器
import './index.css';
export default function Index() {
return (
<div>
<p>I love CSS!</p>
</div>
);
}
一個使用 CSS 導入的範例頁面(
pages/index.js
),這要歸功於通用 Webpack
為了使這個功能正常運作,您可以將您需要的加載器作為對等相依性引入
npm i --save css-loader style-loader postcss-loader
Next.js 讓您可以自由選擇您需要的加載器,並隨意將它們升級到不同的版本。
然後擴展配置以配置您的加載器。在 next.config.js
中
module.exports = {
webpack(config, options) {
const { dev, isServer } = options;
const extractCSSPlugin = new ExtractTextPlugin({
filename: 'static/style.css',
disable: dev,
});
config.module.rules.push({
test: /\\.css$/,
use: cssLoaderConfig(extractCSSPlugin, {
cssModules,
dev,
isServer,
}),
});
return config;
},
};
擴展原始 webpack 配置為您提供了極大的靈活性和控制權
雖然我們的一般建議是使用組件本地樣式解決方案,例如包含的 styled-jsx
babel 外掛程式,但我們相信 CSS 加載器具有許多重要的優勢,例如使重用現有的 CSS 程式碼庫變得容易,並大大簡化將舊程式碼庫遷移到 Next.js 的過程。
我們沒有預設啟用所有可以想像到的功能和加載器,而是推出了Next.js 外掛程式,它們是裝飾您的配置的簡單函數。您只需執行以下操作,而無需像我們上面那樣手動擴展配置來設定加載器
const withCss = require('next-css');
module.exports = withCss({
/* extra optional config */
});
啟用導入
.css
檔案只需引入next-css
閱讀更多關於 CSS 加載器 與 Next.JS 的用法,或參考我們已經為您建立的一些套件
我們的目標是授權社群開發和發展實用、簡單擴展的生態系統。為此,我們正在開放 next-plugins monorepo,供 Next.js 社群維護。歡迎所有 PR!
TypeScript 支援
TypeScript 是 JavaScript 生態系統中成長最快速的技術之一。以至於它正成為 Babel 7 正式支援的技術,這意味著 Next.js 自然會支援它,只需自訂您的 .babelrc 即可。
同時,感謝我們新的通用 Webpack 支援,您今天已經可以獲得完整的 TypeScript 支援了!
您可以像這樣擴展您的 webpack 配置
module.exports = {
webpack(config, options) {
const { dir, defaultLoaders } = options;
config.resolve.extensions.push('.ts', '.tsx');
config.module.rules.push({
test: /\\.+(ts|tsx)$/,
include: [dir],
exclude: /node_modules/,
use: [
defaultLoaders.babel,
{ loader: 'ts-loader', options: { transpileOnly: true } },
],
});
return config;
},
};
我們只需啟用
ts-loader
即可
與 CSS 加載器和預處理器一樣,TypeScript 一直是最受歡迎的功能之一。為了使其像其他任何加載器一樣容易地整合到專案中,我們現在有一個 next-typescript
外掛程式,您可以將其包含在您的 next.config.js
檔案中
const withTs = require('next-typescript');
module.exports = withTs({
/* additional config*/
});
外掛程式可以很容易地組合:它們只是函數
對 React Altlibs 和模組覆載更好的支援
隨著時間的推移,出現了許多 React 的替代實作方案。其中,一些值得注意的包括 [preact
](https://preact.dev.org.tw/)、nervjs
和 inferno
。
其他程式庫專注於取代 DOM 渲染器,例如 react-dom-lite
,其目標是透過在瀏覽器相容性方面做出一些小的權衡,來製作更小的 React 建置版本。
通用 Webpack 支援使整合這些程式庫作為替代方案變得更加容易。與其他外掛程式一樣,這就是您將 Next.js 與 preact 結合使用所需做的一切
npm i @zeit/next-preact preact preact-compat
我們安裝 preact 外掛程式和必要的對等相依性
const withPreact = require('@zeit/next-preact');
module.exports = withPreact();
我們新的
next.config.js
已準備好用於 preact
查看非常簡單的 @zeit/next-preact 模組或建立您自己的模組!
生產環境中可選的外部 Sourcemaps
既然 Next.js 的用戶端和伺服器程式碼都使用 webpack,那麼在生產環境建置中啟用 source-maps 只是對其配置進行一個小的調整。
在開發環境中,source map 會自動啟用,因此我們針對生產環境進行不同的配置
module.exports = {
webpack(config, { dev }) {
if (!dev) {
config.devtool = 'source-map';
}
return config;
},
};
當不在開發環境中時,我們只需以不同的方式配置
devtool
選項
區域
從一開始,Next.js 的既定目標之一 就是恢復並保留 Web 的簡潔性。
伺服器端渲染、一種簡單且與技術無關的資料獲取方法,以及基於檔案系統結構的宣告式頁面,是我們根據這種想法引入的一些功能。
Web 服務和網站經常被忽略的一個方面是它們的自然可組合性和可擴展性。
例如,mydomain.com/settings
和 mydomain.com/
可能是兩個完全不同的應用程式,它們可以獨立部署、獨立擴展,甚至可以執行相同軟體的不同版本。
將它們「黏合在一起」,為終端使用者提供一致的體驗,只需對後端路由層或負載平衡器進行一些簡單的配置,即可將它們暴露給世界。我們非常高興現在能夠帶來組合多個使用 Next.js 建置的應用程式的能力,這些應用程式使用普通的 <Link>
組件連接在一起。我們將此功能稱為 區域。
例如,考慮這兩個獨立的 Next.js 應用程式,它們部署到 Vercel
- https://front.vercel.app
- https://zeit-docs-zbqbsrucga.vercel.app/docs https://zeit-docs-zbqbsrucga.vercel.app/api

當我們改版我們的文件時,我們希望盡可能簡化接受社群貢獻的流程。
我們決定將文件「迷你網站」拆分到其自己的儲存庫中。此外,每當提交 pull request 並提出變更時,我們都會自動隔離部署它

我們最終得到的是兩個區域,它們使用我們的路徑別名功能,被整合到父網域 https://vercel.com
中。它看起來像這樣
{
"rules": [
{ "pathname": "/docs", "dest": "our-docs.vercel.app" },
{ "pathname": "/api", "dest": "our-docs.vercel.app" },
{ "dest": "my-main-website.vercel.app" }
]
}
這些簡單的規則允許您將微服務和區域組合在一起
剩下的就是調用 now alias
命令
now alias -r rules.json my-domain.com
我們的使命是使部署盡可能通用和開放。為了協助本地開發,我們最近開源了 micro-proxy
,這是一個與上面看到的相同配置格式一起使用的工具。
您也可以使用其他解決方案(如 Nginx、HAProxy 或 API Gateway)將區域連接在一起。
更快的生產環境建置時間
我們認為開發人員體驗和使用者體驗是息息相關的。可以更有效率地編寫、測試和部署變更,添加新功能、修正錯誤和改善整體使用者體驗的速度就越快。
因此,我們仍然專注於持續迭代系統最基本構建模組的效能設定檔。
使用 Next.js 5.0,我們有機會再次查看 next build
,這是您在部署到生產環境或將您的 Next.js 應用程式匯出為靜態網站之前執行的命令。
我們很高興地報告,對於 vercel.com(一個由數千個組件組成的 React 應用程式),我們在 Next.js 5.0 中看到了非常顯著的改進,生產環境建置時間縮短了 23.6%

改進動態導入的快取
每當您使用動態 import()
時,這會向 WebPack 發出訊號,表示存在新的程式碼拆分進入點。
在建置時,這意味著為模組的相應子樹產生特定的套件。
在 Next.js 5.0 之前,動態套件會收到類似於以下的 URL
/_next/1517592683901/webpack/chunks/components_hello1_1345d10fc951cd6717c5676c467579a6.js
現在,我們已將動態導入轉換為子樹內容的內容可尋址雜湊值
/_next/webpack/chunks/components_hello1_1345d10fc951cd6717c5676c467579a6-b7874680a9e21fb6eb89.js
這意味著在跨部署中,您的使用者和客戶將不必不必要地重新下載他們已經使用過的程式碼。
片段
Next.js 建置了一個頂層 <Document>
組件,該組件與每個頁面一起進行伺服器端渲染。覆載此組件 使您可以完全控制您的標記,從而啟用許多進階用例。
初始標記的一部分是 Next.js 需要在用戶端評估的腳本列表。自訂 _document
看起來像這樣
import Document, { Head, Main, NextScript } from 'next/document';
export default class extends Document {
render() {
return (
<html>
<Head />
<body>
<Main />
<NextScript />
</body>
</html>
);
}
}
Document
允許您自訂頁面的整個伺服器端渲染輸出
直到最近,我們還被迫將腳本包裝在 <div>
內。
使用 Next.js 5.0,我們現在利用了新的 Fragment
支援,這轉化為更輕量的頁面,並完全控制頁面的樣式,而沒有多餘的標記。
更準確的錯誤訊息
Node.js 不支援 source map,伺服器端發生的錯誤會附帶指向已編譯程式碼的堆疊追蹤。
使用 Next 5,我們改進了伺服器端的 source map 支援。現在,伺服器端渲染時發生的錯誤會指向正確的函數和行號。

結論
通用 Webpack 強化了 Next.js 的基礎,使其更具前瞻性。總體而言,不再有人為區分哪些外掛程式或載入器適用於 Next.js,哪些不適用。
本著零配置的精神,我們很高興推出 Next Plugins,這是一個社群儲存庫,提供自動擴展 Next.js 功能的配方,無需調整特定設定。
有了這個,我們現在支援完整的 CSS 解決方案、編譯成 JavaScript 的語言(如 TypeScript)以及 React 的替代方案(如 Nerve),只需引入一個額外模組並在 next.config.js
中明確包含它即可。簡潔而不隱晦。
Zones 允許互連非根植於相同儲存庫甚至伺服器的 Next.js 應用程式。我們認為這是「團隊擴展性」類別改進中一個非常重要的里程碑。
因此,Next.js 成為由多個團隊維護的大型應用程式的絕佳候選者。他們現在可以同時部署改進,減少錯誤面,提高迭代速度,甚至可以嘗試除核心技術之外的不同技術,例如狀態管理或資料fetch的許多不同方法。
我們想藉此機會感謝 Deep Varma 和 Trulia 工程團隊,他們貢獻了關鍵的見解、程式碼和測試,促成了此功能的設計。
一如既往,沒有眾多開源貢獻者和我們出色的社群,這次發布是不可能實現的。