Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(unplugin): move parsing steps to unplugin #43

Merged
merged 23 commits into from
Nov 1, 2022
Merged

feat(unplugin): move parsing steps to unplugin #43

merged 23 commits into from
Nov 1, 2022

Conversation

Tahul
Copy link
Contributor

@Tahul Tahul commented Sep 13, 2022

This PR moves parsing steps inside an Unplugin, instead of the root scope of the Nuxt module.

This allows supporting HMR.

The PR in its current state supports reparsing components on-save, I get the output file (.nuxt/component-meta.mjs) to refresh on each changes, with proper updates.

It needs fixes on HMR before merging, but I can already see few issues:

  • We can't pass a string to createComponentMetaCheckerByJsonConfig

That would be very helpful to support generating metas from transformed components and not their only the content of the file. That can be useful if the project contains any plugin that may alter the content of or <script>.

I could then run that parsing step from inside the transform hook of the Unplugin, and updating my context from that result based on transformed component content.

cc @johnsoncodehk :)

  • Is there a smoother way of communicating dynamic data between Nitro <=> Vite than writing a file?

Will resolve: #42, #33

Will help on: https://github.com/nuxt-themes/elements/issues/93

@Tahul Tahul marked this pull request as draft September 13, 2022 02:15
@Tahul Tahul marked this pull request as ready for review September 17, 2022 15:43
@Tahul Tahul requested review from farnabaz and atinux and removed request for atinux and farnabaz September 17, 2022 15:43
@Tahul Tahul marked this pull request as draft September 17, 2022 17:14
@Tahul
Copy link
Contributor Author

Tahul commented Sep 17, 2022

putting this back as draft ; virtual modules breaking build ; not ready yet

@Tahul Tahul marked this pull request as ready for review September 18, 2022 15:48
@Tahul
Copy link
Contributor Author

Tahul commented Sep 18, 2022

I changed the implementation for it to work with both build and HMR; should be ready for review @farnabaz

@Tahul
Copy link
Contributor Author

Tahul commented Sep 18, 2022

tests passes :) ; released 0.3.2 beta tag on NPM to use it on @nuxt-themes/elements

@atinux atinux requested a review from farnabaz September 19, 2022 09:21
@farnabaz
Copy link
Collaborator

I think we can remove some fields from generated meta, fields likes fullPath, shortPath, export, fileName, chunkName, ...
I don't see these fields as useful fields in runtime and removing them will reduce template size also

WDYT @Tahul ?

Copy link
Member

atinux commented Sep 19, 2022

Agree that some could be trimmed to the essentials to reduce the generate code.

Another note is that the generated code should never be included in the end-user bundle but only when:

  1. Calling the API endpoint
  2. Calling the composables (that should call the API endpoint in production with no HMR)

@stafyniaksacha
Copy link
Collaborator

Another note is that the generated code should never be included in the end-user bundle but only when:

  1. Calling the API endpoint
  2. Calling the composables (that should call the API endpoint in production with no HMR)

We may want to expose this to the end-user bundle as an opt-in option, so we can use the unplugin as standalone (e.g. with only vite & vue)

@Tahul
Copy link
Contributor Author

Tahul commented Sep 19, 2022

I'm fine with reducing output data, will be pushing that change.

I think we should at least preserve component name, and maybe the relative path inside the project (that might be useful when used in development, or to create some GitHub links from that data for example).


Data can already be queried via API with this version.

The only missing part is using the API in production, instead of inlining the chunk via an import.

Does it inlining the data via an import differs from loading it via an API query, as that chunk will be loaded anyways?


An important note from latest trials with this version;

What happens here is that I have to refresh the vue-component-meta checker on every request, as the file content changes and I don't know the method to refresh the content for a single file.

I checked __internals__ from the vue-component-meta exposed instance, and couldn't find a method made to refresh the TS server files.

I tried running that in a parallel process, but that seem to break HMR.

