Vue源码分析之-Vue的不同构建版本

目录

Vue的不同构建版本

Explanation of Build Files

Terms 术语

**运行时版本与含编译器版本的区别**

准备工作

总结:始终推荐大家使用运行时版本 vue.runtime.xxx.js


Vue的不同构建版本

        也就是打包之后产生的不同版本的vue.js

Explanation of Build Files

UMD CommonJS ES Module
Full vue.js vue.common.js vue.esm.js
Runtime-only vue.runtime.js vue.runtime.common.js vue.runtime.esm.js
Full (production) vue.min.js
Runtime-only (production) vue.runtime.min.js

Terms 术语

  • Full 完整版: builds that contain both the compiler and the runtime. 同时包含编译器和运行时的版本。

  • Compiler 编译器: code that is responsible for compiling template strings into JavaScript render functions.  用来将模版字符串转换为JavaScript渲染函数的代码,体积大,效率低。

  • Runtime 运行时: code that is responsible for creating Vue instances, rendering and patching virtual DOM, etc. Basically everything minus the compiler.  用来创建Vue实例,渲染并处理虚拟DOM等的代码,体积小,效率高,基本上就是除去了编译器的代码。

  • UMD: UMD builds can be used directly in the browser via a <script> tag. The default file from Unpkg CDN at https://unpkg.com/vue is the Runtime + Compiler UMD build (vue.js). UMD版本通用的模块版本,支持多种模块方式,vue.js默认文件就是运行时+编译器的UMD版本。

  • CommonJS: CommonJS builds are intended for use with older bundlers like browserify or webpack 1. The default file for these bundlers (pkg.main) is the Runtime only CommonJS build (vue.runtime.common.js). CommonJS用来配合老的打包工具,如Browserifywebpack 1

  • ES Module: ES module builds are intended for use with modern bundlers like webpack 2 or rollup. The default file for these bundlers (pkg.module) is the Runtime only ES Module build (vue.runtime.esm.js). 从vue2.6版本开始Vue会提供两个ES Modules(ESM)构建文件,为现代化打包工具提供的打包版本。

    • ESM格式被设计为可以被静态分析,所以打包工具可以利用这一点来进行代码树抖摇“tree-shaking”,将并用不到的代码排除出最终的包。(未来的趋势)

    • ES6模块与CommonJS模块的差异

      • 1、ES6 ModuleCommonJS模块的区别:

        • CommonJS 是对模块的浅拷贝,ES6 Module 是对模块的引用,即ES6 Module只存只读,不能改变其值,具体点就是指针指向不能变,类似 const
        • import 的接口是 read-only(只读状态),不能修改其变量值。 即不能修改其变量的指针指向,但可以改变变量内部指针指向,可以对 commonJS 对重新赋值(改变指针指向),但是对 ES6 Module 赋值会编译报错。
      • 2、ES6 ModuleCommonJS模块的共同点:

        • CommonJSES6 Module都可以对引入的对象进行赋值,即对对象内部属性的值进行改变。

**运行时版本与含编译器版本的区别**

准备工作

预先在examples目录下创建一个基本的Hello World的Vue示例,我们取名为01-runtime+compiler。

这个示例非常简单的,仅包含了一个index.html文件,内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">Hello World</div>
    <script src="../../dist/vue.js"></script>
    <script>
        // compiler 编译器,其目的是:把template模版字符串 转换成 render函数
        const vm = new Vue({
            el: '#app',
            template: '<h1>{
  {msg}}</h1>',
            data() {
                return {
                    msg: 'Welcome to Vue World'
                }
            },
        })
    </script>
</body>
</html>

这时候可以看到,我们在文件中通过script标签导入的是dist目录下的vue.js,就是运行时+编译器的UMD完整版本,其使用的模块化方式是UMD,支持在浏览器上直接使用,是包含了compiler编译器代码的,其中的编译器compiler部分代码就有三千多行。

