Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
109
Help us understand the problem. What is going on with this article?
@uto-usui

《Nuxt.js》Sassの共通の変数やmixinを一括で各コンポーネントに読み込む方法。

More than 1 year has passed since last update.

Nuxt.js を利用したプロジェクトで、sass のどこからでも利用したい mixin や変数などを、各コンポーネントで個別にインポートせずに一括で読み込みます。 vue-loader にオプションを渡せばいいのですが、nuxt.config.js から webpack の設定を変更するには、少しだけ工夫が必要です。

導入は vue-cil でサクッと進めます。

/.terminal

npx create-nuxt-app your-title

パッケージのインストール

まず vue-loader で sass(scss) を解釈したいので、node-sass と sass-loader のパッケージをインストールします。

/.terminal

yarn add --dev node-sass sass-loader

nuxt.config.js の設定

nuxt.config.js に次のように記述します。

nuxt.config.js

module.exports = {
  build: {
    extend (config) {
      /**
       * vue-loader に オプションを渡す
       */
      const vueLoader = config.module.rules.find(rule => rule.loader === 'vue-loader');
      const { options: {loaders} } = vueLoader || { options: {} }
      if (loaders) {
        for (const loader of Object.values(loaders)) {
          changeLoaderOptions(Array.isArray(loader) ? loader : [loader])
        }
      }
      config.module.rules.forEach(rule => changeLoaderOptions(rule.use))
    }
  }
}

/**
 * loader の名前一致でオプションをセットする
 */
function changeLoaderOptions(loaders) {
  if (loaders) {
    for (const loader of loaders) {
      let options;
      switch (loader.loader) {
        case 'sass-loader':
          options = {
            includePaths: [
              path.resolve(__dirname, './assets/sass/foundation/variable/'),
              path.resolve(__dirname, './assets/sass/foundation/mixin/')
            ],
            data: '@import "_variable";\n@import "_mixin";'
          };
          break
// 他の loader を追加できる
//        case 'stylus-loader':
//          options = {
//            includePaths: [path.resolve(__dirname, './assets/sass/')],
//            import: ['_import']
//          }
//          break
      }
      if (options) {
        Object.assign(loader.options, options)
      }
    }
  }
}

config の引数から vue-loader にアクセスして、optionincludePaths にディレクトリ、 data に import したいファイルを渡します。
さらにこのコードでは stylus-loader など、Vue-loader の別の loader にもオプションが渡せるようにしています。

これで

_variable.scss

$white: #fafafa !default;

と、用意した変数が、

component.vue

<style lang="scss">

.ex {
  background-color: $white;
}

</style>

というふうにしてあげると、各コンポーネントで import せずに、利用できるようになります。

Nuxt Style Resources で かんたんに読み込む

Nuxt Style Resources というモジュールを利用すると、先に紹介したようなコードを記述せずにシンプルに変数の読み込みを実装できます。(nuxt-sass-resources-loader は終了しました)

/.terminal

yarn add @nuxtjs/style-resources

nuxt.config.js

module.exports = {
  modules: ['@nuxtjs/style-resources'],
  styleResources: {
   scss: [
    '~/assets/sass/foundation/variable/_index.scss',
    '~/assets/sass/foundation/mixin/_index.scss'
    ]
  }
}

というような感じで、手早く実装することができます。ちなみに、Nuxt Style Resources は LESS や Stylus にも対応しているので、同様の方法で必要なリソースを読み込むことができます。

基本はこの方法で実装する方が簡単だしお手軽だとは思いますが、一応 loader にどうやってオプションを渡すのかを理解しておくのも大切かなと思っています。

アトミックデザインの atoms としての変数に

ぼくはここで読み込むような変数や mixin 群を、アトミックデザインの atoms として捉えていて、「components / molecules - organisms」「layouts - templates」「pages - pages」 というように、Nuxt.js のディレクトリ構成と紐づけることができるので、Nuxt.js はアトミックデザインにかなり接近したフレームワークだなあというところで、気に入っています。🍟

nuxt.config.js をうまく扱えるようになると、 Nuxt.js と仲良くなれるみたいなので、またまとめていきたいと思います。

おわります。

109
Help us understand the problem. What is going on with this article?
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
uto-usui
Frontend Engineer @ note, inc. /Songwriter/Fav. 🐈🌸🎸📸📚🛠🍎☕️🍷👩🏻‍💻📻/Win. 👑 ACC TOKYO CREATIVITY AWARDS Finalist, FWA FOTD/ex. Condé Nast 🇯🇵 -WIRED

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
109
Help us understand the problem. What is going on with this article?