美文网首页
vue-cli4 之 vue-loader 工作流程

vue-cli4 之 vue-loader 工作流程

作者: AizawaSayo | 来源:发表于2021-04-23 15:59 被阅读0次

    先整体过一遍 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 配置详解以及资源相对路径处理

    相关文章

      网友评论

          本文标题:vue-cli4 之 vue-loader 工作流程

          本文链接:https://www.haomeiwen.com/subject/minxrltx.html