純html如何識別.vue檔案並搭建vue專案

风希落發表於2024-06-22

前言

使用原生 html 寫 vue 專案。注意:是專案,而不是頁面,此方式是不推薦的,畢竟有腳手架,但在一些及其特殊場景下,可能會需要類似的方式,因此作為一個記錄。

這種方式唯一的優點就是寫完可以直接扔伺服器上了-_-

對 html 寫 vue 的認知

很多人對 在 html 中執行 vue 專案這種內容,認知只停留在引入 vue 的 cdn 檔案,然後在 html 裡一頓寫,就覺得 html 寫 vue 不是很簡單嘛,但請注意用詞,是專案,而不是頁面,你能寫一個 .vue 頁面引入讓 html 去執行嗎?顯然不可以,而此文章就是說這個的。


正常想要在原生 html 中直接寫 .vue 檔案是不現實的,因為 html 壓根就不認識 .vue 檔案,只有腳手架才能識別,那如何才能讓 html 識別 .vue 檔案呢?其實也很簡單,核心就是一個包 vue3-sfc-loader

如何獲取 vue 等 npm 的離線包

  • jsdelivr 推薦
    • 優點:更新及時,所有 npm 包都可查詢到
    • 缺點:自行區分 es 和 umd 包,且部分包依賴檔案需自行查詢
  • cdnjs
    • 優點:有明確的 es 和 umd 包,專案相關包羅列較為完整,如果 jsdelivr 上無法找到 es 和 umd 包的可以使用此網站
    • 缺點:更新並不是最快,很多 npm 包缺失,比如此次的 vue3-sfc-loader 在 cdnjs 上無法搜尋到
  • unpkg
    • 優點:與以上兩個相比,暫無
    • 缺點:需要知道想要下載的檔名,包括區分 es 和 umd

什麼是 es 包和 umd 包

es 包支援 import 匯入的寫法,比如這樣

<script type="module">
  import { createApp, ref } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'

</script>

而 umd 包是直接執行在瀏覽器的,比如我引入了 vue.global.js 這就是一個 browser 包,我可以在 window 上訪問到 Vue 例項

使用時就是這樣

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
  const { createApp, ref } = Vue // window.Vue

</script>

es 包是需要 script 標籤新增 type="module",匯入方式為import
而 umd 包引入之後,會自動掛載到 window 上,匯入方式為解構 const {...} = Vue

讓 html 識別 .vue 檔案

需由一個前提條件,由於下載的都是生產檔案,開啟 html 頁面時需要使用 Live Server 外掛開啟,普通開啟方式無法執行

這裡統一用 es 檔案,模仿腳手架結構進行搭建

  1. 下載 vue 離線 es 檔案: vue.esm-browser.prod.min.js
  2. 下載 vue3-sfc-loader 離線 es 檔案:vue3-sfc-loader.esm.js
  3. 新建 index.html,並引入下載好的 vue 和 sfc 解析檔案

這種 Import maps 寫法在 vue 官網上有 示例

特性: 其實就是一個路徑對映,此時 import {} from "vue" 等價於 import {} from "./lib/es/vue.esm-browser.prod.min.js"
優點:

  • 可以非腳手架專案中可以支援 import {} from "vue"
  • 如果不使用,就需要 import {} from "./lib/es/vue.esm-browser.prod.min.js" 引入相對或絕對路徑,冗餘且意義不大
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <!-- vue 的掛載節點 -->
    <div id="app"></div>
  </body>
  <script type="importmap">
    {
      "imports": {
        "vue": "./lib/es/vue.esm-browser.prod.min.js",
        "vue3-sfc-loader": "./lib/es/vue3-sfc-loader.esm.js",
      }
    }
  </script>
  <script type="module" src="./main.js"></script>
</html>
  1. 新建 main.js 檔案,寫入 sfc 解析 vue 檔案的規則,並掛載 vue 例項,由於 html 的 script 標籤上寫了 type="module",所以可以在 main.js 中使用 import 語法
import { loadModule } from "vue3-sfc-loader";
import * as Vue from "vue";
const { defineAsyncComponent, createApp } = Vue;

const options = {
  moduleCache: {
    vue: Vue,
  },
  async getFile(url) {
    const res = await fetch(url);
    if (!res.ok) return;
    return {
      getContentData: (asBinary) => (asBinary ? res.arrayBuffer() : res.text()),
    };
  },
  addStyle(textContent) {
    const style = Object.assign(document.createElement("style"), {
      textContent,
    });
    const ref = document.head.getElementsByTagName("style")[0] || null;
    document.head.insertBefore(style, ref);
  },
};

// 引入 App.vue 根檔案
const loadComponent = defineAsyncComponent(() =>
  loadModule("./pages/App.vue", options)
);

// 掛載 vue
createApp(loadComponent).mount("#app");

addStyle 是為了解析 .vue 檔案中的 style 樣式插入到 header 中。

  1. 新建 App.vue 檔案,寫入測試內容,然後使用 Live Server 開啟 html 檔案
<script setup>
import { ref } from "vue";
const count = ref(0);

</script>

<template>
  <h1>123</h1>
  <div class="title">count: {{ count }}</div>
  <button @click="count++">+1</button>
</template>

<style scoped>
.title {
  color: red;
}
</style>

效果如圖所示

image

使用第三方元件庫

這個需要對元件庫有一定的熟悉程度,瞭解其構成結構,而且需要官方對 es 格式的元件庫檔案有相當完善的支援。
目前測試下來,只有 antd vue 對此方式的支援度最完善,可以在 cdnjs 中搜尋下載。
element plus arco vue 這些元件庫對 es 的支援度並不是特別好,如果想要使用,只能退而求其次,使用 umd 格式,這種方式就不能 import 匯入,而是從 window 上獲取使用。

  1. 下載 antd vue 相關的 min.js 和 css 並在 index.html 使用 map 對映(官網上還明確標註依賴了 dayjs 的 plugin 外掛)
  <link rel="stylesheet" href="./lib/es/antd.reset.min.css" />

  <script type="importmap">
    {
      "imports": {
        // ...
        "antd": "./lib/es/antd.esm.min.js"
      }
    }
  </script>
  1. main.js 中註冊元件庫
import * as antd from "antd";

const options = {
  moduleCache: {
    vue: Vue,
    antd: antd, // 元件庫等第三方包不在 use 註冊,在此處註冊,否則 sfc 會將 antd 識別為專案內部的 vue 元件,找不到而報錯
  },
// ...
};
  1. 使用元件庫
<script setup>
import { ref } from "vue";
import { Button } from "antd";

const count = ref(0);

</script>

<template>
  <span class="title">count: {{ count }}</span>
  <Button @click="count++"> +1 </Button>
</template>

image

至此,離線方式搭建 vue 專案就此完成。

其實這種方式的缺點還是蠻多的,如果想用的元件庫 es 支援度不夠或有問題,只能選擇 umd 格式使用

相關文章