Nuxt.js

(一)

基於 Vue 的 Server side render framework

unversinal

目錄

  • 什麼是 SSR?

  • 為什麼選擇使用 Nuxt?

  • Nuxt 如何讓一切變方便?

  • Nuxt 的近況

  • Q&A

什麼是 Server Side Render?

簡稱 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 ...

傳統 SSR

or PHP, Java ...

傳統 SSR

請求

後端

資料庫

拿資料

吐資料

HTML

傳統 SSR

每次點擊換頁時,都需要重新拿重新執行 HTML, JavaScript, CSS (沒快取)

模板語言限制了靈活性

前端越來越複雜、互動越來越多需要 Reactive 機制,也會希望互動跟 View 綁在一起

SPA

請求

後端

JavaScript

解析

請求

吐資料

API

SPA

First Content Paint 比較慢 (aka. FCP, 首次渲染內容, 首屏渲染)

不好的 SEO,因為 JavaScript 產生 HTML

白畫面易閃爍

SPA

puppeteer

prerender-spa-plugin

簡化版

寫死

所以 SSR 誕生了

請求

Node.js

Nuxt

API

請求

吐資料

HTML JavaScript

Hydration

吐資料

請求

SSR

Hydration

幫 HTML 加上 Event Listener (SSR 省略) 跟 執行生命週期 (useEffect ...)

Server render 好了,Client 不需要在 Render 一次

同時也會檢查 Server 跟 Client render 的結果是不是一樣,否則噴 Mismatch 警告

SSR

你可以自己來 SSR

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/,
      },
    ],
  },
};

Next.js 或 Nuxt.js 都幫你做好了

除了做好 SSR 之外 還有 ...

為什麼會選擇使用 Nuxt ?

快速搭建

學習曲線

大量動態頁面的 SEO 問題

想讓一切變得方便

就是懶

Nuxt 如何讓一切變方便?

Cli & DOcument

該裝的都裝好,也能自己設定

Vue-router

Vue-meta

(next-head, react-helmet)

Vuex

(Redux)

Vue 本身內建 Transition

(React-transition-group)

Babel

Webpack 最佳化設定

HMR, bundle analyzer...

Loaders

ES Lint

PostCSS

沒有你要的還有 PLUGINS 跟 MODULES,或是你自己包

Page transition

Loading indicator

...

你的資料夾結構就是你的

Route(NEXT.JS) and Store and more ...

/

/about

/contact

/:id/profile

/:id/setting

form store

user/... store

Components and Plugins

SSR 與 效能

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 的近況

Nuxt 的近況

Nuxt 3.0 準備出了 (with Vue 3.0)

有 Composition API plugin

Service worker rendering with SSR

Q & A

Nuxt.js

By Steven Ho

Nuxt.js

  • 432