Open8

CSS-in-JS ライブラリ Compiled を触って理解する

izuminizumin

Next.js に Example with Compiled があるので、それを参考にセットアップする

$ yarn add --dev @compiled/webpack-loader
$ yarn add @compiled/react 

webpack の loader として動作するらしい。CSS の書き出しが必要なときはオプションが必要になる。

next.config.js
module.exports = {
  webpack: (config) => {
    config.module.rules.push({
      test: /\.tsx?/,
      use: ["@compiled/webpack-loader"],
    });

    return config;
  },
};

.babelrc を忘れたらぶっ壊れる。

.babelrc
{
  "presets": ["next/babel"],
  "plugins": ["@babel/plugin-syntax-jsx"]
}
izuminizumin

これ↓が

const MdH1: React.VFC<{ children?: React.ReactNode }> = (props) => {
  return <h1 {...props} css={[textCss, mdH1Css]} />;
};

const textCss = css`
  color: rgba(0, 0, 0, 0.84);
`;

const mdH1Css = css`
  ::before {
    content: "#";
    padding-right: 0.3em;
    font-size: 0.6em;
    color: rgba(0, 0, 0, 0.6);
  }

  font-size: 36px;
`;

yarn dev だとこう↓なる

<style>._syazjvpt{color:rgba(0,0,0,0.84)}._1kt91ihd:before{content:"#"}._p7f0scuo:before{padding-right:0.3em}._l5lo19g5:before{font-size:0.6em}._is061haz:before{color:rgba(0,0,0,0.6)}._1wyb14no{font-size:36px}</style>

<h1 class="_syazjvpt _1kt91ihd _p7f0scuo _l5lo19g5 _is061haz _1wyb14no">Test post</h1>

yarn build && yarn start だとこう↓なる

<style data-cmpld="true">._syazjvpt{color:rgba(0,0,0,0.84)}._1kt91ihd:before{content:"#"}._p7f0scuo:before{padding-right:0.3em}._l5lo19g5:before{font-size:0.6em}._is061haz:before{color:rgba(0,0,0,0.6)}._1wyb14no{font-size:36px}</style>

<h1 class="_syazjvpt _1kt91ihd _p7f0scuo _l5lo19g5 _is061haz _1wyb14no">Test post</h1>

atomic の息吹を感じる

izuminizumin

こういう書き方もイケる

<h1
  {...props}
  css={`
    ${textCss}
    ${mdH1Css}
    ::before {
      content: "#";
      padding-right: 0.3em;
      font-size: 0.6em;
      color: rgba(0, 0, 0, 0.6);
    }
  `}
/>
izuminizumin

これはダメ。静的解析だけだとムリなものはムリか。

<h1
  {...props}
  css={`
    ${textCss}
    ${mdH1Css}
    ${mdFormattingCss("#")}
  `}
/>
izuminizumin

こういうのは OK らしい
CSS Custom Properties になる

const MdH1: React.VFC<{ children?: React.ReactNode; formattingString?: string }> = (props) => {
  const formattingString = props.formattingString ?? "#";
  return (
    <h1
      {...props}
      css={`
        ${textCss}
        ${mdH1Css}
        ::before {
          content: "${formattingString}";
          padding-right: 0.3em;
          font-size: 0.6em;
          color: rgba(0, 0, 0, 0.6);
        }
      `}
    />
  );
};
<style data-cmpld="true">._syazjvpt{color:rgba(0,0,0,0.84)}._1wyb14no{font-size:36px}._1kt91jk6:before{content:var(--_bv993x)}._p7f0scuo:before{padding-right:0.3em}._l5lo19g5:before{font-size:0.6em}._is061haz:before{color:rgba(0,0,0,0.6)}</style>
<h1 class="_syazjvpt _1wyb14no _1kt91jk6 _p7f0scuo _l5lo19g5 _is061haz" style="--_bv993x:&quot;#&quot;">Test post</h1>
izuminizumin

静的解析を頑張るタイプのやつなので当たり前っちゃ当たり前だが、自由度は高くない
css prop に渡すスタイルを返す関数」みたいなのはいまのところエラーになる
css prop に三項演算子を使った式の値を入れる」も壊れる
props.primary && css`color: blue;` みたいなのは許される
エラーメッセージとか見てる感じ、結構どろくさく解析してそう

コントリビューションチャンスが無限にあるとも言える(?)