Vue 2.0的源码构建

Vue.js 源码是基于 Rollup 构建的,它的构建相关配置都在 scripts 目录下。

1. 构建脚本

通常一个基于 NPM 托管的项目都会有一个 package.json 文件,它是对项目的描述文件,它的内容实际上是一个标准的 JSON 对象。

我们通常会配置 script 字段作为 NPM 的执行脚本,Vue.js 源码构建的脚本如下:

{"script": {"build": "node scripts/build.js","build:ssr": "npm run build -- web-runtime-cjs,web-server-renderer","build:weex": "npm run build -- weex"}
}

这里总共有 3 条命令,作用都是构建 Vue.js,后面 2 条是在第一条命令的基础上,添加一些环境参数。

当在命令行运行 npm run build 的时候,实际上就会执行 node scripts/build.js,接下来我们来看看它实际是怎么构建的。

2. 构建过程

我们对于构建过程分析是基于源码的,先打开构建的入口 JS 文件,在 scripts/build.js 中:

let builds = require('./config').getAllBuilds()if (process.argv[2]) {const filters = process.argv[2].split(',')builds = builds.filter(b => {return filters.some(f => b.output.file.indexOf(f) > -1 || b._name.indexOf(f) > -1)})
} else {builds = builds.filter(b => {return b.output.file.indexOf('weex') === -1})
}build(builds)

这段代码逻辑非常简单,先从配置文件读取配置,再通过命令行参数对构建配置做过滤,这样就可以构建出不同用途的 Vue.js 了。接下来我们看一下配置文件,在 scripts/config.js 中:

const builds = {// Runtime only (CommonJS). Used by bundlers e.g. Webpack & Browserify'web-runtime-cjs': {entry: resolve('web/entry-runtime.js'),dest: resolve('dist/vue.runtime.common.js'),format: 'cjs',banner},// Runtime+compiler CommonJS build (CommonJS)'web-full-cjs': {entry: resolve('web/entry-runtime-with-compiler.js'),dest: resolve('dist/vue.common.js'),format: 'cjs',alias: { he: './entity-decoder' },banner},// Runtime only (ES Modules). Used by bundlers that support ES Modules,// e.g. Rollup & Webpack 2'web-runtime-esm': {entry: resolve('web/entry-runtime.js'),dest: resolve('dist/vue.runtime.esm.js'),format: 'es',banner},// Runtime+compiler CommonJS build (ES Modules)'web-full-esm': {entry: resolve('web/entry-runtime-with-compiler.js'),dest: resolve('dist/vue.esm.js'),format: 'es',alias: { he: './entity-decoder' },banner},// runtime-only build (Browser)'web-runtime-dev': {entry: resolve('web/entry-runtime.js'),dest: resolve('dist/vue.runtime.js'),format: 'umd',env: 'development',banner},// runtime-only production build (Browser)'web-runtime-prod': {entry: resolve('web/entry-runtime.js'),dest: resolve('dist/vue.runtime.min.js'),format: 'umd',env: 'production',banner},// Runtime+compiler development build (Browser)'web-full-dev': {entry: resolve('web/entry-runtime-with-compiler.js'),dest: resolve('dist/vue.js'),format: 'umd',env: 'development',alias: { he: './entity-decoder' },banner},// Runtime+compiler production build  (Browser)'web-full-prod': {entry: resolve('web/entry-runtime-with-compiler.js'),dest: resolve('dist/vue.min.js'),format: 'umd',env: 'production',alias: { he: './entity-decoder' },banner}
}

这里列举了一些 Vue.js 构建的配置,关于还有一些服务端渲染 webpack 插件以及 weex 的打包配置就不列举了。

对于单个配置,它是遵循 Rollup 的构建规则的。其中 entry 属性表示构建的入口 JS 文件地址,dest 属性表示构建后的 JS 文件地址。format 属性表示构建的格式,cjs 表示构建出来的文件遵循 CommonJS 规范,es 表示构建出来的文件遵循 ES Module 规范。 umd 表示构建出来的文件遵循 UMD 规范。

以 web-runtime-cjs 配置为例,它的 entry 是 resolve('web/entry-runtime.js'),先来看一下 resolve 函数的定义。

源码目录:scripts/config.js

const aliases = require('./alias')
const resolve = p => {const base = p.split('/')[0]if (aliases[base]) {return path.resolve(aliases[base], p.slice(base.length + 1))} else {return path.resolve(__dirname, '../', p)}
}

这里的 resolve 函数实现非常简单,它先把 resolve 函数传入的参数 p 通过 / 做了分割成数组,然后取数组第一个元素设置为 base。在我们这个例子中,参数 p 是 web/entry-runtime.js,那么 base 则为 web。base 并不是实际的路径,它的真实路径借助了别名的配置,我们来看一下别名配置的代码,在 scripts/alias 中:

const path = require('path')module.exports = {vue: path.resolve(__dirname, '../src/platforms/web/entry-runtime-with-compiler'),compiler: path.resolve(__dirname, '../src/compiler'),core: path.resolve(__dirname, '../src/core'),shared: path.resolve(__dirname, '../src/shared'),web: path.resolve(__dirname, '../src/platforms/web'),weex: path.resolve(__dirname, '../src/platforms/weex'),server: path.resolve(__dirname, '../src/server'),entries: path.resolve(__dirname, '../src/entries'),sfc: path.resolve(__dirname, '../src/sfc')
}

