欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

從Vue轉(zhuǎn)換看Webpack與Vite 代碼轉(zhuǎn)換機(jī)制差異詳解

 更新時(shí)間:2022年10月11日 09:04:17   作者:candyTong  
這篇文章主要為大家介紹了從Vue轉(zhuǎn)換看Webpack與Vite代碼轉(zhuǎn)換機(jī)制差異詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

配置方式

我們知道,Webpack 是使用 loader 轉(zhuǎn)換代碼的,而 Vite/Rollup 則是使用插件轉(zhuǎn)換代碼,那這兩種機(jī)制有什么差異呢?我們用 Vue 的轉(zhuǎn)換來(lái)說(shuō)明一下。

Vite 使用插件轉(zhuǎn)換代碼,直接在 plugins 使用 @vitejs/plugin-vue 即可

// vite.config.js
import vue from '@vitejs/plugin-vue'
export default { 
  plugins: [vue(), /* 其他插件 */ ]
}

Webpack 使用 loader 轉(zhuǎn)換代碼,有時(shí)候需要同時(shí)配合 Plugin 才能完成代碼轉(zhuǎn)換(例如 Vue)

// webpack.config.js
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      // 它會(huì)應(yīng)用到普通的 `.js` 文件
      // 以及 `.vue` 文件中的 `<script>` 塊
      {
        test: /\.js$/,
        loader: 'babel-loader'
      },
      // 它會(huì)應(yīng)用到普通的 `.css` 文件
      // 以及 `.vue` 文件中的 `<style>` 塊
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader'
        ]
      }
    ]
  },
  plugins: [
    new VueLoaderPlugin()
  ]
}

為什么 webpack 使用 loader 還不夠,還需要 Vue plugin?

這個(gè)問(wèn)題我們留在后面說(shuō)明

Vue 文件編譯的流程

下面是一個(gè)簡(jiǎn)單的 Vue SFC (單文件組件):

<script setup>
import { ref } from 'vue'
const msg = ref('Hello World!')
</script>
<template>
  <h2>{{ msg }}</h2>
</template>
<style>
  h2{
    font-size: 50px
  }
</style>

Vue SFC 分為 3 個(gè)部分:

  • script,可以是 JS、TS 等語(yǔ)法
  • template(會(huì)被轉(zhuǎn)換成 render 函數(shù))
  • style,可以是 CSS、Less 等語(yǔ)法

由于 Vue 文件包含三個(gè)部分,而一個(gè)模塊經(jīng)過(guò)轉(zhuǎn)換后仍然是一個(gè)模塊(例如經(jīng)過(guò) loader 轉(zhuǎn)換后,仍然是一份代碼,不能變成三個(gè)部分)

但我們可以用一個(gè)巧妙的辦法去解決這個(gè)問(wèn)題:使用一個(gè)臨時(shí)模塊,去分別引入 script、template、style,并將其組合,偽代碼如下:

// 引入 main script,獲取到的是組件的配置對(duì)象
import script from './Main.vue?vue&type=script'
// 引入 template 
import { render } from './Main.vue?vue&type=template&id=xxxxxx'
// 引入 css
import './Main.vue?vue&type=style&index=0&id=xxxxxx'
// 給組件對(duì)象設(shè)置 render 函數(shù)
script.render = render
// 設(shè)置一些元信息,在開(kāi)發(fā)環(huán)境有用
script.__file = 'example.vue'
// style 的 scope id,用于組件樣式隔離
script.__scopeId = 'xxxxxx'
export default script

一個(gè) Vue 的會(huì)有大致如下的處理流程:

  • 將 Vue SFC 轉(zhuǎn)換成臨時(shí)模塊,分別引入 script、template、style
  • vue-loader/插件會(huì)保存 script、template、style 的內(nèi)容
  • 打包工具遇到 import 語(yǔ)句,會(huì)分別處理:
    • script:從 vue-loader/插件中,取出之前緩存的 script,然后交給其他 JS loader/插件處理(如 babel)
    • template:從 vue-loader/插件中,取出之前緩存的 template,然后交給其他 JS loader/插件處理(因?yàn)?template 轉(zhuǎn)換成 render 函數(shù),這部分也是 JS 類型)
    • style:從 vue-loader/插件中,取出之前緩存的 style,然后交給其他 Style loader/插件處理(如 Less)

