webpack对vue文件的打包(五)

25 Vue源代码的打包

1.介绍

npm install vue@next --save

先安装vue3

在webpack的入口文件main.js里面写入以下代码


import {createApp} from "vue"

const app = createApp({
  template:"<h2>{{title}}</h2>",
  data(){
    return {
      title:"i am vue"
    }
  }
});

app.mount("#app");

运行npm run build, 没有报错

然后打开dist中的index.html,发现并没有显示 i am vue

打开控制台,发现报错

runtime-core.esm-bundler.js:38 [Vue warn]: Component provided template option but runtime compilation is not supported in this build of Vue. Configure your bundler to alias "vue" to "vue/dist/vue.esm-bundler.js". 
08_babel对JS-Vue处理_11.jpg

2. vue版本(runtime-compiler and runtime-only)

08_babel对JS-Vue处理_13.jpg

如果选择对template进行打包,就需要选择第一种,因为compiler就是对template进行编译的。但是vue默认使用的是版本二:runtime-only, 不包含对template的编译,所以编译不会成功,界面渲染不出来。

render函数就是直接渲染出来虚拟节点v-dom

runtime-compiler

使用

new Vue({
    el:"#app",
    template: '<App/>',//template替换el里面的内容
    components:{App}
})

当我们把template传给Vue实例的时候,它会被保存在Vue实例下面的options,

template被解析(parse)成抽象语法树,ast(abstract syntax tree),

然后第三步,complier,编译成render函数

通过render函数把template翻译成virtual dom,虚拟dom

转换成真实的dom

template(html)->ast->render ->vdom ->真实dom

runtime-only(1.性能更高 2.下面的vue代码量更少)

new Vue({
    el:'#app',
    render:h => h(App)
})

render ->vdom ->真实dom

new Vue({
    el:'#app',
      render: function (createElement){
    //1. 普通用法:传入标签createElement('标签',{标签的属性},[''])
    /* return createElement('h2',
     {class:'box'},
    ['Hello! world!', createElement('button', {class:'mybtn'}, ['按钮'])]) */
          

    //2.传入组件对象:
    //return createElement(cpn)
    return createElement(App)
          //创建出来的标签,替换掉之前的<div id="app"><div>
          
    //那么.vue文件中的template是由谁编译的呢?
    //是由vue-template-compier来解析的,将.vue里面的template解析成render函数的,在main.js里面引用的不是整个.vue文件
    //引用的是被解析后的App对象,对象里面没有包含任何关于tenplate信息,所有的template已经转成render函数了


  }
    
})

简单总结
如果在之后的开发中,你依然使用template,就需要选择Runtime-Compiler
如果你之后的开发中,使用的是.vue文件夹开发,那么可以选择Runtime-only

3.vue打包后不同版本解析

08_babel对JS-Vue处理_12.jpg

D:\FrontEnd\07_codershy_Vue3s\webpack_study\code\06_webpack_vue\node_modules\vue\dist文件夹 里面有很多版本的vue。

vue.global.js就是我们cnd引入时候的文件。

如果你不需要编译template,就可以只使用runtime的版本,vue.runtime.global.js

vue.runtime.global.prod.js 是要不要使用生产版本,生成版本是做过压缩的。

  • vue.global.js包含编译器和运行时的完整版,构建过程中支持动态模板编译
  • vue.runtime.global.js 仅预编译了构建过程中的运行时和必要的模板

第二个是正常src引用的话,就是第一个方式,上面的方式,但是表明了src = .. type="module"的时候使用现在这个。

第三个是在wenpack等构建工具中使用。分两个,一个有complier,一个没有。默认使用的是只有runtime的版本 vue.runtime.esm-bundler.js, 不包含对template的解析,所以没有显示出来。

import {createApp} from 'vue/dist/vue.esm-bundler'
//这样npm run build之后,就会渲染出来
//把main.js总的import换成'vue/dist/vue.esm-bundler' 而不是默认的vue.runtime.esm-bundler.js

vue.runtime.esm-bundler.js默认)仅运行时,且要求所有模板必须预编译。这是构建工具的默认入口(通过package.js的module字段),因为当使用构建工具模板时一般都是预编译的(例如:*.vue文件)

vue.esm.bundler.js:包含运行时编译器。当你使用了构建工具但仍然想编译运行时模板(例如,in-DOM模板或通过javascript字符的内联模板)。你需要在构建工具中配置vue别名到这个文件。

vue.cjs(.prod).js:

4.全局标识的配置

08_babel对JS-Vue处理_14.jpg

5.VSCode对SFC文件的支持

08_babel对JS-Vue处理_15.jpg

6 编写App.vue代码

08_babel对JS-Vue处理_16.jpg
//main.js
import { sum } from "./js/math";
const { priceFormat } = require("./js/format");
import "./js/element.js"
import {createApp} from 'vue/dist/vue.esm-bundler'
import App from './vue/App.vue'

