/ Gists / Convert Vue component to Web component
On gists

Convert Vue component to Web component

Web components Vue.js

HelloWorld.ce.vue Raw #

<!-- ce je jen interni oznaceni ze to bude custom element = web component -->
<script setup>
defineProps({
  msg: {
    type: String,
    required: true,
    default: 'AAA'
  }
})
</script>

<template>
  <div>{{ msg }}</div>
</template>

<style scoped>
h1 {
  font-weight: 500;
  font-size: 2.6rem;
  position: relative;
  top: -10px;
}

h3 {
  font-size: 1.2rem;
}

.greetings h1,
.greetings h3 {
  text-align: center;
}

@media (min-width: 1024px) {
  .greetings h1,
  .greetings h3 {
    text-align: left;
  }
}
</style>

vite.config.js Raw #

import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue({
      template: {
        compilerOptions: {
          isCustomElement: (tag) => tag.includes('-')
        }
      }
    })
  ],
  build: {
    lib: {
      entry: './src/main.ce.js',
      name: 'hello-world',
      fileName: 'hello-world'
    }
    // rollupOptions: {
    //   external: ['vue'],
    //   output: {
    //     globals: {
    //       vue: 'vue'
    //     }
    //   }
    // }
  },
  define: {
    'process.env': process.env
  },
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url)),
      vue: 'https://cdn.jsdelivr.net/npm/vue@3.4.27/dist/vue.runtime.esm-browser.prod.js'
    }
  }
})

package.json Raw #

{
  "name": "testik",
  "version": "0.0.0",
  "private": true,
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview",
    "build:webcomponent": "vite build --config vite.config-no-vue.js",
    "build:app": "vite build --config vite.config.app.js",
    "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore",
    "format": "prettier --write src/"
  },
  "dependencies": {
    "pinia": "^2.1.7",
    "vue": "^3.4.21",
    "vue-router": "^4.3.0"
  },
  "devDependencies": {
    "@rushstack/eslint-patch": "^1.8.0",
    "@vitejs/plugin-vue": "^5.0.4",
    "@vue/eslint-config-prettier": "^9.0.0",
    "eslint": "^8.57.0",
    "eslint-plugin-vue": "^9.23.0",
    "prettier": "^3.2.5",
    "vite": "^5.2.8",
    "vite-plugin-cdn-import": "^1.0.1"
  }
}

HelloWorld-compiled.js Raw #

import { openBlock as r, createElementBlock as l, toDisplayString as s, defineCustomElement as i } from "https://cdn.jsdelivr.net/npm/vue@3.4.27/dist/vue.runtime.esm-browser.prod.js";
const c = "h1[data-v-883a1ab3]{font-weight:500;font-size:2.6rem;position:relative;top:-10px}h3[data-v-883a1ab3]{font-size:1.2rem}.greetings h1[data-v-883a1ab3],.greetings h3[data-v-883a1ab3]{text-align:center}@media (min-width: 1024px){.greetings h1[data-v-883a1ab3],.greetings h3[data-v-883a1ab3]{text-align:left}}", d = (e, a) => {
  const t = e.__vccOpts || e;
  for (const [o, n] of a)
    t[o] = n;
  return t;
}, g = {
  __name: "HelloWorld.ce",
  props: {
    msg: {
      type: String,
      required: !0,
      default: "AAA"
    }
  },
  setup(e) {
    return (a, t) => (r(), l("div", null, s(e.msg), 1));
  }
}, m = /* @__PURE__ */ d(g, [["styles", [c]], ["__scopeId", "data-v-883a1ab3"]]), p = i(m);
customElements.define("hello-world", p);

index.html Raw #

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>My Web Component</title>
        <script src="./hello-world.js" type="module"></script>
    </head>
    <body>
        <hello-world></hello-world>
        <hello-world msg="BBB"></hello-world>
    </body>
</html>