3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

CA Tech LoungeAdvent Calendar 2023

Day 2

CDN版Vue3で単一ファイルコンポーネントを作る

Last updated at Posted at 2023-11-07

はじめに

Vueでそこそこの規模のサイト作ろうとするとき、index.htmlにすべての処理を書き下すのではなく、コンポーネント別に.vueファイル、作りたいですよね。
Vue-CLIなら手順がいくらでもありますが、CDNの場合そんなに情報が見当たりません。
こちらはありますが、http-vue-loaderを用いているものはVue2限定です。

ということで、テンプレート化します。

結論

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
    <title>タイトル</title>
    
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue3-sfc-loader/dist/vue3-sfc-loader.js"></script>
    
   </script>
</head>
<body>
    <div id="app"></div>

    <script>
        //vue3-sfc-loader初期設定
        const options = {
            moduleCache: {
                vue: Vue
            },

            //read subdirectory vue component file.
            async getFile(url) {
                
                const res = await fetch(url);
                if ( !res.ok )
                throw Object.assign(new Error(res.statusText + ' ' + url), { res });
                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);
            },
        }
        const { loadModule } = window["vue3-sfc-loader"];
        
        //Appコンポーネントをマウント
        const app = Vue.createApp(
            Vue.defineAsyncComponent(
                () => loadModule("./src/components/App.vue", options)
            ),
        )
        app.mount('#app');
    </script>
</body>
</html>

慣習に倣って、rootのdivをAppコンポーネントにした例をご紹介していますが、マウントの処理は用途にあわせて編集して大丈夫です。

App.vue
<template>

</template>

<script>
    export default Vue.defineComponent({
        name: 'App',
        components: {
            "COMPONENT": Vue.defineAsyncComponent(() => loadModule("PATH.vue", options))
        },
    })
</script>

<style>
</style>

.vueファイルはCLIと同じように構成して大丈夫ですが、コンポーネントの読み込みVue.defineAsyncComponent(() => loadModule("PATH.vue", options))を用いることだけ注意してください。

解説

vue3-sfc-loaderを使います。これにより、CDNでも.vueファイルを読み込むことができます。
しかし、初期設定がhttp-vue-loaderと比べてメンドウなので、index.htmlの初期設定のスクリプトはテンプレートと考えて大丈夫です。

i18nで多言語対応するにはこちらから

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?