Lit2.0でSassを使ってもStorybookでスタイルが適応されない


Lit2.0で作成したコンポーネントをStorybookで表示してもSassのスタイルが当たらなかったのでやったことのメモ。

## rollupの設定

```jsx
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import typescript from '@rollup/plugin-typescript';
import dts from 'rollup-plugin-dts';
import postcss from 'rollup-plugin-postcss';

const packageJson = require('./package.json');

export default [
  {
    input: 'src/index.ts',
    output: [
      {
        file: packageJson.main,
        format: 'esm',
        sourcemap: true,
      },
    ],
    plugins: [
      resolve(),
      commonjs(),
      typescript({ tsconfig: './tsconfig.json' }),
      postcss({
        plugins: [],
      }),
    ],
  },
  {
    input: 'dist/types/index.d.ts',
    output: [{ file: 'dist/index.d.ts', format: 'esm' }],
    plugins: [dts.default()],
    external: [/\.css$/],
  },
];
```

## コンポーネントの設定

src/components/SimpleGreeting

```tsx
import { LitElement, html, unsafeCSS } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import styles from './SimpleGreeting.scss';

@customElement('simple-greeting')
export class SimpleGreeting extends LitElement {

  static styles =[unsafeCSS(styles)]

  override render() {
		return html`<p class="test">Hello!</p>`;
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'simple-greeting': SimpleGreeting;
  }
}
```

src/components/SimpleGreeting/SimpleGreeting.scss

```scss
.text {
  color: red;
}
```

src/components/SimpleGreeting/SimpleGreeting.stories.ts

```tsx
import { html, TemplateResult } from "lit";
import "./SimpleGreeting";

export default {
  title: "SimpleGreeting",
  component: "simple-greeting",
};

const Template = () => html` <simple-greeting></simple-greeting>`;

export const Regular = Template.bind({});
```

src/components/SimpleGreeting/index.ts

```js
export { SimpleGreeting } from './SimpleGreeting';
```

## Storybookの設定

.storybook/main.js

```jsx
const path = require("path");

module.exports = {
  stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
  ],
  framework: "@storybook/web-components",
  core: {
    builder: "@storybook/builder-webpack5",
  },
  webpackFinal: async (config) => {
    config.module.rules.push({
      test: /\.scss$/,
      use: [
        "style-loader",
        {
          loader: "css-loader",
          options: {
            modules: {
              auto: true,
            },
          },
        },
        "sass-loader",
      ],
      include: path.resolve(__dirname, "../"),
    });
    return config;
  },
};
```

`yarn storybook`でStorybookを起動してテキストが赤になれば良いが黒のまま。

![スクリーンショット 2022-12-15 17.36.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349238/fa9fda80-755a-4962-059a-6259306c8c94.png)

unsafeCSSを使わなければCSSが当たる

```diff
- static styles = [unsafeCSS(styles)];
+ static styles = css`
    .test {
      color: red;
    }
  `;
```

![スクリーンショット 2022-12-15 17.39.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349238/ba358567-816f-acb2-21dc-d14a9bce62b1.png)


stylesのログを出すとundifined

```js
import styles from './SimpleGreeting.scss';

console.log(styles) // output: undifined
```

SassをCSSに変更してもうまくいかない

```js
- import styles from './SimpleGreeting.scss';
+ import styles from './SimpleGreeting.css';
```

addonを使ってみてもうまくいかない

[Storybook CSS Modules Addon | Storybook: Frontend workshop for UI development](https://storybook.js.org/addons/storybook-css-modules)

[@storybook/preset-scss](https://www.npmjs.com/package/@storybook/preset-scss)

暫定対応としてweb-dev-serverを使う

```bash
yarn add -D @web/dev-server
```

web-dev-server.config.mjs

```js
// import { hmrPlugin, presets } from '@open-wc/dev-server-hmr'

/** Use Hot Module replacement by adding --hmr to the start command */
const hmr = process.argv.includes('--hmr');

export default /** @type {import('@web/dev-server').DevServerConfig} */ ({
  open: '/demo/',
  /** Use regular watch mode if HMR is not enabled. */
  watch: !hmr,
  /** Resolve bare module imports */
  nodeResolve: {
    exportConditions: ['browser', 'development'],
  },

  /** Compile JS for older browsers. Requires @web/dev-server-esbuild plugin */
  // esbuildTarget: 'auto'

  /** Set appIndex to enable SPA routing */
  // appIndex: 'demo/index.html',

  plugins: [
    /** Use Hot Module Replacement by uncommenting. Requires @open-wc/dev-server-hmr plugin */
    // hmr && hmrPlugin({ exclude: ['**/*/node_modules/**/*'], presets: [presets.litElement] }),
  ],

  // See documentation for all available options
});
```

package.json

```json
"start": "yarn run build && concurrently -k -r \"yarn run watch\" \"wds\""
```

demo/index.html

```html
<!DOCTYPE html>
<html lang="en-GB">
  <head>
    <meta charset="utf-8" />
    <style>
      body {
        background-color: white;
      }
    </style>
  </head>
  <body>
    <div id="demo"></div>

    <script type="module">
      import { html, render } from "lit";
      import "../dist/index.js";
      render(
        html`<simple-greeting><simple-greeting />`,
        document.querySelector("#demo")
      );
    </script>
  </body>
</html>
```
Storybookの代わりにHTMLに作成したWeb Componentsを表示して開発を進めてみる

## 追記
[lit-css-loader](https://github.com/bennypowers/lit-css/tree/main/packages/lit-css-loader)を利用するとstorybookでSassのスタイルが表示されました
```js
const Sass = require('sass');
module.exports = {
  ...
  webpackFinal: async (config) => {
    config.module.rules.push({
      test: /\.scss$/,
      loader: 'lit-css-loader',
      options: {
        transform: (data, { filePath }) =>
          Sass.renderSync({ data, file: filePath })
            .css.toString(),
      }
    });

    return config;
  }
}
```