LoginSignup
0
0

More than 3 years have passed since last update.

Vueでmodule cssを使いたいけど、依存するnode_modulesのCSSが反映できなくなるみたいな話

Last updated at Posted at 2021-03-18

概要

  • Vue(前バージョン共通)でwebpackビルドしている
  • Vueファイル内のstyleタグではCSSmoduleを使いたい
  • node_modulesに入っているCSSは純粋なCSSとしてグローバル反映させたい
  • よくあるgetting started章のドキュメントの通りにコピペするとCSSmoduleにならないか、直接クラス指定したいスタイルが反映されなくなってしまう

上記の状況の際に、雑にCSSmoduleを有効化するとnode_modulesのCSSまでクラス名がハッシュ化されてしまい、不便が発生する場合の対処法。

もしかしたらReactでもelement-plusのような設計のライブラリがあれば起こるかもしれない

自分の場合だと elementUI にて発生したので綴る。

環境

  • Vue 3.0.7
  • Webpack 5.26.2
  • css-loader 5.1.3
  • element-plus 1.0.2-beta.35

対策

node_modules内のCSSはnot CSSmoduleとして読み込む

※以下例ではsass-loaderも使っていますが、sassを使用しない場合は無視してください

webpack.config.js
{
    /* 〜〜〜〜略〜〜〜〜 */
    module: {
        rules: [
            /* 〜〜〜〜略〜〜〜〜 */
            {
                test: /\.(sa|sc|c)ss$/,
                use: [
                    'vue-style-loader',
                    {
                        loader: 'css-loader',
                        options: {
                            modules: true
                        }
                    },
                    'sass-loader',
                ]
            }
            /* 〜〜〜〜略〜〜〜〜 */
        ]
    }
    /* 〜〜〜〜略〜〜〜〜 */
}

こんな風にwebpack.config.jsが書かれていると思うが(vue-loaderのオプションに書いている人はvue-loaderの loader.options.loaders.[任意の拡張子] 等を参照)、このままwebpackを通すと、node_modules内のCSSもCSSmoduleと解釈されるため、CSSライブラリを使うなどしてどうしてもVueテンプレート内に生のクラスで書きたい場合や、 element-plus あるいは element-ui のようにVueファイル内で別途CSSを外部から当てないとimportしたコンポーネントにスタイルが当たらない 使いづらい 仕様のライブラリでは外部CSSまでCSSmoduleとしてクラス名がハッシュ化されてしまうとコンポーネントライブラリのデザインが適用されなくなってしまう。

ここでの問題は、 node_modules の中にあるCSSまでCSSmoduleになることが問題なので、ならばnode_modules 内はCSSmoduleでは無いものとしてwebpackに食わせれば良い。すなわちこうなる

webpack.config.js
{
    /* 〜〜〜〜略〜〜〜〜 */
    module: {
        rules: [
            /* 〜〜〜〜略〜〜〜〜 */
            {
                test: /\.(sa|sc|c)ss$/,
                use: [
                    'vue-style-loader',
                    'css-loader',
                    'sass-loader',
                ],
                include: /node_modules/,
            },
            {
                test: /\.(sa|sc|c)ss$/,
                use: [
                    'vue-style-loader',
                    {
                        loader: 'css-loader',
                        options: {
                            modules: true
                        }
                    },
                    'sass-loader',
                ],
                exclude: /node_modules/,
            },
            /* 〜〜〜〜略〜〜〜〜 */
        ]
    }
    /* 〜〜〜〜略〜〜〜〜 */
}

webpackは配列のconfigでは末尾から処理されていくので、末尾側に options.modules: true にしたcss-loaderをセットして、 exclude: /node_modules/ する。

次に、先頭側に options.modules: false にした include: /node_modules/ する。

webpack5のドキュメントによれば

rule.exclude

Exclude all modules matching any of these conditions. If you supply a Rule.exclude option, you cannot also supply a Rule.resource.

マッチした全てのモジュールを除外する

rule.include

Include all modules matching any of these conditions. If you supply a Rule.include option, you cannot also supply a Rule.resource.

マッチした全てのモジュールを含める

つまり、これを組み合わせたルールを2重に定義することで、特定ディレクトリは純粋なCSSファイルとして、特定ディレクトリはCSSmoduleとしてwebpackに食わせることができる。

ちなみに、先頭側のcss-loaderルールから include: /node_modules/ を外してしまうと、既にwebpackを通しているcssが再度読み込み直されてしまうので注意。

所感

(カスタム性上げたい気持ちはわかるが)令和の時代にESmodule importで完結しない上にbabelを通さないとCSSをグローバル反映させる必要があるようなコンポーネントライブラリを作るな・・・

0
0
0

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
0
0