Do you think you could point us to a fix for this issue @johnsoncodehk?

This PR is blocked by this issue, as it makes HMR really slow and all sizes of projects.

@johnsoncodehk
Copy link

@Tahul We need to have new API in vue-component-meta, maybe I can check it in next week, it would be nice if you could open a feature request.

@Tahul
Copy link
Contributor Author

Tahul commented Sep 21, 2022

@johnsoncodehk ; vuejs/language-tools#1889

You can find the feature request here, please let me know if anything else needed.

@Tahul
Copy link
Contributor Author

Tahul commented Oct 11, 2022

Hey @johnsoncodehk ; I updated this PR, but it seems like the two new APIs clearCache() and reload() has no effect.

Using them before re-querying a component by its path won't change the result of the query.

That still blocks this PR, do you need a sandboxed reproduction?

@johnsoncodehk
Copy link

That still blocks this PR, do you need a sandboxed reproduction?

Yes this will help, I'll also check if there are any issues with the reload logic before I have reproduction.

@johnsoncodehk
Copy link

johnsoncodehk commented Oct 11, 2022

I just found the reason when implement vue-component-meta playground, it should be fixed by vuejs/language-tools@76d3ab8, please wait for v1.0.4.

And I suggest you use updateFile API instead of reload, which has better performance.

@Tahul
Copy link
Contributor Author

Tahul commented Oct 12, 2022

Thank you so much @johnsoncodehk ; latest commit correctly handles HMR in development with useComponentMeta composable.

@atinux ; I stumbled upon an issue with Nitro approach for component meta, as the import seem to be inlined by Nitro (#nuxt-component-meta/nitro), even after a page reload the metas seem to still be the ones from the boot of the server.

I see multiple solutions to this, one would obviously be enforcing the usage of useComponentMeta.

In my opinion, using Nitro should be "default" in production environments, but using local (HMR-compatible) data should be default in development.

What do you think of making useComponentMeta the only entrypoint for that module, and gracefully detect which environments it runs in and use the according approach for each?

  • useComponentMeta() in development would use reactive data source
  • useComponentMeta() in production would use queries to /api/component-meta/...

Copy link
Member

atinux commented Oct 13, 2022

Agree for having:

  • useComponentMeta() in development would use reactive data source
  • useComponentMeta() in production would use queries to /api/component-meta/...

@Tahul
Copy link
Contributor Author

Tahul commented Oct 18, 2022

@atinux ; done :)

useComponentMeta is now async, to be used as await useComponentMeta(name?: string).

name is facultative, and is properly typed so it will autocomplete with a list of all Nuxt loaded components.

It is ready for review @farnabaz ; @larbish ; @atinux

@Tahul Tahul requested review from larbish, atinux and farnabaz and removed request for farnabaz October 18, 2022 16:19
@Tahul
Copy link
Contributor Author

Tahul commented Oct 18, 2022

I added a feature, transformers.

You can push transformers via:
nuxt.hook('component-meta:transformers', ({ transformers }) => { transformers.push() }).

These are useful if you want to apply some transforms to components prior to parsing.

There is two ways to alter component parsing now:

  • Pushing transformers via the hook
    • (code, id) => string
    • Has to be synchronous
  • Using a Volar plugin, pushed into tsconfig relative to the project running nuxt-component-meta

An example is <ContentSlot /> that won't be detected by vue-component-meta as a slot.

Via a transformer, we can rewrite <ContentSlot :use="$slot.default" /> into <slot #default />, allowing vue-component-meta to detect it.

@stafyniaksacha stafyniaksacha requested review from atinux and removed request for atinux October 20, 2022 12:35
Copy link
Member

atinux commented Oct 21, 2022

Last step is to fix the CI and good for me to merge 🚀

@Tahul Tahul merged commit ae5ae18 into main Nov 1, 2022
@Tahul Tahul deleted the feat/unplugin branch November 1, 2022 18:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

HMR Support
5 participants