Babel是一個Javascript的編譯器,經過它你能夠將一些新版本的ECMAScript語法轉換成低版本的語法。以便可以在低版本的瀏覽器或者其它環境平穩運行。html
截至目前筆者寫這篇文章的時候,babel的版本是7.10.0node
mkdir babel-study && cd babel-study
linux
npm init -y
ios
npm i @babel/cli @babel/core @babel/preset-env --save-dev
git
相關依賴包說明:es6
@babel/cli: hello,你好,我是腳手架工具,我能夠經過一些命令將源文件編譯成目標代碼。github
@babel/core: hello,你好,我是一個代碼分析選手,我負責將代碼分析稱ast,方便其餘插件進行相關處理。chrome
@babel/preset-env: hello,你好,我是一個語法轉義器,我負責的內容是將JS的相關語法進行編譯,關於轉義新增的API和全局對象這個我不負責的。npm
樓下這幾位就是經常使用的babel配置參數了,這裏作簡要介紹數組
早期的版本實際上是引入相似babel-preset-x
,這種形式的包,如今官方推薦統一用@babel/preset-env
,這個包來作語法轉義器這部分的工做。
彌補babel自己上的功能不足,好比轉義新增的API和全局對象可能就須要用到一些新的插件來作這部分工做,咱們稱之爲補丁轉義器。
把不須要babel編譯的文件寫配置到這個參數裏面,是一個數組的形式。
Boolean類型的,將其設置爲true後,編譯後的文件會被壓縮。
Boolean類型的,將其設置爲true後,編譯後的文件會有註釋(你項目開發中寫的註釋)。
babel運行的環境變量,若是設置了BABEL_ENV
則使用它,若是沒有設置,它會去找有沒有NODE_ENV
,若是仍是沒有,那就是走默認development
。
這裏附上一份我調研後的配置文件
{ "presets": [[ "@babel/preset-env", { // "modules": false, "corejs": "3", "useBuiltIns": "usage", "targets": { "node": "4" // "browsers": ["last 2 versions"] } } ]], "plugins": ["@babel/plugin-transform-runtime"], "env": { "test": { "presets": [[ "@babel/preset-env", { "modules": false, "targets": { "node": "current", // "chrome": "83", // "edge": "17", // "firefox": "68", // "ie": "11", // "ios": "11.3", // "safari": "5.1", // "samsung": "9.2", "browsers": ["last 2 versions"] } } ]], "minified": true, "comments": true, "ignore": ["./src/test.js"] }, "development": { "presets": [[ "@babel/preset-env", { "targets": { "browsers": ["last 2 versions", "safari 7"] } } ]] }, "production": { "presets": [[ "@babel/preset-env", { "targets": { "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] } } ]], "plugins": ["@babel/runtime"], "minified": true, "comments": true } } }
這裏簡要說明下,modules默認爲true的,在node的環境下(支持COMMONJS),若是使用ES Module的語法(import、export),而後將其設置爲false,你會發現入口文件沒有被編譯,全部這裏把它去掉了。而後targets下面你能夠單獨設置相關環境的支持版本,browsers的優先級高於其餘的。babel7.4.0之後,廢棄了polyfill,須要單獨安裝core-js
這裏咱們測試下ES Module寫法,而後一些新的API的轉義狀況,好比數組的include,箭頭函數、模板字符串、Promise等,這裏咱們不考慮相關的寫法是否是冗餘,單純地就是爲了測試下編譯效果。
animal.js
class Animal { constructor(name) { this.name = name; } eat() { console.log(`${this.name} is eating!`); } } export default Animal;
person.js
import Animal from './animal'; class Person extends Animal { constructor(name, sex) { super(name); this.name = name; this.sex = sex; this.sexMap = new Map([[1, '男'], [0, '女']]); } sing() { console.log(`${this.name} is singing!`); } getSex() { if (![0, 1].includes(this.sex)) { return false; } else { return this.sexMap.get(this.sex); } } testArr(arr) { return arr.map(item => item * 2); } testPromise() { return new Promise((resolve, reject) => { setTimeout(() => { resolve(2020); }, 2000); }); } } export default Person;
index.js
import Person from './person'; // 我就是試試 let ataola = new Person('ataola', 1); ataola.eat(); ataola.sing(); const sex = ataola.getSex(); console.log(sex); let testArr = ataola.testArr([0, 1, 2]); console.log(testArr); ataola.testPromise().then(res => { console.log(res); });
# 單純執行, 它會在控制檯打出編譯後的信息 babel index.js # 完整寫法 babel index.js --out-file bundle.js # 簡寫形式 babel index.js -o bundle.js
# 完整寫法 babel src -out-dir dist # 簡寫形式 babel src -d dist # 生成sourc map文件 babel src -d dist -s
babel-cli自然自帶了一個babel-node的命令,拆分一下也就是babel + node,提供了一個支持ES6的REPL環境,你能夠這麼玩。
# 直接進到這個環境 babel-node # 直接執行這個文件的代碼 babel-node index.js
最後附上個人測試腳本
... "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build:dir": "babel src -d dist", "build:dir:prod": "cross-env BABEL_ENV=production babel src -d dist", "build:dir:dev": "cross-env BABEL_ENV=development babel src -d dist", "build:dir:test": "cross-env BABEL_ENV=test babel src -d dist", "build:dir:s": "babel src -d dist -s", "build:file": "babel ./test/babel_core.test.js -o bundle.js" }, ...
項目地址: https://github.com/ataola/JavaScript-Tsukuki/tree/master/code/babel-study
將高版本的JS語法轉換成低版本的JS語法,可兼容不一樣版本的瀏覽器或者運行環境,劃重點,解決了代碼在不一樣版本的瀏覽器的兼容性問題。人的腦容量都是有限的,兼容的事情就愉快地交給它吧。
首先,這絕對不是爲了裝逼,也不是爲了混淆代碼。咱們先思考下使用高版本的語法它有什麼用?有一些實際上是低版本的語法糖,使用了這些咱們能夠減小代碼量,而後減輕維護成本。可是ECMAScript它是一個語法標準,不一樣的JS引擎以及瀏覽器對它的實現和支持又不大同樣,全部咱們不可以保證使用高版本的語法它可以完美在各平臺運行,這也就是babel的做用體現。
早期地預設有babel-preset-es201五、babel-preset-stage-x之類的啥的,如今官方推薦統一@babel/preset-env,腳手架統一@babel/cli,對,不成文地規定就是@babel打頭基本是對的,polyfill除外。
先說結論,用前者@babel/xxx, @xxx就至關於註冊了一個命名空間,特指這個是xxx下的某包,它是一個範圍,是一種組織的體現形式,例如@ataola/zjt,
若是隻是建立一個.babelrc裏面什麼都不寫,會報錯,由於babel會讀取裏面的格式,加個{}
,這個是能夠運行的,裏面什麼都不寫。這裏思考下babel的默認行爲是什麼?只是轉換了Javascript的語法,而不對新的API進行轉換,新的仍是要用插件的。
在presets裏的形如@babel/preset-env就是語法轉義器,在plugins下的插件包就是補丁轉義器,它們的分工不一樣,前者是將相關語法進行編譯,後者彌補了前者的一些不足,故稱之爲補丁。
設置browsers的優先級高於直接設置瀏覽器的,會覆蓋後者。
說明其默認爲true,默認都是支持commonjs規範的。還能夠設置成amd、umd之類的。
解決了es6語法中全局對象或者全局對象方法編譯不足的狀況。
babel-polyfill , core-js、regenerator-runtime
版本更新迭代太快了,安裝在項目本地易升級。
# osx|linux export NODE_ENV=production #window SET NODE_ENV=production
轉換了形如let、箭頭函數之類的語法, 若是要徹底的ES6語法支持須要安裝plugin-transform-runtime插件,若是須要更高版本的話,那就須要安裝polyfill插件。
babel官網:https://babeljs.io/
@babel/preset-env文檔:https://babeljs.io/docs/en/babel-preset-env/
@babel/plugin-transform-runtime:https://babeljs.io/docs/en/next/babel-plugin-transform-runtime.html
@babel/cli文檔:https://babeljs.io/docs/en/babel-cli
babel配置文件:https://babeljs.io/docs/en/config-files#file-relative-configuration
babel環境變量配置:https://babeljs.io/docs/en/options#envname
@xxx npm包的解釋 About Scope: https://docs.npmjs.com/about-scopes
本做品採用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。