从示例代码中,我们可以观察到,代码中我们创建了一个Vue实例vm,并且传入了一个template属性成员,也就是我们说的模版字符串。

上面示例代码我们在浏览器的运行结果如下:

 可以看到,页面上显示的结果是我们在构建Vue示例时传入的data的msg内容,已经替换掉了原本hard code在div#app中的Hello World。

打开开发者工具工具观察其渲染的DOM结构,如下:

 可以看到,原先写在html内的div#app被我们的vue实例的template中的h1标签给替换了。

接下来我们修改html中引入的vue的文件的版本为:运行时版本的UMD版本,即:vue.runtime.js。再运行查看我们修改后的运行结果:

 可以看到此时页面上什么的都输出,而console控制台出现了一个错误提示,如下:

[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

(found in <Root>)

错误提示的意思是:我们当前正在使用的是运行时的版本(runtime-only build),运行时版本中的不包含编译器的,这时候编译器不可用。有两种解决方案:1)通过预编译(pre-compile)把我们的templates模版转换成render函数;2)或者使用包含编译器的版本(compiler-included build),也就是说我们的模版是需要完整版才能运行的。 

方案2)我们前边已经演示了,是可以正常工作的。这时候我们任然想要使用我们的运行时版本,所以我们template属性成员注释掉,改之使用render函数,修改后的代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">Hello World</div>
    <script src="../../dist/vue.runtime.js"></script>
    <script>
        // compiler 编译器,其目的是:把template模版字符串 转换成 render函数
        const vm = new Vue({
            el: '#app',
            // template: '<h1>{
  {msg}}</h1>', // 需要在compiler-included build,即含编译器的完整版本下才能正常工作
            render(h) { // 可以在runtime-only build,即运行时版本中正常工作
                // render函数中的参数h, h是一个函数,它是虚拟DOM中用来创建虚拟DOM的。
                // render函数中需要把创建出来的虚拟DOM返回出去,才能被正常挂载并渲染到页面上
                return h('h1', this.msg) 
            },
            data() {
                return {
                    msg: 'Welcome to Vue World'
                }
            }
        })
    </script>
</body>
</html>

此时再来刷新我们的的浏览器查看页面的结果,如下:

 可以看到,运行结果跟我们原来在完整版中使用template的结果是一样的。

总结:

  • 1、完整版包含编译器,compiler-included build,而编译器部分的代码三千多行;
  • 2、运行时版不包含编译器,runtime-only build,所以体积会更小;
  • 3、运行时版本的执行效率要比完整版本的执行效率要更高一些。
  • 4、基于vue cli创建的项目默认使用的是运行时版本,配合大打包工具中使用的compiler,在编译阶段就已经可以把我们的.vue文件转换为render函数。

为了验证上面👆的第4点的说法,我们打开一个基于vue cli创建的的项目来参看一下。

 可以看到我们在src/main.js中使用import 导入了 vue,为了查看导入的vue到底是众多vue构建版本中的哪一个,我们需要打开这个项目下的webpack文件,但是vue cli对webpack做了一个深度的封装,所以我们在项目源代码中是看不到webpack的配置文件的。但是它也为我们提供了一个查看项目webpack配置的命令行工具: vue inspect 。  可以看到,使用vue inspect 输出的结果非常的长,不便于查看,我们可以简单使用: vue inspect | grep vue, 大概可以观察出来应该是为vue的引用文件设置了别名alias: vue$, 也就是在项目中使用 import Vue from 'vue' 就是相当于 import Vue from 'vue/dist/vue.runtime.esm.js' 。就是说默认import vue模块的时候,使用的就是vue的运行时版本的esm版本,使用esm模块因为项目使用webpack打包工具,可以方便的实现代码的类型静态分析,以达到实现代码tree-shaking的目的。

当然这里为了更好的查看webpack的配置是否如我们所想,我们还是老老实实版 vue inspect 命令行运行的结果内容输出到我们的物理文件中进行查看。这时我们可以使用命令:vu

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值