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 的设置。