nuxtlabs / nuxt-component-meta

Gather Nuxt components metadata on build time and make them available on production.
69 stars 6 forks source link

feat: add sources option to allow loading external component definition #60

Closed stafyniaksacha closed 7 months ago

stafyniaksacha commented 8 months ago

This PR add a new sources option to allow loading pre-computed component meta file.

export default defineNuxtConfig({
  modules: [
    'nuxt-component-meta',
  ],
  componentMeta: {
    sources: [
      // import from a module
      '@nuxt/ui/component-meta',
      // resolve in project aliases
      '~/meta/library',
      // or directly raw input
      {
        NInput: {
          //...
        },
      }
    ],
  },
})

(This does not cover sources generation, but I have a naive approach here with this)

Atinux commented 8 months ago

Thanks for the PR @stafyniaksacha

How do people generate those pre-computed meta file?

Would be nice to add some document to it since it's a bit of a black box from what I try to understand

stafyniaksacha commented 8 months ago

First, I need to talk about the issue.

When using a module living in node_modules, vue-component-meta can't resolve types of exposed components due to .nuxt/tsconfig.json exclude.

This is a basic example:

<script setup lang="ts">
const meta = await useComponentMeta('UButton')
</script>

<template>
  <div>
    <UButton>Button</UButton>
    <!-- props, slots, events, exposed are all empty -->
    <pre>{{ meta.meta }}</pre>
  </div>
</template>

You can find a working version here: https://github.com/stafyniaksacha/nuxt-component-meta-deep-repro

Also, to me, it does not make sense to scan those components each time we start our nuxt app, as they are not likely to change during development.

The solution I've imagined is that when publishing a component library, we can include those pre-computed meta into the package (at the cost of package size, but we can publish to another meta package).

This PR aims to be able to load and merge pre-computed meta into our app, so we can make our useComponentMeta('UButton') working as expected without needing to parse them.

In order to generate the pre-computed meta in our component library, we can't simply add the nuxt-meta-component because it will affect end-users, instead I made a poc for a CLI using citty. The idea behind is to dynamically register nuxt-component-meta module and do a build. This will generate .nuxt/component-meta.mjs and .nuxt/component-meta.d.ts, we can then either publish them within the package or in another one.

You will find the CLI here: https://github.com/stafyniaksacha/nuxt-meta-component-cli/blob/main/src/main.ts#L33-L75

I think this CLI should be added into this repo if you are ok with the idea.

Then, we can update our component library modules to register those meta if nuxt-component-meta module is detected.

farnabaz commented 8 months ago

Having pre-compiled meta is a good idea to fix typescript exclude issue, and also it will improve performance of development and build.

Having a CLI to generate meta is also a good Idea. Personally, I would like to ship these pre-compiled meta within the components package and not as a different package, therefore I think we might define an output directory for CLI to write generated meta files. This also make it easier for developers to use the CLI and publish meta as separate package.

Additionally, we can create a hook (component-meta:extend) which modules could use it to add/extend components metadata.

Looking forward to seeing the CLI implementation on your PR :)

pi0 commented 8 months ago

In addtion, we might find a hook in nuxt module builder to precompute this meta after mkdist job to prebundle them 👍🏼 This is a lovely and nice perf enhancement ❤️

stafyniaksacha commented 7 months ago

@farnabaz @pi0 The cli is ready for review!

You can use it with:

# build with unbuild
pnpm prepack

# generate meta from playground
./bin/nuxt-component-meta.mjs playground --no-schema

The --no-schema props removes schema information (not types) in the output, to save disk space

There is an issue with the prop type detection into the playground, comment module registration in the nuxt config like:

  modules: [
    '@nuxt/content',
    'pinceau/nuxt',
    // nuxtMetaModule as any
  ],

I think it's due to typescript that can not resolve typing, it's working great when targeting a project that already have older version of this module

stafyniaksacha commented 7 months ago

@farnabaz any chance to see it merged?

Atinux commented 7 months ago

cc @farnabaz