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

Components are resolved in dev mode but not build mode (with VitePress) #801

Open
5 tasks done
dwgray opened this issue Sep 16, 2024 · 0 comments
Open
5 tasks done

Comments

@dwgray
Copy link

dwgray commented Sep 16, 2024

Describe the bug

I'm working on a documentation site using VitePress and a custom theme. I'd like to use unplugin-vue-components to automatically register both the components from the library I'm documenting and the samples and helper components in the documentation build. I have successfully set this up so that it works in dev mode, but it is silently failing in build mode.

I've tracked this down to an issue with using <script setup lang='ts'>

The link to the repro below shows the failing behavior using a simple VitePress site and unplugin-vue-components

Components are not resolved if:

  • I have a setup script (e.g. <script setup lang="ts">

Components are resolved if:

  • I have no script component in my *.md file
  • The script is not a setup script (e.g. <script lang="ts">

When debugging the broken behavior, I find that the transform method of the unplugin-vue-component plugin is not seeing the code that it can transform (the code it gets doesn't have any instances of _resolveComponent* in it - see my 9/20 update below for details). So the issue may be upstream from unplugin-vue-component, but I'm not familiar enough with VitePress or Vue.js SSR to have an idea if they are the culprits.

Expected:
image

Broken (not the missing "this is just testing if a component is resolved" and the styling on the alert):
image


History, in case it helps track this down.

I'm working on a documentation site using VitePress and a custom theme. I'd like to use unplugin-vue-components to automatically register both the components from the library I'm documenting and the samples and helper components in the documentation build. I have successfully set this up so that it works in dev mode, but it is silently failing in build mode.

I have this working for another site that uses Vite directly (not VitePress) without issue. Is there something extra that needs to be done to get rollup to recognize the plugins? Or is it possible that the relative paths are different for rollup? If so is there a way to diagnose this? I'm not seeing either VitePress or Rollup providing a verbose flag, but maybe there is something else to help me drill down?

  vite: {
    plugins: [
      Icons(),
      Components({
        globs: ['components/*.vue', 'docs/**/demo/*.vue'],
        dts: true,
        include: [/\.vue$/, /\.vue\?vue/, /\.md$/],
        resolvers: [BootstrapVueNextResolver()],
      }),
    ],
  },

Full file: https://github.com/bootstrap-vue-next/bootstrap-vue-next/blob/main/apps/docs/.vitepress/config.mts

Running pnpm dev renders all of the components and examples. Running pnpm build followed by pnpm preview does not render the components, it just leave the tags in place. e.g. there is a ComponentSidebar component that is resolved in dev mode but fails in build mode: https://bootstrap-vue-next.github.io/bootstrap-vue-next/docs/components/breadcrumb.html

image

Update: Sorry, this probably should have been a discussion rather than a bug report, but I don't think I can move it at this point.

I am working on a minimal repo. I started out by creating a vanilla VitePress site and then started adding the things we're using. I am at the point where I would expect the issue to reproduce - the configuration for my Component() in Vite Plugins is identical, and I'm consuming custom autogenerated components and bootstrap-vue-next components, but the issue doesn't reproduce. https://github.com/dwgray/vitepress-unplugin

When I have cycles for this again, I'll continue working towards an actual minimal repro, but I'm hoping that someone can point me to how to diagnose this kind of problem (e.g., verbose mode at some layer in this stack or some other way to debug that rollup is reading my configuration and acting on it).

Update 9/20/24:

I am still unable to get this down to a simple repro despite significant effort. However, I was able to get a debugger attached and find some interesting behavior that I suspect is relevant. The code that is being passed to the transform hook is radically different between the working and the broken case. I think this may indicate something going on with how SSR is working in VitePress, but I'm pretty new to this toolset, so that's a pretty wild guess.

Here's the line I'm looking at:

const result = await ctx.transform(code, id)

For one of my affected files breadcrumbs.md all calls have an id of C:/Projects/bootstrap-vue-next/apps/docs/src/docs/components/breadcrumb.md.

In the broken (build) case, I'm seeing two calls.

1st call:

import _sfc_main from "C:/Projects/bootstrap-vue-next/apps/docs/src/docs/components/breadcrumb.md?vue&type=script&setup=true&lang.ts";
export * from "C:/Projects/bootstrap-vue-next/apps/docs/src/docs/components/breadcrumb.md?vue&type=script&setup=true&lang.ts";
export default _sfc_main;

2nd call:

import _sfc_main from "C:/Projects/bootstrap-vue-next/apps/docs/src/docs/components/breadcrumb.md?vue&type=script&setup=true&lang.ts";
export * from "C:/Projects/bootstrap-vue-next/apps/docs/src/docs/components/breadcrumb.md?vue&type=script&setup=true&lang.ts";
import { useSSRContext as __vite_useSSRContext } from "vue";
const _sfc_setup = _sfc_main.setup;
_sfc_main.setup = (props, ctx) => {
  const ssrContext = __vite_useSSRContext();
  (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("docs/components/breadcrumb.md");
  return _sfc_setup ? _sfc_setup(props, ctx) : void 0;
};
export default _sfc_main;

In the working (dev and rollup for my simple non-repro) case, I'm seeing one call:

import { defineComponent as _defineComponent } from "vue";
import { data } from "../../data/components/breadcrumb.data";
export const __pageData = JSON.parse(\'{"title":"Breadcrumb","description":"","frontmatter":{},"headers":[],"relativePath":"docs/components/breadcrumb.md","filePath":"docs/components/breadcrumb.md"}\');
const __default__ = { name: "docs/components/breadcrumb.md" };
const _sfc_main = /* @__PURE__ */ _defineComponent({
  ...__default__,
  setup(__props, { expose: __expose }) {
    __expose();
    const __returned__ = { __pageData, get data() {
      return data;
    } };
    Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true });
    return __returned__;
  }
});
import { createElementVNode as _createElementVNode, createTextVNode as _createTextVNode, resolveComponent as _resolveComponent, withCtx as _withCtx, createVNode as _createVNode, createStaticVNode as _createStaticVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue";
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
  const _component_ComponentSidebar = _resolveComponent("ComponentSidebar");
  const _component_BreadcrumbOverview = _resolveComponent("BreadcrumbOverview");
  const _component_HighlightCard = _resolveComponent("HighlightCard");
  const _component_BreadcrumbAsArray = _resolveComponent("BreadcrumbAsArray");
  const _component_BreadcrumbManual = _resolveComponent("BreadcrumbManual");
  const _component_BreadcrumbSlots = _resolveComponent("BreadcrumbSlots");
  const _component_ComponentReference = _resolveComponent("ComponentReference");
  return _openBlock(), _createElementBlock("div", null, [
  ...
  ]);
}
_sfc_main.__hmrId = "e1842bb7";
typeof __VUE_HMR_RUNTIME__ !== "undefined" && __VUE_HMR_RUNTIME__.createRecord(_sfc_main.__hmrId, _sfc_main);
import.meta.hot.accept((mod) => {
  if (!mod) return;
  const { default: updated, _rerender_only } = mod;
  if (_rerender_only) {
    __VUE_HMR_RUNTIME__.rerender(updated.__hmrId, updated.render);
  } else {
    __VUE_HMR_RUNTIME__.reload(updated.__hmrId, updated);
  }
});
import _export_sfc from "\\0plugin-vue:export-helper";
export default /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render], ["__file", "C:/Projects/bootstrap-vue-next/apps/docs/src/docs/components/breadcrumb.md"]]);