很显然,这里 web 对应的真实的路径是 path.resolve(__dirname, '../src/platforms/web'),这个路径就找到了 Vue.js 源码的 web 目录。然后 resolve 函数通过 path.resolve(aliases[base], p.slice(base.length + 1)) 找到了最终路径,它就是 Vue.js 源码 web 目录下的 entry-runtime.js。因此,web-runtime-cjs 配置对应的入口文件就找到了。

它经过 Rollup 的构建打包后,最终会在 dist 目录下生成 vue.runtime.common.js。

3. Runtime Only VS Runtime + Compiler

通常我们利用 vue-cli 去初始化我们的 Vue.js 项目的时候会询问我们用 Runtime Only 版本的还是 Runtime + Compiler 版本。下面我们来对比这两个版本。

3.1. Runtime Only

我们在使用 Runtime Only 版本的 Vue.js 的时候,通常需要借助如 webpack 的 vue-loader 工具把 .vue 文件编译成 JavaScript,因为是在编译阶段做的,所以它只包含运行时的 Vue.js 代码,因此代码体积也会更轻量

3.2. Runtime + Compiler

我们如果没有对代码做预编译,但又使用了 Vue 的 template 属性并传入一个字符串,则需要在客户端编译模板,如下所示:

// 需要编译器的版本
new Vue({template: '<div>{{ hi }}</div>'
})// 这种情况不需要
new Vue({render(h) {return h('div', this.hi)}
})

因为在 Vue.js 2.0 中,最终渲染都是通过 render 函数,如果写 template 属性,则需要编译成 render 函数,那么这个编译过程会发生运行时,所以需要带有编译器的版本。

很显然,这个编译过程对性能会有一定损耗,所以通常我们更推荐使用 Runtime-Only 的 Vue.js。

4. 总结

通过这一节的分析,我们可以了解到 Vue.js 的构建打包过程,也知道了不同作用和功能的 Vue.js 它们对应的入口以及最终编译生成的 JS 文件。尽管在实际开发过程中我们会用 Runtime Only 版本开发比较多,但为了分析 Vue 的编译过程,接下来重点分析的源码是 Runtime + Compiler 的 Vue.js。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/152905.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Autox.js和Auto.js4.1.1手机编辑器不好用我自己写了一个编辑器

