babel 在前端工程化开发中发挥着至关重要的作用,它能将较高级的语法转成浏览器可识别的代码,无论中 es6 中 const 、promise 还是 React、TypeScript。

以下babel在线工具中左侧输入代码,右侧为编译后的结果,设置需要浏览器兼容的版本后,可以看到 "const" 编译成 "var","箭头函数" 编译成 "普通函数"。

命令行使用

babel 和之前说到的 postcss 一样,可以通过命令行运行,解析文件夹或者文件。安装命令行工具所需要的依赖,npm install @babel/cli @babel/core -D

通过 npx 执行 .bin 目录下的指令,--out-file 表示输出文件地址,执行编译语句 npx babel src --out-file dist/main.js

可我们发现,目标文件和源文件代码是一样的,const 和 箭头函数都没有被编译。这是因为,我们没有设置编译代码所需要的插件。

上面代码中有标识符和箭头函数,需要【安装】并使用这些插件

  • 转换箭头函数:@babel/plugin-transform-arrow-functions
  • 转换const:@babel/plugin-transform-block-scoping

插件需要通过 --plugins 添加在命令后面

  1. npx babel src --out-file dist/function.js --plugins=@babel/plugin-transform-arrow-functions
  2. npx babel src --out-file dist/const.js --plugins=@babel/plugin-transform-block-scoping
  3. npx babel src --out-file dist/plugins.js --plugins=@babel/plugin-transform-arrow-functions, @babel/plugin-transform-block-scoping

指定插件之后,babel 就会根据插件的功能再进行编译

但插件只能实现单一功能,我们代码里一般也不只有 const 、箭头函数这种语法,当需要处理的代码种类变多,可能就要罗列出非常多的插件来执行,所以 babel 提供了一种插件的集合,叫做"预设","预设"会根据我们所配置的需要兼容处理的逻辑来进行编译。

安装 @babel/preset-env 依赖后,在命令行使用 --presets 来替代 --plugins。npx babel src --out-file dist/presets.js --presets=@babel/preset-env

babel-loader

除了在命令行中直接通过 babel 编译文件,更多情况下会在项目中对批量文件进行处理,这时候就需要用到 babel-loader 来进行处理啦。

安装依赖 npm install babel-loader @babel/core @babel/core是babel的核心

在webpack.config.js文件中配置对于js的处理规则,如果对配置不清楚可以参考 webpack初体验loader配置方式,这里和在命令行中执行一样,需要配置"插件"或者"预设"。

  1. const path = require("path");
  2. module.exports = {
  3.   entry: "./src/index.js",
  4.   output: {
  5.     filename: "./bundle.js",
  6.     path: path.resolve(__dirname, "./dist"),
  7.   },
  8.   mode: "development",
  9.   devtool: "source-map",
  10.   module: {
  11.     rules: [
  12.       {
  13.         test: /\.js/,
  14.         exclude: /node_modules/,
  15.         use: [
  16.           {
  17.             loader: "babel-loader",
  18.             options: {
  19.               // "插件"是这样配置,这里直接使用"预设"
  20.               // plugins: [
  21.               //   "@babel/plugin-transform-arrow-functions",
  22.               //   "@babel/plugin-transform-block-scoping",
  23.               // ],
  24.               presets: ["@babel/preset-env"],
  25.             },
  26.           },
  27.         ],
  28.       },
  29.     ],
  30.   },
  31. };

这样 babel 就会把代码编译成我们所需要的兼容要求

这里我们没有设置到底需要对什么样的浏览器进行兼容,使用的就是browserslist默认配置,browserslist作用及详细介绍

有两种方式可以设置babel兼容性处理的规则

  • browserslist:设置的兼容规则对css和js都通用,可配置在 .browserslist 或 package.json 文件中
  • targets:webpack.config.js 中配置在 loader 的options里

以上两种方式都可以配置,但更建议使用 browserslist,因为 css 和 js 需要兼容的浏览器版本一般来说是一致的,使用 browserslist 只需要配置一套规则即可。

