vue-cli4 之 vue-loader 工作流程

先整体过一遍 vue-cli4 处理单文件组件 (SFCs)的大致过程

webpack并不认识.vue后缀的单文件组件,因此需要强大的 vue-loader 来处理。

首先,vue-loader 通过@vue/component-compiler-utils解析.vue源代码,为每个语言块生成一个导入(可以将每个块看作一个“虚拟模块”),这一步实际返回的模块代码看起来像这样:

// import <template> 块
import render from 'source.vue?vue&type=template'
// import <script> 块
import script from 'source.vue?vue&type=script'
export * from 'source.vue?vue&type=script'
// import <style> 块
import 'source.vue?vue&type=style&index=1'

script.render = render
export default script

VueLoaderPlugin插件会基于webpack配置的每个模块规则, 创建针对 Vue 相应语言块请求的克隆版本。vue-cli 已经为.js文件配置了 babel-loader 和 cache-loader,因此这个规则也会被复制并应用到导入的<script>模块。同样地, import 的<style> 块会按需应用 sass-loader、css-loader、vue-style-loader 等预处理器、 <template> 的部分则会交由 pug-plain-loader 和 raw-loader 处理。

在webpack内部,一个import script from 'source.vue?vue&type=script'的模块请求会被扩展为:

import script from 'babel-loader!vue-loader!source.vue?vue&type=script'

如果对 “用 import 方式指定文件loader相关规则” 不清楚,可以参阅【 webpack 之 Loader 详解内联方式(inline) 部分】和 【loader使用之内联方式】。

相似地, 假设为 *.scss 文件配置了 style-loader + css-loader + sass-loader,

<style scoped lang="scss">
...
</style>

经由 vue-loader 解析后返回:

import 'source.vue?vue&type=style&index=1&scoped&lang=scss'

跟着被webpack扩展为:

import 'style-loader!css-loader!sass-loader!vue-loader!source.vue?vue&type=style&index=1&scoped&lang=scss'

像这样,vue-loader 经多重处理,使 Vue 组件同时可以使用其它loader,然后用自己的专用 loader 链处理每个语言块,最终将这些块组装到一个ES Module中。它的默认导出是一个包含 Vue.js 组件选项的对象。

<style><template> 中引用的资源会被当作模块依赖来处理

模版,即<template>的内容将被提取并以模版字符串的形式传递给 vue-template-compiler,预处理为 JavaScript 渲染函数,并最终注入到从 <script> 导出的组件中。
Vue Loader 编译<template>块时,会将遇到的资源URL转为 webpack 模块请求。即将资源作为模块 require() 进来。
比如模版中有如下代码片段,

<img src="../image.png">

会被编译成:

createElement('img', {
  attrs: {
    src: require('../image.png') // 现在这是一个模块的请求了
  }
})

任何匹配 .css (或通过 <style> 的 lang 特性指定的扩展名) 文件的 webpack 规则都将会运用到 <style> 块的内容中。

<style scoped>块内部的 CSS 只作用于当前组件中的元素,在应用css-loader之前,它会先通过postcss-loader进行以下转换来实现样式的本地化:

<style scoped>
.example {
  color: red;
}
</style>

<template>
  <div class="example">hi</div>
</template>

转换结果:

<style>
.example[data-v-f3f3eg9] {
  color: red;
}
</style>

<template>
  <div class="example" data-v-f3f3eg9>hi</div>
</template>

<style>块都会经过 css-loader 处理,来把其中 @import 和 url() 的资源URL转为模块请求。如果是<style lang='sass'>,在 css-loader 之前还要先执行 sass-loader,把 sass 文件转换 成 css。

// 把 `@import` 或`url()` 变成 `require()`
url(../image.png) => require('../image.png')

webpack 会在 import 或 "load(加载)" 模块时预处理文件。而资源URL经解析转换后指向的文件(如.png)仍然不是js模块,就需要 url-loaderfile-loader 进一步处理了。
vue-cli4 的默认配置中,当资源小于4kb( url-loader 配置项 limit 定义的值 )就会被转换成内联的 base-64 URL,这会大大减少小文件的 HTTP 请求数。而如果文件大于该阈值,会自动交给 file-loader 处理。
源码详见./node_modules/@vue/cli-service/lib/config/base.js

file-loader 可以指定要复制/放置资源文件的目标位置,以及使用版本哈希命名这些文件以获得更好的缓存。此外,还会在打包输出中自动重写文件路径为正确的 URL(文件访问路径)。这意味着你可以按自己的喜好管理输出文件的目录或文件名,并且可以在开发时使用相对路径,完全不用担心部署时 URL 会出问题。

样式的最后处理:非生产环境,vue-style-loader 会往 head 标签中注入多个 style 标签。而生产环境,mini-css-extract-plugin插件会将 CSS 样式提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 .css 文件,并且支持 CSS 和 SourceMaps 的按需加载。

关于 file-loader 的具体配置,请移步 file-loader 配置详解以及资源相对路径处理

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355

推荐阅读更多精彩内容