vue的不同构建版本的解释(阉割版vs完整版)
vue的不同构建版本的解释
前言:最近在做vue2组件库升级到vue3,有些高级组件用到了 组件选项对象 <component :is="{ 组件选项对象 }"></component>
,并且用到vue2的 extend,也支持组件选项对象。使用类似下面
// 创建构造器
var Profile = Vue.extend({ // 组件选项对象
template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
data: function () {
return {
firstName: 'Walter',
lastName: 'White',
alias: 'Heisenberg'
}
}
})
// 创建 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#mount-point')
问题是:升级到vue3后,发现并不支持了,感觉很难受,因为封装了组件选项的组件特别好用。 后面发现,引入另一个vue的构建版本就可以搞定了!!
解法也很简单,配置一下vue的构建版本即可。目前我用的是vite。用webpack配置文件也是一样的写法
// 找到 vite.config.js 或 webpack。config.js 或 vue.config.js
// 找到 resolve属性, 配置别名
resolve: {
alias: {
vue: 'vue/dist/vue.esm-bundler.js' // 增加这一行 , 增加动态编译的能力
}
}
要解释为什么这样就可以,需要理解vue的构建版本,首先需要知道vue的默认构建版本是什么?
vue的构建版本解释
问题:import { createApp } from 'vue'
(vue3的引入), from后面跟的是 vue哪个版本? 如果不用import不用打包,直接在script标签内用呢?vue是引入哪个构建版本?
- 打开vue的源码dist包 或 找vue的CDN,会有多个构建版本。默认是什么?分别是在什么场景下去用?
// 服务端渲染。 通过 `require()` 在 Node.js 服务器端渲染使用。
vue.cjs.js
vue.cjs.prod.js
// 使用构建工具,如 `webpack`,`rollup` 和 `parcel` 等打包出来的工程项目
vue.esm-bundler.js
vue.runtime.esm-bundler.js
// 通过浏览器中的 `<script src="...">` 直接使用,暴露全局Vue
vue.global.js
vue.global.prod.js
vue.runtime.global.js
vue.runtime.global.prod.js
// 在浏览器中通过 `<script type="module">` 来使用(浏览器原生 ES 模块导入使用)
vue.esm-browser.js
vue.esm-browser.prod.js
vue.runtime.esm-browser.js
vue.runtime.esm-browser.prod.js
我们使用vue可能会有4种场景:
-
通过浏览器中的
<script src="...">
直接使用,暴露全局Vue -
在浏览器中通过
<script type="module">
来使用(浏览器原生 ES 模块导入使用)- 使用带
esm-browser
关键字的**.esm-browser.**.js
- 使用带
-
使用构建工具,如
webpack
,rollup
和parcel
等打包出来的工程项目-
使用带
esm-bundler
关键字的**.esm-bundler.**.js
-
以下是 解决我上面提的问题,
import { createApp } from 'vue'
(vue3的引入) from后面默认 跟的是 vue哪个版本?-
是
vue.runtime.esm-bundler.js
(默认) -
特点:
-
vue.runtime.esm-bundler.js
是 仅运行版本(阉割版,体积小,不带动态编译的能力)。 要求所有模板(<template>..</template>
)都要预先编译(编译.vue文件)- 用vue-loader打包的过程中就编译了(
<template>..</template>
转成render(..)
)
- 用vue-loader打包的过程中就编译了(
-
构建工具的默认入口:
package.json
中的 module 字段 -
vue.esm-bundler.js
是:完整版(无阉割的,体积会大一些。能在打包编译后,还能识别<template>..</template>
模板代码,拥有编译模板的能力)
-
-
-
-
服务端渲染。 通过
require()
在 Node.js 服务器端渲染使用。- 使用带
cjs
关键字的**.cjs.**.js
- 使用带
细心的小伙伴应该有疑问, runtime 和 prod 是啥意思? 有什么区别? 比如
vue.esm-browser.js
vue.esm-browser.prod.js
vue.runtime.esm-browser.js
vue.runtime.esm-browser.prod.js
- prod:这个很好理解,就是生产环境使用的压缩版
- runtime:表示 仅运行版本(阉割版,体积小,不带动态编译的能力)。 要求所有模板(
<template>..</template>
)都要预先编译(编译.vue文件)- 用vue-loader打包的过程中就编译了(
<template>..</template>
转成render(..)
) - 但是如果,某些vue的api会用到动态编译的能力,比如 extend,那么这个阉割版就不适用了。需要用不带runtime的完整版
- 用vue-loader打包的过程中就编译了(
-
比如文章的开头,Vue.extend需要动态编译
<template>..</template>
模板的能力,所以需要使用不带runtime关键字的构建版本 以下是vue.extend的用法,感受一下运行时 动态编译// 创建构造器 var Profile = Vue.extend({ // 组件选项对象 template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>', data: function () { return { firstName: 'Walter', lastName: 'White', alias: 'Heisenberg' } } }) // 创建 Profile 实例,并挂载到一个元素上。 new Profile().$mount('#mount-point')
另外 render 方法是底层生成vnode的api,在任何一个vue的构建版本都需要,所以render方法不需要编译器
// 如果需要在客户端上编译模板 (即:将字符串传递给 template 选项,或者使用元素的 DOM 内 HTML 作为模板挂载到元素),你将需要编译器,因此需要完整的构建版本: // 需要编译器 使用不带runtime关键字的构建版本 Vue.createApp({ template: '<div>{{ hi }}</div>' }) // 不需要编译模板,可以用带runtime的阉割版 Vue.createApp({ render() { return Vue.h('div', {}, this.hi) } })
总结:
-
vue的构建版本为了适应不同的环境去使用,总的有4种版本
-
构建版本的名字中:除了4种环境外,还有2个关键字:prd和runtime
-
prd好理解,是压缩版,体积小
-
runtime版,可以理解为:阉割版,体积小,不带动态编译模板的能力
- 需要编译模板的能力的话,比如vue.extend,那么要用不带runtime的完整版,体积会稍微大一些
-
编译模板是什么意思?
比如,vue需要把
<template>..</template>
内的html代码,生成虚拟dom树,那么需要编译器,去解析html代码(可以理解为,把html 转成 js 代码,需要编译器,编译器是一个额外的引入),比如:模板
const profile = ( <div> <img src="avatar.png" className="profile" /> <h3>{[user.firstName, user.lastName].join(" ")}</h3> </div> );
编译后
import { jsx as _jsx } from "react/jsx-runtime"; import { jsxs as _jsxs } from "react/jsx-runtime"; const profile = _jsxs("div", { children: [ _jsx("img", { src: "avatar.png", className: "profile", }), _jsx("h3", { children: [user.firstName, user.lastName].join(" "), }), ], });
正常我们使用vue-loader,就是在打包阶段 编译好。所以默认是带runtime的阉割版,体积小
码字不易,点赞鼓励!
转载自:https://juejin.cn/post/7043991342166310942