Vue Loader 學習記錄
Vue Loader 是什麼?
webpack的lodaer. 單檔案元件 (SFCs)的格式撰寫元件。
<template> <div class="example">{{ msg }}</div> </template> <script> export default { data () { return { msg: 'Hello world!' } } } </script> <style> .example { color: red; } </style>
- 允許為 Vue 元件的每個部分使用其它的 webpack loader,例如在
<style>
的部分使用 Sass 和在<template>
的部分使用 Pug; - 允許在一個
.vue
檔案中使用自定義塊,並對其運用自定義的 loader 鏈; - 使用 webpack loader 將
<style>
和<template>
中引用的資源當作模組依賴來處理; - 為每個元件模擬出 scoped CSS;
- 在開發過程中使用熱過載
Vue CLI
腳手架
手動配置
// webpack.config.js const path = require('path') const VueLoaderPlugin = require('vue-loader/lib/plugin') module.exports = { mode: 'development', module: { rules: [ { test: /\.vue$/, loader: 'vue-loader' }, // 它會應用到普通的 `.js` 檔案 // 以及 `.vue` 檔案中的 `<script>` 塊 { test: /\.js$/, loader: 'babel-loader' }, // 它會應用到普通的 `.css` 檔案 // 以及 `.vue` 檔案中的 `<style>` 塊 { test: /\.css$/, use: [ 'vue-style-loader', 'css-loader' ] } ] }, plugins: [ // 請確保引入這個外掛來施展魔法 new VueLoaderPlugin() ] }
處理資源路徑
當 Vue Loader 編譯單檔案元件中的 <template>
塊時,它也會將所有遇到的資源 URL 轉換為 webpack 模組請求。
<img src="../image.png">
createElement('img', {
attrs: {
src: require('../image.png') // 現在這是一個模組的請求了
}
})
轉換規則
資源 URL 轉換會遵循如下規則:
-
如果路徑是絕對路徑 (例如
/images/foo.png
),會原樣保留。 -
如果路徑以
.
開頭,將會被看作相對的模組依賴,並按照你的本地檔案系統上的目錄結構進行解析。 -
如果路徑以
~
開頭,其後的部分將會被看作模組依賴。這意味著你可以用該特性來引用一個 Node 依賴中的資源: -
如果路徑以
@
開頭,也會被看作模組依賴。如果你的 webpack 配置中給@
配置了 alias,這就很有用了。所有vue-cli
建立的專案都預設配置了將@
指向/src
。
相關的 Loader
使用前處理器
Sass
需要先進行安裝以及在webpack中進行配置,就可以在css部分解析sass型別的檔案
sass-loader
會預設處理不基於縮排的 scss
語法。
共享全域性變數
sass-loader
也支援一個 data
選項,這個選項允許你在所有被處理的檔案之間共享常見的變數,而不需要顯式地匯入它們:
// webpack.config.js -> module.rules
{
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
// 你也可以從一個檔案讀取,例如 `variables.scss`
data: `$color: red;`
}
}
]
}
Less
less-loader
Stylus
stylus-loader
PostCSS
postcss-loader
Babel
babel的配置可以通過.babelrc 或babel-loader來完成
TypeScript
type-lodaer ->tsconfig.json來配置完成
Pug
HTML 字串的 loader,例如 pug-plain-loader
Scoped CSS
<style scoped>
.example {
color: red;
}
</style>
<template>
<div class="example">hi</div>
</template>
style scoped 只作用於當前元件中。
混用本地和全域性樣式
可以在一個元件中混合使用 本地樣式和全域性樣式(stlye帶不帶scpoed)
子元件的根元素
使用scoped以後,父元件的樣式不會滲透到子元件中。子元件的根節點受到父元件和其他元件樣式的影響。
深度作用選擇器
<style scoped>
.a >>> .b { /* ... */ }
</style>
>>>
留意點:
1.scoped不能代替class 會比class渲染的慢
2.在遞迴子元件中小心使用後代選擇器
CSS Modules
模組化和組合css的系統
css modules 需要css-loader中的modules為true.
// webpack.config.js
{
module: {
rules: [
// ... 其它規則省略
{
test: /\.css$/,
use: [
'vue-style-loader',
{
loader: 'css-loader',
options: {
// 開啟 CSS Modules
modules: true,
// 自定義生成的類名
localIdentName: '[local]_[hash:base64:8]'
}
}
]
}
]
}
}
在html中的部署 需要加上module
<style module>
.red {
color: red;
}
.bold {
font-weight: bold;
}
</style>
從而使得該style 成為一個vue-loader下的計算書型$style
可以進行繫結,也可以在 JS中訪問到它。
<template>
<p :class="$style.red">
This should be red
</p>
</template>
<template>
<div>
<p :class="{ [$style.red]: isRed }">
Am I red?
</p>
<p :class="[$style.red, $style.bold]">
Red and bold
</p>
</div>
</template>
<script>
export default {
created () {
console.log(this.$style.red)
// -> "red_1VyoJ-uZ"
// 一個基於檔名和類名生成的識別符號
}
}
</script>
可選用法
oneOf 匹配一部分的modules
// webpack.config.js -> module.rules
{
test: /\.css$/,
oneOf: [
// 這裡匹配 `<style module>`
{
resourceQuery: /module/,
use: [
'vue-style-loader',
{
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[local]_[hash:base64:5]'
}
}
]
},
// 這裡匹配普通的 `<style>` 或 `<style scoped>`
{
use: [
'vue-style-loader',
'css-loader'
]
}
]
}
和前處理器配合使用
可以與sass-loader 等其他處理器一起配合使用
自定義的注入名稱
<style module="a">
/* 注入識別符號 a */
</style>
<style module="b">
/* 注入識別符號 b */
</style>
熱過載
特別好的一點!!。可以在不重新整理頁面的情況下可以看到你修改的部分!!
狀態保留規則
- <template>重新渲染,保留私有狀態。
- <script>銷燬了並重新建立。元件狀態會保留,但可能含有其他鉤子,重新載入是必須的,保持一致性
- <style>會通過vue-style-loader自行熱過載。
關閉熱過載
- webpack 的
target
的值是node
(服務端渲染) - webpack 會壓縮程式碼
process.env.NODE_ENV === 'production'
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
hotReload: false // 關閉熱過載
}
}
]
}
函式式元件
函式式的元件需要新增functional特性
<template functional>
<div>{{ props.foo }}</div>
</template>
<template functional>
<div>{{ parent.$someProperty }}</div>
</template>
自定義塊
自定義語言塊。
resourceQuery
來為一個沒有 lang
的自定義塊匹配一條規則。
{
module: {
rules: [
{
resourceQuery: /blockType=foo/,
loader: 'loader-to-use'
}
]
}
}
為了注入自定義塊的內容,我們將會撰寫一個自定義 loader:
module.exports = function (source, map) {
this.callback(
null,
`export default function (Component) {
Component.options.__docs = ${
JSON.stringify(source)
}
}`,
map
)
}
<!-- ComponentB.vue -->
<template>
<div>Hello</div>
</template>
<docs>
This is the documentation for component B.
</docs>
<!-- ComponentA.vue -->
<template>
<div>
<ComponentB/>
<p>{{ docs }}</p>
</div>
</template>
<script>
import ComponentB from './ComponentB.vue';
export default {
components: { ComponentB },
data () {
return {
docs: ComponentB.__docs
}
}
}
</script>
CSS 提取
請只在生產環境下使用 CSS 提取,這將便於你在開發環境下進行熱過載。
webpack 4
npm install -D mini-css-extract-plugin
// webpack.config.js
var MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
// 其它選項...
module: {
rules: [
// ... 忽略其它規則
{
test: /\.css$/,
use: [
process.env.NODE_ENV !== 'production'
? 'vue-style-loader'
: MiniCssExtractPlugin.loader,
'css-loader'
]
}
]
},
plugins: [
// ... 忽略 vue-loader 外掛
new MiniCssExtractPlugin({
filename: style.css
})
]
}
webpack 3
npm install -D extract-text-webpack-plugin
// webpack.config.js
var ExtractTextPlugin = require("extract-text-webpack-plugin")
module.exports = {
// 其它選項...
module: {
rules: [
// ...其它規則忽略
{
test: /\.css$/,
loader: ExtractTextPlugin.extract({
use: 'css-loader',
fallback: 'vue-style-loader'
})
}
]
},
plugins: [
// ...vue-loader 外掛忽略
new ExtractTextPlugin("style.css")
]
}
程式碼校驗 (Linting)
ESLint
便於統一風格。規範程式碼格式。
Eslint 配置檔案
// .eslintrc.js
module.exports = {
extends: [
"plugin:vue/essential"
]
}
eslint --ext js,vue MyComponent.vue
或者:loader
npm install -D eslint eslint-loader
// webpack.config.js
module.exports = {
// ... 其它選項
module: {
rules: [
{
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /node_modules/
}
]
}
}
stylelint
stylelint 支援在 Vue 單檔案元件的樣式部分的程式碼校驗。
stylelint MyComponent.vue
或者:
npm install -D stylelint-webpack-plugin
// webpack.config.js
const StyleLintPlugin = require('stylelint-webpack-plugin');
module.exports = {
// ... 其它選項
plugins: [
new StyleLintPlugin({
files: ['**/*.{vue,htm,html,css,sss,less,scss,sass}'],
})
]
}
測試
-
Vue CLI 提供了預配置的單元測試和 e2e 測試安裝。
-
如果你有興趣為
*.vue
檔案手動設定單元測試,請查詢 @vue/test-utils 的文件,這份文件涵蓋了對 mocha-webpack 或 Jest 的設定。