导入 HeadlessUI 的组件在构建并在另一个项目中使用时抛出错误

phi*_*nny 7 javascript module npm reactjs headless-ui

我目前正在使用React、Tailwind、HeadlessUI 和 Storybook开发 UI 库。一旦我完成了组件,并确保它们可以在 Storybook 和 React 开发服务器上工作,我就构建了它们并将它们打包到私有 npm package中。

当我使用创建的包将它们导入到测试项目中时,大多数都可以正常工作,但有些则不能。所有不工作的组件都有一个共同点:从@headlessui/react.
(工作组件不从 headlessui 导入任何内容)

当我尝试在测试项目中使用这些组件时,它们都抛出相同的错误:(
这里我选择组件“Select”作为示例)

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports. Check the render method of 'Select'.

该错误实际上没有意义,因为这些组件从我的库导出并导入到我的测试项目中,与工作的组件完全相同。我什至通过在所有组件上使用简单的方法来检查这一点console.log。结果是一样的。
以下是它们的导入和导出方式:

// imported into test project:
import { Select, Form, Dropdown, /* ... */ } from "@my-package";
Run Code Online (Sandbox Code Playgroud)
//exported from the library in index.js:
// ...
import Select from "./components/Select";
export { Select, /* ... */ };
Run Code Online (Sandbox Code Playgroud)

因为我确信我已将它们正确导入到我的测试项目中,所以我确信它一定与构建或 HeadlessUI 有关。

为了构建我使用babel
尽管 babel在构建时从未抛出错误,但我认为我仍然会在这里发布配置。
我的构建脚本:"build": "cross-env BABEL_ENV=production babel src -d dist"
我的 .babelrc:

{
  "presets": [
    [
      "react-app",
      {
        "absoluteRuntime": false
      }
    ]
  ],
  "plugins": ["babel-plugin-react-css-modules"]
}

Run Code Online (Sandbox Code Playgroud)

以下是组件“Select”中的一些非构建和构建代码:

// Select.jsx
import React, { Fragment, useState } from "react";
import { Listbox, Transition } from "@headlessui/react";
import { CheckIcon, SelectorIcon } from "@heroicons/react/solid";
import PropTypes from "prop-types";

function classNames(...classes) {
  return classes.filter(Boolean).join(" ");
}

export default function Select({
  //...
}) {
  const selects = options;
  let selectedOption;
  let i = 0;
  selects.map((select) => {
    if (select.default) {
      selectedOption = selects[i];
      return true;
    }
    i++;
    return false;
  });

  const [selected, setSelected] = useState(selectedOption);

  return (
    <div className={className}>
      <Listbox value={selected} onChange={setSelected}>
        {({ open }) => (
          <>
            <Listbox.Label className="block text-sm font-medium text-gray-700">
              {title}
            </Listbox.Label>
            <div className="mt-1 relative">
              <Listbox.Button
                className={` bg-white relative border border-gray-300 rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-primary/60 focus:border-primary sm:text-sm ${
                  !length || length === "md"
                    ? "w-72"
                    : length === "fit"
                    ? "w-full"
                    : length === "lg"
                    ? "w-96"
                    : length === "sm" && "w-44"
                }`}
              >
              // ...
Run Code Online (Sandbox Code Playgroud)
// Select.js
"use strict";

var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = Select;
exports.getSelected = getSelected;

var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/slicedToArray"));

var _react = _interopRequireWildcard(require("react"));

var _react2 = require("@headlessui/react");

var _solid = require("@heroicons/react/solid");

function Select(_ref) {
// ...
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_react2.Listbox.Label, {
      className: "block text-sm font-medium text-gray-700"
    }, title), /*#__PURE__*/_react.default.createElement("div", {
      className: "mt-1 relative"
    }, /*#__PURE__*/_react.default.createElement(_react2.Listbox.Button, {
      className: " bg-white relative border border-gray-300 rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-primary/60 focus:border-primary sm:text-sm ".concat(!length || length === "md" ? "w-72" : length === "fit" ? "w-full" : length === "lg" ? "w-96" : length === "sm" && "w-44")
    }, /*#__PURE__*/_react.default.createElement("span", {
      className: "block truncate ".concat(placeholder && !selected ? "text-gray-400" : "text-gray-700")
    }, selected ? selected.text : placeholder), /*#__PURE__*/_react.default.createElement("span", {
      className: "absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none"
    }, /*#__PURE__*/_react.default.createElement(_solid.SelectorIcon, {
      className: "h-5 w-5 text-gray-400",
      "aria-hidden": "true"
    }))), // ...

Run Code Online (Sandbox Code Playgroud)

快速总结:

  • 导入 headlessui 的组件不会按预期呈现/工作。
  • 问题可能不是导入/导出,而是构建或 HeadlessUI。

我不知道该怎么办。
感谢任何帮助,提前致谢!

Ste*_*ner 2

问题在于 headless-ui package.json 引用入口点的方式。安装后,在自定义组件的 node_modules 文件夹中,您将看到对 _react2 = require('@headlessui/react') 的引用。如果你查看它的值,它是一个不存在的文件的字符串路径:

'/static/media/index.bad31bab1c06d3ff486c.cjs'

如果您查看此库的 package.json 文件,您将看到它在需要时指向 cjs 文件。因为现在大多数应用程序/组件都是使用 webpack、babel 等构建的,所以它总是使用 require:

在此输入图像描述

如果您进入组件中的构建文件并通过添加下面的代码行强制它成为一个模块,以便它拾取 .js 文件,您将看到它工作。所以这不是问题的答案,因为这是图书馆所有者必须解决的问题,这只是您看到问题的原因。

在此输入图像描述

问题是