比如我们设置 兼容谷歌浏览器版本99

  1. // package.json
  2. "browserslist": [
  3. "chrome 99"
  4. ]
  5. // 配置在 webpack.config.js 中
  6. use: [
  7.   {
  8.     loader: "babel-loader",
  9.     options: {
  10.       presets: [
  11.         [
  12.           "@babel/preset-env",
  13.           {
  14.             targets: ["chrome 99"],
  15.           },
  16.         ],
  17.       ],
  18.     },
  19.   },
  20. ],

因为 chrome 99 是最新的浏览器版本,对于高级的js语法都能够支持,所以不需要将es6编译成es5的语法。

babel 处理文件不止在 js 中需要,如果是 react 项目的话,还需要支持 jsx 文件、可能还存在 ts 文件,所以可以将 babel 配置信息放到一个单独的文件中,达到共享的目的。

  1. // webpack.config.js
  2. rules: [
  3. {
  4. test: /\.js/,
  5. exclude: /node_modules/,
  6. use: [
  7. {
  8. loader: "babel-loader",
  9. },
  10. ],
  11. },
  12. ],
  13. // babel.config.js
  14. module.exports = {
  15.   presets: ["@babel/preset-env"],
  16. };

polyfill

以上 babel 可以对于一些 js 语法进行处理,但有些新特性比如 promise 在默认情况下不会被处理,这样不能被低版本浏览器所识别。

那么我们需要借助"polyfill"来打补丁,对某些特定的语法做处理,这样编译后的代码中就能包含这些新特性。

  • babel 7.4 以前,通过 @babel/polyfill
  • babel 7.4 以后,通过 core-js regenerator-runtime

这里使用的 babel 版本是7.17,所以使用第二种方式,安装依赖 npm install core-js regenerator-runtime @babel/runtime-corejs3,在 babel.config.js 中给 preset 配置 polyfill 相关的属性

  • useBuiltIns:规定以什么方式来使用 polyfill

    • false:不使用 polyfill,不用配置 corejs
    • usage:自动检测源代码所需要使用的 polyfill,需配置corejs
    • entry:导入所有 polyfill,文件体积很大,需配置corejs,以及在入口文件中引入 core-js 与 regenerator-runtime
  • corejs:所使用的 corejs 版本
  1. // babel.config.js
  2. module.exports = {
  3.   presets: [
  4.     [
  5.       "@babel/preset-env",
  6.       {
  7.         useBuiltIns: "entry",
  8.         corejs: 3,
  9.       },
  10.     ],
  11.   ],
  12. };
  13. // 入口文件
  14. import "core-js/stable";
  15. import "regenerator-runtime/runtime";

使用所有的 polyfill ,编译后的代码行数达到了一万七,里面包括很多新特性的实现

对React的支持

react 使用的是 jsx 语法,babel 可以直接对其处理,与 js 文件的处理方式一样,可以选择使用"插件"或者插件的集合"预设"。

插件

  • @babel/plugin-syntax-jsx
  • @babel/plugin-transform-react-jsx
  • @babel/plugin-transform-react-display-name

预设

  • @babel/preset-react
  1. // babel.config.js
  2. module.exports = {
  3.   presets: [
  4.     [
  5.       "@babel/preset-env",
  6.       {
  7.         useBuiltIns: "entry",
  8.         corejs: 3,
  9.       },
  10.     ],
  11.     ["@babel/preset-react"],
  12.   ],
  13. };

react 代码被处理且编译成功,可以在浏览器上看到渲染的页面效果

处理TypeScript文件

在项目中处理 ts 文件有两种方式

  • ts-loader:将ts文件编译成js文件,有类型检测,但没有polyfill
  • babel-loader:有polyfill,没有类型检测,代码错误不会提示

首先来看 ts-loader 处理的情况,安装 ts-loader,ts-loader 依赖于 typescript 这个工具,npm install ts-loader typscript -D

在 webpack.config.js 配置 ts-loader 处理 ts 文件

  1. module: {
  2.   rules: [
  3.     {
  4.       test: /\.ts$/,
  5.       exclude: /node_modules/,
  6.       use: [
  7.         {
  8.           loader: "ts-loader",
  9.         },
  10.       ],
  11.     },
  12.   ],
  13. },