console.log(sum(20, 30));
console.log(priceFormat());

/* const app = createApp({
  template: `<h2>我是vue渲染出来的</h2>`,
  data(){
    return { 
      title: "hello world"
    }
  }
}); */

const app = createApp(App)
app.mount("#app");

template在public的index.html里面,js在main.js里面,这样的话比较麻烦,如果有样式的话,就更麻烦了,三个部分在三个不同的文件里,为了解决这个问题,我们就有了.vue文件,把这三个部分放到一个文件里面。

在src里面创建一个vue文件夹,里面创建一个App.vue文件

App.vue

<template>
<h2>我是Vue渲染出来的</h2>
<h2>{{title}}</h2>
</template>

<script>
export default {
  data() {
    return {
      title: "Hello world",
      message:"hahahha"
    }

  },
  methods: {

  }
}
</script>

<style>
h2{
  color: red;
}

</style>

main.js文件修改为以下

import {createApp} from "vue/dist/vue.esm-bundler"
import App from "./vue/App.vue"
const app = createApp(App )
/*虽然只导出了{
  data() {
    return {
      title: "Hello world",
      message:"hahahha"
    }

  },
  methods: {

  }
}
这个对象,但是其实会用一个loader对这个vue文件进行编译,它会自动把template里面的东西放到导出的这个对象里面
*/
app.mount("#app"); 

然后运行npm run build 报错了,原因是无法解析.vue文件

7. App.vue的打包过程

默认情况下vue-loader是对vue2的源代码进行解析的,所以我们要使用vue-loader@next

npm i vue-loader@next -d

08_babel对JS-Vue处理_17.jpg

然后修改配置文件

{
        test:/\.vue$/,
        loader:"vue-loader"
      }

然后还是会报错,因为vue-loader是依赖@vue/compiler-sfc这个包的,其实对单文件解析的时候是@vue/complier-sfc这个包对他进行解析的。vue2是@vue/vue-template-compiler.

npm i @vue/compiler-sfc -d

8. vue/complier-sfc

08_babel对JS-Vue处理_18.jpg

如上,对@vue/compiler-sfc 进行配置后,就可以npm run build进行打包。打开index文件。就可以看到我是Vue渲染出来的和Hello world。

9. GlobalFeatureFlags的配置

虽然正确的显示出来了,但是console里面会有一下的报错

runtime-core.esm-bundler.js:3705

   Feature flags __VUE_OPTIONS_API__, __VUE_PROD_DEVTOOLS__ are not explicitly defined. You are running the esm-bundler build of Vue, which expects these compile-time feature flags to be globally injected via the bundler config in order to get better tree-shaking in the production bundle.
   For more details, see https://github.com/vuejs/vue-next/tree/master/packages/vue#bundler-build-feature-flags

Starting with 3.0.0-rc.3, esm-bundler builds now exposes global feature flags that can be overwritten at compile time: 从3.0.0版本开始, esm-bundler要求我们设置一个global feature 的flag。这里面有两个参数

  • __VUE_OPTIONS_API__ (enable/disable Options API support, default: true)

    对vue2做适配,默认是true,就是意味着源代码里面是有一部分代码是对vue-options-api做解析的,

    如果代码里面写的都是setup()也就是vue3的代码,我就不需要这部分代码,你就可以设置为false,tree-shaking在打包的时候,发现是false的话,就会把这一部分代码从源代码里面删除掉,体积就会小一些

  • __VUE_PROD_DEVTOOLS__ (enable/disable devtools support in production, default: false)

    生产环节下要不要支持devtool,devtool一般是开发阶段使用,生产阶段一般不用它生效,所以设置成false

    new DefinePlugin({
      BASE_URL : "'./'",
      __VUE_OPTIONS_API__: true,
      __VUE_PROD_DEVTOOLS__:false
    }),

警告全部消除了
因为已经使用了vue-loader和vue/complier-sfc对template等等进行处理
然后这时候可以直接使用

import {createApp} from "vue"
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 本文整理来自深入Vue3+TypeScript技术栈-coderwhy大神新课[https://ke.qq.com...
    Imkata阅读 2,412评论 0 2
  • 一、FLow类型检测 安装Flownpm install flow-bin 初始化flow项目flow init ...
    zackxizi阅读 576评论 1 1
  • vue3.2.33源码解析 1. 准备工作 vue3源码地址:git地址[https://github.com/v...
    东方三篇阅读 983评论 0 0
  • Vue3源码解析 准备工作至项目结构为翻译官方贡献者指南[https://github.com/vuejs/cor...
    晓蟲QwQ阅读 9,788评论 0 7
  • 源码组织方式 提升代码可维护性,源码采用 TypeScript 重写 使用 Monorepo 管理项目结构,将独立...
    翔子丶阅读 1,821评论 0 3