写点什么

三言两语说透 webpack 对 vue 的编译

  • 2023-08-07
    福建
  • 本文字数:2908 字

    阅读完需:约 10 分钟

1.写在前面


Webpack 作为当下最流行的前端构建工具,它可以处理模块化的 JavaScript 项目,进行代码打包和优化。在 Vue 项目中,Webpack 发挥着不可或缺的作用,它负责分析项目中的依赖图谱,递归地构建 bundles,从而实现整个项目的构建。


那么 Webpack 是如何处理 Vue 单文件组件的呢?它又是通过哪些具体的步骤实现 Vue 项目的打包和部署的呢?这是每一个 Vue 开发者都应该理解和掌握的关键知识点。

2.前置条件


当我们使用 Vue CLI 创建一个 Vue 项目时,会自动配置 Webpack 相关的配置。在项目的根目录下会有一个 webpack.config.js 文件,这就是 Webpack 的配置文件。


我们来看一下这个配置文件中与 Vue 相关的主要内容:


// webpack配置const vueLoaderPlugin = require('vue-loader/lib/plugin') 
module.exports = { // ...省略其他配置 module: { rules: [ // ... 其他规则 { test: /\.vue$/, loader: 'vue-loader' } ] },
plugins: [ // 请确保引入这个插件! new vueLoaderPlugin() ]}
复制代码


vue-loader 是 Vue 单文件组件(SFC)的 Webpack 加载器,它允许你以单文件组件的格式开发 Vue 组件。在 Vue 3 中,vue-loader 封装了 @vue/compiler-sfc,用于预处理单文件组件。我们来看看 vue-loader 的源码是如何工作的。

3.源码分析


在 vue-loader 的源码中,定义了一个 NormalModule 类,这是 webpack 模块中代表一个模块的类。在它的 build 方法中,会调用 this._compile 方法对单文件组件进行加载和解析:


// webpack/lib/NormalModule.js
class NormalModule { // ... build(options, compilation, resolver, fs, callback) { this._compile(options, compilation, resolver, fs, (err, result) => { // 处理结果... }); }
_compile(options, compilation, resolver, fs, callback) { const loaderContext = this.createLoaderContext(resolver, options, fs, compilation);
runLoaders( { resource: this.resource, loaders: this.loaders, context: loaderContext, readResource: fs.readFile.bind(fs) }, (err, result) => { // 处理结果... } ); }}
复制代码


在 _compile 中,会调用 runLoaders 方法,执行配置的所有 loader,其中就包含了 vue-loader。

接下来我们看一下 vue-loader 的源码,主要的是 pitch 方法:


// vue-loader/index.js
module.exports.pitch = function(remainingRequest) { const { loaders, resourcePath, resourceQuery } = this;
const doTransform = !remainingRequest.includes(hotReloadAPIPath); // 过滤热重载请求
if (doTransform && resourceQuery && resourceQuery.includes('type=script')) { // 处理 <script> 部分 }
if (doTransform && resourceQuery && resourceQuery.includes('type=template')) { // 处理 <template> 部分 }
if (doTransform && resourceQuery && resourceQuery.includes('type=style')) { // 处理 <style> 部分 }
// 调用默认的 pitch 方法 defaultPitch.call(this, remainingRequest); };
复制代码


pitch 方法会在一个 loader 处理资源之前被调用。在 vue-loader 中利用这一点,根据 resourceQuery 中传入的 type,分别处理单文件组件中的三个部分:

  • <script> 部分会使用 babel-loader 进行编译;

  • <template> 部分会使用 @vue/compiler-sfc 进行编译,输出 render 函数;

  • <style> 部分会使用 css-loader 和 style-loader 处理。


接下来我们重点看一下对 <template> 的处理:


const { compileTemplate } = require('@vue/compiler-sfc')
const compiled = compileTemplate({ source: templateContent, filename, id})
// 处理编译结果
复制代码


这里使用了 @vue/compiler-sfc 的 compileTemplate 方法来编译模板,会得到编译后的 render 函数代码。

对样式部分的处理也类似,使用 compileStyle 方法编译生成 CSS 代码。

通过这种方式,vue-loader 最终输出浏览器可执行的 JS 代码和 CSS 样式代码,以及一些模块之间的依赖关系,供 webpack 进行模块合并打包。

综上,我们看到 vue-loader 的主要工作就是调用 @vue/compiler-sfc 对每个部分进行编译,输出浏览器可用的代码。并利用 webpack 的模块机制,输出浏览器可用的 bundle。


这种做法的优点是:

  • 将组件的三部分代码进行了逻辑上的分割,更清晰;

  • 编译过程可以复用 compiler 模块,并做缓存等优化;

  • 可以方便地对每个部分使用不同的 loader 做深度处理。


通过源码分析,我们可以更深入理解 vue-loader 的工作原理,以及 Vue SFC 的编译过程。这可以帮助我们更好地掌握单文件组件的开发方式,编写规范的组件代码。

4.大厂面试回答


在大厂面试中经常会出现这个问题,那么需要在下面几个方面进行回答:


  • 说明 Vue 项目中,Webpack 的作用是打包构建 Vue 组件、资源等,输出浏览器可执行的代码。

  • 介绍在 Vue 项目中,使用 vue-loader 来解析 Vue 的单文件组件(.vue 文件)。

  • 解释 vue-loader 会将单文件组件的模板编译为 render 函数,脚本部分编译为 JS 代码,样式提取为 CSS 代码。

  • 举例说明 vue-loader 对组件模板的编译过程,使用了 @vue/compiler-sfc 的 compileTemplate 方法。

  • 概述对组件脚本的处理,会经过 babel 转译,解析 ES6 等代码为 ES5。描述对样式的处理,使用 CSS 加载器提取并处理为浏览器可用的 CSS。

  • 解析出组件之间的依赖关系,输出给 Webpack 进行模块打包。

  • 总结 Webpack 通过 vue-loader 解析组件,输出经过优化的浏览器可执行代码。


下面就是可以详细回答的内容:


在 Vue 项目中,Webpack 的作用是对代码进行模块打包和构建,最终输出浏览器可以直接执行的 JavaScript 代码。为了实现这个目的,Webpack 需要解析 Vue 的单文件组件,也就是以.vue 结尾的文件。


Webpack 通过 vue-loader 来专门处理 Vue 组件的解析。vue-loader 会将单文件组件分割成三部分,分别是模板代码、脚本代码和样式代码。对于模板部分,vue-loader 会使用 @vue/compiler-sfc 中的 compileTemplate 方法把模板编译成 render 函数,这是 Vue 实际运行时使用的渲染逻辑。对于脚本部分,会使用 babel 对其进行编译和转换,输出符合 ES5 标准的 JavaScript 代码。样式部分则会通过 CSS 加载器进行处理,最终提取并生成浏览器可用的 CSS 样式。


在解析组件的过程中,vue-loader 还会分析出组件之间的依赖关系,例如组件导入了其它子组件等。这些依赖关系的信息会输出给 Webpack,用于其进一步进行模块 Resolve 和依赖收集,最终生成浏览器可执行的 JavaScript 代码。


所以,Webpack 通过 vue-loader 解析 Vue 组件,对不同部分应用不同的加载器进行转换和处理,输出一个优化且浏览器可执行的 JavaScript 包,以及所需的 CSS、资源等,从而实现了对整个 Vue 项目的构建和打包。这大大简化了 Vue 项目的开发流程。

5.总结

总结来说,vue-loader 为 Vue 单文件组件提供了非常好的 webpack 支持。通过分析它的源码,可以让我们对 Vue SFC 的编译过程有一个更清晰全面的理解,加深对 Vue 开发的掌握。理解其工作原理也有助于我们更好地运用它,解决实际开发中遇到的问题。

发布于: 刚刚阅读数: 4
用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
三言两语说透webpack对vue的编译_源码_互联网工科生_InfoQ写作社区