UUUM攻殻機動隊(エンジニアブログ)

UUUMのエンジニアによる技術ブログです

Vue単一ファイルコンポーネントで共通のSCSSファイルを読み込む

どうもエンジニアのやまぐちです。

年末はビルドツールを触る機会が多かったため寝ても覚めてもWebpackな感じでした。 そんな中で単一ファイルコンポーネントでSCSS共通の変数やmixinを使う場合に少し悩んだので、 同じように苦労している方がいれば参考にしていただけたら幸いです。

https://github.com/webpack-contrib/sass-loader

ディレクトリ構成

ディレクトリ構成は以下で進めていきます。

/example
 ├ webpack.config.js
 ├ dist
 │ ├ app.js
 │ └ index.html
 └ src
  └ assets
   ├ script
   │ ├ app.js
   │ └ App.vue
   └ style
     ├ global.scss
     ├ _mixins.scss
     └ _variables.scss

/src/assets/style/global.scssでは、更に変数とMixinのファイルをimportします。

# global.scss

@charset "utf-8";

@import "_variables";
@import "_mixins";

単純に@import

styleの中で@importすれば読み込むことが可能です。

# App.vue

<template>...</template>
<script>...</script>

<style lang='scss' scoped>
@import "../style/global.scss";

h1 {
  @include font-size($font-md);
}
</style>

しかし、この方法だと各ファイルのstyleに@importを記述する必要があり、保守性も悪いため実用的ではありません。

vue-loaderで設定

vueファイル内でscssを使うためにvue-loaderのオプションにsass-loaderを設定していると思います。
このsass-loaderのオプションを更に設定することで共通のscssファイルを読み込むことができます。

# webpack.config.js

module.exports = {
  entry: './resorces/assets/script/app.js',
  output: {
    path: './dist',
    filename: '[name].js',
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          loaders: {
            css: {
              loader: 'css-loader',
            },
            scss: {
              loader: 'sass-loader',
              options: {
                data: '@import "global.scss";',
                includePaths: path.resolve(__dirname, './src/assets/sass/'),
              }
            },
          },
        },
      },
      ...
    ],
    ...
  },
  ...
}

sass-loaderオプションのdataincludePathsを指定することにより共通のSCSSファイルを読み込むことができます。

  • dataにはstringが設定でき@importを記述することでビルドに読み込まれるvueファイル内に自動的に追加されます。
  • includePathsにはimportしたいファイルが格納されているパスを指定します。

上記の設定をすることで全ての.vueファイルのscssの記述で@importが必要なくなります。

もちろんこちらの設定はSCSSファイルをビルドする際にも使用できます。
(SCSSファイルのビルド時には起点となるファイルでimportすれば良いのであまり必要なさそうですが。。)

# App.vue

<template>...</template>
<script>...</script>

<style lang='scss' scoped>
h1 {
  @include font-size($font-md);
}
</style>

まとめ

Webpack側で上記の設定しておくことで単一ファイルコンポーネント側に余計な記述をしなくて済みました。 ただしwebpack.config.jsへ単純に記述してしまうとmoduleの中が冗長になってしまうので関数化するなどの対応をしたほうが良いと思いました。
頑張って調べたけれどもっと効率の良い方法などありましたらご教授お願いいたします!