npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

vue-web-component-wrapper

v1.4.4

Published

A Vue 3 plugin that provides a web component wrapper with styles, seamlessly integrating with Vuex, Vue Router, Vue I18n, and supporting Tailwind CSS and Sass styles.

Downloads

3,590

Readme

Introduction

vue-web-component-wrapper is a powerful Vue 3 plugin designed for transforming full-fledged Vue applications into reusable web components (custom elements). These web components can be integrated into any website, enhancing flexibility and reusability.

Why use vue-web-component-wrapper?

As of now, Vue 3 does not support the creation of full aplication as web components out of the box. This plugin aims to solve this problem by providing a simple and easy-to-use solution for creating web components from Vue applications. It also provides support for Vue ecosystem plugins such as Vuex or Pinia, Vue Router, Vue I18n and VeeValidate.

Demo

Check out these demo projects to see vue-web-component-wrapper in action:

Documentation

Check out the Docs

Key Features:

  • Vue Plugins Compatibility: Seamlessly integrates with Vue ecosystem plugins such as Vuex, Vue Router, and Vue I18n.
  • CSS Framework Support: Works with popular CSS frameworks like Tailwind CSS, Bootstrap.
  • CSS Preprocessor Support: Allows you to use CSS preprocessors like SCSS and LESS.
  • Scoped CSS: Allows you to use scoped css in your components.
  • Shadow DOM Support: Facilitates the encapsulation of styles and scripts for your components, preventing clashes with the rest of your application.
  • VUE Devtool Support: Supports the Vue DevTools browser extension.
  • Slot and Named Slot Support: Define and use slots and named slots within web components.
  • v-model Support: Improved support for two-way data binding using v-model architecture.
  • Event Emitting Support: Emit and handle custom events from web components.
  • Provide/Inject Support: Pass data from parent to child components using provide and inject.
  • Disable Removal of Styles on Unmount: Control the removal of styles upon component unmount which can solve issue with css transition.

Installation

npm install vue-web-component-wrapper
# or
yarn add vue-web-component-wrapper
# or
pnpm add vue-web-component-wrapper

Usage

To create a web component using vue-web-component-wrapper, follow the steps below:

  1. Import the necessary modules in your entry file:
import App from './App.vue';
import tailwindStyles from './assets/tailwind.css?raw';
import { createWebHashHistory, createRouter } from "vue-router";
import { createI18n } from 'vue-i18n';
import { createStore } from 'vuex'
import { createPinia } from 'pinia'
import { defaultRoutes } from './main.routes.js'
import { store } from './store/index.js'
import { defineCustomElement as VueDefineCustomElement, h, createApp, getCurrentInstance } from 'vue';
import { createWebComponent } from 'vue-web-component-wrapper';
  1. Set up the instances and use your plugins. This is where you configure your Vuex/Pinia store, Vue router, and other Vue plugins.
export const pluginsWrapper = {
  install(GivenVue: any) {
    const Vue = GivenVue

    //Vuex
    const createdStore = createStore(store)
    Vue.use(createdStore)

    //or Pinia
    const pinia = createPinia()
    Vue.use(pinia)

    //Vue Router
    const router = createRouter({
      history: createWebHashHistory(),
      routes: defaultRoutes,
    })
    Vue.use(router)

    //Vue I18n
    const i18n = createI18n({
      locale: 'en',
      fallbackLocale: 'en',
    })
    Vue.use(i18n)
  },
}
  1. Create your web component using createWebComponent. It takes an options object where you specify your root Vue component, the element name for your custom element, any plugins you want to use, and any CSS framework styles.
createWebComponent({
  rootComponent: App,
  elementName: 'my-web-component',
  plugins: pluginsWrapper,
  cssFrameworkStyles: tailwindStyles,
  VueDefineCustomElement,
  h,
  createApp,
  getCurrentInstance,
  disableStyleRemoval: false,
});

