参考にさせていただいたページ
TextField.vueを編集する
src/javascripts/vue_applications/common/components/TextField.vue
のtemplate に以下の通り追記します。
<div class="mod-error-messages"> <ul class="mod-error-messages__list"> <li class="mod-error-messages__item"> sample message </li> </ul> </div>
ファイル末尾に以下の通り追記します。
<style lang="scss" scoped> .mod-error-messages { .mod-error-messages__list { box-sizing: border-box; } .mod-error-messages__item { color: #ff0000; } } </style>
TextField.vueは以下のようになりました。
<template> <section> <label>TextField: </label> <input :value="value" type="text" @input="onInput" > <div class="mod-error-messages"> <ul class="mod-error-messages__list"> <li class="mod-error-messages__item"> sample message </li> </ul> </div> <div class="test-synced-text"> value: {{ value }} </div> </section> </template> <script> import { mapState, mapGetters, mapActions, mapMutations } from 'vuex'; export default { name: 'TextField', computed: { ...mapState('textFieldUnit/textField', [ 'value', ]), }, methods: { ...mapMutations('textFieldUnit/textField', [ 'setState', ]), onInput(e) { this.setState({ key: 'value', value: e.target.value, }); }, }, } </script> <style lang="scss" scoped> .mod-error-messages { .mod-error-messages__list { box-sizing: border-box; border-radius: 4px; } .mod-error-messages__item { color: #ff0000; } } </style>
一度ビルドを実行してみる
以下のコマンドでビルドを実行してみます。
webpack -d
以下のようなエラーが出ました。
ERROR in ./src/vue_applications/components/TextField.vue?vue&type=style&index=0&id=273a995e&lang=scss&scoped=true& (./node_modules/vue-loader/lib??vue-loader-options!./src/vue_applications/components/TextField.vue?vue&type=style&index=0&id=273a995e&lang=scss&scoped=true&) 40:0 Module parse failed: Unexpected token (40:0) You may need an appropriate loader to handle this file type. | | > .mod-error-message { | color: red; | } @ ./src/vue_applications/components/TextField.vue?vue&type=style&index=0&id=273a995e&lang=scss&scoped=true& 1:0-160 1:176-179 1:181-338 1:181-338 @ ./src/vue_applications/components/TextField.vue @ ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib??vue-loader-options!./src/vue_applications/components/TextFieldUnit.vue?vue&type=script&lang=js& @ ./src/vue_applications/components/TextFieldUnit.vue?vue&type=script&lang=js& @ ./src/vue_applications/components/TextFieldUnit.vue @ ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib??vue-loader-options!./src/vue_applications/App.vue?vue&type=script&lang=js& @ ./src/vue_applications/App.vue?vue&type=script&lang=js& @ ./src/vue_applications/App.vue @ ./src/index.js
node_modulesを追加する
.vueにscssを記述できるように以下の4つのモジュールを追加します。
npm install --save-dev style-loader css-loader sass-loader node-sass
ここまでやった段階でのpackage.json
{ "name": "webpack_4_vue_introduction", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "watch": "webpack -d --watch", "test": "jest" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "@babel/cli": "^7.2.3", "@babel/core": "^7.4.0", "@babel/preset-env": "^7.4.2", "@vue/test-utils": "^1.0.0-beta.29", "babel-core": "^7.0.0-bridge.0", "babel-jest": "^24.5.0", "babel-loader": "^8.0.5", "css-loader": "^2.1.1", "jest": "^24.5.0", "jest-serializer-vue": "^2.0.2", "node-sass": "^4.11.0", "sass-loader": "^7.1.0", "style-loader": "^0.23.1", "vue-jest": "^3.0.4", "vue-loader": "^15.7.0", "vue-template-compiler": "^2.6.10", "webpack": "^4.29.6", "webpack-cli": "^3.3.0" }, "dependencies": { "vue": "^2.6.10", "vuex": "^3.1.0" } }
webpack.config.jsを編集する
rulesに渡している配列に以下の行を追加します。
.vueの中にscssを書くのですが、test: /\.scss$/,
のルールを追加することになります。
// 拡張子.scssのファイルに対する設定(.vueの中にscssを書きたい場合もここに設定します。) { test: /\.scss$/, use: [ { loader: 'style-loader', }, { loader: 'css-loader', }, { loader: 'sass-loader', }, ] },
ここまでやった段階でのwebpack.config.js
以下のようになっています。
const path = require('path'); const VueLoaderPlugin = require('vue-loader/lib/plugin'); module.exports = { // entry point entry: { 'javascripts/first_page': './src/javascripts/entry_points/first_page.js', }, // 出力するパスは絶対パスで書きます output: { path: `${__dirname}/webroot/packed`, filename: (arg) => { return '[name].bundle.js' }, }, // webpack4はlordersではなくなりました module: { rules: [ // 拡張子.vueのファイルに対する設定 { test: /\.vue$/, use: [ { loader: "vue-loader", options: { loaders: { js: 'babel-loader', }, }, }, ] }, // 拡張子.jsのファイルに対する設定 { test: /\.js$/, exclude: /node_modules/, use: [ { loader: 'babel-loader', }, ] }, // 拡張子.scssのファイルに対する設定(.vueの中にscssを書きたい場合もここに設定します。) { test: /\.scss$/, use: [ { loader: 'style-loader', }, { loader: 'css-loader', }, { loader: 'sass-loader', }, ] }, ] }, // デフォルトの設定値だけでは足りないことについて解決します resolve: { // モジュールを読み込むときに検索するディレクトリの設定 modules: [path.join(__dirname, 'src'), 'node_modules'], // importするときに省略できる拡張子の設定 extensions: ['.js', '.vue'], alias: { // importのファイルパスを相対パスで書かないようにsrcのrootを設定 '@': path.join(__dirname, 'src'), // 例えばmain.js内で `import Vue from 'vue';` と記述したときの`vue`が表すファイルパスを指定 'vue$': 'vue/dist/vue.esm.js' }, }, // プラグインを列挙 plugins: [ new VueLoaderPlugin() ], }
もう一度ビルドを実行してみる
以下のコマンドでビルドを実行してみます。
webpack -d
今度はビルド成功したと思います。
first_page.htmlをブラウザで開いてみる
スタイルが適用されて赤い文字になっているのがわかります。
また、開発者ツールなどで確認してみると、セレクタが追加されてscopedな状態になっていることがわかります。
おわりに
今回のポイントは.vueにstyleを書くために、.scssのルールを追加するところだと思います。
変数やmixinなど複数のコンポーネントで共通して使用する部分をsass-resources-loader
で読み込むことができるのでそのうちこの記事に追記するかもしれません。
次回はeslintで.vueと.jsの構文チェックをしようと思います。