{"action":"opened","issue":{"url":"https://api.github.com/repos/py419569317/blog/issues/6","repository_url":"https://api.github.com/repos/py419569317/blog","labels_url":"https://api.github.com/repos/py419569317/blog/issues/6/labels{/name}","comments_url":"https://api.github.com/repos/py419569317/blog/issues/6/comments","events_url":"https://api.github.com/repos/py419569317/blog/issues/6/events","html_url":"https://github.com/py419569317/blog/issues/6","id":308351499,"number":6,"title":"由浅入深webpack - 04.02   使用babel-loader编译ES6","user":{"login":"py419569317","id":22902187,"avatar_url":"https://avatars0.githubusercontent.com/u/22902187?v=4","gravatar_id":"","url":"https://api.github.com/users/py419569317","html_url":"https://github.com/py419569317","followers_url":"https://api.github.com/users/py419569317/followers","following_url":"https://api.github.com/users/py419569317/following{/other_user}","gists_url":"https://api.github.com/users/py419569317/gists{/gist_id}","starred_url":"https://api.github.com/users/py419569317/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/py419569317/subscriptions","organizations_url":"https://api.github.com/users/py419569317/orgs","repos_url":"https://api.github.com/users/py419569317/repos","events_url":"https://api.github.com/users/py419569317/events{/privacy}","received_events_url":"https://api.github.com/users/py419569317/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-03-25T13:52:53Z","updated_at":"2018-03-25T13:52:53Z","closed_at":null,"author_association":"OWNER","body":"# babel\r\n安装babel-core babel-loader转义es6语法\r\n`npm i -D babel-loader babel-core`\r\n创建一个webpack.config.js\r\n```\r\nmodule.exports = {\r\n\tentry: {\r\n\t\tapp: './app.js'\r\n\t},\r\n\toutput: {\r\n\t\tfilename: '[name].[hash:5].js'\r\n\t},\r\n\tmodule: {\r\n\t\trules: [\r\n\t\t\t{\r\n\t\t\t\ttest: /\\.js$/,\r\n\t\t\t\texclude: /node_modules/,\r\n\t\t\t\tuse: 'babel-loader'\r\n\t\t\t}\r\n\t\t]\r\n\t}\r\n}\r\n```\r\ntest定义一个规则，匹配所有以.js结尾的文件，对这些文件用babel-loader进行es6的转义，exclude表示不需要对node_modules中的第三方库进行转义\r\n# babel-preset\r\n虽然定义好了loader，但是babel-loader不知道以什么规范进行转义，这时候需要用到babel的presets，presets其实是对babel规范的汇总，一般有一下几类：\r\n\r\n- es2015/es2016/es2017/latest\r\n  使用es2015也就是我们常说的es6,编译箭头函数、编译const、let、编译class等待，更多细节查看[文档](https://babeljs.io/docs/plugins/preset-es2015/)\r\n  使用es2016也就是es7，涉及到幂运算符，更多细节可看[文档](https://babeljs.io/docs/plugins/preset-es2016/)\r\n  使用es2017也就是es8，包含我们经常使用的async/await语法糖，更多细节可看[文档](transform-async-to-generator)\r\n  latest是个特殊的presets，包含了es2015、es2016、es2017一直到目前为止正式发布(不包括stage0-stage3)的规范\r\n\r\n- [env](https://github.com/babel/babel/tree/master/packages/babel-preset-env)\r\n  babel-preset-es20xx和babel-preset-lastest的问题在于它们太过于庞大，即包含了过多在某些情况下不需要的功能，比如大多数浏览器已经支持generator，如果你使用babel-preset-es2015，它仍然会将generator函数编译成复杂的es5代码，这是没有必要的\r\n ### 解决方案：\r\n babel-preset-env和babel-preset-lastest功能相似，但是使用babel-preset-env我们可以声明环境，然后该preset只会编译该环境下缺少的特性的代码\r\n 比如我们根据[browserslist](https://github.com/browserslist/browserslist)针对某些浏览器环境进行转义：\r\n 比如：\r\n   \r\n\r\n1. 支持大部分浏览器最新的两个版本以及IE 7+:\r\n```\r\n\"babel\": {\r\n\"presets\": [\r\n    [\r\n      \"env\",\r\n      {\r\n        \"targets\": {\r\n          \"browsers\": [\"last 2 versions\", \"ie >= 7\"]\r\n        }\r\n      }\r\n    ]\r\n  ]\r\n},\r\n```\r\n\r\n2.支持超过市场份额5%的浏览器\r\n```\r\n\"targets\": {\r\n  \"browsers\": \"> 5%\"\r\n}\r\n``` \r\n\r\n3. 某个固定版本的浏览器\r\n```\r\n\"targets\": {\r\n  \"chrome\": 56\r\n}\r\n```\r\n 如何安装: npm install --save-dev babel-preset-env，如果安装的是最新的babel-loader，需要安装最新的preset-env：npm install \"babel-loader@^8.0.0-beta\" @babel/core @babel/preset-env\r\n 更多配置可以参考[官方文档](https://github.com/babel/babel/tree/master/packages/babel-preset-env)\r\n 要注意：这也意味着我们需要安装一些插件或preset以处理某些实验特性(stage0-stage3)，这些往往不是babel-preset-lastest的一部分\r\n 使用babel-preset-env的好处就是你不再需要使用babel-preset-esxxxx\r\n\r\n- babel-preset-react\r\n 与react相关的\r\n- babel-preset-stage 0 - 3\r\n 实验特性，未正式被发布的\r\n\r\n继续对我们的webpack.config.js做修改，增加preset预设\r\n```\r\nmodule.exports = {\r\n\tentry: {\r\n\t\tapp: './app.js'\r\n\t},\r\n\toutput: {\r\n\t\tfilename: '[name].[hash:5].js'\r\n\t},\r\n\tmodule: {\r\n\t\trules: [\r\n\t\t\t{\r\n\t\t\t\ttest: /\\.js$/,\r\n\t\t\t\texclude: /node_modules/,\r\n\t\t\t\tuse: {\r\n\t\t\t\t\tloader: 'babel-loader',\r\n\t\t\t\t\toptions: { // 给这个loader指定参数\r\n\t\t\t\t\t\tpresets: [ // 给babel-preset-env设置参数\r\n\t\t\t\t\t\t\t[\r\n\t\t\t\t\t\t\t\t'env',\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\ttargets: {\r\n\t\t\t\t\t\t\t\t\t\tbrowsers: ['>1%', 'last 2 versions']\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t]\r\n\t\t\t\t\t\t]\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t]\r\n\t}\r\n}\r\n```\r\n对app.js进行修改，增加一些es6的代码\r\n```\r\nlet func = () => {}\r\nconst NUM = 40\r\nlet arr = [1, 2, 3]\r\nlet arrB = arr.map(item => item * 4)\r\n\r\nconsole.log(arrB)\r\n```\r\n执行webpack打包，观察打包后生成的文件把es6的代码成功转义成es5：\r\n![image](https://user-images.githubusercontent.com/22902187/37875449-ff1272b8-3071-11e8-8e09-291ef9422bcc.png)\r\n\r\n如果把target改成只针对chome浏览器版本为52：\r\n```\r\ntarget: {\r\n   chrome: '52'\r\n}\r\n```\r\n![image](https://user-images.githubusercontent.com/22902187/37875436-be60f348-3071-11e8-8f55-3cedf084fcee.png)\r\n\r\n# babel-plugin\r\n如果给app.js增加一些es6的方法，比如includes和new Set()\r\n```\r\nlet func = () => {}\r\nconst NUM = 40\r\nlet arr = [1, 2, 3]\r\nlet arrB = arr.map(item => item * 4)\r\n\r\nconsole.log(arrB.includes(8))\r\nconsole.log('new set', new Set(arrB))\r\n```\r\n打开编译后的文件，发现并没有对includes和set进行转义，而低版本浏览器显然是没有这些方法的，其实babel-preset-env只会针对语法进行转义，而不会对函数和方法(Set、Map、Promise、Generator、Array.from、Object.assign等等)进行转义，因此我们需要babel-polyfill和babel-runtime\r\n- babel-polyfill\r\n  全局垫片，为应用准备，不适用于框架，相当于对全局的变量进行污染，把没有的方法定义到全局\r\n  安装：npm install --save babel-polyfill\r\n\r\n- babel-runtime\r\n  局部垫片，为开发框架准备，使用es6语法，又不想污染全局变量\r\n 安装：npm install --save babel-plugin-transform-runtime   npm install --save babel-runtime\r\n\r\n### 解决babel-preset-env无法转义部分es6的函数和方法：\r\n\r\n1. 应用级\r\n\r\napp.js引入安装的babel-polyfill:\r\n```\r\nimport 'babel-polyfill'\r\nlet func = () => {}\r\nconst NUM = 40\r\nlet arr = [1, 2, 3]\r\nlet arrB = arr.map(item => item * 4)\r\n\r\nconsole.log(arrB.includes(8))\r\nconsole.log(arrB)\r\nconsole.log('new set', new Set(arrB))\r\n```\r\n发现打包后的文件增大了到了265kb，因为引入了全局垫片\r\n![image](https://user-images.githubusercontent.com/22902187/37875597-5e0bbe08-3074-11e8-8e46-1e71df6a5ad2.png)\r\n同时babel-polyfill给全局定义了includes方法和set函数\r\n![image](https://user-images.githubusercontent.com/22902187/37875812-c5f8f16e-3076-11e8-893f-aeb3a585f8cb.png)\r\n![image](https://user-images.githubusercontent.com/22902187/37875718-c9999d9c-3075-11e8-926c-c7d234696d7d.png)\r\n![image](https://user-images.githubusercontent.com/22902187/37875728-d782fa70-3075-11e8-9dc9-0f350f8b9932.png)\r\n\r\n2.非应用级：如开发框架 \r\n修改webpack.config.js配置，新建.babelrc文件，把options的配置放在.babelrc中\r\n```\r\nmodule.exports = {\r\n\tentry: {\r\n\t\tapp: './app.js'\r\n\t},\r\n\toutput: {\r\n\t\tfilename: '[name].[hash:5].js'\r\n\t},\r\n\tmodule: {\r\n\t\trules: [\r\n\t\t\t{\r\n\t\t\t\ttest: /\\.js$/,\r\n\t\t\t\texclude: /node_modules/,\r\n\t\t\t\tuse: {\r\n\t\t\t\t\tloader: 'babel-loader',\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t]\r\n\t}\r\n}\r\n```\r\n.babelrc:\r\n```\r\n{\r\n\t\"presets\": [ \r\n\t\t[\r\n\t\t\t\"env\",\r\n\t\t\t{\r\n\t\t\t\t\"targets\": {\r\n\t\t\t\t\t\"browsers\": ['>1%', 'last 2 versions']\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t]\r\n\t],\r\n\tplugins: [\"transform-runtime\"]\r\n}\r\n```\r\n观察打包后的文件，发现run-time仅仅是对es6的方法进行了修改，没有增加全局变量\r\n![image](https://user-images.githubusercontent.com/22902187/37875755-1c652122-3076-11e8-8462-d31fb2463e7a.png)\r\n![image](https://user-images.githubusercontent.com/22902187/37875807-a0863928-3076-11e8-9590-8e5a385aa578.png)\r\n\r\n\r\n\r\n"}}
{"actor":{"display_login":"py419569317"}}