It's pretty obvious why unplugin-vue-components isn't doing anything in the broken case - there are no component references to resolve! But that means something in the build process isn't giving you the file code actually contains the _resolveComponent* references. So I'm pretty sure this is the problem, I just can't find anything that could be causing vite/vitepress/rollup to behave differently in the broken case than the working case.

working-unplugin.txt

Thanks in advance for any help or direction on this.

Reproduction

https://github.com/bootstrap-vue-next/bootstrap-vue-next/blob/main/apps/docs/.vitepress/config.mts

System Info

System:
    OS: Windows 11 10.0.22631
    CPU: (16) x64 Intel(R) Core(TM) i9-10885H CPU @ 2.40GHz
    Memory: 8.66 GB / 31.75 GB
  Binaries:
    Node: 20.16.0 - C:\Program Files\nodejs\node.EXE
    npm: 10.8.1 - C:\Program Files\nodejs\npm.CMD
    pnpm: 9.5.0 - C:\Program Files\nodejs\pnpm.CMD
  Browsers:
    Edge: Chromium (127.0.2651.74)
    Internet Explorer: 11.0.22621.3527

Used Package Manager

pnpm

Validations

  • Follow our Code of Conduct
  • Read the Contributing Guide.
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
  • Check that this is a concrete bug. For Q&A, please open a GitHub Discussion instead.
  • The provided reproduction is a minimal reproducible of the bug.
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

No branches or pull requests

1 participant