質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.34%

webpackでvueコンポーネントのsassをバンドルする方法

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,134

SystemAjisai

score 144

 前提・実現したいこと

webpack4というツールでバンドルする環境を作っています。

バンドル対象は、

  • ライブラリ(vue)
  • 自作のjavascript
  • 自作のvueコンポーネント(単一コンポーネント)
  • 自作のcss(sassで書いてます)

の4つです。

バンドルは無事にできたのですが、バンドルしたらcssがjsファイルの中に入ってしまうというのが、
どうしても脳みその中で処理しきれないので、
「MiniCssExtractPlugin」というプラグインを使って、cssだけ別ファイルにしたいと思っています。

以下のようなwebpack.config.jsを書いたら、無事に.cssファイルになったのですが、
vueの単一コンポーネントファイルの中に書いているcss(sass)だけ、
他のcssと一緒にバンドルされず、別のファイルになってしまいます。

cssファイルとvueのcssファイルと2個なので両方読み込めば問題ないのはわかるのですが、
なんだかスッキリしません。
.vueの中のcssも他のcssと同じファイル、もしくはこれだけjsの中に入れるというのはできないでしょうか。

 発生している問題・エラーメッセージ

![イメージ説明](00434619907fb338eaba3ad402cb79c5.png)

 該当のソースコード

webpack.config.js
※(追記)ミスがあったので差し替えました※

const path = require('path');
const { VueLoaderPlugin } = require("vue-loader");
const MiniCssExtractPlugin  = require("mini-css-extract-plugin");
const setPath = function(folderName) {
  return path.join(__dirname, folderName);
}
module.exports = {
  // development|production|none
  mode: 'development',
  entry: {
    // javascript
    "js/app" : "./resources/src/js/app.js",
    // css
    "main"   : "./resources/src/css/main.scss",
  },
  output: {
    path: setPath('/resources'),
    filename: "[name].js"
  },
  optimization: {
    splitChunks: {
      name: 'js/vendor',
      chunks: 'initial',
    }
  },
  module:{
    rules:[
      {
        test: /\.vue?$/,
        loader: 'vue-loader',
      },
      {
        test: /\.scss$/,
        use: [
            MiniCssExtractPlugin.loader,
            {
              loader: 'css-loader',
              options: {
                url: false, 
                minimize: true, 
                sourceMap: true
              }
            },
            {
              loader: 'sass-loader',
              options: {
                sourceMap: true
              }
            }
        ]
      }
    ]
  },
  plugins: [
    new VueLoaderPlugin(),
    new MiniCssExtractPlugin({
        // prefix は output.path
        filename: 'css/[name].css'
    })
  ]
}

test.vue
※vue公式の単一コンポーネントのテンプレートからテスト用にコピーしてちょっと変えたものです。

<template>
  <div id="app">
    <h1>{{ msg }}</h1>
    <h2>Essential Links</h2>
    <ul>
      <li><a href="https://vuejs.org" target="_blank">Core Docs</a></li>
      <li><a href="https://forum.vuejs.org" target="_blank">Forum</a></li>
      <li><a href="https://chat.vuejs.org" target="_blank">Community Chat</a></li>
      <li><a href="https://twitter.com/vuejs" target="_blank">Twitter</a></li>
    </ul>
    <h2>Ecosystem</h2>
    <ul>
      <li><a href="http://router.vuejs.org/" target="_blank">vue-router</a></li>
      <li><a href="http://vuex.vuejs.org/" target="_blank">vuex</a></li>
      <li><a href="http://vue-loader.vuejs.org/" target="_blank">vue-loader</a></li>
      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank">awesome-vue</a></li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'app',
  data () {
    return {
      msg:'Welcome to Your Vue.js App'
    }
  }
}
</script>
// ☆ここから↓だけ別のcssファイルになってしまいます。
<style lang="scss" scoped>
 #app {
   font-family: 'Avenir', Helvetica, Arial, sans-serif;
   -webkit-font-smoothing: antialiased;
   -moz-osx-font-smoothing: grayscale;
   text-align: center;
   color: #2c3e50;
   margin-top: 60px;
 }
 h1, h2 {
   font-weight: normal;
 }
 ul {
   list-style-type: none;
   padding: 0;
 }
 li {
   display: inline-block;
   margin: 0 10px;
 }
 a {
   color: #42b983;
 }
</style>

 試したこと

最初はwebpack.config.jsでexportsを1つにして、entryにjavascriptもcssも一緒に書いていました。 exportsは配列で渡せるとあったのでjsとsassの設定を分けて書いて、sass側だけプラグインの設定を書いてみた(掲載ソース)のですが、同じ結果になってしまいました。

(追記)
上記の方法ではバンドル時にエラーになっていました。
watchという、ファイルを変更したらすぐバンドルしてくれる機能を使っていましたが、
監視中にwebpack.config.jsを変えたせいか、全く反映されていませんでした。
掲載ソースは当初のものに差し替えました。

 環境

windows 10
Webpack 4.16.5
webpack-cli 3.1.0
css-loader 1.0.0
mini-css-extract-plugin 0.4.1
sass-loader 7.1.0
vue-loader 15.3.0
vue-template-compiler 2.5.17

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

0

無事に目的を果たせましたのでクローズします。

(追記)
落ち着いて考えたら変な回答を書いてしまったので訂正します。

そもそも、参考にしたサイトがエントリーポイントにsassファイルを書いていたので、
「javascriptとsassファイルは別のエントリーポイントを用意するものなんだ」
と勘違いしてしまっていましたが、
エントリーポイントをjavascript側だけにして、その中でsassをインポートすれば解決でした。

私がcssとjsを分けたかっただけで、本来全部1ファイルにバンドルしてくれるツールなんだから
エントリーポイントが1個でいいのは当たり前ですね。。。

以下、当初の回答
結果的にはどんなに無い知恵絞っても、Vueコンポーネント内のcssの記載を
他のsassファイルと一緒に1ファイルにバンドルすることができませんでした。
方向としてはVueコンポーネント内のcssの記載だけ、jsファイルに入れるようにしました。
方法はmodule.exportsの設定を複数(js用とsass用)に分けて書くことで解決できました。

私が間違ってたのは、
Vueコンポーネント内のsassも、書かれいているファイルは「~.vue」なので、

    module:{
      rules:[
        {
          test: /\.vue?$/,
          loader: 'vue-loader',
          options: {
           // ここら辺に何とかしてコンポーネント内のsassのバンドル設定を書く
          }
        },


と思っていましたが、 test: /\.scss$/ の設定が適用されていました。

このためバンドル時にエラーになったり、 test: /\.scss$/ 側の設定が適用されて
2つファイルができたりしてしまっていました。

js用のバンドル設定に test: /\.scss$/ のルールも増やし、
sass用のバンドル設定ではpluginsからVueLoaderPluginを消すことで解決できました。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る