Vue源码解读 Day1

本文解析了Vue源码的打包过程,介绍了package.json中的打包命令,详细讲解了配置文件scripts/config.js中的构建选项,以及RuntimeOnly与Runtime+Compiler的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Vue源码解读 Day1

从源码打包入手,解读Vue源码

1. 启动脚本

启动脚本文件是package.json,脚本命令在“script”对象中。
在这里插入图片描述

vue文件打包命令有三条,后两条是在第一条命令的基础上,添加一些环境参数。

2. build文件发生了什么?

2.1 检查是否存在用于存放打包文件的dist目录,如果没有就创建dist目录

在这里插入图片描述

2.2 获取所有环境打包过程中的配置信息在这里插入图片描述

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

配置属性如下:

  • entry:构建的入口 JS 文件地址
  • dest:构建后的 JS 文件地址
  • format:构建的格式(cjs、es、umd)
  • env:环境(development、production)
  • banner:打包后的App.vue文案
  • alias: 别名
  • plugins:插件
  • external:外部依赖,引用某个package.json中的dependencies

部分配置详情:

const builds = {
  // Runtime only (CommonJS). Used by bundlers e.g. Webpack & Browserify
  'web-runtime-cjs-dev': {
    entry: resolve('web/entry-runtime.js'),
    dest: resolve('dist/vue.runtime.common.dev.js'),
    format: 'cjs',
    env: 'development',
    banner
  },
  'web-runtime-cjs-prod': {
    entry: resolve('web/entry-runtime.js'),
    dest: resolve('dist/vue.runtime.common.prod.js'),
    format: 'cjs',
    env: 'production',
    banner
  },
  // Runtime+compiler CommonJS build (CommonJS)
  'web-full-cjs-dev': {
    entry: resolve('web/entry-runtime-with-compiler.js'),
    dest: resolve('dist/vue.common.dev.js'),
    format: 'cjs',
    env: 'development',
    alias: { he: './entity-decoder' },
![在这里插入图片描述](https://img-blog.csdnimg.cn/1fbaaa3a5e9f4af2bd9ace64742ad6b0.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAbmV3IOS4gOS4quS4lueVjA==,size_20,color_FFFFFF,t_70,g_se,x_16)
    banner
  },
  'web-full-cjs-prod': {
    entry: resolve('web/entry-runtime-with-compiler.js'),
    dest: resolve('dist/vue.common.prod.js'),
    format: 'cjs',
    env: 'production',
    alias: { he: './entity-decoder' },
    banner
  },
  // Runtime only ES modules build (for bundlers)
  'web-runtime-esm': {
    entry: resolve('web/entry-runtime.js'),
    dest: resolve('dist/vue.runtime.esm.js'),
    format: 'es',
    banner
  },
  // Runtime+compiler ES modules build (for bundlers)
  '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+compiler ES modules build (for direct import in browser)
  'web-full-esm-browser-dev': {
    entry: resolve('web/entry-runtime-with-compiler.js'),
    dest: resolve('dist/vue.esm.browser.js'),
    format: 'es',
    transpile: false,
    env: 'development',
    alias: { he: './entity-decoder' },
    banner
  },
  ...others
}

3. 以 web-runtime-cjs 配置为例深入理解构建过程

她的entry是resolve(‘web/entry-runtime.js’),先来看一下 resolve 函数的定义。
源码目录:/scripts/config.js

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。注意web并不是真实路径,它的真实路径借用了别名的配置。别名配置如下(scripts/alias):

const path = require('path')

const resolve = p => path.resolve(__dirname, '../', p)

module.exports = {
  vue: resolve('src/platforms/web/entry-runtime-with-compiler'),
  compiler: resolve('src/compiler'),
  core: resolve('src/core'),
  shared: resolve('src/shared'),
  web: resolve('src/platforms/web'),
  weex: resolve('src/platforms/weex'),
  server: resolve('src/server'),
  sfc: resolve('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

在构建配置中我们能看到Runtime only 和 Runtime+compiler两大模块。同时在我们利用 vue-cli 脚手架去初始化 Vue.js 项目的时候会询问是用 Runtime Only 版本的还是 Runtime+Compiler 版本。那么他们到底有什么区别,以及优劣呢。下面我们来对比这两个版本。

  • Runtime Only
    我们在使用 Runtime Only 版本的 Vue.js 的时候,通常需要借助如 webpack 的 vue-loader 工具把 .vue 文件编译成 JavaScript,因为是在编译阶段做的,所以它只包含运行时的 Vue.js 代码,因此代码体积也会更轻量。
// 不需要译器的版本
new Vue({
	render (h) {
		return h('div', this.hi)
	}
})
  • Runtime+Compiler
    我们如果没有对代码做预编译,但又使用了 Vue 的 template 属性并传入一个字符串,则需要在客户端编译模板,如下所示:
// 需要编译器的版本
new Vue({
	template: '{{ hi }}'
})

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值