У меня есть турборепозиторий с библиотекой компонентов реагирования, которую я публикую в NPM. Назовите это @myscope/react
— он связан с CSS с помощью RollupJS. А у Turbo есть несколько хороших документов по публикации локальных пакетов здесь.
В репозитории также есть два приложения: веб-сайт, использующий библиотеку компонентов React, и сборник рассказов. Компоненты корректно импортируются веб-приложением, а TypeScript работает даже в каталоге Storybook. Но когда Storybook запускается, я получаю:
The requested module '/@fs/Users/{user}/mre/packages/react/dist/index.js' does not provide an export named 'MyComponent'
Почему? Я посмотрел на dist/index.js
, и кажется, что он экспортирован, но является ли это ограничением стратегии модуля, которую поддерживает Storybook?
Минимальное воспроизведение ошибки я создал здесь.
.storybook/main.ts
:
import type { StorybookConfig } from "@storybook/react-vite";
import { join, dirname } from "path";
/**
* This function is used to resolve the absolute path of a package.
* It is needed in projects that use Yarn PnP or are set up within a monorepo.
*/
function getAbsolutePath(value: string): any {
return dirname(require.resolve(join(value, "package.json")));
}
const config: StorybookConfig = {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
addons: [
getAbsolutePath("@storybook/addon-onboarding"),
getAbsolutePath("@storybook/addon-links"),
getAbsolutePath("@storybook/addon-essentials"),
getAbsolutePath("@chromatic-com/storybook"),
getAbsolutePath("@storybook/addon-interactions"),
],
framework: {
name: getAbsolutePath("@storybook/react-vite"),
options: {},
},
};
export default config;
Сборник рассказов package.json
:
{
"name": "my-storybook",
"private": true,
"version": "0.1.2",
"type": "module",
"scripts": {
"dev": "storybook dev -p 6006",
"build": "storybook build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
},
"dependencies": {
"@myscope/react": "workspace:*",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"storybook": "^8.2.7"
},
"devDependencies": {
"@chromatic-com/storybook": "^1.6.1",
"@storybook/addon-essentials": "^8.2.7",
"@storybook/addon-interactions": "^8.2.7",
"@storybook/addon-links": "^8.2.7",
"@storybook/addon-onboarding": "^8.2.7",
"@storybook/blocks": "^8.2.7",
"@storybook/react": "^8.2.7",
"@storybook/react-vite": "^8.2.7",
"@storybook/test": "^8.2.7",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^7.15.0",
"@typescript-eslint/parser": "^7.15.0",
"@vitejs/plugin-react": "^4.3.1",
"eslint": "^8.57.0",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-react-refresh": "^0.4.7",
"eslint-plugin-storybook": "^0.8.0",
"tsconfig": "workspace:*",
"typescript": "^5.2.2",
"vite": "^5.3.4"
}
}
vite.config.ts
:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
})
Я просмотрел это обсуждение и все равно продолжил. Но мне бы хотелось хотя бы понять, почему это не работает.
Для моих уважаемых коллег, проголосовавших за закрытие моего вопроса без комментариев из-за недостаточности информации для отладки, когда я связал репозиторий GitHub с минимальным воспроизведением, вот скриншот ошибки, которую я получаю по адресу http://localhost:6006/?path=/docs/example-mycomponent--docs
Я ожидаю, что компонент будет отображаться так же, как в localhost:3000
.
Проблема в том, что ваш apps/storybook/package.json
файл использует "type": "module"
и собран с помощью vite, поэтому по умолчанию используются модули ES, но ваш packages/react/rollup.config.js
указывает результат сборки format: 'cjs'
.
Все, что вам нужно сделать, это перейти на format: 'es'
, и ваша проблема исчезнет.
Итак, вам нужно решить, хотите ли вы по-прежнему использовать предыдущую сборку cjs
, или es
, или двойную сборку из packages/react
.
Перейти на format: 'es'
— самый простой путь. Двойная сборка была бы следующей простейшей, но я бы рекомендовал использовать exports
в packages/react/package.json
, чтобы лучше это поддержать. Вы также можете заставить Vite поддерживать commonjs, добавив предустановку Babel в конфигурацию @vitejs/plugin-react
, но я бы не пошел по этому пути.
Двойная сборка является наиболее универсальной, но CJS вам, вероятно, тоже не понадобится.
Если вы собираетесь опубликовать библиотеку, то, как правило, желательно поддерживать модули ES и CommonJS, чтобы сделать ее более удобной для пользователя. Однако, если ваша библиотека в первую очередь ориентирована на браузерных клиентов, я бы рекомендовал беспокоиться только о модулях ES. В любом случае, двойные сборки не так уж сложны в реализации, и с таким же успехом можно получить свой пирог и съесть его, если это не потребует слишком больших накладных расходов с точки зрения обслуживания и сборки. Кстати, всякий раз, когда я публикую библиотеку, я создаю двойную сборку.
Еще раз спасибо!
Большое спасибо! Это помогло мне преодолеть ошибку импорта и перейти к проблеме, связанной с использованием Rollup встроенной криптографии NodeJS... можете ли вы рассказать больше о «двойном построении» и преимуществах CJS?