使用 Vue 和 Gridsome 構建靜態站點

語言: CN / TW / HK

靜態站點介紹

靜態網站生成器所做的事情也就是傳統開發中所謂的「靜態化渲染」,經常出現在一些 CMS 系統中。

它是預渲染的,但是和服務端渲染有所不同。具體差異可以看這篇文章,靜態化與服務端渲染

靜態網站不需要服務端支援,只需要將靜態生成的檔案放到任意的檔案託管伺服器或者 CND 上即可。比如GitHub Pages 和阿里雲 OSS 等。

靜態網站的優點總結為:省錢、快速、安全

省錢是值不需要完整的伺服器,只需要檔案託管服務求或者 CND,這類雲服務的價格通常來說很便宜。

快速是指不需要呼叫後端 API 介面,也不需要服務端渲染時的資料填充和類似 MVVM 的客戶端渲染,瀏覽器拿到的就是可以直接使用的 HTML、CSS 和 JavaScript。

安全是指沒有後端服務的支援,理論上也就沒有任何漏洞,網站上的任何連結都是靜態內容。

常見的靜態網站生成器有很多,比如 Ruby 的 Jekyll、Node 的 Hexo、Golang 的 Hugo、React 的 Gatsby、Vue 的 Gridsome 等等。

靜態網站還有一個別名,叫做 JAMStack。JAM分別是 JavaScript、Api、Markup 的首字母組合。

靜態化本質上是一種胖前端。它也是前後端的模式,只不過在生成靜態網站後,前後端就不再有聯絡了。

在靜態網站生成時,提供資料的後端可以來自多個服務,比如 RESTFul API、GraphQL、JSON 檔案、無頭 CMS 等等。

在靜態網站執行時,靜態網站需要的一些功能比如登陸、閱讀量、收藏、點贊、評論等等可以來自不同的服務廠商,而不需要自己開發。除了使用專業服務外,另一種比較流行的方案是使用 serverless 自行開發,以此實現更高的客製化功能,比如騰訊雲的雲函式和阿里雲的函式計算。

靜態化的適用場景通常是純內容、弱互動的網站。如果網站有大量動態內容,就不適合使用靜態化渲染了。它在本質解決的問題就是提供極致的閱讀體驗

靜態站點框架 Gridsome 基礎教程

Gridsome 是一個免費開源,基於 Vue.js 技術棧的靜態網站生成器。使用 Gridsome 需要有一定的 Vue 基礎和 GraphQL 基礎。

安裝、建立、啟動 gridsome 專案

首先全域性安裝 gridsome 的命令列工具。

npm install --global @gridsome/cli
複製程式碼

然後使用 gridsome create <application-name> 命令建立專案。

gridsome create my-gridsome-site
複製程式碼

最後進入專案目錄下,使用 npm run develop 或 gridsome develop 啟動開發伺服器。

cd my-gridsome-site && gridsome develop
複製程式碼

gridsome 啟動成功後會提示 3 個地址。

Site running at:
- Local:                 http://localhost:8080/
- Network:               http://192.168.1.131:8080/

Explore GraphQL data at: http://localhost:8080/___explore
複製程式碼

第一個是本地地址。

第二個是公網IP地址。

第三個是管理 GraphQL 資料的控制檯地址。

預渲染

路由規則

開啟專案,可以在 src/pages 目錄下看到 Index.vue 和 About.vue 檔案,這兩個檔案對應的就是頁面中的 Home 頁面和 About 頁面。

在 girdsome 中,pages 目錄下的每個 vue 檔案都對應一個路由。

現在來新增第一個頁面。

// src/pages FirstPage.vue
<template>
  <div>hello,my first page</div>
</template>

<script>
export default {
  name: "first-page",
};
</script>
複製程式碼

然後訪問 http://localhost:8080/first-page,就可以看到對應的內容了。

編譯專案

接下來我們將專案編譯為靜態內容。執行下面的命令。

gridsome build
複製程式碼

gridsome 會在專案中建立 dist 目錄,其中儲存了所有的網頁。每一個 vue 檔案都會被渲染為純 HTML 檔案。這些檔案都不會進行客戶端渲染,而是由瀏覽器直接呈現。也不會有 vue 執行時等 JavaScript 資源。所以可以做到極致的訪問速度。

部署專案

現在將 dist 目錄部署到任意伺服器中即可。

下面使用 npm 的 serve 模組啟動專案。

全域性安裝 serve。

npm i serve -g
複製程式碼

啟動專案。

serve dist
複製程式碼

目錄結構

src

layouts 目錄中存放了全域性的佈局元件,在 main.js 中註冊了 Layout 元件。用於設定頁面的通用樣式佈局。

像一些全域性的樣式檔案或者全域性元件,都可以在 main.js 中引入。

pages 目錄存放了與路由相對應的 vue 檔案。

components 目錄存放公共元件。

templates 目錄中存放了 GraphQL Collection 的模板。

.temp 目錄是 gridsome 在執行中生成的臨時檔案。

.cache

存放了快取檔案。

static

存放靜態檔案,一些不需要編譯的檔案,比如圖片、字型等資源。

girdsome.config.js 和 gridsome.server.js

分別是客戶端和服務端的配置檔案,用於配置外掛、設定站點全域性資訊、或者注入資料等等。

配置檔案修改後需要重啟開發伺服器才可以生效。

Pages 頁面

gridsome 支援兩種建立頁面的方式。一種是基於檔案的方式,一種是程式設計的方式。

基於檔案的方式

