RemixにCSS Modulesを導入する
公開日:
はじめに
リリースノート
https://github.com/remix-run/remix/releases/tag/remix%401.16.0
公式ドキュメント
https://remix.run/docs/en/main/guides/styling#css-modules
Remix のバージョン 1.16.0
から CSS Bundling が stable 化され、CSS Modules
などがデフォルトで使えるようになりました。
数行追加するだけなのでとても簡単です。
使用するパッケージのバージョンは記事執筆時点で以下の通りです。
- @remix-run/css-bundle@1.17.1
- @remix-run/dev@1.17.1
- @remix-run/node@1.17.1
- @remix-run/react@1.17.1
- @remix-run/serve@1.17.1
CSS Modules の導入
公式ドキュメントに従って導入していきます。
https://remix.run/docs/en/main/guides/styling#css-modules
CSS のバンドリングはデフォルトで行われるようになったので、@remix-run/css-bundle
というパッケージを使用して、
バンドリングされた CSS ファイルの参照を取得して links 関数に追加するだけです。
npm install @remix-run/css-bundle
import { cssBundleHref } from '@remix-run/css-bundle';
import type { LinksFunction } from '@remix-run/node'; // or cloudflare/deno
export const links: LinksFunction = () => {
return [
...(cssBundleHref ? [{ rel: 'stylesheet', href: cssBundleHref }] : []),
// ...
];
};
cssBundleHref
の参照はroot.tsx
などで行うと良いらしいです。
これだけで CSS Modules
が使えるようになっています。
.root {
border: solid 1px;
background: white;
color: #454545;
}
import styles from './styles.module.css';
export const Button = React.forwardRef(({ children, ...props }, ref) => {
return <button {...props} ref={ref} className={styles.root} />;
});
Button.displayName = 'Button';
落とし穴
モジュールを 再 export している場合、CSS ファイルがバンドルに含まれない
具体的にはindex.js
などで
export * from './Button.jsx';
このような感じで再 export していると、Button.jsx
ファイルの中で
import styles from './styles.module.css';
このように CSS ファイルを参照していても、このファイルは現状バンドル化されないため、スタイルが適用されません。
これは公式ドキュメントにも書いてあることなんですが、注意は必要です。
https://github.com/evanw/esbuild/issues/1370
どうすれば良いか
この不具合は esbuild
の問題で、esbuild
のバージョン0.17.7
で修正されています。
しかし、現状の Remix
の最新バージョンである0.17.1
では esbuild の0.17.6
、つまりまだ不具合が修正されていないバージョンを使用していないためこの不具合が起きていると思われます。また、ワークアラウンドとして、
export { Button } from './Button.jsx';
このように名前付きで再 export することで CSS ファイルがバンドルに含まれるというものがあります。なので現状の解決策としては
- Remix に
esbuild
の0.17.7
が採用されるのを待つ - 名前付きの再 export を採用する
の 2 択になるかなと思います。
最後に
とても簡単に CSS Modules
の導入ができました。
まぁ自分は連携するライブラリのバージョンがずれていることに気が付かずに 1 日溶かしたんですけどね
では
Bye