1.vue-loader 的使用
相关的loader:
- vue-loader
- vue-style-loader
- vue-template-compiler 用于编译模板
- css-loader
- 如果使用css扩展语言,可能还需要导入:
- sass-loader/less-loader/url-loader等 vue-loader的🌰使用例子
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { VueLoaderPlugin } = require('vue-loader')
const isProduction = process.env.NODE_ENV === 'production'
const extractLoader = {
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../',
hmr: process.env.NODE_ENV === 'development'
},
}
const cssExtractplugin = new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css',
ignoreOrder: false
})
const webpackConfig = {
entry: {...},
output: {...},
optimization: {...},
resolve: {...},
modules: {
rules: [{
test: /.vue$/,
loader: 'vue-loader'
}, {
test: /.css$/,
oneOf: [{
resourceQuery: /?vue/,
use: [isProduction ? extractLoader : 'vue-style-loader', 'css-loader']
}, {
use: [isProduction ? extractLoader : 'style-loader', 'css-loader']
}]
},
...
]
},
plugins: [
new VueLoaderPlugin(),
isProduction ? cssExtractplugin : ''
]
}
2.vue-loader 工作原理
通过webpack通过vue-loader插件,把.vue文件转化为js。
- 注意里面包含3个部分: template、script、styles vue-loader 的工作流程
- template : 通过 vue-template-compiler 生成 ast 转 render,所有的render函数都会push到 staticRenderFns。
- script :返回的配置项对象 scriptExports。
- styles :通过 css-loader、vue-style-loader, 添加到 head 中, 或者通过 css-loader、MiniCssExtractPlugin 提取到一个公共的css文件中。
- 使用 vue-loader 提供的 normalizeComponent 方法, 合并 scriptExports、render、staticRenderFns, 返回构建vue组件需要的配置项对象 - options, 即 {data, props, methods, render, staticRenderFns...} 。
代码:
// 从 template区域块 获取 render、 staticRenderFns 方法
import { render, staticRenderFns } from "./App.vue?vue&type=template&id=89kjg85f&scoped=true&"
// 从 script区域块 获取 组件的配置项对象
import script from "./App.vue?vue&type=script&lang=js&"
export * from "./App.vue?vue&type=script&lang=js&"
// 获取 styles区域块的内容
import style0 from "./App.vue?vue&type=style&index=0&lang=css&"
// 获取 styles(scoped)区域块的内容
import style1 from "./App.vue?vue&type=style&index=1&id=89kjg85f&scoped=true&lang=css&"
/* normalize component */
import normalizer from "!../node_modules/_vue-loader@15.7.1@vue-loader/lib/runtime/componentNormalizer.js"
// 返回构建组件需要的配置项对象, 包含 data、props、render、staticRenderFns 等
var component = normalizer(
script,
render,
staticRenderFns,
false,
null,
"89kjg85f",
null
)
component.options.__file = "src/App.vue"
// 输出组件完整的配置项
export default component.exports
3.css scoped原理
当.vue 文件中的 style 标签有scoped 属性时,它的 css 样式 只作用于当前 组件中的元素。
css scoped 的 工作流程 如下:
- 使用 vue-loader 处理.vue文件,根据.vue文件 的 请求路径和文件内容,生成 .vue 文件的hash值, 如:89kjg85f;
- 如果 .vue 文件 的 某一个style 标签 有 scoped 属性,为.vue 文件 生成一个 scopedId,scopedId 的格式为 data-v-hash, 如:data-v-89kjg85f;
- 使用 vue-loader 从.vue 文件 中获取 style区域块(scoped) 的 样式内容(字符串) ;
- 如果使用了 less 或者 sass,要使用less-loader或者sass-loader 处理 样式内容,使样式内容 变为 浏览器可识别的css样式;
- 然后使用 PostCSS 提供的 parser 处理 样式内容,为 样式内容中的每一个 css选择器添加[data-v-hash];
- 再使用 css-loader;最后使用 style-loader把 css 样式添加到 head 中
- 或者通过 miniCssExtractPlugin 将 css 样式 提取一个公共的 css 文件中。
-
通过 normalizer 方法返回 完整的组件配置项 options, options 中有属性 _scopeId, 如 _scopedId: data-v-89kjg85f;
-
使用 组件配置项 options 构建组件实例,给组件中每一个dom元素 添加属性: data-v-hash。
-
经历上述过程,style(scoped)中的样式就变成了组件的私有样式。