按照規則直接在 pages 目錄下建立 vue 檔案就可以生成頁面。它有一些預設規則。

  1. Index.vue 表示跟路徑 /
  2. 駝峰命名法會轉換為中橫線命名法。比如 AboutUs.vue 生成 about-us
  3. 巢狀檔案生成巢狀路由。比如 /about/vision 生成 about/vision
  4. 預設尋找 Index.vue。比如 src/pages/blog/Index.vue 生成 /blog/

程式設計的方式

在 girdsome.server.js 檔案中預設匯出方法中進行配置。

module.exports = function (api) {
  api.createPage(({ createPage}) => {
  	createPage({
    	path: "/my-page",
      component: "./src/templates/MyPage.vue"
    })
  })
}
複製程式碼

動態路由

gridsome 支援動態路由,使用中括號包裹路由引數。

src/pages/user/[id].vue 生成 user/:id。

src/pages/user/[id]/settings.vue 生成 user/:id/settings。

無論是基於檔案還是程式設計的方式,都支援動態路由。

頁面 Meta 資訊

gridsome 支援給每個頁面設定不同的 meta 資訊。在預設匯出的物件中新增 metaInfo 屬性,就可以生成 meta 資訊。

export default {
  name: "first-page",
  metaInfo: {
    title: "Hello,World!",
    meta: [{ name: "authro", content: "John Doe" }],
  },
};
複製程式碼

自定義 404 頁面

gridsome 提供了一個預設的 404 頁面。

如果需要自定義 404 頁面,可以建立 src/pages/404.vue 檔案。這個檔案可以取代預設的 404 頁面。

Collections 集合

一個頁面可以通過呼叫介面來獲取資料動態填充頁面。呼叫介面獲取資料填充頁面這個步驟可以放到客戶端也可以放到服務端。

如果放到服務端,需要使用 gridsome 的 collections。

在 gridsome 的動態資料生成動態頁面的設計中,有 Data Sources、Collections 和 Nodes 三個概念。

Data Sources 是指資料來源,可以來自任意形式的 API 介面,比如 WordPress、JSON 或者 Markdown 等等。

Collections 是 girdsome 將資料來源轉換後的結果。

Nodes 是 collections 對應的節點,每一個 node 都會生成一個頁面。

新增 Collections

建立 collections 有兩種方式,第一種是使用外掛的形式(source plugins),在 gridsome.config.js 中進行配置。第二種是使用程式碼呼叫介面的方式(Data Store API),在 gridsome.server.js 進行呼叫。

有一個開源的專案 jsonplaceholder。它是基於 JSON Server 和 LowDB 建立的,可以為我們提供免費的 Mock RESTful API 服務用於測試。

安裝用於請求的 axios 模組。

npm i axios
複製程式碼

修改 gridsome.server.js 中的 loadSource 方法,去呼叫 jsonplaceholder 的 posts 載入資料。posts 介面提供了一百條 post 資料。

// gridsome.server.js
// ...
api.loadSource(async ({ addCollection }) => {
  const collection = addCollection('Post')

  const { data } = await axios.get('http://jsonplaceholder.typicode.com/posts')

  for (const item of data) {
    collection.addNode({
      id: item.id,
      title: item.title,
      content: item.content
    })
  }
})
複製程式碼

查詢 Collections

修改全域性的配置需要重新啟動服務,重新啟動後可以進入 http://localhost:8080/___explore,這是 GraphQL 的控制檯。

在控制檯右側有 DECS,其中包含了剛剛新增的 psot 和 allPost。

image.png

在左側編輯 GraphQL 查詢語句,點選執行,就可以從右側的資料預覽欄中看到查詢結果。

比如查詢 id 為 10 的文章資料。

query {
  post(id: 10) {
    id
    title
    content
  }
}
複製程式碼

使用分頁查詢前 10 條資料以及總條數。

query {
  allPost(skip: 0, limit: 10, order: ASC) {
    totalCount
    edges {
      node {
        id
        title
        content
      }
    }
  }
}

複製程式碼

在頁面和模板中獲取 GraphQL 資料

使用 page-query 標籤。page-query 和 template 標籤是平級的。page-query 中直接編寫 GraphQL 查詢語句,可以設定變數。查詢結果預設存入 $page 變數中。

<template>
  <div>
    <h1 v-html="$page.post.title" />
    <div v-html="$page.post.content" />
  </div>
</template>

<page-query>
query ($id: ID!) {
  post(id: $id) {
    title
    content
  }
}
</page-query>
複製程式碼

在元件中獲取 GraphQL 資料

使用 static-query 標籤,用法與 page-query 類似。查詢結果放入 $static 中。

<template>
  <div v-html="$static.post.content" />
</template>

<static-query>
query {
  post (id: "1") {
    content
  }
}
</static-query>
複製程式碼

Templates 模板

模板專門用於渲染 nodes。建立 template 需要兩步。

首先在 src/templates 中建立模板元件。

<template>
  <div>
    <h1 v-html="$page.post.title" />
    <div v-html="$page.post.content" />
  </div>
</template>

<page-query>
query ($id: ID!) {
  post(id: $id) {
    title
    content
  }
}
</page-query>
複製程式碼

之後在 gridsome.config.js 中配置路由和模板元件。

module.exports = {
  templates: {
    Post: [
      {
        path: '/post/:id',
        component: './src/templates/Post.vue'
      }
    ]
  }
}
複製程式碼

如果想在 metaInfo 中獲取 GraphQL 中的資料,可以將 mateInfo 設定為函式。

metaInfo() {
  return {
    title: this.$page.post.title,
  };
}
複製程式碼

以上就是 Gridsome 基礎教程的全部內容。