更新時間:2024-05-05 19:45:05作者:佚名
前言問題
當我們使用各種打包工具,需要配置 Babel 的時候,相信大家一開始都會直接網上復制粘貼一個配置,然后運行順利就萬事大吉了吧? 因此,我們有時會遇到打包部署后手機運行白屏等問題; 或者打包后的代碼包太大,加載緩慢等。
其實這一切的大部分原因是我們對 Babel 的各種配置沒有系統的了解。 因此,即使從網上復制粘貼配置后出現問題,我們也不知道如何分析問題。
準備
如果你已經對 Babel 有一個大概的了解,閱讀本文會讓你對配置有一個更系統的了解; 如果你剛剛接觸Babelentry是什么意思,或者對Babel感到困惑,那么我強烈建議你先閱讀這篇文章——想了解Babel? 首先要了解這些包[1],主要介紹和分析一些概念和以下幾個包:
他還回答了我們在看官網時提出的一些問題。 因為了解了這些包之后,我們學習配置的時候會更容易理解。
注:我們再來說一下core-js
通過上一篇文章——想了解Babel? 你必須首先了解這些包 [2] 我們知道:core-js 是一種提供舊版本瀏覽器中缺少的所有 ES6+ API 方法和實現的類型。
在這里,以及下面,我們將引入 core-js 的模塊來實現老版本瀏覽器不支持的 ES6+ API 的過程稱為 。
我們看一下core-js包中的主要模塊:
pic_5.png
所以,我們可以這樣使用它:
以上是我個人的使用習慣,因人而異。 具體介紹可以閱讀參考文章。
參考文章:core-js[3]
我們再談談@bable/-env
通過上一篇文章——想了解Babel? 首先必須了解這些包[4],我們知道:
那么我們就可以清楚地知道:
我們先看一下@babel/-env的配置項:
//?babel.config.js
const?presets?=?[
????[
????????'@babel/preset-env',
????????{
????????????modules,
????????????targets,
????????????corejs,
????????????useBuiltIns,
????????????
????????????spec,
????????????loose,
????????????debug,
????????????bugfixes,
????????????include,
????????????exclude,
????????????forceAllTransforms,
????????????configPath,
????????????ignoreBrowserslistConfig,
????????????browserslistEnv,
????????????shippedProposals
????????}
????]
];
module.exports?=?{presets};
復制代碼
我們可以看到配置項相當多(有些配置項后面可能會被廢棄),但實際上我們日常項目中主要使用的是前四種配置,所以這里重點關注前四種配置(盡量不要能學就學吧,太累了)。
參考文章:@babel/-env[5]
當我們設置為 false 時,Babel 編譯生成的一些輔助函數的引入方法將變成 ES6 模式引入(A from 'B')。
我們把use--[6]案例中的Babel配置改為如下配置來感受一下這個配置的作用。
//?babel.config.js
const?plugins?=?[
????'@babel/plugin-transform-runtime'
]
const?presets?=?[
????[
????????'@babel/preset-env',
????????{
????????????modules:?false
????????}
????]
];
module.exports?=?{plugins,?presets};
復制代碼
當不設置配置項時,編譯后的文件為:
我們會發現途中引入了輔助功能;
設置好配置項后,編譯后的文件為:
我們會發現輔助函數已經變成了我們熟悉的ES6模塊介紹。
這樣做的一個好處是,當我們使用一些打包工具的時候,我們可以對代碼進行靜態分析,很好的減少代碼體積。 因此,我們在配置Babel時,建議設置:false
參考文章:[7]
影響
其用法與[8]一致。 它可以用來設置我們的代碼需要兼容的目標環境,所以它:
注意第一點
如果我們不設置這個配置項,它就會去我們的Babel配置文件中尋找最頂層的配置項; 如果沒有設置頂層,就會去我們的.json或者根目錄中查找; 如果不是,則默認值為 {} 。 搜索過程大致如下,序號代表搜索順序:
//?Babel配置文件
{
????targets:?'ie?10',?//?2.?如果presets里面沒有設置targets,會來這里查找
????presets:?[
????????[
????????????'@babel/preset-env',
????????????{
????????????????targets:?'ie?9'?//?1.?先在這里查找,沒的話去頂層targets查找
????????????}
????????]
????]
}
//?package.json
{
????...,
????browserslist:?[
????????'ie?11'?// 3. 如果頂層targest里面沒有設置,會來這里查找;如果這里也沒設置,則為默認值{}
????]
}
復制代碼
第二點
如果我們不設置這個配置項,Babel 會假設我們要兼容的目標環境是最老的瀏覽器,因此它會把所有 ES6+ 語法的代碼轉換為 ES5。 所以我們在配置 Babel 的時候,需要對其進行設置,以減少輸出代碼的大小。
鑒于此,我們用這個案例-env--[9]來感受一下:
我們會發現ES6+的所有寫法都轉換成了ES5,并且增加了一些輔助功能(白框)。
好的,我們設置:“80”。 這意味著我們的代碼要在80上運行。我們看一下打包結果:
pic_4.png
我們會發現編譯出來的代碼和我們入口文件中寫的代碼基本是一樣的。 因為80已經實現了編寫入口文件代碼的方式。 因此,如果我們的代碼不需要在一些低端瀏覽器中運行,那么設置是非常有必要的。
參考文章:[10]
當不為false時,需要設置該配置項
配置
它有兩種配置方法:
直接設置core-js版本號
...
{
useBuiltIns:?'usage',
corejs:?'3.27.2'
}
...
復制代碼
配置
...
{
useBuiltIns:?'usage',
corejs:?{
????version:?'3.27.2',
????//?是否編譯提案階段ES6+?API
????proposals:?false
},
}
...
復制代碼
注意
當我們的不為false時,我們需要設置這個配置項
不再推薦 core-js 版本 2; 當然我們必須使用最新版本。 最新版本是 core-js@3.27.2
我們安裝的 core-js 必須盡可能保持最新,因為包越新,包含的內容就越多。
當我們設置版本號時,不要直接指定2或3,它會被解析為2.0或3.0。因此,我們應該帶上號(3.27.2),這樣我們就可以得到最新的
Core-js 默認使用穩定版本entry是什么意思,但如果有時我們想使用仍處于提案階段的 API 怎么辦?
其作用將在下文中一并討論。
參考文章:[11]
上面我們提到,我們把引入 core-js 的一個模塊來實現舊版本瀏覽器不支持的 ES6+ API 的過程稱為 。
該配置用于設置我們的core-js的方法。 它有以下三個值:
為了更好地理解,我們使用這個 ES6+ API 作為示例。 我們都知道:
入口
我們可以這樣理解。 中文里的entry是“進入”的意思。 這個值表明我們的應該從某個入口引入來平整它。
表現
我們將配置設置為::'entry'
分析總結
所以我們總結一下它的執行原理大致如下:
我們需要手動全部或某個塊
Babel 會根據我們設置的(目標環境)來判斷當前是否缺少我們手動設置的全部或某一部分。
如果是這樣,我們將手動將所有或某些塊拆分為許多小模塊,并引入我們的目標環境不支持的模塊。
注意
參考文章:[13]
用法
這個值的目的是我們不需要手動做,它會自動幫助我們完成當前缺少的內容。
表現
我們將配置設置為::'usage'
分析總結
所以我們可以總結一下它的執行原理大致如下:
我們不需要手動全部或某個塊
Babel 會根據我們當前代碼使用的 ES6+ API 來判斷當前支持是否支持我們使用的 ES6+ API。
如果不支持,會自動導入對應的ES6+ API。
因為它會自動導入,所以我們可以專注于編寫 ES6+。
參考文章:[14]
錯誤的
這是默認值。 意味著它不會自動添加到每個文件中,也不會根據是否缺失來判斷,也不會我們手動將所有或某個塊拆分為單個引入。
表現
我們將配置設置為::false
總結
設置為假:
參考文章:[15]
使用適配的IE 11
相信通過上面的講解,我們對各個配置項已經有了一個大概的了解,下面我們來更深入的體驗一下。
我們都知道IE 11基本不支持ES6+。 我們來看看一些常用的ES6+ API:
.png
然后我們將使用 IE 11 作為我們的(目標環境)并研究如何配置 Babel 以便我們編寫的 ES6+ 代碼可以在 IE 11 中運行。我們使用這個案例 -env--[16]
注意:為了避免打包錯誤,我們寫在.json中,以便識別環境打包
...
"browserslist":?[
???"ie?11"
?]
?...
復制代碼
我們使用這段代碼作為我們的入口文件:
//?如果用`usage`方式,則注釋掉這段代碼
import?'core-js/stable';
const?lMC?=?{
????name:?'limingcan',
????like:?['eat',?'drink',?'play',?'fun'],
????breath()?{
????????return?new?Promise(resolve?=>?{
????????????setTimeout(()?=>?resolve(),?1000)
????????})
????}
};
lMC.breath().then(()?=>?console.log('breath'));
console.log(lMC.like.includes('play'));
console.log(Array.of(1,?2,?3));
復制代碼
根據我們上面幾個配置項的解釋,如果我們想要:
常見問題
通過上面的例子,我們會發現:
如果配置是:'entry'
我們扁平化的東西是注入到全局的,或者內置對象的()中,影響全局
一勞永逸的方法會將目前不支持的所有 ES6+ API 扁平化,這很方便,但會導致包變得非常大。
如果配置是:'usage'
它還向全局注入填充。
因為:‘usage’是判斷當前的是否支持我們代碼中使用的ES6+ API。 如果它不支持它,它會告訴自己。
有一種情況,如果第三方庫使用了我們目前不支持的ES6+ API,但是我們自己的代碼沒有使用這個API,那么這個API就不會被扁平化,從而導致我們的項目報錯。
第三方庫問題
關于:‘usage’配置的第二個缺點,我們看這個例子use-third-party--[17]來更直接地感受一下。
我們設置為IE 11,我們自己的代碼只使用這個ES6+ API,然后使用第三方庫tars-utils[18]的方法生成Blob對象(使用``[19]實現) )。
讓我們在 IE 11 中運行一下,看看:
.png
通過Babel編譯的文件,我們會發現:
我們來看看更高級的瀏覽器(108):
.png
在108上運行沒有問題,因為108內部已經實現了。
總結
看到這里,相信我們對@babel/-env的配置功能有了一個大概的了解。 上述問題對于我們來說確實是非常現實的問題。
所以,到底是設置入口還是使用方式,就看我們項目的實際需要了。 我個人推薦:
我們再聊聊@babel/--
如上所述,@babel/-env配置方法會將當前瀏覽器中缺少的API注入到全局世界中。 那么有沒有辦法不將其注入全球世界呢? 答案是肯定的。 接下來我們要討論的就是@babel/--。
我們先看一下它有多少個配置項(幸好不多):
//?babel.config.js
const?plugins?=?[
????[
????????'@babel/plugin-transform-runtime',
????????{
????????????helpers,
????????????regenerator,
????????????corejs,
????????????
????????????version
????????}
????]
];
module.exports?=?{plugins};
復制代碼
&& 解析
我們先看看前兩個配置。 因為前兩種配置比較簡單,所以我們就放在一起說。
通過上一篇文章——想了解Babel? 首先要了解這些包[20],我們知道:
關于@babel/
關于輔助函數
關于
例如,我們使用class語法糖和async(){},然后使用@babel/和@babel/--(默認情況下該值為true)。 編譯后如下圖所示:
當我們將heel的值設置為false時:
我們會發現我們的輔助函數,并且 - 包返回到內聯模式。 所以:
:和 類似,它控制這個包的代碼是否不內聯到我們的代碼中。
注意
官網上的解釋大致意思是:如果設置為false,我們需要提供一個全局對象。
但:
解析
一旦這個配置項不為 false英語作文,它就用于設置我們的 ES6+ API 以不污染全局和局部變量的方式進行扁平化。
它有三個值:
該值對應依賴補充
假(默認)
@巴貝爾/
@巴貝爾/-
1.只能編譯支持全局變量(如 )和靜態屬性(如Array.from);
2. 無法編譯實例相關方法([].)
@巴貝爾/-
1.不僅可以編譯支持全局變量和靜態屬性,還可以編譯實例方法。
2.:true,也可以在階段編譯API
我們用這個例子-[22]來體驗一下。
我們會發現實例方法被扁平化了,提出的API(Math.)也被扁平化了; 但它們都是作為局部變量注入的。
因此,如果我們不想以一種全局污染的方式扁平化我們的 ES6+ API,我們就不能將其設置為 false,而更喜歡使用 @babel/- 包進行扁平化(設置為 3)
優化
我們沒有設置上述情況,因此 @babel/-- 配置將扁平化我們代碼中使用的所有 ES6+ API。 讓我們設置一下,看看是否可以平滑我們不支持的 ES6+ API。
我們可以在.json中添加,也可以在配置文件頂層添加(經測試,在@babel/-env中設置不起作用):
//?package.json
"browserslist":?[
????"chrome?80"
]
//?或者在頂層添加
module.exports?=?{
????targets:?{chrome:?80},?//?在這里添加
????presets:?['@babel/preset-env'],
????plugins:?[
????????[
????????????"@babel/plugin-transform-runtime",
????????????{
????????????????...
????????????}
????????]
????]
}
復制代碼
輸出:
我們會發現后跟并沒有被壓扁,因為80已經支撐好了。
總結
參考文章:babel---[23]
其他最后
通過上面的理解,我們最終總結了這個配置。
文章涉及的例子已上傳[30]。 如果您覺得有幫助,歡迎您Star或Fork來學習。
如果讀完本文后您覺得確實有幫助,請點贊并保存; 如果有什么相同點或者不同點,歡迎在評論區討論。
關于本文