可以看到,ts 代码已经被完全编译成了 js 代码,但是 Promise 是没有被处理的

换成 babel-loader 来处理,和 react 、js 一样,可以选择"插件"或者插件的集合"预设"。

  • 插件 @babel/plugin-transform-typescript
  • 预设 @babel/preset-typescript

将webpack.config.js 中的 ts-loader 替换成 babel-loader,以及在 babel.config.js 中进行配置。

  1. // babel.config.js
  2. module.exports = {
  3.   presets: [
  4.     [
  5.       "@babel/preset-env",
  6.       {
  7.         useBuiltIns: "usage",
  8.         corejs: 3,
  9.       },
  10.     ],
  11.     ["@babel/preset-typescript"],
  12.   ],
  13. };

这种情况下,编译后文件就增加了 polyfill 的处理,这里 useBuiltIns 使用的是 usage,比 entry 这种模式下代码量要少一些。

从 polyfill 的角度来说,babel-loader 处理 ts 文件会更好,毕竟我们写的代码可能会有新特性和兼容性要求,但 babel-loader 存在的问题是无法进行错误类型检测,也就是检测不到代码出错,仍然会编译通过。

但我们是希望能够在开发阶段尽早的发现错误,这样就能避免测试阶段或者发布线上存在问题,在这里可以配合编译的命令来解决这个问题。

tsc 就是 typescript 工具的命令行语法,执行 npm run build通过 tsc 来检测代码是否正确,正确时才使用 webpack 编译,或者执行 npm run type-check-watch实时检测ts代码是否正确

  1. // package.json
  2. "scripts": {
  3. "build": "npm run type-check && webpack",
  4. "type-check": "npx tsc --noEmit",
  5. "type-check-watch": "npx tsc --noEmit --watch"
  6. },

当代码中存在错误语法时,会直接报错。

这样就可以对ts文件达到类型错误的检测以及polyfill的效果了。

以上关于 babel-loader 处理 js、react、ts 文件,以及对于新特性的 polyfill,设置浏览器兼容版本,babel 配置文件 都非常的重要, 更多有关webpack的内容可以参考我其它的博文,持续更新中~

