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,發(fā)現(xiàn)并沒有顯示 i am vue

打開控制臺,發(fā)現(xiàn)報錯

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默認(rèn)使用的是版本二:runtime-only, 不包含對template的編譯,所以編譯不會成功,界面渲染不出來。

render函數(shù)就是直接渲染出來虛擬節(jié)點v-dom

runtime-compiler

使用

new Vue({
    el:"#app",
    template: '<App/>',//template替換el里面的內(nèi)容
    components:{App}
})

當(dāng)我們把template傳給Vue實例的時候,它會被保存在Vue實例下面的options,

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

然后第三步,complier,編譯成render函數(shù)

通過render函數(shù)把template翻譯成virtual dom,虛擬dom

轉(zhuǎn)換成真實的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. 普通用法:傳入標(biāo)簽createElement('標(biāo)簽',{標(biāo)簽的屬性},[''])
    /* return createElement('h2',
     {class:'box'},
    ['Hello! world!', createElement('button', {class:'mybtn'}, ['按鈕'])]) */
          

    //2.傳入組件對象:
    //return createElement(cpn)
    return createElement(App)
          //創(chuàng)建出來的標(biāo)簽,替換掉之前的<div id="app"><div>
          
    //那么.vue文件中的template是由誰編譯的呢?
    //是由vue-template-compier來解析的,將.vue里面的template解析成render函數(shù)的,在main.js里面引用的不是整個.vue文件
    //引用的是被解析后的App對象,對象里面沒有包含任何關(guān)于tenplate信息,所有的template已經(jīng)轉(zhuǎn)成render函數(shù)了


  }
    
})

簡單總結(jié)
如果在之后的開發(fā)中,你依然使用template,就需要選擇Runtime-Compiler
如果你之后的開發(fā)中,使用的是.vue文件夾開發(fā),那么可以選擇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 是要不要使用生產(chǎn)版本,生成版本是做過壓縮的。

  • vue.global.js包含編譯器和運行時的完整版,構(gòu)建過程中支持動態(tài)模板編譯
  • vue.runtime.global.js 僅預(yù)編譯了構(gòu)建過程中的運行時和必要的模板

第二個是正常src引用的話,就是第一個方式,上面的方式,但是表明了src = .. type="module"的時候使用現(xiàn)在這個。

第三個是在wenpack等構(gòu)建工具中使用。分兩個,一個有complier,一個沒有。默認(rèn)使用的是只有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' 而不是默認(rèn)的vue.runtime.esm-bundler.js

vue.runtime.esm-bundler.js默認(rèn))僅運行時,且要求所有模板必須預(yù)編譯。這是構(gòu)建工具的默認(rèn)入口(通過package.js的module字段),因為當(dāng)使用構(gòu)建工具模板時一般都是預(yù)編譯的(例如:*.vue文件)

vue.esm.bundler.js:包含運行時編譯器。當(dāng)你使用了構(gòu)建工具但仍然想編譯運行時模板(例如,in-DOM模板或通過javascript字符的內(nèi)聯(lián)模板)。你需要在構(gòu)建工具中配置vue別名到這個文件。

vue.cjs(.prod).js:

4.全局標(biāo)識的配置

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里面創(chuàng)建一個vue文件夾,里面創(chuàng)建一個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 )
/*雖然只導(dǎo)出了{
  data() {
    return {
      title: "Hello world",
      message:"hahahha"
    }

  },
  methods: {

  }
}
這個對象,但是其實會用一個loader對這個vue文件進行編譯,它會自動把template里面的東西放到導(dǎo)出的這個對象里面
*/
app.mount("#app"); 

然后運行npm run build 報錯了,原因是無法解析.vue文件

7. App.vue的打包過程

默認(rèn)情況下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要求我們設(shè)置一個global feature 的flag。這里面有兩個參數(shù)

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

    對vue2做適配,默認(rèn)是true,就是意味著源代碼里面是有一部分代碼是對vue-options-api做解析的,

    如果代碼里面寫的都是setup()也就是vue3的代碼,我就不需要這部分代碼,你就可以設(shè)置為false,tree-shaking在打包的時候,發(fā)現(xiàn)是false的話,就會把這一部分代碼從源代碼里面刪除掉,體積就會小一些

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

    生產(chǎn)環(huán)節(jié)下要不要支持devtool,devtool一般是開發(fā)階段使用,生產(chǎn)階段一般不用它生效,所以設(shè)置成false

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

警告全部消除了
因為已經(jīng)使用了vue-loader和vue/complier-sfc對template等等進行處理
然后這時候可以直接使用

import {createApp} from "vue"
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文整理來自深入Vue3+TypeScript技術(shù)棧-coderwhy大神新課[https://ke.qq.com...
    Imkata閱讀 2,524評論 0 2
  • 一、FLow類型檢測 安裝Flownpm install flow-bin 初始化flow項目flow init ...
    zackxizi閱讀 668評論 1 1
  • vue3.2.33源碼解析 1. 準(zhǔn)備工作 vue3源碼地址:git地址[https://github.com/v...
    東方三篇閱讀 1,108評論 0 0
  • Vue3源碼解析 準(zhǔn)備工作至項目結(jié)構(gòu)為翻譯官方貢獻者指南[https://github.com/vuejs/cor...
    曉蟲QwQ閱讀 9,993評論 0 7
  • 源碼組織方式 提升代碼可維護性,源碼采用 TypeScript 重寫 使用 Monorepo 管理項目結(jié)構(gòu),將獨立...
    翔子丶閱讀 2,071評論 0 3

友情鏈接更多精彩內(nèi)容