功能有 撤销 重做 格式化 跳转关键词 下面展示一些 内联代码片。 "ui"; ui.layout( <drawer id"drawer"><vertical><appbar><toolbar id"toolbar"title""h"20"/></appbar><horizontal b…

get_cli_args函数

CLI是"Command Line Interface"的缩写&#xff0c;中文意为"命令行界面"。它是一种与计算机进行交互的方式&#xff0c;用户通过键盘输入文本命令来执行特定的任务&#xff0c;而不是通过图形用户界面&#xff08;GUI&#xff09;进行操作。在命令行界面中…

P1734 最大约数和

P1734 最大约数和 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 预处理出小于等于S的数的约数和&#xff0c;将一个数的值作为体积&#xff0c;这个数的约数和作为价值&#xff0c;之后01背包模板。 void solve() {int n; cin>>n;vector<array<int,2>> a…

Linux环境搭建(tomcat,jdk,mysql下载)

是否具备环境&#xff08;前端node&#xff0c;后端环境jdk&#xff09;安装jdk,配置环境变量 JDK下载 - 编程宝库 (codebaoku.com) 进入opt目录 把下好的安装包拖到我们的工具中 把解压包解压 解压完成&#xff0c;可以删除解压包 复制解压文件的目录&#xff0c;配置环境变量…

【opencv】debug报错HEAP CORRUPTION DETECTED

运行至第一句涉及矩阵运算的代码&#xff08;如cv::multiply&#xff09;时报错 HEAP CORRUPTION DETECTED: after Normal block (#45034) at 0x000001BDC586F0E0. CRT detected that the application wrote to memory after end of heap buffer.release下不会报错&#xff0…

vue3使用西瓜播放器播放flv、hls、mp4视频

vue3使用西瓜播放器播放flv、hls、mp4视频 安装相关的插件 npm install xgplayer npminstall xgplayer-flv npm install xgplayer-hls npm install xgplayer-mp4 组件封装 <template><div :id"${playerId}" /> </template> <script setup la…

PDF控件Spire.PDF for .NET【转换】演示:自定义宽度、高度将 PDF 转 SVG

我们在上一篇文章中演示了如何将 PDF 页面转换为 SVG 文件格式。本指南向您展示如何使用最新版本的 Spire.PDF 以及 C# 和 VB.NET 指定输出文件的宽度和高度。 Spire.Doc 是一款专门对 Word 文档进行操作的 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻…

MyBatis 快速入门

MyBatis 快速入门 前言什么是 MyBatis简介核心特性使用示例配置文件Mapper 接口SQL 映射文件使用 MyBatis 如果大家对以上的导读很懵怎么办&#xff01;没关系 往下阅读&#xff01; 1. MyBatis 介绍1.1. 什么是MyBatis1.2. 持久层1.3. 框架1.4. JDBC 弊端1.5.…

如何解决网站被攻击的问题:企业网络攻防的关键路径

在当今数字化时代&#xff0c;企业面临着不断升级的网络威胁&#xff0c;网站遭受攻击的风险也与日俱增。解决网站被攻击的问题对企业发展至关重要&#xff0c;不仅关系到企业的信息安全&#xff0c;也直接影响到企业的声誉和利益。从企业发展的角度出发&#xff0c;我们将探讨…

科技云报道:全球勒索攻击创历史新高,如何建立网络安全的防线?

科技云报道原创。 最简单的方式&#xff0c;往往是最有效的&#xff0c;勒索软件攻击就属于这类。 近两年&#xff0c;随着人类社会加速向数字世界进化&#xff0c;勒索软件攻击成为网络安全最为严重的威胁之一。今年以来&#xff0c;勒索软件攻击在全球范围内呈现快速上升态…

开源和闭源的优劣势比较

开源与闭源软件之争一直是技术领域一个备受关注的话题&#xff0c;而在近期特斯拉CEO马斯克的表态中&#xff0c;关于开源的讨论更是引发了广泛的关注。以下是一些关于开源和闭源的优劣势以及对未来大模型发展的一些见解&#xff1a; 开源软件的优势&#xff1a; 创新与合作&a…

HDCTF2023 - Reverse方向全WP

文章目录 [HDCTF 2023]easy_re[HDCTF 2023]easy_asm[HDCTF 2023]fake_game[HDCTF 2023]enc[HDCTF 2023]double_code[HDCTF 2023]买了些什么呢[HDCTF2023]basketball [HDCTF 2023]easy_re UPX壳&#xff0c;脱壳 一个base64编码。 [HDCTF 2023]easy_asm ida打开后可以看到xor 10…

【FPGA】IP核

一.IP核是什么 IP&#xff1a;知识产权&#xff0c;半导体产业中&#xff1a;在ASIC和FPGA中定义为预先设计好的电路功能模块。 在使用的时候其他用户可以直接调用IP核心。 二. 为什么要是有IP核 提高开发效率&#xff0c;减小设计和调试的时间&#xff0c;加速开发进程&am…

go 判断两棵树内容是否一致

goroutine http://127.0.0.1:3999/concurrency/8 question 使用 go 判断 两个 树 存放的 序列 是否 相同, 如果 相同 他们 被称为 equivalent_tree tree struct type Tree struct {Left *TreeValue intRight *Tree }由于 递归的 写法 比较简单, 此处 使用循环的 形式 来实…

Rabin加解密算法(python3)

Rabin加解密算法 详细代码如下&#xff1a; # 空空 # dahouzi.cn import random from sympy import isprimedef decrypt_rabin(c, p, q):"""解密 Rabin 密文Args:c (int): 密文p (int): 素数 pq (int): 素数 qReturns:tuple: 解密结果 M1, M2, M3, M4"&q…

数据库管理工具,你可以用Navicat,但我选DBeaver!

大家好&#xff0c;我是豆小匠。数据库GUI工具哪家强&#xff0c;众人遥指Navicat。 可是Navicat老贵了。 如果公司有正版授权的还好&#xff0c;如果没有正版授权&#xff0c;还不给你用盗版&#xff0c;那才叫绝绝子。 好了&#xff0c;主角登场&#xff0c;DBeaver&#x…

Protege简单教程(安装启动建模推理)

Protege 是一个用于本体编辑和OWL (Web Ontology Language) 开发的开源工具。下面是一个简单的 Protege 使用教程。 1. 下载和安装 Protege 首先&#xff0c;需要下载 Protege。可以从官方网站 Protege 下载最新版本。 2. 启动 Protege 安装完成后&#xff0c;启动 Protege…

基于安卓android微信小程序美容理发店预约系统app

项目介绍 为美容院设计一个系统以减少员工的工作量就成为了想法的初始状态。紧接着对美容院进行进一步的调查发现我的想法已然落后。基本上每个美容院都以有了自己的信息系统&#xff0c;并且做的已经较完善了。 在这时我突然想到&#xff0c;现在关注美容养生的人越来越多&am…

智能井盖传感器建设信息化时代智慧城市

近年来随着信息技术的快速发展和城市化进程的加速推进&#xff0c;智慧城市的概念逐渐成为现实。作为智慧城市生命线建设中的重要组成部分&#xff0c;智能井盖传感器的应用正在为城市的可持续发展和居民的生活质量提供新的解决方案。 智能井盖传感器能够实时监测井盖状态&…

小程序如何刷新当前页面

小程序可以通过调用wx.pageScrollTo()方法来实现刷新当前页面&#xff0c;该方法可以滚动页面并使页面滚动到顶部&#xff0c;从而达到刷新页面的效果。具体的操作步骤如下&#xff1a; 在需要刷新的页面中添加一个按钮或其他触发事件的元素。 绑定相应的点击事件&#xff0c;…