Each option in the createWebComponent function has a specific purpose:

  • rootComponent: The root component of your Vue application.
  • elementName: The tag name for your custom web component. It must contain a hyphen and be lowercase.
  • plugins: Any Vue plugins you want to use in your application.
  • cssFrameworkStyles: Any CSS or SCSS styles that your application needs.
  • VueDefineCustomElement: The defineCustomElement function from Vue.
  • h: The h function from Vue.
  • createApp: The createApp function from Vue.
  • getCurrentInstance: The getCurrentInstance function from Vue.
  • disableStyleRemoval: Boolean to disable removal of styles on unmount.

cssFrameworkStyles

The cssFrameworkStyles option is used to import the CSS of your CSS framework or any other css style that your application needs to have globally, this option can also handle css vars that define on a :root selector.

  1. Build your application. Tested bundler to build the web-component application.

Bundlers Configuration

Vite.js Configuration

Here's a sample Vite configuration. Comparing with Webpack, Vite.js is able to handle assets files like .css and .scss, and media files, importing them as you do regularly. Vue files will be parsed using oficial @vitejs/plugin-vue depending of config. If you would like to add plugins for Vite, just install them with your favorite Node package manager.

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  build: {
    sourcemap: 'inline',
  },
  plugins: [
    vue({
      customElement: true,
    }),
  ],
})

In your main.js/ts file, you will have to import the css framework in slightly different way then webpack with ?inline at the end of the import statement. This leads to a new iusse with fonts, which are not loaded when using ?inline. To fix this, you can import the font css in the App.vue file.

main.js/ts

// ?inline can not handle import url() in css therefore fonts are not loaded, workaround is to add font css to the App.vue
import style from './style.css?inline' 

Workaround for fonts:

App.vue

<style>
header  {
  @apply font-sans;
}

main {
  @apply font-sans;
}
</style>

Webpack Configuration

Here's a sample webpack configuration that helps webpack understand how to load and process .vue, .css, and .scss files. It also sets up an HTML plugin for webpack.

const path = require('path');
const { VueLoaderPlugin } = require('vue-loader');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  mode: 'production',
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-web-component.js',
  },
  module: {
    rules: [
      {
        test: /\.(vue|ce\.vue)$/,
        loader: 'vue-loader',
        options: {
            customElement: true,
        },
      },
      {
        test: /\.(css|scss)$/,
        oneOf: [
          {
            resourceQuery: /raw/,
            use: [
              'to-string-loader',
              'css-loader',
              'postcss-loader',
              {
                loader: 'sass-loader',
                options: {
                  sassOptions: {
                    indentedSyntax: false, // Use the SCSS syntax
                  },
                },
              },
            ],
          },
          {
            use: [
              'style-loader',
              'css-loader',
              'postcss-loader',
              {
                loader: 'sass-loader',
                options: {
                  sassOptions: {
                    indentedSyntax: false, // Use the SCSS syntax
                  },
                },
              },
            ],
          },
        ],
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'file-loader',
        options: {
          name: 'assets/[name].[hash:7].[ext]',
        },
      },
    ],
  },
  plugins: [
    new VueLoaderPlugin(),
    new HtmlWebpackPlugin({
      template: './public/index.html',
    }),
  ],
  resolve: {
    alias: {
      vue$: 'vue/dist/vue.esm-bundler.js',
    },
    extensions: ['.js', '.vue', '.json'],
  },
};

With webpack you will have to import the css framework in slightly different way then vite with ?raw at the end of the import statement.

main.js/ts

import style from './style.css?raw' 

Tips

  • Testing Production Build: the easiest way to test your production build is to run a local server in the dist folder. I use valet for this, but any local server should work.

Future Plans

  1. TypeScript Support: Adding proper strict types.

Contributing

Contributions are welcome! To contribute to the project, please follow these steps:

  • Fork the repository
  • Create a new branch for your feature or bug fix
  • Make your changes and commit them with a clear message
  • Push your changes to your fork
  • Submit a pull request to the main repository

Please make sure to follow the code style and conventions used in the project. If you find a bug or have a feature request, please open an issue on the repository.

License

This project is licensed under the MIT License