什麼是 SSR?
為什麼選擇使用 Nuxt?
Nuxt 如何讓一切變方便?
Nuxt 的近況
Q&A
簡稱 SSR
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>EJS template</title>
</head>
<body>
<h1><%= title %></h1>
<%- category %>
<ul>
<% for(var i=0; i < characters.length; i++) { %>
<li><%= characters[i] %></li>
<% } %>
</ul>
</body>
</html>
ejs pug erb thymeleaf ...
or PHP, Java ...
請求
後端
資料庫
拿資料
吐資料
HTML
每次點擊換頁時,都需要重新拿重新執行 HTML, JavaScript, CSS (沒快取)
模板語言限制了靈活性
前端越來越複雜、互動越來越多需要 Reactive 機制,也會希望互動跟 View 綁在一起
請求
後端
JavaScript
解析
請求
吐資料
API
First Content Paint 比較慢 (aka. FCP, 首次渲染內容, 首屏渲染)
不好的 SEO,因為 JavaScript 產生 HTML
白畫面易閃爍
請求
Node.js
Nuxt
API
請求
吐資料
HTML JavaScript
Hydration
吐資料
請求
幫 HTML 加上 Event Listener (SSR 省略) 跟 執行生命週期 (useEffect ...)
Server render 好了,Client 不需要在 Render 一次
同時也會檢查 Server 跟 Client render 的結果是不是一樣,否則噴 Mismatch 警告
import express from "express";
import React from "react";
import { renderToString } from "react-dom/server";
import App from "./client/App";
const app = express();
app.use(express.static("public"));
app.get("/", (req, res) => {
const content = renderToString(<App />);
const html = `
<html>
<head></head>
<body>
<div id="root">${content}</div>
<script src="bundle.js"></script>
</body>
</html>
`;
res.send(html);
});
app.listen(3000, () => {
console.log("listening on port 3000");
});
const path = require("path");
const webpackNodeExternals = require("webpack-node-externals");
module.exports = {
target: "node",
entry: "./src/index.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "build"),
},
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/,
},
],
},
externals: [webpackNodeExternals()]
};
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
ReactDOM.hydrate(<App />, document.getElementById("root"));
const path = require("path");
module.exports = {
target: "node",
entry: "./src/client/client.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "public"),
},
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/,
},
],
},
};
Vue-router
Vue-meta
(next-head, react-helmet)
Vuex
(Redux)
Vue 本身內建 Transition
(React-transition-group)
Babel
Webpack 最佳化設定
HMR, bundle analyzer...
Loaders
ES Lint
PostCSS
Page transition
Loading indicator
...
/
/about
/contact
/:id/profile
/:id/setting
form store
user/... store
Modern mode (ESModule)
Smart prefetching
http2 push, Gzip (or use nginx)
Code splitting
Critical CSS per route
SEO
First Content Paint
(FCP, 首次繪製內容, 首屏渲染)
較少的閃爍
(Middleware, 和不用等待 Js)
有 SSR 可以做很多後端在做的事
(Image compressor, base auth, error page, or 再包一層 API, Proxy)
SSR 第一次只需要一次請求
就算你不要 SSR 也可以關掉當 SPA 來用
或是 Build Static 的頁面
如果是 SSR 的話你的 Server 當然要一直開著
很大的機率會遇到 Memory Leaks 的問題
有些套件、Plugins 不支援 SSR (好解決)
不習慣 SSR 的你會一直炸
Dev or Build 會有點慢 (包兩份或三份 modern ...)
Library 和 Framework
Nuxt 3.0 準備出了 (with Vue 3.0)
有 Composition API plugin
Service worker rendering with SSR