webpack - babel 篇

前言

基于我的上篇文章,webpack4.0 入门篇 - 构建前端开发的基本环境,补充对babel进行的一次探究。上篇文章讲叙到的 webpack babel 时几乎一笔带过,所以这篇文章将进行补充说明.

Babel 是一个让我们能够使用 ES 新特性的 JS 编译工具,我们可以在 webpack 中配置 Babel,以便使用 ES6、ES7 标准来编写 JS 代码。

本文以当前最新版本的 babel - 7.10 为例, 做 babel 的配置. 相关版本号如下

{
  "devDependencies": {
    "@babel/core": "^7.1.6",
    "@babel/plugin-proposal-decorators": "^7.1.6",
    "@babel/plugin-transform-runtime": "^7.1.0",
    "@babel/preset-env": "^7.1.6",
    "@babel/runtime": "^7.1.5",
    "babel-loader": "^8.0.4",
    "webpack": "^4.26.1",
    "webpack-cli": "^3.1.2"
  }
}

babel-loader 和 @babel/core

建立基本的 webpack 配置文件

mkdir webpack-babel => cd  webpack-babel => yarn init -y  // 初始化
npm i yarn -g // 安装了yarn可以忽略
yarn add webpack webpack-cli -D

// package.json 中添加:
"scripts": {
  "start": "webpack --mode development",
  "build": "webpack --mode production"
}

yarn add babel-loader @babel/core -D
  • yarn : 和 npm 几乎一样,本文使用 yarn 安装...
  • babel-loader: 转义 js 文件代码的 loader
  • @babel/core:babel 核心库

根目录下添加 webpack.config.js

const path = require('path')

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[hash:8].js'
  },
  module: {
    rules: [
      {
        test: /\.m?js$/,
        exclude: /(node_modules|bower_components)/,
        use: { loader: 'babel-loader' } // options 在 .babelrc 定义
      }
    ]
  }
}

src/index.js

const func = () => {
  console.log('hello webpack')
}
func()

class User {
  constructor() {
    console.log('new User')
  }
}

const user = new User()

执行 yarn build 后就可以打包成功,打包后的代码是压缩后的。而 yarn start 后的代码是未压缩的。为了使代码可读性高一点,我们可以在webpack.config.js添加:

module.exports = {
  //...
  devtool: true
}

@babel-preset-env

打包后我们可以发现箭头函数并未转化为 ES5 语法!

查阅 babel plugins 文档,如果要转义箭头函数,需要使用到 @babel/plugin-transform-arrow-functions 这个插件
同理转义 class 需要使用 @babel/plugin-transform-classes

yarn add @babel/plugin-transform-arrow-functions @babel/plugin-transform-classes -D

根目录下建立 .babelrc 文件:

{
  "plugins": [
    "@babel/plugin-transform-arrow-functions",
    "@babel/plugin-transform-classes"
  ]
}

yarn build 之后可以看出 箭头函数和类都被转义了。

但是假如你再使用 async await 之类的 es6 语法,你还得一个个添加,这是不实际的。

@babel-preset-env 就整合了这些语法转义插件:

Using plugins:
transform-template-literals {}
transform-literals {}
transform-function-name {}
transform-arrow-functions {}
transform-block-scoped-functions {}
transform-classes {}
transform-object-super {}
//...

使用如下:

yarn add @babel-preset-env -D

.babelrc

{
  "presets": ["@babel/preset-env"]
}

@babel/polyfill

Babel 默认只转换新的 JavaScript 句法(syntax),而不转换新的 API ,比如 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign)都不会转码。

这样就导致了一些新的 API 老版浏览器不兼容。如上述所说,对于新的 API,你可能需要引入 @babel-polyfill 来进行兼容

yarn add @babel-polyfill -D

修改 weboack.config.js

module.exports = {
  entry: ['@babel-polyfill', './src/index.js']
}

yarn build 发现文件体积大了很多,因为上面的代码表示将 @babel-polyfill 的代码也打包进去了。

当然这不是我们希望的,如何按需编译呢? 我们可以这么做:

index.js

import '@babel/polyfill' // 引入

const func = () => {
  console.log('hello webpack')
}
func()

class User {
  constructor() {
    console.log('new User')
  }
}

const user = new User()

new Promise(resolve => console.log('promise'))

Array.from('foo')

还原 webpack.config.js

module.exports = {
  entry: './src/index.js'
}

修改 .babelrc

{
  "presets": [["@babel/preset-env", { "useBuiltIns": "usage" }]]
}

yarn build 后发现我们的代码体积就变得很小了!

@babel/runtime 和 @babel/plugin-transform-runtime

  • babel-polyfill 会污染全局作用域, 如引入 Array.prototype.includes 修改了 Array 的原型,除此外还有 String...
  • babel-polyfill 引入新的对象: PromiseWeakMap

这也不是我们希望出现的。

  • @babel/runtime 的作用:
    • 提取辅助函数。ES6 转码时,babel 会需要一些辅助函数,例如 _extend。babel 默认会将这些辅助函数内联到每一个 js 文件里, babel 提供了 transform-runtime 来将这些辅助函数“搬”到一个单独的模块 babel-runtime 中,这样做能减小项目文件的大小。
    • 提供 polyfill:不会污染全局作用域,但是不支持实例方法如 Array.includes
  • @transform-runtime 的作用:
    • babel-runtime 更像是分散的 polyfill 模块,需要在各自的模块里单独引入,借助 transform-runtime 插件来自动化处理这一切,也就是说你不要在文件开头 import 相关的 polyfill,你只需使用,transform-runtime 会帮你引入。
yarn add  @babel/runtime-corejs2
yarn add @babel/plugin-transform-runtime -D

修改 .babelrc

{
  "presets": ["@babel/preset-env"],
  "plugins": [["@babel/plugin-transform-runtime", { "corejs": 2 }]]
}

index.js 移除 import '@babel/polyfill'

@babel/plugin-proposal-decorators

添加装饰器模式的支持

yarn add @babel/plugin-proposal-decorators -D

index.js

function annotation(target) {
  target.annotated = true
}

@annotation
class User {
  constructor() {
    console.log('new User')
  }
}
//...

.babelrc

{
  "presets": ["@babel/preset-env"],
  "plugins": [
    ["@babel/plugin-proposal-decorators", { "decoratorsBeforeExport": true }],
    ["@babel/plugin-transform-runtime", { "corejs": 2 }]
  ]
}

结尾

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,440评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,814评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,427评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,710评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,625评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,014评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,511评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,162评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,311评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,262评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,278评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,989评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,583评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,664评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,904评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,274评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,856评论 2 339

推荐阅读更多精彩内容