来会会babel这个重要且神奇的工具的更多相关文章

  1. 七牛云——qshell一个神奇的工具

    前言 qshell是利用七牛文档上公开的API实现的一个方便开发者测试和使用七牛API服务的命令行工具.该工具设计和开发的主要目的就是帮助开发者快速解决问题.目前该工具融合了七牛存储,CDN,以及其他 ...

  2. USB中TOKEN的CRC5与CRC16校验(神奇的工具生成Verilog实现)

    USB2.0IP设计 最近,在学习USB2.0IP的设计,其中包含了CRC校验码的内容,之前学习千兆以太网曾经用到过CRC32校验(https://www.cnblogs.com/Xwangzi66/ ...

  3. 一篇文章图文并茂地带你轻松学完 JavaScript 设计模式(二)

    JavaScript 设计模式(二) 本篇文章是 JavaScript 设计模式的第二篇文章,如果没有看过我上篇文章的读者,可以先看完 上篇文章 后再看这篇文章,当然两篇文章并没有过多的依赖性. 5. ...

  4. Webpack使用教程五(Babel)

    Babel是一个JavaScript编译和工具平台,使用Babel我们可以:使用新版本的JavaScript(ES6/ES2015,ES7/ES2016),尽管有些浏览器不能全部支持新特性:使用Jav ...

  5. 深入浅出ES6(九):学习Babel和Broccoli,马上就用ES6

    作者 Jason Orendorff  github主页  https://github.com/jorendorff 现在,我们将向你分步展示如何做到的这一切.上面提及的工具被称为转译器,你可以将它 ...

  6. [转] 如何写好.babelrc?Babel的presets和plugins配置解析

    什么是Babel The compiler for writing next generation JavaScript. 官网是这么说的,翻译一下就是下一代JavaScript 语法的编译器. 作为 ...

  7. 如何写好.babelrc?Babel的presets和plugins配置解析

    什么是Babel The compiler for writing next generation JavaScript. 官网是这么说的,翻译一下就是下一代JavaScript 语法的编译器. 作为 ...

  8. ES6 - Babel编译环境搭建

    都看到这里了,我就不写什么node环境安装之类的了. 直接从新建项目文件夹后开始吧! 安装依赖: 命令行cd到项目文件夹之后,执行以下命令:(mac记得前边加sudo) npm init –y  // ...

  9. 前端利器躬行记(2)——Babel

    Babel是一个JavaScript编译器,不仅能将当前运行环境不支持的JavaScript语法(例如ES6.ES7等)编译成向下兼容的可用语法(例如ES3或ES5),这其中会涉及新语法的转换和缺失特 ...

  10. ES6入门一:ES6简介及Babel转码器

    ES6简介 Babel转码器 Nodejs中使用ES6 WebPack中使用ES6及Babel转码插件 一.ES6简介与转码  1.1一个常见的问题,ECMAScript和JavaScript到底是什 ...

随机推荐

  1. Docker私有仓库harbor

    Docker私有仓库harbor 目录 Docker私有仓库harbor Harbor私有仓库介绍 Harbor部署 harbor页面不显示排错思路 Harbor的使用 Harbor拉镜像 自制镜像推 ...

  2. 程序员IT行业,外行眼里高收入人群,内行人里的卷王

    程序员 一词,在我眼里其实是贬义词.因为我的其他不是这行的亲朋友好友,你和他们说,你是一名程序员· 他们 第一刻板影响就是,秃头,肥胖,宅男,油腻,不修边幅 反正给人一种不干净,不好形象,,,,不知道 ...

  3. 2022-11-19:第二高的薪水。表结构和数据的sql语句如下,输出200,因为200是第二大的。请问sql语句如何写? DROP TABLE IF EXISTS `employee`; CREAT

    2022-11-19:第二高的薪水.表结构和数据的sql语句如下,输出200,因为200是第二大的.请问sql语句如何写? DROP TABLE IF EXISTS `employee`; CREAT ...

  4. 2021-02-04:第一年农场有1只成熟的母牛A,往后的每年:①每一只成熟的母牛都会生一只母牛 ②每一只新出生的母牛都在出生的第三年成熟 ③每一只母牛永远不会死 。请问N年后牛的数量是多少 ?

    2021-02-04:第一年农场有1只成熟的母牛A,往后的每年:①每一只成熟的母牛都会生一只母牛 ②每一只新出生的母牛都在出生的第三年成熟 ③每一只母牛永远不会死 .请问N年后牛的数量是多少 ?福哥答 ...

  5. 2022-03-02:k8s安装minio,yaml如何写?

    2022-03-02:k8s安装minio,yaml如何写? 答案2022-03-02: yaml如下: apiVersion: apps/v1 kind: Deployment metadata: ...

  6. defer()排除某些字段

    defer()排除某些字段 不显示nickname,age两列的数据 Student.objects.all().defer('nickname','age')

  7. django 整合 vue

    django 整合 vue   安装 vue 1. 安装 node.js , 官网地址: https://nodejs.org/zh-cn/download/ 2. 使用 npm 淘宝镜像 npm i ...

  8. tryhackme-OWASP

    tryhackme-OWASP Top 10部分记录 敏感信息泄露 在assets目录中 可以看到到一个sqlite数据库的webapp.db文件 使用sqlite3 webapp.db .table ...

  9. Python 列表推导式:简洁、高效的数据操作艺术

    Python 列表推导式:简洁.高效的数据操作艺术 Python 的列表推导式,这个看似简单的语法糖,实则内含无限威力.在 Python 代码编写中,列表推导式的灵活性和简洁性让它成为了不可或缺的一部 ...

  10. 【python基础】循环语句-continue关键字

    1.continue关键字 continue关键字的作用是:用来告诉 Python 跳过当前循环代码块中的剩余语句,然后继续进行下一轮循环. 其在while循环和for循环中的作用示意图如下 我们通过 ...