Vue 的轉(zhuǎn)換,在 webpack 和 vite 都是類似的思路,只不過(guò)由于 webpack 和 Vite 的機(jī)制不同,在 Vue 的轉(zhuǎn)換插件上的的使用和實(shí)現(xiàn)上,也會(huì)有所差異。

Vite 的 Vue 轉(zhuǎn)換流程

Vite/Rollup 使用插件轉(zhuǎn)換模塊,由于沒(méi)有顯式地聲明模塊跟插件的匹配規(guī)則(例如 webpack 顯式聲明了 Vue 文件用 vue-loader 處理),因此每個(gè)模塊的轉(zhuǎn)換都需要經(jīng)過(guò)所有的插件

插件只能處理它能處理的模塊(例如:Vue 插件不能后處理 less 模塊),Vite/Rollup 插件必須要在插件內(nèi)部對(duì)模塊類型進(jìn)行判斷,然后后決定是否進(jìn)行處理。

export default function vuePlugin() {
  return {
    name: 'transform-vue',
    transform(source, id) {
      // source 文件的內(nèi)容或上一個(gè)插件轉(zhuǎn)換過(guò)的內(nèi)容
      // id 一般為文件的真實(shí)路徑,需要在插件內(nèi)判斷文件是否為 vue 后綴
      if (isVueFile(id)) {
        // 對(duì) Vue 模塊進(jìn)行轉(zhuǎn)換
        return // 返回轉(zhuǎn)換后的內(nèi)容
      }
      // 其他類型模塊不作處理
    }
  }
}

上面的插件,就只對(duì) Vue 模塊進(jìn)行處理,其他的模塊,則直接交給下一個(gè)插件處理。

Vite Vue 插件的大致處理流程如下:

  • ./Main.vue 在 load 階段,會(huì)依次經(jīng)過(guò)所有插件,如果沒(méi)有被處理,則默認(rèn)是讀取文件的內(nèi)容。(一般情況下也不需要處理)
  • ./Main.vue 在 transform 階段,會(huì)依次經(jīng)過(guò)所有插件,經(jīng)過(guò) Vue 處理后(分離 template、script、style),會(huì)轉(zhuǎn)換成臨時(shí)模塊,然后再經(jīng)過(guò)其他插件處理(例如 babel)
  • 打包工具解析轉(zhuǎn)換后的代碼,遇到 ./Main.vue?vue&type=script
  • ./Main.vue?vue&type=script 在 load 階段,會(huì)依次經(jīng)過(guò)所有插件,經(jīng)過(guò) Vue 插件,從之前的緩存中,取出 script 部分(如果插件執(zhí)行 load 階段時(shí)有返回值,則立即結(jié)束 load 階段)
  • ./Main.vue?vue&type=script 在 transform 階段,會(huì)依次經(jīng)過(guò)所有插件,最終得到轉(zhuǎn)換后的代碼

template 和 style 部分類似就不重復(fù)寫(xiě)了。

需要注意的是,這跟 @vite/plugin-vue 實(shí)際的處理方式不完全一致,主要的區(qū)別是:我們這里在臨時(shí)模塊,引入了 template、script、style 三個(gè)部分,實(shí)際上,可以直接將 template、script 內(nèi)聯(lián)到臨時(shí)模塊,這樣就只需要 import style 部分即可。

Webpack 的 Vue 轉(zhuǎn)換流程

在 webpack 的配置文件中,需要顯式聲明 rule,為對(duì)應(yīng)的模塊配置對(duì)應(yīng)的 loader。

