vue的不同构建版本的解释

前言:最近在做vue2组件库升级到vue3,有些高级组件用到了 组件选项对象 <component :is="{ 组件选项对象 }"></component> ,并且用到vue2的 extend,也支持组件选项对象。使用类似下面

  1. // 创建构造器
  2. var Profile = Vue.extend({ // 组件选项对象
  3. template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
  4. data: function () {
  5. return {
  6. firstName: 'Walter',
  7. lastName: 'White',
  8. alias: 'Heisenberg'
  9. }
  10. }
  11. })
  12. // 创建 Profile 实例,并挂载到一个元素上。
  13. new Profile().$mount('#mount-point')

问题是:升级到vue3后,发现并不支持了,感觉很难受,因为封装了组件选项的组件特别好用。 后面发现,引入另一个vue的构建版本就可以搞定了!!

解法也很简单,配置一下vue的构建版本即可。目前我用的是vite。用webpack配置文件也是一样的写法

  1. // 找到 vite.config.js 或 webpack。config.js 或 vue.config.js
  2. // 找到 resolve属性, 配置别名
  3. resolve: {
  4. alias: {
  5. vue: 'vue/dist/vue.esm-bundler.js' // 增加这一行 , 增加动态编译的能力
  6. }
  7. }

要解释为什么这样就可以,需要理解vue的构建版本,首先需要知道vue的默认构建版本是什么?

vue的构建版本解释

问题:import { createApp } from 'vue'(vue3的引入), from后面跟的是 vue哪个版本? 如果不用import不用打包,直接在script标签内用呢?vue是引入哪个构建版本?

  • 打开vue的源码dist包 或 找vue的CDN,会有多个构建版本。默认是什么?分别是在什么场景下去用?
  1. // 服务端渲染。 通过 `require()` 在 Node.js 服务器端渲染使用。
  2. vue.cjs.js
  3. vue.cjs.prod.js
  4. // 使用构建工具,如 `webpack`,`rollup` 和 `parcel` 等打包出来的工程项目
  5. vue.esm-bundler.js
  6. vue.runtime.esm-bundler.js
  7. // 通过浏览器中的 `<script src="...">` 直接使用,暴露全局Vue
  8. vue.global.js
  9. vue.global.prod.js
  10. vue.runtime.global.js
  11. vue.runtime.global.prod.js
  12. // 在浏览器中通过 `<script type="module">` 来使用(浏览器原生 ES 模块导入使用)
  13. vue.esm-browser.js
  14. vue.esm-browser.prod.js
  15. vue.runtime.esm-browser.js
  16. vue.runtime.esm-browser.prod.js

我们使用vue可能会有4种场景:

  1. 通过浏览器中的 <script src="..."> 直接使用,暴露全局Vue
    • 使用带global关键字的 **.global.**.js
    • 提示:全局打包不是 UMD 构建的,它们被打包成 IIFEs,并且仅用于通过 <script src="..."> 直接使用。
  2. 在浏览器中通过 <script type="module"> 来使用(浏览器原生 ES 模块导入使用)
    • 使用带esm-browser关键字的 **.esm-browser.**.js
  3. 使用构建工具,如 webpackrollupparcel 等打包出来的工程项目
    • 使用带esm-bundler关键字的 **.esm-bundler.**.js
    • 解决我上面提的问题,import { createApp } from 'vue'(vue3的引入) from后面默认 跟的是 vue哪个版本?
      • 首先是通过打包工具构建的,所以是 带esm-bundler关键字的
      • vue.runtime.esm-bundler.js (默认) 仅运行时,并要求所有模板都要预先编译。这是构建工具的默认入口 (通过 package.json 中的 module 字段),因为在使用构建工具时,模板通常是预先编译的 (例如:在 *.vue 文件中)。
      • vue.esm-bundler.js 包含运行时编译器。如果你使用了一个构建工具,但仍然想要运行时的模板编译 (例如,DOM 内 模板或通过内联 JavaScript 字符串的模板),请使用这个文件。你需要配置你的构建工具,将 vue 设置为这个文件。
  4. 服务端渲染。 通过 require() 在 Node.js 服务器端渲染使用。
    • 使用带cjs关键字的 **.cjs.**.js

细心的小伙伴应该有疑问, runtime 和 prod 是啥意思? 有什么区别? 比如

  1. vue.esm-browser.js
  2. vue.esm-browser.prod.js
  3. vue.runtime.esm-browser.js
  4. vue.runtime.esm-browser.prod.js
  1. prod:这个很好理解,就是生产环境使用的压缩版
  2. runtime:表示 仅运行时(运行时的意思:项目在运行中 使用中)并要求所有模板都要预先编译,无动态编译的能力。 (某些vue的api会用到动态编译的能力)
  • 比如文章的开头,Vue.extend需要动态编译的能力,所以需要使用不带runtime关键字的构建版本 以下是vue.extend的用法,感受一下运行时 动态编译
    另外 render 方法是底层生成vnode的api,在任何一个vue的构建版本都需要,所以render方法不需要编译器
    另外,敲黑板:
    1. // 创建构造器
    2. var Profile = Vue.extend({ // 组件选项对象
    3. template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
    4. data: function () {
    5. return {
    6. firstName: 'Walter',
    7. lastName: 'White',
    8. alias: 'Heisenberg'
    9. }
    10. }
    11. })
    12. // 创建 Profile 实例,并挂载到一个元素上。
    13. new Profile().$mount('#mount-point')
    ```javascript // 如果需要在客户端上编译模板 (即:将字符串传递给 template 选项,或者使用元素的 DOM 内 HTML 作为模板挂载到元素),你将需要编译器,因此需要完整的构建版本:

// 需要编译器 使用不带runtime关键字的构建版本 Vue.createApp({ template: ‘

{{ hi }}
‘ })

// 不需要 Vue.createApp({ render() { return Vue.h(‘div’, {}, this.hi) } }) ```

  • 当使用 vue-loader 时,*.vue 文件中的模板会在构建时预编译为 JavaScript,在最终的捆绑包中并不需要编译器,因此可以只使用运行时构建版本(带runtime的,不做额外配置控制的话,vue脚手架 默认是用这个版本)。
    • 即使有vue-loader,如果需要 动态编译能力 的话,还是要用不带runtime的版本

码字不易,点赞鼓励!