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

@heavymedl/vue-plugin-global-components

v1.2.0

Published

A Vue plugin that uses Vite's Glob Import feature to register global async components for Vue applications

Downloads

11

Readme

vue-plugin-global-components

A Vue plugin that uses Vite's Glob Import feature to register global async components for Vue applications.

Install

npm i @heavymedl/vite-plugin-global-components

Usage

Import the plugin into your app's isomorphic entry point, then pass a directory path containing Vue components to be registered as global to Glob Import.

import { createSSRApp } from 'vue';
import App from './App.vue';

import GlobalComponentsPlugin from '@heavymedl/vue-plugin-global-components';

export default function createApp(props) {
  const app = createSSRApp(App, props);
  app.use(
    GlobalComponentsPlugin,
    import.meta.glob('../GlobalComponents/**/*.vue')
  );
  return { app };
}

The plugin loops through the object keys and registers global async components on your Vue app instance with app.component(defineAsyncComponent(...)).

Theory

This plugin expects Glob Import to return dynamic import references, e.g. used in lazy mode, which it does by default.

// Default type of import.meta.glob
export default interface GlobDynamicImport {
  [key: string]: () => Promise<object>;
}

When Vite compiles your application, defineAsyncComponent forces the generation of JavaScript and CSS chunks representing each component.

At runtime, the dynamic import references of import.meta.glob allows us to leverage defineAsyncComponent to register global async components, which can then be used everywhere, without statically importing them in every parent component.

Because we have individual chunks for each component, we have flexibility with how they're delivered. You can swap them in and out on demand, lazy hydrate non-interactive components, or a combination of both techniques.

Side effects

You should be aware of the implications of using Glob Import and defineAsyncComponent in your project.

Glob Import at build time

import.meta.glob is statically processed at build time. Under the hood, Vite uses fast-glob to process all *.vue files matching the string directory argument. Each individual .vue file gets its own JS chunk (and CSS chunk if applicable). Therefore, you should be cognizant of the number of chunk assets your application will output. Use import.meta.glob sparingly and ensure all of the global async components you build are used in some context.

Nature of global async components and cumulative layout shift (CLS)

When we use async components, the chunks that comprise them (JS and CSS) are loaded in a "lazy" fashion. They are generally loaded later in the hydration lifecycle. This can lead to an increase in cumulative layout shift (CLS) in your application. Therefore, it's recommended that you load the individual CSS chunks of the components you'll use for the page in your template.

Upon building, your global async components will get a CSS entry point defined in the Vite manifest. It might look something like this:

{
  "src/app/components/component-a.css": {
    "file": "component-a-8dd27c5b.css",
    "src": "src/app/components/component-a.css"
  }
}

Take care to server-render stylesheets to mitigate CLS side effects.

<link href="component-a-8dd27c5b.css" />

Lazy hydration

At runtime, your global async components will server render HTML with ssr and return it to be incorporated into the final page HTML served to the end user. If we determine that a particular component is "static", or non-interactive, it might be a good candidate to delay, or even omit client-side hydration.

We can use vue3-lazy-hydration to conditionally omit/delay client-side hydration, which prevents your end users from fetching an unnecessary chunk of JavaScript at runtime.

import { createSSRApp } from 'vue';
import { LazyHydrationWrapper } from 'vue3-lazy-hydration';
import GlobalComponentsPlugin from '@heavymedl/vue-plugin-global-components';
import App from './App.vue';

export default function createApp(props) {
  const app = createSSRApp(App, props);
  app.use(
    GlobalComponentsPlugin,
    import.meta.glob('../GlobalComponents/**/*.vue')
  );
  app.component('LazyHydrationWrapper', LazyHydrationWrapper);
  return { app };
}
<template>
  <LazyHydrationWrapper
    v-bind="getLazySettings(isClientHydrate)"
    @hydrated="onHydrated"
  >
    <keep-alive>
      <component :is="componentName" v-bind="componentProps" />
    </keep-alive>
  </LazyHydrationWrapper>
</template>

Development

Run the Vite development server:

npm run dev

This should open the test application in test/app.

The test application is a basic Vue app that uses @heavymedl/vue-plugin-global-components to register global async components contained within test/app/src/components.