MUKI AI Summary
公司開發網站後台,使用 Vue.js 結合 SPA 開發,無需 SEO。後來因 B 公司需求,增加多個入口網址,並替換登入頁 LOGO。未登入時,訪客會看到不同 LOGO,登入後 LOGO 依 platform 顯示。設定路由匹配同元件,使用 meta.platform 區分 LOGO。網站標題問題透過複製 index.html 為 b.html,修改標題,並用 nginx 指向不同入口解決。這樣可達成多入口網址,且有獨立標題與 LOGO。...
需求與緣起
我們公司開發了一個網站後台,當初,因為以下考量,我選擇了 Vue.js 結合 SPA 的方式來開發應用程式,而不是使用 Nuxt.js 預設的 SSR 模式:
- 他是網站後台
- 需要帳號密碼才能登入管理
- 不需要做搜尋引擎優化 (SEO)
需求調整
後台上線一段時間後,跟 B 公司有業務合作,B 公司希望能讓他們的客戶也使用這個後台,但前提是,需要將「登入網址」以及 LOGO 替換成他們家的品牌。如下所示:
- 原本 (A) 的後台登入頁:https://mukispace.com
- 新增 (B) 的後台登入頁:https://mukispace.com/b_company
- 在沒有登入的情況下,訪客瀏覽這兩頁,會跳到對應的登入頁,但看到的 LOGO 會不同。
- 登入情況下,訪客瀏覽 (A) 登入頁,會跳轉至
https://mukispace.com/home
;訪客瀏覽 (B) 登入頁,一樣會跳轉到https://mukispace.com/home
- 呈上,跳轉的網址一樣,但是 LOGO 不同
設定路由匹配同個元件
要做到上述功能,其實很簡單。我們只要新增 /b_company
路由,並渲染元件 login
即可。這樣就會有兩個路由都使用同一個 login
元件。
{ path: '/login', name: 'Login', meta: { head: '公司 A 的登入頁', title: '登錄', platform: 'ACompany' }, component: Login }, { path: '/b_company', name: 'bLogin', meta: { head: '公司 B 的登入頁', title: '登錄', platform: 'BCompany' }, component: Login }
至於該如何顯示對應的 LOGO?我使用 meta.platform
來作識別
<!-- 取得 route.meta.platform 後,再根據 platform 顯示對應的 LOGO --> <template> <img v-if="platform === 'BCompany'" src="/b.svg"> </template> <script setup lang="ts"> import { useRoute } from 'vue-router' const route = useRoute() const platform = route.meta.platform </script>
登入後的 LOGO,則使用如 vuex, pinia 等狀態管理取得 platform 資料
<!-- 取得 store 的 platform 值後,再根據 platform 顯示對應的 LOGO --> <template> <img v-if="platform === 'BCompany'" src="/b.svg"> </template> <script lang="ts" setup> import { useUserStore } from '@/stores' const useStore = useUserStore() const platform = useStore.platform </script>
登入後不需要分兩個網址,也不需要拆成兩個站,所以我只處理登入頁的路由,以及顯示的 LOGO 。
原本以為這樣就交付完成,直到這兩天發現新的問題 ... 😂
網站標題與設定不符
當客戶將新的登入頁網址:https://mukispace.com/b_company
透過 LINE、FB 等社群分享給他人時,我們發現預覽顯示的網站標題,不是我在路由設定的 '公司 B 的登入頁'
▼ 我期望的是,從 /b_company
進來的訪客,看到的是 meta.head
的「公司 B 的登入頁」
{ path: '/login', name: 'Login', meta: { head: '公司 A 的登入頁', title: '登錄', platform: 'ACompany' }, component: Login }, { path: '/b_company', name: 'bLogin', meta: { head: '公司 B 的登入頁', title: '登錄', platform: 'BCompany' }, component: Login }
但事實上,雖然我可以透過修改 document.title
去替換網站的標題,但這是透過 JavaScript 動態修改的,只有在瀏覽器的網站標題才有效;如果透過社群分享,他們抓的是靜態 HTML 的網站標題,也就是 dist/index.html
的網站標題
▼ 搜尋引擎與社群分享爬的內容來自於 index.html
,執行 npm run build
之後會產出至 dist/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>公司 A 的登入頁</title> </head> <body> <div id="app"></div> <script type="module" src="/src/main.ts"></script> </body> </html>
因此不管我輸入哪一個網址,透過分享都會抓到 dist/index.html
的標題:「公司 A 的登入頁」
這是使用 SPA 最基本的常識,當時我也有想到這個問題,但當時只是要先提案,所以我給了一個簡單的 DEMO,也沒特別處理這塊,沒想到繞了一圈,還是要回來搞這個坑 😂...。
想了一堆方案
當時想了一堆有的沒的方案,甚至還想說要不要換框架整個重寫 (真的瘋了,這什麼鬼 XXD),也曾想說乾脆自己用 HTML + jQuery + AJAX 寫一個重複的登入頁好了,但想想又覺得好麻煩 QQ。
後來在洗澡的時候,靈光一閃!
洗澡真的是寫 code 的好朋友,
洗澡好棒!洗澡我愛你!大家每天都要洗澡唷 ^.<
打包 (build) 網站的過程中,是將 index.html 打包成 dist/index.html,
那我只要複製一份 index.html 到 b.html,修改 b.html 的標題後,打包成 dist/b.html;再透過 nginx 指向,將 https://mukispace.com/b_company 指到 dist/b.html,這樣好像就能解決我的問題了。
▼ 簡易示意圖如下
步驟一:複製一份 b.html
▼ 原本的 index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>公司 A 的登入頁</title> </head> <body> <div id="app"></div> <script type="module" src="/src/main.ts"></script> </body> </html>
▼ 另存一份成為 b.html,並修改網站標題
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>公司 B 的登入頁</title> </head> <body> <div id="app"></div> <script type="module" src="/src/main.ts"></script> </body> </html>
步驟二:修改 vite 設定檔
▼ vite 有一個 rollupOptions
可以設定打包後的檔案,我們在此設定好對應的 input
資料
import path from 'path' export default () => { build: { rollupOptions: { input: { main: path.resolve(__dirname, 'index.html'), b_company: path.resolve(__dirname, 'b.html') } } } }
有朋友提到這個就是 Vite 的 Multi Page App,我也補上連結給大家參考
步驟三:nginx 指向
▼ 前端的路由維持原樣,不需修改
{ path: '/b_company', name: 'bLogin', meta: { head: '公司 B 的登入頁', title: '登錄', platform: 'BCompany' }, component: Login }
請後端增加 nginx 指向,例如:將 https://mukispace.com/b_company 指向到 dist/b.html
修改後,再開啟 https://mukispace.com/b_company(此為示意網址,不要真的點唷 😂),搜尋引擎就會爬到 dist/b.html 這份檔案,並顯示 b.html 的網站標題。
如此就能做到兩個入口連到同一個網站後台,而且有獨立的標題與 LOGO。
後記
在這篇文章中,跟大家分享了如何在 Vue.js 中設定多個入口網址,並顯示對應的網站標題。希望你在閱讀這篇文章後,能對你有所幫助。
這篇文章是基於我個人的學習經驗和理解寫成的,如果有任何錯誤或不足,歡迎指正。有任何問題或建議,都歡迎在下方留言唷!