Vue3 构建模式详解:如何选择最适合你的方式

603 阅读3分钟

准备工作

当设计一个框架时,我们有三种选择:纯运行时、运行时+编译时、纯编译时。为了做出合适的决策,你需要清楚地知道什么是运行时,什么是编译时,它们各自有什么特征,对框架有哪些影响。

Vue 有两个主要部分:编译器(Compiler)和运行时(Runtime),这两部分可以分别或一起使用,这就导致了 Vue 有三种主要的构建方式:纯运行时、运行时+编译器、纯编译器。

  1. 纯运行时:此构建方式仅包含运行时部分。由于模板需要编译器来编译成 JavaScript,这种构建方式中无法在 Vue 组件中直接编写模板。因此,需要预编译模板(例如,使用 Vue 单文件组件或 webpack 的 vue-loader 插件),或者使用 render 函数。

  2. 运行时+编译器:这是 Vue.js 的完整构建,包含运行时和编译器。这样可以直接在 Vue 组件中编写模板,Vue.js 会在运行时编译这些模板。尽管这使开发更方便,但会导致最终的代码体积变大,因为包含了编译器。

  3. 纯编译器:在这种构建方式中,Vue.js 只包含编译器部分。这种构建方式比较少见,通常在特殊的构建工具中使用。

通常情况下,在开发环境(npm run dev)中使用运行时+编译器构建,而在生产环境(npm run build)中使用纯运行时构建。

我们以 packages/vue 为例,因为它的 dist 目录下包含了所有的构建版本,共 12 个,结构如下:

├── packages/
│   ├── vue/
│   │   ├── dist/
│   │   ├   ├── vue.cjs.js
│   │   ├   ├── vue.cjs.prod.js
│   │   ├   ├── vue.esm-browser.js
│   │   ├   ├── vue.esm-browser.prod.js
│   │   ├   ├── vue.esm-bundler.js
│   │   ├   ├── vue.global.js
│   │   ├   ├── vue.global.prod.js
│   │   ├   ├── vue.runtime.esm-browser.js
│   │   ├   ├── vue.runtime.esm-browser.prod.js
│   │   ├   ├── vue.runtime.esm-bundler.js
│   │   ├   ├── vue.runtime.global.js
│   │   ├   ├── vue.runtime.global.prod.js

接下来,我们来探讨这 12 个构建版本之间的不同之处。

构建版本说明

构建版本开发版生产版运行时版
esm-bundler.esm-bundler.js.esm-bundler.prod.js.runtime.esm-bundler.js
esm-browser.esm-browser.js.esm-browser.prod.js.runtime.esm-browser.js
global.global.js.global.prod.js.runtime.global.js 和 .runtime.global.prod.js
cjs.cjs.js.cjs.prod.js
  • 开发版: 包含完整的警告和调试模式,未压缩和混淆,用于开发环境。

  • 生产版: 移除了警告和调试模式,经过压缩和混淆,用于生产环境。

  • 运行时版: 更轻量,不包含模板编译器,不能编译模板。

1. esm-bundler

这种构建模式适用于现代打包器,如 Rollup,支持 tree-shaking 和代码分割。主要优势是可以按需引入 Vue 的特性,减小最终的打包体积。包含开发版、生产版和运行时版:

  1. 开发版:.esm-bundler.js

  2. 生产版:.esm-bundler.prod.js

  3. 运行时版:.runtime.esm-bundler.js

以下是一个使用示例:

import { createApp } from 'vue'

const app = createApp({
  data() {
    return {
      message: '瓶子'
    }
  }
})

app.mount('#app')

2. esm-browser

适用于 Web 开发中使用原生 ES 模块进行编写和打包。由于现代浏览器都支持 ES modules,因此可以直接在浏览器中使用 Vue,无需打包步骤。但不能进行 tree-shaking,可能会导致最终的代码体积较大。包含开发版、生产版和运行时版。

  1. 开发版:.esm-browser.js

  2. 生产版:.esm-browser.prod.js

  3. 运行时版:.runtime.esm-browser.js

以下是一个使用示例:

<!DOCTYPE html>
<html>
<body>
    <div id="app">
        {{ message }}
    </div>

    <!-- 引入 Vue 的 ESM Browser 构建 -->
    <script type="module">
      import { createApp } from 'https://unpkg.com/vue@next/dist/vue.esm-browser.js'

      const app = createApp({
        data() {
          return {
            message: '瓶子'
          }
        }
      })

      app.mount('#app')
    </script>
</body>
</html>

3. global

为浏览器直接使用的构建版本,将所有核心功能以及常用插件打包在一起,并暴露为全局变量 Vue,可以直接在 HTML 中使用。包含开发版、开发运行时版、生产版和生产运行时版。

  1. 开发版:.global.js

  2. 开发运行时版:.runtime.global.js

  3. 生产版:.global.prod.js

  4. 生产运行时版:.runtime.global.prod.js

该版本通过 <script> 标签直接引入:

<!DOCTYPE html>
<html>
  <body>
    <div id="app">
      {{ message }}
    </div>

    <!-- 引入通过 global 构建的文件 -->
    <script src="https://unpkg.com/vue@next"></script>

    <script>
      const app = Vue.createApp({
        data() {
          return {
            message: "瓶子"
          }
        }
      })

      app.mount("#app")
    </script>
  </body>
</html>

4. cjs

使用 CommonJS 规范构建,可以和 Node.js 一起使用。包含开发版和生产版。

  1. 开发版:.cjs.js

  2. 生产版:.cjs.prod.js

以下是一个使用示例:

// 引入 Vue
const { createApp } = require('vue')

const app = createApp({
  data() {
    return {
      message: '瓶子'
    }
  },
  mounted() {
    console.log(this.message)
  }
})

app.mount('#app')