vue3-SPA sample

紀錄一下使用 vite.js 建立 vue3 練習專案的步驟

基礎語法及使用請參閱其他教學資源,此處僅簡單紀錄提示一些我覺得較為重要、容易忘記或者是方便複製貼上使用的部分,相對的 vue3 的練習主要放在專案內的 aboutmonsterteams這三個路由,練習範例是依照udemy課程下去改的,有興趣了解課程也可以參考一下我的文章學習紀錄-Vue - The Complete Guide (incl. Router & Composition API) (只是到今天我還沒看完就是了,但目前為止的感想是適合初學者,有中文字幕,買了不虧)

  1. vite 線上試用:StackBlitz

建立專案

1
2
# 新建專案
npm create vite@latest
  1. vite.js document

練習專案目錄結構

  1. 練習範例程式碼 github:lab-vite-spa
路徑 說明
/dist: 編譯產出路徑
/src: 前端原始碼路徑
/src/components: 全站共用元件
/pages/*.vue: 主要頁面元件
/pages/*/.vue: 各頁面非公用元件
/src/router.js: 路由設定
/src/App.vue: 網站進入點
/vite.config.js: vite 設定檔

路徑別名設定

  1. 專案原始碼路徑放置於專案根目錄下的src內,可依需要自行設定
  2. 前端編譯 production 時的產出路徑為 /dist
  3. resolve.alias設定宣告了@表示為 src,便於引用資源時不必再使用../../Home.vue的相對路徑語法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// vite.config.js
import { resolve } from "path"
import { defineConfig } from "vite"
import vue from "@vitejs/plugin-vue"

const root = resolve(__dirname, "src")
const outputDir = resolve(__dirname, "dist")
export default defineConfig({
root,
plugins: [vue()],
build: {
outDir: outputDir,
},
optimizeDeps: {
include: ["vue", "vue-router"],
},
resolve: {
alias: {
"@": resolve(__dirname, "src"),
},
},
})

前端路由設定 & 動態引用元件

  1. 透過()=>import("@/pages/Home.vue")即可動態引用元件,第一次使用該元件會另外發出請求取得元件 js 檔案;進入頁面不需要再將所有的資源全數載入,優化頁面速度
  2. linkActiveClass設定會在使用者點擊路由連結後,添加所設定的類別樣式名稱,此處設定會添加一個active的樣式
  3. 路由設定指定 name 可用於 router-link
  4. 指定 HTML5 mode 處理前端路由 (createWebHistory())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// src/main.js
import { createApp } from "vue"
import App from "./App.vue"
import router from "@/router.js"

createApp(App).use(router).mount("#app")

// src/router.js
import { createRouter, createWebHistory } from "vue-router"
export const routes = [
{ name: "home", path: "/", component: () => import("@/pages/Home.vue") },
{ name: "about", path: "/about", component: () => import("@/pages/About.vue") },
]

const router = createRouter({
linkActiveClass: "active",
history: createWebHistory(),
routes,
})

export default router

導航條(路由連結範例)

basic sample

1
<router-link to="/">Go to Home</router-link> <router-link to="/about">Go to About</router-link>

navBar sample

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<header>
<ul>
<li v-for="m in menu">
<router-link :to="m.to">{{ m.text }}</router-link>
</li>
</ul>
</header>
</template>

<script setup>
import { routes } from "@/router"
const menu = routes.filter((r) => r.name).map((r) => ({ to: r.path, text: r.name }))
</script>
  1. Vue router
  2. Vue Router 路由設定 - 重新認識 vue.js

透過 docker 佈署網站

  1. npm ci 會依照 package-lock.json 安裝套件,npm install 則是依照 package.json
  2. docker內複製檔案COPY,會略過在.dockerignore內的檔案
  3. 第二段 docker 命令在建構 production 的時候,是將第一段的編譯成果,複製到 nginx 的預設網站目錄下
  4. nginx 設定檔也從專案目錄複製到 image 內的 nginx 設定目錄下,請特別注意此處設定檔 spa.conf 的編碼應為 ASCII,不要用 UTF8

.dockerignore

1
2
3
4
5
6
7
8
.dockerignore
node_modules
dist
.vscode
.run
.idea
.git
README.md

Dockerfile

1
2
3
4
5
6
7
8
9
10
11
FROM node:alpine as builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build


FROM nginx:alpine as production-build
COPY --from=builder /app/dist /usr/share/nginx/html
COPY ./.nginx/spa.conf /etc/nginx/conf.d/

docker cli commands

1
2
3
4
5
# build docker image
docker build -t lab-vite-spa .

# create container
docker run -d --name=lab-vite-spa -p 80:80 lab-vite-spa

nginx 設定

開發階段採用 npm run dev 不會發現,但若將程式碼佈署於 IIS 就會發現無法正確的顯示畫面,因為在重新整理過後,IIS 接收到的網址請求的資源是不存在的,此時應該是要吃首頁的路由設定。IIS 可以透過 UrlReWrite 處理;若佈署於 linux 則可以利用 nginx 解決,請參閱下方設定檔內容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# /etc/nginx/conf.d/spa.conf

server {
listen 80 default_server;
listen [::]:80 default_server;

root /usr/share/nginx/html;

index index.html;
# server_name you.server.com;
location / {
try_files $uri $uri/ @rewrites;
}

location @rewrites {
rewrite ^(.+)$ /index.html last;
}

location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
# Some basic cache-control for static files to be sent to the browser
expires max;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
}

結論

這篇主要應該都不是在說 vue3、或 composition API 怎麼寫,記錄下來的重點反而都比較偏向佈署、開發過程。寫這一篇之前其實我也寫了 MPA,就是因為原始需求是前後端整合開發,到後面發現分離會比較好,而分離之後採用MPA也難以達成需求,也因此才會有 SPA + 動態載入的練習 PoC,目前這樣的開發配置是我覺得很不錯的,比起以往前後端混合,利用 webpack 編譯,每改一次都要等編譯很久,希望之後也能慢慢應用在工作上