// webpack.config.js
{
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      // 它會(huì)應(yīng)用到普通的 `.js` 文件
      // 以及 `.vue` 文件中的 `<script>` 塊
      {
        test: /\.js$/,
        loader: 'babel-loader'
      },
      // 它會(huì)應(yīng)用到普通的 `.css` 文件
      // 以及 `.vue` 文件中的 `<style>` 塊
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader'
        ]
      }
    ]
  },
}

配置 Vue 時(shí),我們做了如下配置:

  • Vue 文件會(huì)交給 vue-loader 處理
  • js 文件給 babel-loader 處理
  • CSS 文件給 css-loader 和 style-loader 處理

我們?cè)賮?lái)回顧一下這個(gè)流程:

  • Main.vue 匹配中 vue-loader,被處理成臨時(shí)模塊
  • ./Main.vue?vue&type=script 匹配中 vue-loader(webpack 會(huì)去掉 query 部分,因此 /\.vue$/ 可以匹配),從緩存中取出 Vue SFC script 的內(nèi)容。

到了這一步,我們會(huì)發(fā)現(xiàn),匹配不到其他 loader 了,因?yàn)?babel-loader 匹配的規(guī)則是 /\.js$/,這樣轉(zhuǎn)換就沒(méi)辦法再進(jìn)行下去了,這就是 webpack loader 機(jī)制的局限性。

因此僅僅使用 loader,是沒(méi)有辦法將 JS、CSS 傳遞給對(duì)應(yīng) loader 處理的,這也是 webpack loader 機(jī)制的局限性

為了解決這個(gè)問(wèn)題,借助 webpack plugin:

// webpack.config.js
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
  module: {
    rules: [
        // 省略...
    ]
  },
  plugins: [
    new VueLoaderPlugin()
  ]
}

VueLoaderPlugin 做了什么?

VueLoaderPlugin 的內(nèi)容比較復(fù)雜,本文不會(huì)詳細(xì)的說(shuō)明。這里直說(shuō)最終的轉(zhuǎn)換結(jié)果:

Webpack 提供一種內(nèi)聯(lián) loader 的能力:

import script from "-!babel-loader!vue-loader??ref--0!./App.vue?vue&type=script&setup=true&lang=js"

這種內(nèi)聯(lián) loader 的能力,在 import 的路徑中顯式的指定了該模塊會(huì)經(jīng)過(guò)的 loader:

  • 從后往前看,最后的是處理的文件
  • loader 的執(zhí)行順序?yàn)閺挠业阶螅╨oader 用 ! 分割)

VueLoaderPlugin 會(huì)為 script、template、style,根據(jù)不同給的類型,生成不同的內(nèi)聯(lián) loader import 語(yǔ)句,使它們能夠正確地被其他的 loader 處理

對(duì)比和總結(jié)

webpack 顯式指定了模塊對(duì)應(yīng)的 loader,正是這個(gè)機(jī)制,導(dǎo)致 vue SFC 的 script、template、style,沒(méi)辦法被其他 loader 處理,需要插件做一些復(fù)雜的操作,最終用 Inline loader import 強(qiáng)制指定 loader,整個(gè)過(guò)程比較復(fù)雜。

Vite/Rollup 的模塊會(huì)經(jīng)過(guò)所有的插件,在插件中過(guò)濾出需要處理的模塊,其他的交給下一個(gè)插件處理。這樣的機(jī)制使 Vue 文件的各個(gè)部分,能經(jīng)過(guò)所有插件的處理,從而避免了 webpack 遇到的問(wèn)題,這也使 Vue 在 Vite/Rollup 中的轉(zhuǎn)換實(shí)現(xiàn)更為清晰和簡(jiǎn)單。

最后,我們通過(guò)這樣的對(duì)比,目的不能說(shuō)明 Webpack/Vite/Rollup 誰(shuí)好誰(shuí)壞,而是在學(xué)習(xí)過(guò)程中,橫向?qū)Ρ?,加深?duì)它們的了解。

