5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

完走賞を目指す @xrxoxcxoxAdvent Calendar 2022

Day 7

@emotion/reactで自動付与されるベンダープレフィックスを外す

Last updated at Posted at 2022-12-06

この記事の概要

CSS in JSのライブラリであるEmotionを使うと自動でベンダープレフィックスが付与されます。
されるのですが、その内訳があまり現実に即していないラインナップです。

というわけでベンダープレフィックスを外す方法を記事にしました。

autoprefixerを外すのを推奨する記事ではなく、あくまで「こういうアプローチもある」という紹介です。

検証した際の環境

パッケージ バージョン
react 18.2.0
react-dom 18.2.0
@emotion/react 11.10.5
@emotion/cache 11.10.5
typescript 4.6.4
vite 3.2.3

デフォルトの挙動とその問題点

分かりやすい例としてdisplay: flex;を使用した際に出力されるCSSをお見せします。

打ち消し線が入っていて少し見づらいですが、display: flex;以外に以下の3つの指定が追加されています。

  • -webkit-box
  • -webkit-flex
  • -ms-flexbox

例えば-webkit-flexは、Chromeでいうとバージョン21から28まで必要でした。
-ms-flexboxはIE 10のために必要です(IE 11では不要です。)

この記事を書いている2022年12月現在、ここまでのサポートが必要な場面がどれだけあるのでしょう?

Autoprefixer CSS onlineで確かめてみるとBrowsers: > 0.01%の指定でようやく-webkit-flex-ms-flexboxが現れます。
よしんば0.01%まで対応しようと思っても、-moz-boxはEmotionからは生成されていないため不十分です。

そもそも現在はベンダープレフィックスはあまり使う必要がありません。

かつてCSSにおいて実験的なプロパティを出す際、ベンダープレフィックス付きで実装していました。
今は、フラグや設定によってユーザーが制御して追加できるようになっています。(あくまで傾向の話ですが。)

ただしそうは言っても必要なベンダープレフィックスもあります。
そちらは以下の記事でまとめました。
https://qiita.com/xrxoxcxox/items/3e0e34003a45d3618b29

解決策

  1. createCachestylisPlugins: []を指定する
  2. CacheProviderでラップする

createCachestylisPlugins: []を指定する

@emotion/react@emotion/styledの他に@emotion/cacheが必要になるのでインストールします。

2022/12/7 追記
@emotion/reactをインストールした時点で@emotion/cacheもインストールされるため、別途の導入は不要でした。

Reactのルートになるファイルを編集します。
先程インストールした@emotion/cacheからcreateCacheをインポートし、適当な名前で定義します。
その中でstylisPlugins: []を指定します。

App.jsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import createCache from '@emotion/cache'

const myCache = createCache({
  key: 'css',
  stylisPlugins: [], // これが重要
})

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
)

Emotionは内部でstylisというCSSプリプロセッサーを使用しています。
デフォルトではstylisPluginsの中にprefixerが指定されているのを「何も使用しない」と上書きしているのがこのコードです。
ちなみにEmotionではprefixer以外は使用していないので、この変更による他の影響は起きないはずです。


ちなみにcreateCacheの中のkeyは、今回の内容には何も関係ないのですが指定しなければなりません。
createCacheを使わないときは'css'が指定されていて、特に変更したい意図もないのでこう記載しています。

CacheProviderでラップする

ここは特に説明する箇所はありません。
よくある感じで、Providerでラップするだけです。

App.jsx
  import React from 'react'
  import ReactDOM from 'react-dom/client'
  import App from './App'
  import createCache from '@emotion/cache'
+ import { CacheProvider } from '@emotion/react'

  const myCache = createCache({
    key: 'css',
    stylisPlugins: [],
  })

  ReactDOM.createRoot(document.getElementById('root')).render(
    <React.StrictMode>
+     <CacheProvider value={myCache}>
        <App />
+     </CacheProvider>
    </React.StrictMode>
  )

これにより、無事ベンダープレフィックスが消えました。

最後に

「browserlistを更新するとかで解決するでしょ?」と思っていたのに、随分とハマってしまいました。
実はstylisのprefixerプラグインは、どのプロパティにどのベンダープレフィックスをつけるかをハードコーディングしています。

そのためprefixerプラグインを使わないという強硬策に出る他ありませんでした。
検索してもあまり出てこない話題だったので困っている人自体が少ないのかもしれませんが……どなたかのお役に立てれば幸いです。


最後まで読んでくださってありがとうございます!
Twitterでも情報を発信しているので、良かったらフォローお願いします!

Devトークでのお話してくださる方も募集中です!

5
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?