我是一個標題黨,這篇文章介紹一點babel的默認配置套路,總結了一點遇到的項目管理問題。javascript
_objectSpread is not defined
_objectSpread
就是使用了新的對象展開的語法...obj
,編譯以後纔出現的。固然這裏我也調試了編譯後打代碼。【若是你想看編譯打包後代碼,介紹一篇文章給你: webpack編譯vue項目生成的代碼探索】git log
快速分析package.json
的變動,發現只更新過babel
相關。因此實錘是babel
問題。分析git log
時,咱們當時作的commit message style
統一的做用就發揮出來了,全部的工具鏈相關變動,統一都是chore
開頭,因此才能作到快速定位。順便看看咱們項目的commit message
css
場景重現:babel repl demo連接html
真實緣由:對象展開的語法,babel編譯以後注入了
_objectSpread
或者_objectSpread2
函數來處理,維護的小夥伴沒有把全部的分支都覆蓋。修復這個issues的小夥伴也挺幽默,估計也是被折騰的夠嗆,說了一句玩笑話I'll now go hiding myself somewhere and I won't touch an helper for a few months 😆前端並且此bug是
babel v7.5.4
修復的,並且在低版本的@babel/core
使用了高版本的@babel/plugin-proposal-object-rest-spread
才能重現。vue
_objectSpread
官方issues相關連接:java
ReferenceError: _objectSpread is not defined after updatenode
Missing helpers only throw oncewebpack
Fix _objectSpread2 for realgit
找的問題的根源了,新問題來了,我怎麼更新
@babel/core
呢?github由於不是項目直接依賴的
@babel/core
,而是其它工具依賴,我更新了也不必定起做用。
介紹npm
兩個很是有用的命令:
查看項目中安裝的package版本和依賴關係
npm ls @babel/core
`-- @vue/cli-plugin-babel@3.9.2
`-- @babel/core@7.5.4
複製代碼
知道了依賴@babel/core是@vue/cli-plugin-babel
,那升級@vue/cli-plugin-babel
就好了。
查看npm
倉庫的package版本和依賴
npm show @babel/core
複製代碼
推薦一個npm-check
工具,專門用來更新依賴。
能夠執行
npm-check -u
來進行交互式選擇更新,並且還列出了官方文檔,能夠直接看看release log以後再決定是否更新。
babel
的plugin和preset配置默認套路原本我就比較懶,一直在計劃學習的路上,基本都沒落實行動。此次項目出現問題,我不得不去了解了一下,babel配置的那些套路。Babel的v7版本全部包都重命名了,因此仍是要作到了解。
包含的內容太多,仔細過一遍才行,不少配置或者包名稱命名規則都修改了。
babel v7.4
支持core-js@3
babel v7.4支持core-js@3,尤爲是對
@babel/polyfill
和@babel/preset-env
又帶來了不少改變。
新的corejs
配置項
corejs配置項連接options corejs
當項目中的babel升級到v7.4+時會出現下面的警告:
WARNING: We noticed you're using the
useBuiltIns
option without declaring a core-js version. Currently, we assume version 2.x when no version is passed. Since this default version will likely change in future versions of Babel, we recommend explicitly setting the core-js version you are using via thecorejs
option.
// 使用core-js@3的babel.config.js
module.exports = function (api) {
api.cache(true);
const presets = [
["@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs":3, // 指定版本
"targets":{
"browsers":["> 1%", "last 2 versions", "not ie <= 8"]
}
}
]
];
return {
presets,
// plugins
};
}
複製代碼
注意: 把相應的core-js安裝到項目依賴中,npm i core-js@2
或者npm i core-js@3
@babel/polyfill
不支持從core-js2升級到core-js3,因此v7.4開始@babel/polyfill
變成過期(deprecated)
若是項目中使用core-js@3,則應該修改導入配置
import "@babel/polyfill";
複製代碼
替換爲:
import "core-js/stable";
import "regenerator-runtime/runtime";
複製代碼
直接安裝依賴到項目:
npm i --save core-js regenerator-runtime
複製代碼
由於babel和core-js綁定的很緊密,因此推薦看一下core-js做者的文章:core-js-3-babel-and-a-look-into-the-future詳細介紹了core-js@3版本帶來的改變,以及解決的問題。
syntax plugins容許babel去parse特定的類型的syntax而不是去轉換變形(transform)
注意:transform plugins會自動啓用syntax plugins。 所以,若是已經使用了相應的transform plugins,則無需指定syntax plugins。
若是 plugin 在 npm 上,你能夠傳入預設名稱,babel 將檢查它是否已安裝在 node_modules
中
{
"plugins": ["babel-plugin-myPlugin"]
}
複製代碼
還能夠指定的相對/絕對路徑。
{
"plugins": ["./node_modules/asdf/plugin"]
}
複製代碼
若是包的名稱以 babel-plugin-
爲前綴,可使用簡寫:
{
"plugins": [
"myPlugin",
"babel-plugin-myPlugin" // equivalent
]
}
複製代碼
這也適用於 scoped 包:
{
"plugins": [
"@org/babel-plugin-name",
"@org/name" // equivalent
]
}
複製代碼
若是兩個transforms都訪問「程序」節點,則transforms將以plugin或preset順序運行。
- plugin在preset以前運行。
- plugin執行順序是第一個到最後一個。
- preset順序相反(從最後到第一個)。
{
"plugins": ["transform-decorators-legacy", "transform-class-properties"]
}
複製代碼
先執行transform-decorators-legacy
後transform-class-properties
plugins和 presets 均可以經過將名稱和選項對象放在配置中的數組中來指定選項。
對於不指定選項,這些都是等同的:
{
"plugins": ["pluginA", ["pluginA"], ["pluginA", {}]]
}
複製代碼
要指定選項,請使用選項名稱做爲 key 傳遞對象。
{
"plugins": [
[
"transform-async-to-module-method",
{
"module": "bluebird",
"method": "coroutine"
}
]
]
}
複製代碼
preset是一個插件數組
module.exports = function() {
return {
plugins: [
"pluginA",
"pluginB",
"pluginC",
]
};
}
複製代碼
Presets 能夠包含其餘的 presets 以及帶有選項的插件。
module.exports = () => ({
presets: [
require("@babel/preset-env"),
],
plugins: [
[require("@babel/plugin-proposal-class-properties"), { loose: true }],
require("@babel/plugin-proposal-object-rest-spread"),
],
});
複製代碼
若是 preset 在 npm 上,你能夠傳入預設名稱,babel 將檢查它是否已安裝在 node_modules
中
{
"presets": ["babel-preset-myPreset"]
}
複製代碼
還能夠指定 presets 的相對/絕對路徑。
{
"presets": ["./myProject/myPreset"]
}
複製代碼
若是包的名稱以 babel-preset-
爲前綴,可使用簡寫:
{
"presets": [
"myPreset",
"babel-preset-myPreset" // 等同
]
}
複製代碼
這也適用於 scoped 包:
{
"presets": [
"@org/babel-preset-name",
"@org/name" // 等同
]
}
複製代碼
// vue-cli生成的babel.config.js
module.exports = {
presets: [
[
'@vue/app', // 對應 @vue/babel-preset-app,當時害的我找來找去都沒找到包
{
useBuiltIns: 'entry',
corejs: 2, // @see https://babeljs.io/docs/en/babel-preset-env#corejs
},
],
};
複製代碼
Preset 的順序是相反的(從最後一個到第一個).
{
"presets": [
"a",
"b",
"c"
]
}
複製代碼
將會按照如下順序運行:c
, b
, 而後 a
。
插件和 presets 均可以經過將名稱和選項對象放在配置中的數組中來指定選項。
對於不指定選項,這些都是等同的:
{
"presets": [
"presetA",
["presetA"],
["presetA", {}],
]
}
複製代碼
要指定選項,請使用選項名稱做爲 key 傳遞對象。
{
"presets": [
["@babel/preset-env", {
"loose": true,
"modules": false
}]
]
}
複製代碼
ant-desgin-vue
的依賴加載配置:
module.exports = {
presets: [
[
'@vue/app',
{
useBuiltIns: 'entry',
corejs: 2, // @see https://babeljs.io/docs/en/babel-preset-env#corejs
},
],
],
plugins: [
[ // @see https://github.com/vueComponent/ant-design-vue/issues/193
'import', // babel-plugin-import
{ libraryName: 'ant-design-vue', libraryDirectory: 'es', style: true },
],
],
};
複製代碼
前端的知識鏈太長,技術更新愈來愈快。前端的投資風險仍是很大,因此謹慎選擇框架,分配一點時間投資在業界公認的工具上也是不錯的,例如:webpack, babel, vs code, scss等。這些都是現代前端工程的構建工具,因此生命週期會比某一個框架更長遠。
core-js-3-babel-and-a-look-into-the-future
A Beginner’s Guide to npm — the Node Package Manager
關注微信公衆號,發現更多精彩內容