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。
相关文章:
Vue 2.0的源码构建
Vue.js 源码是基于 Rollup 构建的,它的构建相关配置都在 scripts 目录下。 1. 构建脚本 通常一个基于 NPM 托管的项目都会有一个 package.json 文件,它是对项目的描述文件,它的内容实际上是一个标准的 JSON 对象。 我们通常会配置 script …...
Kubernetes Gateway API 攻略:解锁集群流量服务新维度!
Kubernetes Gateway API 刚刚 GA,旨在改进将集群服务暴露给外部的过程。这其中包括一套更标准、更强大的 API资源,用于管理已暴露的服务。在这篇文章中,我将介绍 Gateway API 资源,并以 Istio 为例来展示这些资源是如何关联的。通…...
直播间弹幕直播游戏开发教程
随着直播技术的不断发展,交互式弹幕直播游戏成为吸引用户参与的新兴方式。这种游戏融合了实时弹幕互动和直播视频,为观众和主播提供了更加丰富的互动体验。在这篇文章中,我们将探讨从概念到实现的步骤,帮助你打造一款引人入胜的交…...
通过AppLink把拼多多热门榜单商品同步至小红书
上篇说到AppLink当中定时调度方式如何配置,这次来演示一下,如何把热门榜单信息同步至小红书 1.拉取一个定时器作为触发动作,通过配置定时器调度时间将定时策略配置为每天执行一次 2.触发动作完成后通过好单库获取拼多多每日热门榜单…...
力扣题目学习笔记(OC + Swift)
训练思维,提高编程能力,不为刷题而刷题 文章目录 1. 两数之和Swift版本OC版本 2. 两数相加Swift实现OC实现 3.无重复字符的最长子串SwiftOC 4.寻找两个正序数组的中位数SwiftOC 1. 两数之和 给定一个整数数组 nums 和一个整数目标值 target,请…...
20. Spring源码篇之@Lookup详解
简介 Lookup注解可能平时开发中大家接触的少,但是又确实挺有用的,比如我们一个单例Bean注入了一个原型Bean,原型Bean的效果其实是会失效的,因为单例Bean一开始就实例化好了,后面也不会再变化,但我们可能需…...
2.5计划任务远程管理
2.5计划任务/远程管理 一、计划任务 1、计划任务概念解析 在Linux操作系统中,除了用户即时执行的命令操作以外,还可以配置在指定的时间、指定的日期 执行预先计划好的系统管理任务(如定期备份、定期采集监测数据)。RHEL6系统中…...
光伏、储能双层优化配置接入配电网研究(附带Matlab代码)
由于能源的日益匮乏,电力需求的不断增长等,配电网中分布式能源渗透率不断提高,且逐渐向主动配电网方向发展。此外,需求响应(demand response,DR)的加入对配电网的规划运行也带来了新的因素。因此,如何综合考…...
低代码服务商,中小型数字化软件服务商的新出路
数字化时代大背景下,企业信息化向数字化转型成为所有企业发展的必由之路,企业在对业务模式、流程、组织形式、信息技术等方面进行重新定义时,软件必然参与价值创造的全过程,这势必驱使软件成为推动数字化转型的“引擎”࿰…...
Arcgis 日常天坑问题2——三维场景不能不能加载kml图层,着手解决这个问题
arcgis js api官网介绍kml图层的地址: shttps://developers.arcgis.com/javascript/latest/api-reference/esri-layers-KMLLayer.html从文档里看到kml图层有诸多限制,比较重要的两点是: 1、不能在三维场景(SceneView࿰…...
Ubuntu22.04 交叉编译GCC13.2.0 for Rv1126
一、安装Ubuntu22.04 sudo apt install vim net-tools openssh-server 二、安装必要项 sudo apt update sudo apt upgrade sudo apt install build-essential gawk git texinfo bison flex 三、下载必备软件包 1.glibc https://ftp.gnu.org/gnu/glibc/glibc-2.38.tar.gz…...
什么是EVM?以太坊EVM合约交互
目录 什么是EVM? 为什么 EVM 很重要? 结论 虚拟机引擎 以太坊虚拟机...
Vue Treeselect el-tree-select 多选 只选中第三级
话不多说,直接看代码: <Treeselect v-model"scope.row.mdeptIds" :normalizernormalizer :defaultExpandLevel"2" :disable-branch-nodes"true" :multiple"true":append-to-body"true" :z-index"9999" style…...
Stable Diffusion专场公开课
从SD原理、本地部署到其二次开发 分享时间:11月25日14:00-17:00 分享大纲 从扩散模型DDPM起步理解SD背后原理 SD的本地部署:在自己电脑上快速搭建、快速出图如何基于SD快速做二次开发(以七月的AIGC模特生成系统为例) 分享人简介 July&#…...
【Typroa使用】Typroa+PicGo-Core(command line)+gitee免费图片上传配置
TyproaPicGo-Core(command line)gitee免费图片上传配置 本文是在win10系统下配置typroapicGo-Core(command line)gitee图片上传的教程。需要的环境和工具有: gitee账号,新建仓库及token令牌;已经安装了的typroa,需要0.9.98版本以上…...
【云原生-Kurbernetes篇】HPA 与 Rancher管理工具
文章目录 一、Pod的自动伸缩1.1 HPA1.1.1 简介1.1.2 HPA的实现原理1.1.3 相关命令 1.2 VPA1.2.1 简介1.2.2 VPA的组件1.2.3 VPA工作原理 1.3 metrics-server简介 二、 HPA的部署与测试2.1 部署metrics-serverStep1 编写metrics-server的配置清单文件Step2 部署Step3 测试kubect…...
Python学习笔记(4)
《Python编程:从入门到实践》学习笔记 1.文件和异常 1.1 从文件中读取数据 1.1.1 读取整个文件 要读取文件,需要一个包含几行文本的文件。下面首先来创建一个文件,它包含精确到小数 点后30位的圆周率值,且在小数点后每10位处都换…...
算法通关村第十二关-青铜挑战字符串
大家好我是苏麟 , 今天带来字符串专题 . 转换成小写字母 描述 : 给你一个字符串 s ,将该字符串中的大写字母转换成相同的小写字母,返回新的字符串。 题目 : LeetCode 709.转换成小写字母 : 709. 转换成小写字母 分析 : 这个题可以先遍历整个字符串…...
网站被反诈拦截该怎么申诉与解封
随着互联网的发展,网络诈骗问题也日益突出。为了打击这类问题,反诈中心采取了一系列的措施,如打击违规诈骗网站和APP,标记诈骗手机号等。虽然这些措施在一定程度上取得了效果,但是也不可避免会出现审核不到位的情况。 …...
【机器学习】033_反向传播
一、计算图、反向传播原理 1. 回顾前向传播 例:假设现在有一个神经网络,其仅有一个输出层和一个神经单元 定义 定义 ,即激活函数对激活值不再做具体处理 定义平方损失函数 ,计算a的值与真实值的差距 此时,通过计算…...
无数据收集AI:在线学习与信号生成技术实战指南
1. 项目概述:当AI不再需要“喂养”数据最近和几个做量化交易的朋友聊天,他们都在为一个问题头疼:模型训练需要海量的历史数据,但市场是动态变化的,去年的“圣杯”策略今年可能就失效了。重新收集、清洗、标注数据&…...
别再让Spark JOIN拖慢你的任务了:手把手教你根据数据量选对策略(附实战参数调优)
Spark JOIN性能优化实战:从策略选择到参数调优全指南 在数据量爆炸式增长的时代,Spark JOIN操作已成为ETL流程和数据分析中最耗时的环节之一。许多数据团队都遇到过这样的困境:明明集群资源充足,一个看似简单的JOIN查询却运行了数…...
华为CANN/ops-math反射填充3D梯度算子
ReflectionPad3dGrad 【免费下载链接】ops-math 本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。 项目地址: https://gitcode.com/cann/ops-math 产品支持情况 产品是否支持Ascend 950PR/Ascend 950DTAtlas A3 训练系列产品/Atlas A3 推…...
CANN/cannbot-skills NPU推理优化
【免费下载链接】cannbot-skills CANNBot 是面向 CANN 开发的用于提升开发效率的系列智能体,本仓库为其提供可复用的 Skills 模块。 项目地址: https://gitcode.com/cann/cannbot-skills name: infer-model-optimize-team description: NPU 模型推理优化助手…...
为你的OpenClaw智能体工作流配置Taotoken作为模型供应商
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 为你的OpenClaw智能体工作流配置Taotoken作为模型供应商 基础教程类,面向使用OpenClaw框架构建AI智能体工作流的开发者…...
从零实现扩散模型:数学原理与PyTorch实战图像生成
1. 项目概述与核心价值最近几年,AI图像生成领域最让人兴奋的突破,莫过于扩散模型(Diffusion Models)的崛起。从DALLE 2、Midjourney到Stable Diffusion,这些能根据一句话就生成惊艳图片的工具,其核心引擎都…...
基于Electron与LLM的CK3智能对话模组开发实战
1. 项目概述:当《十字军之王3》的宫廷角色开始“思考”如果你和我一样,是个策略游戏迷,同时又对AI技术充满好奇,那么“Voices of the Court”(宫廷之声)这个项目绝对会让你眼前一亮。简单来说,这…...
CANN π₀.₅模型训练优化说明
π₀.₅ 模型训练昇腾迁移与性能优化说明 【免费下载链接】cann-recipes-embodied-intelligence 本项目针对具身智能业务中的典型模型、加速算法,提供基于CANN平台的优化样例 项目地址: https://gitcode.com/cann/cann-recipes-embodied-intelligence 背景介…...
Go语言消息队列监控:指标采集与告警
Go语言消息队列监控:指标采集与告警 1. 监控指标 消息队列系统需要监控的指标包括队列深度、消费延迟、消息吞吐量、错误率等。 package mqmonitorimport ("context""sync""time""github.com/prometheus/client_golang/promethe…...
基于Claude的智能任务编排引擎:从对话到执行的AI范式跃迁
1. 项目概述:一个基于Claude的智能任务编排与执行引擎最近在GitHub上看到一个挺有意思的项目,叫eyaltoledano/claude-task-master。光看名字,你可能会觉得这又是一个简单的Claude API调用封装。但深入研究后,我发现它的定位远不止…...
