Да, вы можете!
Если вы хотите писать свои трафаретные истории для storybook с помощью TSX (Typescript-версия JSX), это действительно возможно. Немного доработок, и все получится.
НО — это все еще очень предварительная работа, и я ожидаю, что в различных сценариях она будет иметь довольно много ошибок. Тем не менее, я подумал, что этим стоит поделиться, так как я знаю, что люди искали решение.
Предполагается, что вы используете html-версию Storybook с трафаретом. Вы можете найти рабочую версию в моей демо-репо stencil-one. (Это мой демо-репо для модульного тестирования в Stencil, так что не стесняйтесь его просматривать).
Это основные версии, с которыми я работал. Я понятия не имею, будет ли он совместим с другими версиями.
- Stencil: 2.15
- Storybook: 6
- webpack: 5
- babel-loader: 8
Шаг 1: Напишите свою историю
Вот как должна выглядеть история, использующая CSF3 (Component Story Format). Очевидно, что он должен быть в файле с именем .tsx
, чтобы он прошел через нужный инструментарий. Кроме того, измените путь поиска историй, чтобы он включал файлы .tsx. (опция stories в главном файле).
/** @jsx h */
/** @jsxRuntime classic */
import {h} from '@stencil/core';
export default {
title: 'My Basic',
};
export const Default = {
render: () => (<my-basic first="Millie" last="Brown"></my-basic>)
};
Обратите внимание на директивы @jsx
. Они кажутся необходимыми.
Шаг 2: Настройте Webpack для jsx
Мы собираемся настроить .storybook/main
так, чтобы он включал трансформатор babel jsx. Для этого найдем правило, которое обрабатывает tsx, и добавим @babel/plugin-transform-react-jsx
как плагин с pragma: {'h'}
.
webpackFinal: async (config) => {
const tsxRule = config.module.rules.find(rule => 'a.tsx'.match(rule.test));
if(tsxRule) {
const options = tsxRule.use[0].options;
options.plugins = [
['@babel/plugin-transform-react-jsx', {
prgama: 'h'
}],
...options.plugins
];
}
return config;
}
Шаг 3: Рендеринг историй с помощью renderVDom от Stencil
Последняя часть — это изменения в коде storybook/preview
. Создайте функцию, которая будет использоваться в качестве декоратора и будет рендерить элементы в DOM.
const stencilWrapper = (storyFn, context) => {
const host = document.createElement('div');
stencilClient.renderVdom(
{
$ancestorComponent$: undefined,
$flags$: 0,
$modeName$: undefined,
$cmpMeta$: {
$flags$: 0,
$tagName$: 'div',
},
$hostElement$: host,
},
storyFn(context)
);
return host.children[0];
}
А затем активируйте его:
Вам также нужно убедиться, что вы вызываете defineCustomElements (что вы должны делать в любом случае) в коде предварительного просмотра или html-файле preview-manager.
Как упоминалось выше, это все еще чревато ошибками. Если у вас есть какие-либо предложения, улучшения, исправления ошибок и т.д., пожалуйста, пишите в комментариях.