tailwindlabs/headlessui

HeadlessUI is not working with Nuxt 3

bayramorhan opened this issue ยท 31 comments

What package within Headless UI are you using?

@headlessui/vue

What version of that package are you using?

"devDependencies": {
    "autoprefixer": "^10.4.0",
    "nuxt3": "latest",
    "postcss": "^8.4.4",
    "tailwindcss": "^2.2.19"
  },
  "dependencies": {
    "@headlessui/vue": "^1.4.2",
    "@heroicons/vue": "^1.0.5",
    "@tailwindcss/forms": "^0.3.4"
  }

Describe your issue

It works fine with development but when I build nuxt (nuxi build) and start (yarn start) it gives error. I've tried to import headless ui component from @headlessui/vue/dist/index.js instead of @headlessui/vue but its still same.

TypeError: Cannot read property 'buttonRef' of undefined
    at setup (D:\projects\headless-test\nuxt3-app\.output\server\node_modules\@headlessui\vue\dist\headlessui.cjs.development.js:2622:15)
    at callWithErrorHandling (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:7158:22)
    at setupStatefulComponent (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:6874:29)
    at setupComponent (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:6855:11)
    at renderComponentVNode (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9757:17)
    at renderVNode (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9863:22)
    at renderVNodeChildren (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9878:9)
    at renderElementVNode (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9929:17)
    at renderVNode (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9860:17)
    at renderVNodeChildren (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9878:9)
[Vue warn]: inject() can only be used inside setup() or functional components.
TypeError: Cannot read property 'menuState' of undefined
    at Proxy.render$1 (D:\projects\headless-test\nuxt3-app\.output\server\node_modules\@headlessui\vue\dist\headlessui.cjs.development.js:2522:17)
    at renderComponentRoot (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:2015:44)
    at renderComponentSubTree (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9828:51)
    at renderComponentVNode (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9773:16)
    at renderVNode (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9863:22)
    at renderVNodeChildren (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9878:9)
    at renderElementVNode (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9929:17)
    at renderVNode (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9860:17)
    at renderVNodeChildren (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9878:9)
    at renderElementVNode (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9929:17)
[Vue warn]: inject() can only be used inside setup() or functional components.
[Vue warn]: Unhandled error during execution of watcher callback
TypeError: Cannot read property 'itemsRef' of undefined
    at ReactiveEffect.fn (D:\projects\headless-test\nuxt3-app\.output\server\node_modules\@headlessui\vue\dist\headlessui.cjs.development.js:2685:24)
    at ReactiveEffect.run (D:\projects\headless-test\nuxt3-app\.output\server\node_modules\@vue\reactivity\dist\reactivity.cjs.js:164:29)
    at ComputedRefImpl.get value [as value] (D:\projects\headless-test\nuxt3-app\.output\server\node_modules\@vue\reactivity\dist\reactivity.cjs.js:1075:39)
    at D:\projects\headless-test\nuxt3-app\.output\server\node_modules\@headlessui\vue\dist\headlessui.cjs.development.js:2336:26
    at callWithErrorHandling (D:\projects\headless-test\nuxt3-app\.output\server\node_modules\@vue\runtime-core\dist\runtime-core.cjs.js:6615:22)
    at callWithAsyncErrorHandling (D:\projects\headless-test\nuxt3-app\.output\server\node_modules\@vue\runtime-core\dist\runtime-core.cjs.js:6624:21)
    at ReactiveEffect.getter [as fn] (D:\projects\headless-test\nuxt3-app\.output\server\node_modules\@vue\runtime-core\dist\runtime-core.cjs.js:6970:24)
    at ReactiveEffect.run (D:\projects\headless-test\nuxt3-app\.output\server\node_modules\@vue\reactivity\dist\reactivity.cjs.js:164:29)
    at doWatch (D:\projects\headless-test\nuxt3-app\.output\server\node_modules\@vue\runtime-core\dist\runtime-core.cjs.js:7078:16)
    at Object.watchEffect (D:\projects\headless-test\nuxt3-app\.output\server\node_modules\@vue\runtime-core\dist\runtime-core.cjs.js:6890:12)
