我們都知道,在ES6中新增了很的方法.
比如下面這些:
Array.prototype.forEach
Array.prototype.map
String.prototype.startWith
......
這些都是在ES6中新增的,如果一個(gè)瀏覽器并不支持ES6的語法,那么肯定也不會(huì)存在這些方法.
但是我們寫代碼的時(shí)候,又希望用到這些方法.
并希望,webpack在打包的時(shí)候,能夠[有誰]可以幫我們判斷一下.
如果當(dāng)前的瀏覽器不支持這些方法的話,就使用平滑后退的方式去處理.
雖然 babel
可以轉(zhuǎn)化 ES6
-> ES5
.
但是對于 ES6
里面新增的這些方法,它就無能為力的.
babel 只處理語法層面的問題.不能處理API相關(guān)的問題.
webpack
僅僅是一個(gè)處理文件依賴關(guān)系,并打包的工具.
它更無能為力.
開始例子
首先定義一個(gè) ES6FN.js
的文件.
let moduleName = 'es6方法'
export default {
moduleName,
useMap () {
console.log('usermap')
let obj = {
name: '李四',
age: 22
}
// Object.keys() ,map 都是 ES6 新增的方法.
return Object.keys(obj).map(key => {
return {
keyName: key,
keyValue: obj[key]
}
})
},
toString () {
console.log(`${this.keyName} ${this.keyValue}`)
}
}
首先用 webpack + babel 打包一次.
證明,babel 只能轉(zhuǎn)換語法,不能轉(zhuǎn)化API
查看結(jié)果
-
let
->var
-
userMap()
->useMap:function(){}
說明語法轉(zhuǎn)換確實(shí)完成.
-
Object.keys() & map()
仍然存在,證明 babel 僅僅只能轉(zhuǎn)化語法.
最終使用 webpack + babel
生成的代碼.
雖然在語法層面成功的從 ES6
-> ES5
.
但是由于代碼中使用了 ES6 新增的一些方法
.
所以,這份打包好的代碼,最終在一些不支持 ES6特性
的瀏覽器中,仍然是無法運(yùn)行和使用的.
所以,僅僅是語法轉(zhuǎn)化是不行的.
使用 babel-polyfill
babel-polyfill
是一個(gè)用于解析目標(biāo)代碼中,是否包含 ES6
新增方法的腳本.
如果它發(fā)現(xiàn)了里面有,就會(huì)以當(dāng)前瀏覽器支持的方式轉(zhuǎn)換這些方法以便可以正常運(yùn)行.
之前在瀏覽器中,我們一般會(huì)這么引用.
<script src='babel-polyfill.js' />
<script src='es6-fn-in-this-file.js'></script>
其實(shí)也是同樣的原理,
我們只需要在我們打包代碼的最前面加載 babel-polyfill
的 js
代碼即可.
npm i babel-polyfill
關(guān)于 babel-polyfill
使用的兩種方式
- 配置
webpack.config.js
里的entry
設(shè)置為entry: ['babel-polyfill',path.join(__dirname, 'index.js')]
運(yùn)行打包 npm run build
打包成功.文件大小 280KB
- 在
webpack.config.js
配置的主入口index.js
文件的最頂層鍵入import 'babel-polyfill'
運(yùn)行打包 npm run build
同樣也打包成功.文件大小 280KB.
打開其中任意一份打包好的代碼,查看 Object.keys().map()
方法是否仍然存在.
發(fā)現(xiàn)這些只屬于 ES6
的方法仍然是存在的.
那么 babel-polyfill
肯定是通過某種方式(墊片),添加了這些方法,讓我們可以正常的這樣去調(diào)用.
至于這些墊片加載哪,如何做到的..我沒有在原始的代碼中找到相應(yīng)的位置.
本地也沒有低版本的瀏覽器.所以暫時(shí)先不做測試.
使用 babel-plugin-transform-runtime
我們之前利用的 babel-polyfill
,使用墊片支持我們本來使用的ES6
語法,
打包成功之后,文件的大小是 280KB
我們在看一下,之前沒有使用 babel-polyfill
之前的打包出來的文件是多大.
兩則相差大概 81.6倍
原因是 webpack
把 babel-polyfill
整體全部都打包進(jìn)去了.
而babel-polyfill
肯定也實(shí)現(xiàn)了所有 ES6新API
的墊片,文件一定不會(huì)小.
所以,文件變的這么大,也在常理之中了.
那么有沒有一種辦法,根據(jù)實(shí)際代碼中用到的
ES6
新增API ,來使用對應(yīng)的墊片,而不是全部加載進(jìn)去呢?
使用 babel
提供的 babel-runtime
& babel-plugin-transform-runtime
就可以滿足要求.
- 首先安裝這兩個(gè)包.
npm i --save-dev babel-runtime babel-plugin-transform-runtime
- 在
.babelrc
里配置plugins:["tranform-runtime"]
最后運(yùn)行 npm run build
打包結(jié)果
利用babel-runtime
& babel-plugin-transform-runtime
按需加載墊片的方式,最終打包出來的結(jié)果僅僅只是 17.4kb.比之前的 280KB要小了許多.
最后總結(jié):
-
babel
僅僅只能將es6->es5
. 如果源代碼中使用ES6
新增的API(**Object.keys() & [].map()**)
,babel
就無能為力了. -
babel-polyfill
可以解決這個(gè)問題,但是會(huì)造成打包的文件大小變的巨大.-
babel-polyfill
內(nèi)部實(shí)現(xiàn)了所有的新API
的墊片功能 - 在打包的時(shí)候,會(huì)將整個(gè)
babel-polyfill
都打包進(jìn)去. - 所以最終打包出來的文件,就會(huì)變的很大(280KB).
-
-
babel-runtime
&babel-plugin-transform-runtime
是babel
提供的類似babel-polyfill
功能的一個(gè)插件.- 它可以根據(jù)實(shí)際源代碼使用到的
ES6新增API
按需打入墊片. - 最終打包的大小結(jié)果是 : 17.4KB
- 它可以根據(jù)實(shí)際源代碼使用到的
- 最重要的有點(diǎn):不管是使用babel-polyfill
還是 babel-runtime & babel-plugin-transform-runtime 的目的就是:
轉(zhuǎn)換那些我們寫在源文件中的ES6方法添加墊片,
能夠被無法識(shí)別的低瀏覽器也能夠正常運(yùn)行webpack最終打包出來的js文件.
babel 解決 語法層面的問題
babel-runtime & babel-plugin-transform-runtime解決API層面的問題.