如果要使用 vue3 runtime,也就是 vue.runtime.esm-browser.js,而不使用 vue.esm-browser.js。這兩個版本的差異是使用後者,有支援 template,可直接將 template 字串寫在 component 裡面,但如果使用 runtime library,因為這個檔案大小比較小,缺少了動態編譯 template 的功能,必須改寫為使用 render function。
實例
以下是可以直接在 browser 執行的範例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title></title>
</head>
<body>
<div id="app"></div>
<script type="importmap">
    {
        "imports": {
            "vue": "https://unpkg.com/vue@3.5.13/dist/vue.runtime.esm-browser.js",
            "vue-i18n": "https://unpkg.com/vue-i18n@11.1.1/dist/vue-i18n.runtime.esm-browser.js"
        }
    }
</script>
<script type="module">
    import { createApp, h } from 'vue';
    import { createI18n, useI18n } from 'vue-i18n';
    const messages = {
        en: { greeting: 'Hello!' },
        zh: { greeting: '你好!' }
    };
    const i18n = createI18n({
        legacy: false,
        locale: 'en',
        messages
    });
    const App = {
        setup() {
            const { t, locale } = useI18n(); // 正確取得 t() 函數
            const toggleLang = () => {
                locale.value = locale.value === 'en' ? 'zh' : 'en';
            };
            return () =>
                h('div', [
                    h('h1', t('greeting')),
                    h('button', { onClick: toggleLang }, '🌐 Switch Language')
                ]);
        }
    };
    createApp(App).use(i18n).mount('#app');
</script>
</body>
</html>
compiler-dom
vue3 官方提供了一個 compiler-dom,可以將 template 字串轉換為 render function。
安裝首先要安裝 compiler-dom
npm i @vue/compiler-dom
撰寫一個 convert.js
// https://www.npmjs.com/package/@vue/compiler-dom
// npm i @vue/compiler-dom
const fs = require('fs');
const path = require('path');
const { compile } = require('@vue/compiler-dom');
const file = process.argv[2];
if (!file || !file.endsWith('.template.html')) {
  console.error('請提供一個 .template html 檔案,例如:node convert.js MyComponent.html');
  process.exit(1);
}
const filePath = path.resolve(process.cwd(), file);
const template = fs.readFileSync(filePath, 'utf-8');
// 編譯 template 成 render 函數
const { code } = compile(template, {
  mode: 'module',
  prefixIdentifiers: true, // 避免 with()
  filename: file
});
// 產出 JS 檔案名稱
const baseName = path.basename(file, '.template.html');
const outputFile = `${baseName}.template.render.js`;
// // 包裝為可匯入的模組
const outputContent = `
${code}
`;
// 寫入檔案
fs.writeFileSync(outputFile, outputContent.trim());
console.log(`Render function 已輸出為:${outputFile}`);
使用方法
把 template 的部分,改為獨立的 test.template.html 檔案
<div>
    <h1> {{ t("greeting") }} </h1>
    <button @click="toggleLang()">🌐 Switch Language</button>
</div>
透過 nodejs 將 template 轉換為 render function
import { toDisplayString as _toDisplayString, createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"
export function render(_ctx, _cache) {
  return (_openBlock(), _createElementBlock("div", null, [
    _createElementVNode("h1", null, _toDisplayString(_ctx.$t("greeting")), 1 /* TEXT */),
    _createElementVNode("button", {
      onClick: $event => (_ctx.toggleLang())
    }, "🌐 Switch Language", 8 /* PROPS */, ["onClick"])
  ]))
}
改寫原本的測試網頁
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title></title>
</head>
<body>
<div id="app"></div>
<script type="importmap">
    {
        "imports": {
            "vue": "https://unpkg.com/vue@3.5.13/dist/vue.runtime.esm-browser.js",
            "vue-i18n": "https://unpkg.com/vue-i18n@11.1.1/dist/vue-i18n.runtime.esm-browser.js",
            "render": "./test.template.render.js"
        }
    }
</script>
<script type="module">
    import { createApp, h } from 'vue';
    import { createI18n, useI18n } from 'vue-i18n';
    import {render} from 'render';
    const renderFn = render;
    const i18n = createI18n({
        legacy: false,
        locale: 'en',
        fallbackLocale: "en",
        messageCompiler: null,
        messages: {
            "en": {
                "greeting": 'Hello!'
            },
            "zh": {
                "greeting": '你好!'
            },
        },
    });
    const App = {
        setup() {
            const { t, locale } = useI18n();
            const toggleLang = () => {
                locale.value = locale.value === 'en' ? 'zh' : 'en';
            };
            return {
                t, locale, toggleLang
            };
        },
        render: renderFn,
        methods: {
        }
    };
    createApp(App).use(i18n).mount('#app');
</script>
</body>
</html>
note
點擊切換語言時,網頁 console 會出現這樣的警告訊息
[intlify] the message that is resolve with key 'greeting' is not supported for jit compilation
不影響網頁操作,但還不知道為什麼會出現這個 warning