Nuxtで運用しているサービスで productionビルドリリース
したもののみスタイル崩れが発生する、という不具合に遭遇。
詳しく調査した結果、スタイル適用順序がproductionビルドとそれ以外とで違ってくる、というのが原因でした。
確認した環境
- nuxt@2.11.0
- スタイルはsass(scss)を選択
発生パターンと根本的な原因
これは幅広く発生するというものではなく、特定の条件の場合にのみ発生。
以下のように 自ら定義したカスタムコンポーネントにスタイル上書きをする
場合にのみ発生します。
<template>
<div class="container">
</div>
</template>
<style lang="scss" scoped>
.container {
width: 100%;
height: 100px;
background-color: #f00; // 背景色に赤を設定
}
</style>
<template>
<div>
<CustomComponent class="override" />
</div>
</template>
<style lang="scss" scoped>
.override {
background-color: #ff0; // CustomComponentの背景色を黄色で上書き
}
</style>
<script>
import CustomComponent from '~/components/CustomComponent';
export default {
components: {
CustomComponent,
},
};
</script>
こちらのコードを実行する際、 NODE_ENV=staging
や NODE_ENV=development
の場合には
- CustomComponentのstyleタグ
- Indexページのstyleタグ
の順でstyleタグが挿入されるため、想定した通りにCustomComponentの背景が黄色でスタイル上書きされます。
ですが NODE_ENV=production
ではこれが逆転し
- Indexページのstyleタグ
- CustomComponentのstyleタグ
の順でstyleタグ挿入されてしまうためスタイル上書きが効かなくなり、結果想定したスタイルが適用されなくなります。
対処方法
class属性でなくstyle属性で上書き
単純にスタイル詳細度を高めることにより、適用順序に関係なく上書きスタイルが想定通り適用されるようにします。
<template>
<div>
<CustomComponent :style="{'background-color': '#ff0'}" />
</div>
</template>
extractCSSをONにしてスタイル適用順序をコントロール
若干無理矢理感とextractCSSを入れること自体に抵抗があるかもしれませんが、一応載せます。
...
build: {
extractCSS: true,
optimization: {
splitChunks: {
cacheGroups: {
// globalスタイル
styles: {
name: 'styles',
test: /\.(css|scss)$/,
chunks: 'initial',
enforce: true
},
// components配下のスタイル
components: {
name: 'components',
test: /app\/components/,
chunks: 'all',
enforce: true
},
}
}
},
}
...
このようにbuildオプションを設定してcomponents配下のスタイルのみ別の外部cssとして吐き出し読み込みます。
この設定で
- components.css
- styles.css
- pages/index.css(ページ単位で生成され遷移のたびに追加される)
の順序でcss読み込みされるようになるため、pages/indexで定義したCustomComponentの上書きスタイルが常に想定通りに適用される、という寸法です。
style属性上書きの方が手軽ではありますが、こちらの場合は開発者が productionビルドの癖を意識せず自由に実装できる
というメリットがあります。
まとめ
どちらの対処方法も一長一短ではありますが、私が試行錯誤した範囲ではこの2つしか対処方法が見つかりませんでした。
(というかなんでproductionビルドでこの挙動になってるの・・・)
何か良い方法がありましたらぜひコメントでつっこみお願いします!