vue-loader 要約
公式ドキュメント
lang属性とloader
Vueのファイルは3つの言語ブロック(template
、 script
、style
)から構成されるが、これらの言語ブロックにはそれぞれデフォルト言語がある。
言語ブロック | デフォルト言語 |
---|---|
template | html |
script | javascript |
style | css |
scriptではTypeScriptを、styleではSCSSといった他の言語を使用したい場合はlang属性
をつけることでvue-loaderがバンドルする前に適切なloaderを理解し、先にデフォルト言語への変換処理を行う。
<script lang="ts"></script>
<style lang="scss"></style>
lang属性とloaderはセットで設定することを忘れないように。
babel-loaderの役割
<script>
タグを処理してES2015(ES6)を使用できるようにする。
コマンドで実行すればbabel-loaderの設定は記載済みになっている。
module: {
rules: [{
test: /\.(js|jsx)$/,
include: [path.resolve(__dirname, 'src')],
loader: 'babel-loader'
},
vue-loaderが.vueファイルを処理後、babel-loaderが.jsを処理する。
スタイル関連
動的に生成されるコンテンツへのスタイル
v-html
などによって生成されるDOMはScoped CSSの影響を受けることができない。
その場合はディープセレクタ を使うことができる。
<style scoped>
.a >>> .b { /* ... */ }
</style>
頭の片隅に。
Scoped CSS vs CSS Modules
Scoped CSS
ブラウザのインスペクタで確認すると下記のようになっている。
<div data-v-xxxx>
<h1 data-v-xxxx class="title">Hello!</h1>
</div>
1つのコンポーネント内で共通のカスタムデータ属性(=data-v-xxxx
)が付与されることで、このコンポーネントのスタイルは外部へ影響しないように制御している。
.title[data-v-xxx] {
color: 'red';
}
クラスについても末尾にカスタムデータ属性をくっつけることで実質一意にしている。
CSS Modules
<div>
<h1 class="HeaderText_title_xxx">Hello</h1>
</div>
クラス名を[コンポーネント名]_[class名]_[ランダムな文字列]
に上書きすることでクラス名を一意にしている。
Scoped CSS
Cons: 子要素で同じ名前のクラスをつけた場合にスタイルが漏洩する。
ここで実際のコードを見ると理解できる。
親のカスタムデータ属性は子要素にも引き継がれていくので同じクラス名wrapper
に対し、親のスタイルが子要素にもかかってしまっている。
Modules CSS
Pros: どこのコンポーネントで定義しているスタイルがあたっているのか即座に理解できる
クラス名が [コンポーネント名]_[class名]_[ランダムな文字列]
に変換されるため。
Pros: モジュールとしての扱いやすさ
すべてのクラスは$styleオブジェクトを介して利用できるため、propsを介して必要な深さまでクラスを渡すことができ、子コンポーネントの任意の場所でクラスを非常に簡単に使用できる。
<template>
< BasePanel
title = " Lorem ipsum "
:titleClass = " $style.title"
>>
// コンテンツ
</ BasePanel >
</template>
【結論】
使いやすさから小~中規模のプロジェクトではScoped CSSで良さそうだが、大規模なプロジェクトではModules CSSを採用した方が堅牢に組むことができる。
Post CSSの役割
vue-loader
が処理したCSSをスコープされたものに書き換える。
ホットリロード機能
.vue
ファイルを編集した時に再読み込みなしで変更を反映してくれる。
コマンド webpack-dev-server --hot
で有効にできる。
アセットURLハンドリング
css-loaderと協力して<style>
タグと<script>
タグ内のアセットのURLを解決してくれる。