[Vue warn]: inject() can only be used inside setup() or functional components.
TypeError: Cannot read property 'menuState' of undefined
    at Proxy.render$1 (D:\projects\headless-test\nuxt3-app\.output\server\node_modules\@headlessui\vue\dist\headlessui.cjs.development.js:2656:17)
    at renderComponentRoot (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:2015:44)
    at renderComponentSubTree (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9828:51)
    at renderComponentVNode (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9773:16)
    at renderVNode (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9863:22)
    at renderComponentSubTree (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9828:13)
    at renderComponentVNode (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9773:16)
    at renderVNode (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9863:22)
    at renderComponentSubTree (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9780:9)
    at renderComponentVNode (file:///D:/projects/headless-test/nuxt3-app/.output/server/chunks/index.mjs:9773:16)

+1 on this one.

+1

+1

It works for me with the following package.json/versions.

Can you share your .vue script where you import and call what you need.

{
  "private": true,
  "scripts": {
    "dev": "nuxi dev",
    "build": "nuxi build",
    "start": "node .output/server/index.mjs"
  },
  "devDependencies": {
    "@headlessui/vue": "^1.4.2",
    "@iconify/json": "^1.1.434",
    "@nuxtjs/eslint-config-typescript": "^7.0.2",
    "@pinia/nuxt": "^0.1.5",
    "@tailwindcss/aspect-ratio": "^0.3.0",
    "@tailwindcss/forms": "^0.3.4",
    "@vueuse/core": "^7.1.2",
    "autoprefixer": "^10.4.0",
    "nuxt3": "latest",
    "pinia": "^2.0.4",
    "postcss": "^8.3.11",
    "tailwindcss": "^2.2.19",
    "unplugin-icons": "^0.12.18"
  },
  "pnpm": {
    "overrides": {
      "@nuxt/kit": "npm:@nuxt/kit-edge@latest",
      "@nuxt/kit-edge": "latest"
    }
  },

}

Are you trying in development mode or production mode with built files (.output) ?

import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue';

export default {
  layout: 'individual-main',
  components: {
    Menu,
    MenuButton,
    MenuItem,
    MenuItems,
  },
  setup() {...

I have it working in both, dev and production build. I didn't try to use them in pages directly, I create components with headlessui parts in it. (should not make a difference) let me test this right now

I have it working in both, dev and production build. I didn't try to use them in pages directly, I create components with headlessui parts in it. (should not make a difference) let me test this right now

Thank you for your response. I also tried with this nuxt 3 starter but I 've got same error.

https://github.com/productdevbook/nuxt3-app?ref=bestofvue.com

Is your default "open" state true? for example let isOpen = ref(true); ?

I got the same errors now with the Menu components. On page and also when its wrapped in a component.
Only in the server on SSR.

[Vue warn]: provide() can only be used inside setup().
[Vue warn]: provide() can only be used inside setup().
[Vue warn]: inject() can only be used inside setup() or functional components.
TypeError: Cannot read properties of undefined (reading 'buttonRef')

We need to make a small reproduction i think

Reproduction

https://codesandbox.io/s/angry-orla-qf02s?file=/pages/index.vue

Opening a new terminal and running npm run build && PORT=4000 node .output/server/index.mjs\

EDIT:

CodeSandbox is to complicated for this simple test

created: https://github.com/vanling/nuxt3-issue-reproduction/
It doesn't get more basic then this npm i && npm run build && npm run start open localhost:3000 and check terminal for errors in server

+1

weleo commented

Adding to this issue as a reminder because there is more than one issue with HeadlessUI x Nuxt 3.

I am getting the following error in Safari using the Disclosure component in a production environment:

TypeError: null is not an object (evaluating 't.insertBefore').  

The component also doesn't work in other browsers, but it shows no error messages in the console. Hoping to use HeadlessUI in Nuxt 3 sometime in the future ๐Ÿคž

Hey! Thank you for your bug report!
Much appreciated! ๐Ÿ™

This should be fixed, and will be available in the next release.

You can already try it using:

  • npm install @headlessui/react@insiders or yarn add @headlessui/react@insiders.
  • npm install @headlessui/vue@insiders or yarn add @headlessui/vue@insiders.

@headlessui/vue@insiders

This throws an error with the webpack bundler. Webpack support is important as nuxt3's vite implementation doesnt resolves dynamic assets via props properly.

To reproduce, in vaning's repro https://github.com/vanling/nuxt3-issue-reproduction/, in nuxt.config.ts set

export default defineNuxtConfig({
  ...,
  vite: false
});

Here is the error.

โœ” Server Compiled successfully in 2.03s                                                    23:36:20
โœ” Client Compiled successfully in 2.15s                                                    23:36:20
โœ” Client Compiled successfully in 242.09ms                                                 23:36:20
โœ” Nitro built in 319 ms                                                                    23:36:20
โœ” Server Compiled successfully in 81.98ms                                                  23:36:21
(node:132991) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)

 ERROR  [worker] Cannot use import statement outside a module                              23:36:50

  import{defineComponent as X,ref as A,provide as Oo,inject as To,onMounted as st,onUnmounted as Co,computed as w,nextTick as L,watchEffect as pt,toRaw as dt,watch as Ro}from"vue";import{h as so,cloneVNode as po}from"vue";function S(t,n,...a){if(t in n){let o=n[t];return typeof o=="function"?o(...a):o}let e=new Error(`Tried to handle "${t}" but there is no handler defined. Only defined handlers are: ${Object.keys(n).map(o=>`"${o}"`).join(", ")}.`);throw Error.captureStackTrace&&Error.captureStackTrace(e,S),e}function g({visible:t=!0,features:n=0,...a}){if(t||n&2&&a.props.static)return ye(a);if(n&1){let e=a.props.unmount??!0?0:1;return S(e,{[0](){return null},[1](){return ye({...a,props:{...a.props,hidden:!0,style:{display:"none"}}})}})}return ye(a)}function ye({props:t,attrs:n,slots:a,slot:e,name:o}){let{as:r,...u}=D(t,["unmount","static"]),p=a.default?.(e);if(r==="template"){if(Object.keys(u).length>0||Object.keys(n).length>0){let[l,...i]=p??[];if(!fo(l)||i.length>0)throw new Error(['Passing props on "template"!',"",`The current component <${o} /> is rendering a "template".`,"However we need to passthrough the following props:",Object.keys(u).concat(Object.keys(n)).map(s=>`  - ${s}`).join(`
  ^^^^^^
  
  SyntaxError: Cannot use import statement outside a module
  at Object.compileFunction (node:vm:352:18)
  at wrapSafe (node:internal/modules/cjs/loader:1031:15)
  at Module._compile (node:internal/modules/cjs/loader:1065:27)
  at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
  at Module.load (node:internal/modules/cjs/loader:981:32)
  at Function.Module._load (node:internal/modules/cjs/loader:822:12)
  at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:190:29)
  at ModuleJob.run (node:internal/modules/esm/module_job:185:25)
  at async Promise.all (index 0)
  at async ESMLoader.import (node:internal/modules/esm/loader:281:24)
```

Hello! It doesn't seem to work with Vite, either, after compilation:

(base) raymonf@Raymonf-MBP frontend % yarn start      
yarn run v1.22.17
warning ../../../../package.json: No license field
$ node .output/server/index.mjs
Listening on http://localhost:3000/
Named export 'Menu' not found. The requested module '@headlessui/vue' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from '@headlessui/vue';
const { Menu, TransitionRoot, MenuItems, MenuItem, MenuButton } = pkg;

  at ModuleJob._instantiate (node:internal/modules/esm/module_job:124:21)  
  at async ModuleJob.run (node:internal/modules/esm/module_job:181:5)  
  at async Promise.all (index 0)  
  at async ESMLoader.import (node:internal/modules/esm/loader:281:24)  
  at async file://./.output/server/chunks/app/render.mjs:527:24  
  at async renderMiddleware (file://./.output/server/chunks/app/render.mjs:575:20)  
  at async handle (file://./.output/server/node_modules/h3/dist/index.mjs:601:19)
Named export 'Menu' not found. The requested module '@headlessui/vue' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from '@headlessui/vue';
const { Menu, TransitionRoot, MenuItems, MenuItem, MenuButton } = pkg;

  at ModuleJob._instantiate (node:internal/modules/esm/module_job:124:21)  
  at async ModuleJob.run (node:internal/modules/esm/module_job:181:5)  
  at async Promise.all (index 0)  
  at async ESMLoader.import (node:internal/modules/esm/loader:281:24)  
  at async file://./.output/server/chunks/app/render.mjs:527:24  
  at async renderMiddleware (file://./.output/server/chunks/app/render.mjs:575:20)  
  at async handle (file://./.output/server/node_modules/h3/dist/index.mjs:601:19)

Hello! It doesn't seem to work with Vite, either, after compilation:

Strange, the repro when using the insider build was working with the vite bundler, but not webpack

@Blakeinstein I actually tried it anyways, and for some reason my site did load without problems even though this error was spat out. SSR seemed to be correct, too, with the client not complaining during hydration. I'm not really sure what's happening. ๐Ÿ˜…

@Blakeinstein I actually tried it anyways, and for some reason my site did load without problems even though this error was spat out. SSR seemed to be correct, too, with the client not complaining during hydration. I'm not really sure what's happening. sweat_smile

I am myself now getting the same error? I changed the import statement to be

import * as headlessui from '@headlessui/vue'

const { Popover, PopoverButton, PopoverPanel } = headlessui

and now am getting the type: module error as i got in webpack.

@RobinMalfait I think its a bit too early to close this issue.

Do you transpile @headlessui/vue package in nuxt.config ?

https://v3.nuxtjs.org/concepts/esm/#transpiling-libraries

Do you transpile @headlessui/vue package in nuxt.config ?

v3.nuxtjs.org/concepts/esm/#transpiling-libraries

Can confirm this works. But not sure if this is a fix or a workaround.

Do you transpile @headlessui/vue package in nuxt.config ?
v3.nuxtjs.org/concepts/esm/#transpiling-libraries

Can confirm this works. But not sure if this is a fix or a workaround.

it's definitely a workaround, HeadlessUi needs to work so that it can be imported natively into Nuxt 3 without build bugs. but for now it is enough for us.

Did a few improvements and it fixes the important parts, it's a proper type: module and all cjs files are using .cjs instead of `.js.

You can already try it using npm install @headlessui/vue@insiders or yarn add @headlessui/vue@insiders.


Creating a new Nuxt 3 app and loading Headless UI gives me the expected output without console warnings.
image


@Blakeinstein When I pull down the repro you provided, and bump to the latest insiders version I linked above then I do get the correct output:
image

The terminal correctly outputs the following information:
image

However, it looks like there is a server side rendering Nuxt bug once you load the page:
image

After some digging, @thecrypticace found that Nuxt loads 2 versions of Vue which results in these errors because they check if the same instance of Vue is used. But you should get this warning for any external library that depends on Vue, I think.

image


Can somebody verify the latest insiders build?

Can somebody verify the latest insiders build?

Can confirm that it is fixed, both on vite and on webpack. Apart from said errors warnings. Much thanks!

Thanks for testing, @Blakeinstein!

Going to close this issue, if somebody still has an issue, please open a new issue with a reproduction. Also make sure that for now you have to use the insiders build.

NidMo commented

ๆ„Ÿ่ฐขๆ‚จ็š„ๆต‹่ฏ•๏ผŒ@Blakeinstein๏ผ

ๆ‰“็ฎ—ๅ…ณ้—ญ่ฟ™ไธช้—ฎ้ข˜๏ผŒๅฆ‚ๆžœๆœ‰ไบบไป็„ถๆœ‰้—ฎ้ข˜๏ผŒ่ฏทๆ‰“ๅผ€ไธ€ไธชๅธฆๆœ‰ๅคๅˆถ็š„ๆ–ฐ้—ฎ้ข˜ใ€‚่ฟ˜่ฆ็กฎไฟ็Žฐๅœจๆ‚จๅฟ…้กปไฝฟ็”จinsidersๆž„ๅปบใ€‚

this problem is nuxt3 bug? how can i use headlessUI in nuxt3? install headlessUI@insiders?

this problem is nuxt3 bug? how can i use headlessUI in nuxt3? install headlessUI@insiders?

npm install @headlessui/vue@insiders or yarn add @headlessui/vue@insiders.

Thats it

Solution (workaround) tldr;

  1. Use the insiders version of @Headless ui: npm install @headlessui/vue@insiders or yarn add @headlessui/vue@insiders

  2. Add the library for transpiling during build in nuxt.config.ts|js:

import { defineNuxtConfig } from 'nuxt3'

export default defineNuxtConfig({
  build: {
    transpile: ['@headlessui/vue']
  }
})
  1. build, then nuxi preview, and voilร . Works.
2. Add the library for transpiling during build in `nuxt.config.ts|js`

I am using it in prod without adding this package to transpile

Hey there ๐Ÿ‘‹

I'm currently facing very similar issue using headlessui with Nuxt3.

Until version 3.0.0-27447229.20f3171 of Nuxt, everything was working fine ๐Ÿ‘Œ

Then I tried to update latest Nuxt version (current version is 3.0.0-27457855.7c0b914) and :

  • it still works in dev mode (npm run dev)
  • it breaks when building and previewing (npm run build and npx nuxi preview). It also breaks when deploying on vercel or netlify (tried both).

When looking at logs, it seems that errors and warns are coming from headlessui

TypeError: Cannot read properties of undefined (reading 'button')
    at setup (/.output/server/node_modules/@headlessui/vue/dist/headlessui.esm.js:4:46368)
[Vue warn]: Component PopoverButton  is missing template or render function.
TypeError: Cannot read properties of undefined (reading 'panel')
at setup (/.output/server/node_modules/@headlessui/vue/dist/headlessui.esm.js:4:49526)
[Vue warn]: Component PopoverPanel  is missing template or render function.

I also tried to use @headlessui/vue@insiders with no significant change.
Anyone facing similar issue with latest nuxt 3 releases ?

These errors are probably coming from Nuxt.

See this github issue : nuxt/nuxt#13500
And this one : nuxt/nuxt#12996

When looking at logs, it seems that errors and warns are coming from headlessui

The thing is, its most likely another error in your code. Those errors can be ignored, but nuxt doesnt report the errors properly making some headlessui events (like expanding popovers) break. I faced this in a particular instance but I cannot recall what error I had, but it was not in headless ui