Help us understand the problem. What is going on with this article?

Nuxtで本番リリースした際にのみスタイル崩れ

Nuxtで運用しているサービスで productionビルドリリース したもののみスタイル崩れが発生する、という不具合に遭遇。
詳しく調査した結果、スタイル適用順序がproductionビルドとそれ以外とで違ってくる、というのが原因でした。

確認した環境

発生パターンと根本的な原因

これは幅広く発生するというものではなく、特定の条件の場合にのみ発生。
以下のように 自ら定義したカスタムコンポーネントにスタイル上書きをする 場合にのみ発生します。

components/CustomComponent.vue
<template>
  <div class="container">
  </div>
</template>

<style lang="scss" scoped>
.container {
  width: 100%;
  height: 100px;
  background-color: #f00; // 背景色に赤を設定
}
</style>
pages/index.vue
<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=stagingNODE_ENV=development の場合には

  1. CustomComponentのstyleタグ
  2. Indexページのstyleタグ

の順でstyleタグが挿入されるため、想定した通りにCustomComponentの背景が黄色でスタイル上書きされます。

ですが NODE_ENV=production ではこれが逆転し

  1. Indexページのstyleタグ
  2. CustomComponentのstyleタグ

の順でstyleタグ挿入されてしまうためスタイル上書きが効かなくなり、結果想定したスタイルが適用されなくなります。

対処方法

1. class属性でなくstyle属性で上書き

単純にスタイル詳細度を高めることにより、適用順序に関係なく上書きスタイルが想定通り適用されるようにします。

pages/index.vue
<template>
  <div>
    <CustomComponent :style="{'background-color': '#ff0'}" />
  </div>
</template>

2. extractCSSをONにしてスタイル適用順序をコントロール

若干無理矢理感とextractCSSを入れること自体に抵抗があるかもしれませんが、一応載せます。

nuxt.config.js
  ...
  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として吐き出し読み込みます。
この設定で

  1. components.css
  2. styles.css
  3. pages/index.css(ページ単位で生成され遷移のたびに追加される)

の順序でcss読み込みされるようになるため、pages/indexで定義したCustomComponentの上書きスタイルが常に想定通りに適用される、という寸法です。

1のstyle属性上書きの方が手軽ではありますが、こちらの場合は開発者が productionビルドの癖を意識せず自由に実装できる というメリットがあります。

まとめ

どちらの対処方法も一長一短ではありますが、私が試行錯誤した範囲ではこの2つしか対処方法が見つかりませんでした。
(というかなんでproductionビルドでこの挙動になってるの・・・)
何か良い方法がありましたらぜひコメントでつっこみお願いします!

goodtea0223
渋谷のアメーバな会社に4年半勤めた後にフリーのフロントエンドエンジニアとして独立したしがないJS書きです。 よろしくお願いします。 JavaScript, React, Vue.js, Webpack, Node.js, PhantomJS
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした