vue3-SPA sample


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

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

  1. vite 線上試用:StackBlitz

建立專案

# 新建專案
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的相對路徑語法
// 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())
// 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

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

navBar sample

<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

.dockerignore
node_modules
dist
.vscode
.run
.idea
.git
README.md

Dockerfile

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

# 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 解決,請參閱下方設定檔內容

# /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 編譯,每改一次都要等編譯很久,希望之後也能慢慢應用在工作上

SPA