事情是這樣...
我最近接了一個設計靜態網頁案子
但雇主的需求就是拿到打包好的網站就直接開啟(雙點擊 index.html)
但我習慣用 vue3 和 vite 來開發,但我發現我 vite build 出來最終的結果,
直接雙點擊 index.html,現在唯一卡住我的問題就是我引入的那個最終 main.js 檔案
會被瀏覽器 CORS 政策所阻擋,所以無法載入該 js 檔案。
我看爬了文章是說 CORS 只能透過後端解決,不然就是要使用到 Proxy Server (也就是說無論無何都要架設 local server),但是顧客那邊說網站專案會放在公用電腦上,所以也不能安裝其他東西例如 Node.js、Apache 或 Ngnix。
因為顧客目的也不是為了要上架或內網往使用,單純就是瀏覽靜態網頁並靠 js 和 css 做酷炫動畫導覽這樣。
可是我已經很習慣用 vue3 和 vite 搭配使用設計出來的專案,程式碼模相比原生的可以更組化也比較好維護跟優雅。
所以我很納悶真的使用 vue3 + vite 開發的專案,如果要瀏覽勢必就要搭配 local server 嗎?沒辦法直接 local file access?
感謝樓上大大們的幫助,我針對每個解決方法來說明一下
首先是 @小哈片刻 提出的採用 --allow-file-access-from-files
方法,確實這個方法可以有效地取消本地端瀏覽器 CORS 的規範,讓我成功載入 main.js
。
基本上用這個方法我任何資源(css, js, svg, icon)都可以正常載入,但還是遇到限制:
譬如:透過 npm run preview
然後使用 localhost:4173
瀏覽的範例專案,它頁面的右側欄位應該要是有東西的,例如:
然後如果你點擊 About 會跳轉到 localhost:4173\about
,應該會變成這樣:
但如果是直接 Local Files Access 會變成這樣:
基本上路由相關的功能都會壞掉,譬如理論上那個 Home 應該要是灰色的(當前所在路由),然後右邊欄位是完全沒有顯示
如果嘗試點擊 Home 則會跳轉到 file:///C:/
、About 則變成了 file:///C:/about
。
我有嘗試去 App.vue
把 <RouterLink to="/">Home</RouterLink>
改成 <RouterLink to="./">Home</RouterLink>
用相對路徑的方式,但結果 Home
會變成連結到 file:///C:/Users/Jack/Desktop/%E7%B6%B2%E7%AB%99/vue-project/dist/
;而 About
會連結到 file:///C:/Users/Jack/Desktop/%E7%B6%B2%E7%AB%99/vue-project/dist/about
基本上就是檔案瀏覽器了...
至於 @bendwarn 和 @海綿寶寶 提出的方法中有一個想法是使用 @vite-plugin-singlefile
套件,來把所有 js 和 css 都輸出在 index.html
檔案上面,確實這樣也可以避開 CORS 甚至不用去 CMD 下 --allow-file-access-from-files
指令,但小缺點就是我 svg 和 icon 的資源路徑生成還是錯誤的,即使我有在 vite.config.ts
中設定 base: './'
,也沒有辦法變成相對路徑,這些圖檔的存取都是絕對路徑例如 file:///C://favicon.ico
這樣。
我有發現我只要使用 vite-plugin-singlefile
套件就會把 base: './'
設定給覆寫掉。
然後最大的問題就是依舊是我上面說的路由連結問題,後來我有去 stackexchange 上面找到一個討論
大概的含意就是說雖然靜態網站可以在不需要伺服器的情況下被瀏覽器來瀏覽,但會有諸多限制,例如路由連結就是一個很大的問題。
所以我目前研究下來如果真的要使用 vite + vue3 開發的話,不架一個 local server 可能真的無法讓我想要的功能都正常。
也許我要考慮說服客戶端能不能讓我安裝 local server;或是說我有想過要不要用 electron 包起來;不然就是我要妥協可能就乖乖地寫 native 網站了 QQ
Base64編碼: 將您的JavaScript代碼轉換為Base64編碼,並使用標籤內聯到HTML文件中。這種方法允許您繞過CORS問題,因為您不再使用外部文件加載代碼。以下是一個示例:
<script>
const encodedScript = "BASE64_ENCODED_SCRIPT";
const decodedScript = atob(encodedScript);
eval(decodedScript);
</script>
要使用此方法,您需要將您的JavaScript代碼轉換為Base64編碼。可以使用在線工具或編程語言來執行此操作。
請注意:這種方法可能不適用於包含大量JavaScript代碼的項目,而且對於安全性有一定的風險,請確保信任代碼來源。
以上是ChatGPT給的答案之一,
實測之後是可以使用。
建議使用的條件是:
專案簡單,只有一個JS檔案時。
用法是:
(1)npm run build打包後
(2)將打包後的xxxxx.js,用Js file to base64,去變成base64字串。
(3)修改打包後的index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
<!--註解掉js-->
<!-- <script type="module" crossorigin src="./assets/index.5d3.js"></script> -->
<link rel="stylesheet" href="./assets/index.6ec.css">
</head>
<body>
<div id="app"></div>
<!--變數encodedScript = base64字串-->
<script>
const encodedScript ='Y29uc3QgVHI9ZnVuY3Rpb2nQucX'
const decodedScript = atob(encodedScript);
eval(decodedScript);
</script>
</body>
</html>