next 服務端渲染
實際上,next 一直都是執行的服務端渲染.npm start
執行的是 next 自帶的服務器來運行你的應用.next 是支持自定義服務器的,同時能夠支持現有的路由和模式,你可以在此基礎上添加一些自己的需求.
新建/server.js
const express = require("express");
const next = require("next");
const dev = process.env.NODE_ENV !== "production"; //判斷是否開發環境
const app = next({ dev }); //創建一個next的app
const handle = app.getRequestHandler(); //請求處理
app
.prepare()
.then(() => {
const server = express();
//用來進行簡化路徑匹配
server.get("/b/:currentBookId", (req, res) => {
const actualPage = "/book/[currentBookId]";
const queryParams = { currentBookId: req.params.currentBookId };
app.render(req, res, actualPage, queryParams);
});
server.get("*", (req, res) => {
return handle(req, res);
});
server.listen(6776, err => {
if (err) throw err;
console.log("> Ready on http://localhost:6776");
});
})
.catch(ex => {
console.error(ex.stack);
process.exit(1);
});
其中 app 有 next(opts: object)創建而來
- dev(bool)是否在開發模式下啟動 Next.js-默認 false
- dir(string)項目所在的位置-默認'.'
- quiet(bool)隱藏包含服務器信息的錯誤消息-默認 false
- conf(object)與您要使用的對象相同 next.config.js-默認{}
同時修改 package.json 中的配置
"server:dev": "node server.js",
"server:start": "NODE_ENV=production node server.js",
解決使用路由隱藏 as 會 404 的問題
例如
<Link href={`/book/${item.id}`} as={`/b/${item.id}`}>
然后在npm run dev
的情況下,我們使用 next 默認的服務器.頁面在使用 as 的時候起了一個縮寫路徑名稱,這種情況在第一次進入是正常匹配的,但是刷新就會 404,原因在於服務器目前並不清楚 b 代表的是什么路徑.
而在 server.js 中就添加了關於 b 的縮寫匹配
//用來進行簡化路徑匹配
server.get("/b/:currentBookId", (req, res) => {
const actualPage = "/book/[currentBookId]";
const queryParams = { currentBookId: req.params.currentBookId };
app.render(req, res, actualPage, queryParams);
});
此時我們npm run server:dev
開啟自定義服務器,打開頁面進入縮寫路徑,我們刷新發現頁面會保留.
之后
npm run dev
命令可以拋棄了
多路徑頁面
next 默認會將 pages 下的 js 文件創建出對應的路徑.我們起了路由別名,並且通過自定義路由讓路由的別名生效.但是我們再次輸入 book/[currentBookId],發現依舊可以匹配到同樣的頁面,造成一個頁面擁有的 2 個及以上的路徑.這可能會導致 SEO 和 UX 問題
我們通過設置 useFileSystemPublicRoutes 來禁用默認路由
// next.config.js
module.exports = {
useFileSystemPublicRoutes: false,
}
重啟打開網站,book/[currentBookId]就會直接 404 了.
useFileSystemPublicRoutes 禁用來自 SSR 的文件名路由.客戶端路由仍然可以訪問這些路徑,需要攔截 popstate來配置客戶端也禁用.
動態 assetPrefix
有時候我們需要動態路由,比如根據基於請求更改 assetPrefix,這時候我們需要使用 app.setAssetPrefix
server.get("*", (req, res) => {
if (req.headers.host === "my-app.com") {
app.setAssetPrefix("http://cdn.com/myapp");
} else {
app.setAssetPrefix("");
}
return handle(req, res);
});
禁用 X-Powered-By
Next.js 將添加 x-powered-by 到請求標頭中。這個是由語言解析器或者應用程序框架輸出的。這個值的意義用於告知網站是用何種語言或框架編寫的。
直接禁用它
// next.config.js
module.exports = {
poweredByHeader: false,
}