系列博客链接
webpack4 入门学习笔记(一) https://juejin.im/post/5cbc65e76fb9a068b3679294
webpack4 入门学习笔记(二) https://juejin.im/post/5cbc7da06fb9a0686c019b79
webpack4 入门学习笔记(三)--Babel 的使用 https://juejin.im/post/5cbfb0f86fb9a031ec6d27b8
代码
下载代码(demo3):GitHub
本文的代码是在前面笔记基础上修改的, 可以下载代码: GitHub https://github.com/qfstudy/webpack4 参考或是先看前面的笔记.
Babel https://babeljs.io/ 是一个广泛使用的转码器, 可以将 ES6 代码转为 ES5 代码, 从而在现有环境执行.
Babel 总共分为三个阶段: 解析(parse), 转换(transform), 生成(generate).
Babel 本身不具有任何转化功能, 它把转化的功能都分解到一个个 plugin 里面. 因此当我们不配置任何插件时, 经过 Babel 输出的代码和输入是相同的.
Babel 插件的使用
将插件的名字增加到配置文件中: 项目根目录下创建. babelrc 配置文件或是 webapck.config.JS 中配置, 一般都是在. babelrc 中配置.
使用 NPM install xxx 进行安装
Babel 的配置文件是. babelrc, 存放在项目的根目录下. 使用 Babel 的第一步, 就是配置这个文件.
该文件用来设置转码规则和插件, 基本格式如下.
- {
- "presets": [],
- "plugins": []
- }
Babel 简单介绍
preset
preset(预设)就是一系列插件的集合
@babel/preset-env 包含所有 ES6 转译为 ES5 的插件集合
core-JS
转换一些内置类 (Promise, Symbols 等等) 和静态方法(Array.from 等).
@babel/core
是作为 Babel 的核心存在, Babel 的核心 API 都在这个模块里面.
babel-loader
babel-loader 在 webpack 中使用, 是 webpack 和 Babel 之间的通讯桥梁
@babel/polyfill 介绍
@babel/preset-env 默认只转译 JS 语法, 而不转译新的 API, 比如 Iterator,Generator,Set,Maps,Proxy,Reflect,Symbol,Promise 等全局对象, 以及一些定义在全局对象上的方法 (比如 Object.assign) 都不会转译. 这时就必须使用 @babel/polyfill(内部集成了 core-JS 和 regenerator).
使用时, 在所有代码运行之前增加 import "@babel/polyfill"
或者是在 webpack.config.JS 入口配置
- module.exports = {
- entry: ["@babel/polyfill", "./app/js"],
- }
因此必须把 @babel/polyfill 作为 dependencies 而不是 devDependencies
@babel/polyfill 主要有两个缺点:
1. 使用 @babel/polyfill 需要做些额外配置, 实现打包的时候按需引入, 否则会把 @babel/polyfill 全部注入代码中会导致打出来的包非常大.
2.@babel/polyfill 会污染全局变量.
Babel7 的一个重大变化就是 NPM package 名称的变化, 把所有 babel-* 重命名为 @babel/*, 例如:
babel-polyfill 重命名为 @babel/polyfill
babel-preset-env 重命名为 @babel/preset-env
Babel 在 webpack 中的用法
首先实现对 ES6 语法的转译
安装 babel-loader, @babel/core,@babel/preset-env
- NPM i babel-loader -D
- NPM i @babel/core -D
- NPM i @babel/preset-env -D
babel-loader@8 需要安装 @babel/core7.x 版本.
在 webpack.config.JS 配置
- module.exports={
- module: {
- rules:[
- {
- test: /\.JS$/,
- exclude: /node_modules/,
- use:{
- loader: 'babel-loader',
- options:{
- presets: [
- ["@babel/preset-env",{
- //targets: 表示编译出的代码想要支持的浏览器版本
- targets: {
- Chrome: "67"
- }
- }]
- ]
- }
- }
- }
- ]
- }
- }
执行 NPM run build 或 npx webpack 就可以看到 dist 目录下的打包文件, 但是只是将 ES6 的语法进行转译, 并没有对 ES6 新 API 进行转译, 所以我们需要配置 @babel/polyfill 解决这个问题.
安装 @babel/polyfill
NPM i @babel/polyfill --save
在 index.JS 中引入 @babel/polyfill
index.JS
- //index.JS
- import '@babel/polyfill'
- let arr=[
- new Promise(()=>{}),
- new Promise(()=>{}),
- 2
- ]
- arr.map((item)=>{
- console.log(item)
- })
引入 @babel/polyfill 前, main.JS 的大小为 29.5KB
引入 @babel/polyfill 后, main.JS 的大小为 1MB
注意: 以上对比都是在没有 targets 这个选项的情况下, 因为有些浏览器几乎都支持 ES6, 在这种情况下,@babel/preset-env 将不会对代码进行处理.
这是因为把 @babel/polyfill 对所有 API 的实现都注入到打包文件中, 但是里面很多的 API 我们在代码中并没有用到, 所以需要修改配置, 按需引入对应的 API.
修改 webpack.config.JS 配置
添加 "useBuiltIns": "usage" 以后, 需要安装 core-JS@2, 并且添加 "corejs": 2 配置项, 这时配置选项比较多, 需要在项目根目录下新建. babelrc 文件, 在这个文件中配置.
.babelrc 配置如下:
"useBuiltIns" 属性值为 "usage" 时, 会自动引入 @babel/polyfill, 必须保证已经安装了 @babel/polyfill
"useBuiltIns" 属性值为 "usage" 时, 需要添加 "corejs": 2 配置项, 否则报错, 需要安装 core-JS
首先删掉 index.JS 中的 import '@babel/polyfill'
安装 core-JS
NPM i --save core-JS@2 或 NPM i --save core-JS@3
- {
- "presets": [["@babel/preset-env",{
- "useBuiltIns": "usage", // 不需要把 polly 都打包到代码中, 根据代码按需转译
- // core-JS@3和 core-JS@2二选一
- //"corejs": 3, //NPM i --save core-JS@3
- "corejs": 2 //NPM i --save core-JS@2
- }]]
- }
修改 webpack.config.JS, 删除 options 对象
- module.exports={
- module: {
- rules:[
- {
- test: /\.JS$/,
- exclude: /node_modules/,
- loader: 'babel-loader'
- }
- ]
- }
- }
执行 NPM run build, 打包后的文件大小为 165KB
但是, 在开发类库或是第三方模块时不适合使用 @babel/polyfill, 所以接下来使用 @babel/plugin-transform-runtime 来解决这个问题.
@babel/plugin-transform-runtime,@babel/runtime 和 @babel/runtime-corejs2 的用法
@babel/runtime-corejs2 https://babeljs.io/docs/en/babel-runtime-corejs2 : 是一个包含 Babel modular runtime helpers 和 regenerator-runtime 以及 core-JS 的库.
@babel/runtime https://babeljs.io/docs/en/babel-runtime#docsNav : 是一个包含 Babel modular runtime helpers 和 regenerator-runtime 的库.
在配置项中 corejs 属性值为默认为 false, 如果需要将 Promise 等 API 进行转译, 则需要设置属性值为 2 时, 并且安装 @babel/runtime-corejs2
安装:
- NPM i @babel /plugin-transform-runtime -D
- NPM i --save @babel/runtime
- NPM i --save @babel/runtime-corejs2
修改. babelrc 文件
- {
- "plugins": [
- ["@babel/plugin-transform-runtime",{
- "helpers": true,
- "regenerator": true,
- "useESModules": false,
- "corejs": 2
- }]
- ]
- }
我们把 presets 配置项去掉了, 然后 NPM run build 打包, 打开打包后的 main.JS 查看, 虽然把转译了 Promise, 但是 ES6 新语法并没被转译, 例如: let 没有被转译为 var.
所以还是需要配置 presets, 因为 "@babel/preset-env" 包含了对所有 ES6 语法转译为 ES5 插件.
再次修改. babelrc 文件
- {
- "presets": ["@babel/preset-env"],
- "plugins": [
- ["@babel/plugin-transform-runtime",{
- "helpers": true,
- "regenerator": true,
- "useESModules": false,
- "corejs": 2
- }]
- ]
- }
添加 presets 配置项, 然后 NPM run build 打包, 打开打包后的 main.JS 查看, 可以看到 let 和箭头函数都被转译为 ES5 语法了.
来源: https://www.cnblogs.com/qfstudy/p/10760426.html