35
19

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 3 years have passed since last update.

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

Last updated at Posted at 2020-02-17

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

確認した環境

  • nuxt@2.11.0
  • スタイルはsass(scss)を選択

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

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

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タグ
  1. Indexページのstyleタグ

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

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

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

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

対処方法

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

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

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

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
  1. styles.css
  2. pages/index.css(ページ単位で生成され遷移のたびに追加される)

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

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

まとめ

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

35
19
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
35
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?