以上就是從Vue轉(zhuǎn)換看Webpack與Vite 代碼轉(zhuǎn)換機(jī)制差異詳解的詳細(xì)內(nèi)容,更多關(guān)于Vue Webpack Vite代碼轉(zhuǎn)換機(jī)制差異的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • el-table 選擇框根據(jù)條件設(shè)置某項(xiàng)不可選中的操作代碼

    el-table 選擇框根據(jù)條件設(shè)置某項(xiàng)不可選中的操作代碼

    這篇文章主要介紹了el-table 選擇框根據(jù)條件設(shè)置某項(xiàng)不可選中的操作代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2024-03-03
  • vue element實(shí)現(xiàn)將表格單行數(shù)據(jù)導(dǎo)出為excel格式流程詳解

    vue element實(shí)現(xiàn)將表格單行數(shù)據(jù)導(dǎo)出為excel格式流程詳解

    這篇文章主要介紹了vue element實(shí)現(xiàn)將表格單行數(shù)據(jù)導(dǎo)出為excel格式流程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2022-12-12
  • vite打包去除console.log和debugge的方法實(shí)踐

    vite打包去除console.log和debugge的方法實(shí)踐

    本文主要介紹了vite打包去除console.log和debugge的方法實(shí)踐,vite 已經(jīng)將這個(gè)功能內(nèi)置了,所以我們只需要修改配置文件,下面就來(lái)介紹一下如何修改
    2023-12-12
  • Vue對(duì)象的單層劫持圖文詳細(xì)講解

    Vue對(duì)象的單層劫持圖文詳細(xì)講解

    這篇文章主要介紹了vue2.x對(duì)象單層劫持的原理實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • 詳解vue使用$http服務(wù)端收不到參數(shù)

    詳解vue使用$http服務(wù)端收不到參數(shù)

    這篇文章主要介紹了vue使用$http服務(wù)端收不到參數(shù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Vue el-autocomplete遠(yuǎn)程搜索下拉框并實(shí)現(xiàn)自動(dòng)填充功能(推薦)

    Vue el-autocomplete遠(yuǎn)程搜索下拉框并實(shí)現(xiàn)自動(dòng)填充功能(推薦)

    在elementui Input輸入框中可以找到遠(yuǎn)程搜索組件,獲取服務(wù)端的數(shù)據(jù)。這篇文章主要給大家介紹Vue el-autocomplete遠(yuǎn)程搜索下拉框并實(shí)現(xiàn)自動(dòng)填充功能,感興趣的朋友一起看看吧
    2019-10-10
  • vue.js實(shí)現(xiàn)簡(jiǎn)單計(jì)時(shí)器功能

    vue.js實(shí)現(xiàn)簡(jiǎn)單計(jì)時(shí)器功能

    這篇文章主要為大家詳細(xì)介紹了vue.js實(shí)現(xiàn)簡(jiǎn)單計(jì)時(shí)器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • vue+swiper實(shí)現(xiàn)側(cè)滑菜單效果

    vue+swiper實(shí)現(xiàn)側(cè)滑菜單效果

    這篇文章主要為大家詳細(xì)介紹了vue+swiper實(shí)現(xiàn)側(cè)滑菜單效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • vue項(xiàng)目中常用解決跨域的方法總結(jié)(CORS和Proxy)

    vue項(xiàng)目中常用解決跨域的方法總結(jié)(CORS和Proxy)

    在vue項(xiàng)目中,一般我們會(huì)遇到跨域的問(wèn)題,vue項(xiàng)目中解決跨域是非常簡(jiǎn)單的,下面這篇文章主要給大家介紹了關(guān)于vue項(xiàng)目中常用解決跨域的方法,主要解釋CROS和Proxy兩種方式,需要的朋友可以參考下
    2022-12-12
  • ElementUI年份范圍選擇器功能實(shí)現(xiàn)

    ElementUI年份范圍選擇器功能實(shí)現(xiàn)

    elementUI中有日期范圍組件,月份范圍選擇的,就是沒(méi)有年份范圍選擇的,需要加一個(gè)類似風(fēng)格的,下面這篇文章主要給大家介紹了關(guān)于ElementUI年份范圍選擇器功能實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下
    2023-02-02

最新評(píng)論