前言
我觉得事情不大对,好像我之前几篇,太长了,以后我尽量控制下长度
babel
官网:https://babeljs.io/
中文网(非官方):https://www.babeljs.cn/
babel是一个编译器,可以把不同标准书写的语言,编译为统一的、能被各种浏览器识别的语言
babel转化的方式和postcss差不多,都是本身只提供一些分析的功能,具体的转化依靠的是插件

安装babel
babel可以和构建工具联合使用,也可以独立使用
如果要独立的使用babel,需要安装下面两个库:
- @babel/core:babel核心库,提供了编译所需的所有api
- @babel/cli:提供一个命令行工具,调用核心库的api完成编译
| 1
 | npm install @babel/core @babel/cli -D
 | 
@babel/cli提供了一个命令babel
| 12
 3
 4
 5
 
 | # 按文件编译babel 要编译的文件 -o 编辑结果文件
 
 # 按目录编译
 babel 要编译的整个目录 -d 编译结果放置的目录
 
 | 
比如说
| 1
 | babel ./src/index.js -o ./src/script/index.js
 | 
但是现在没有插件,做不了什么,只是原样输出而已
配置文件
babel转化代码要依托于babel插件和babel预设来完成,那我们就需要一个配置文件来告诉babel使用哪些插件和预设,这个配置文件默认是.babelrc
新建.babelrc
| 12
 3
 4
 
 | {"presets": [],
 "plugins": []
 }
 
 | 
babel预设
babel有多种预设,最常见的预设是@babel/preset-env
@babel/preset-env 文档 https://www.babeljs.cn/docs/babel-preset-env#options
@babel/preset-env可以让你使用最新的JS语法,而无需针对每种语法转换设置具体的插件
安装
| 1
 | npm install @babel/preset-env -D
 | 
配置
| 12
 3
 4
 
 | {"presets": ["@babel/preset-env"],
 "plugins": []
 }
 
 | 
使用
转化后变成
| 12
 3
 
 | "use strict";
 var a = Math.pow(3, 4);
 
 | 
但是只是这样还有一个问题,那就是现在只会对新语法进行处理,而不对新的API进行处理
比如说Promise是不会进行转化的

如果遇到没有Promise构造函数的旧版本浏览器,该代码就会报错
因此我们要进行一些配置
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | {"presets": [
 ["@babel/preset-env", {
 "useBuiltIns": "usage",
 "corejs": 3
 }
 ]
 ],
 "plugins": []
 }
 
 | 
而配置usebuiltins可以在编译结果中注入这些新的API,它的值默认为false,表示不注入任何新的API,可以将其设置为usage,表示根据API的使用情况,按需导入API
重新执行babel命令

从打包结果看出,我们还需要安装一个corejs库
安装后就可以运行了

注意,配置usebuiltins后,即使不安装core-js也可以转化成一样的打包结果,但是不安装core-js就无法运行
顺带一提,如果要转化async和await,需要再安装一个库regenerator-runtime
| 1
 | npm install regenerator-runtime
 | 
加了后就可以了

另外,@babel/preset-env需要根据兼容的浏览器范围来确定如何编译,和postcss一样,可以使用文件.browserslistrc来描述浏览器的兼容范围
| 12
 3
 
 | last 3 version> 1%
 not ie <= 8
 
 | 
babel插件
通常情况下,@babel/preset-env只转换那些已经形成正式标准的语法,对于某些处于早期阶段、还没有确定的语法不做转换。
如果要转换这些语法,就要单独使用插件,下面介绍一些插件
安装
| 12
 
 | cnpm install @babel/plugin-proposal-class-properties @babel/plugin-proposal-function-bind @babel/plugin-proposal-optional-chaining babel-plugin-transform-remove-console @babel/plugin-transform-runtime
 
 | 
| 1
 | cnpm install --save @babel/runtime
 | 
配置
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | {"presets": [
 ["@babel/preset-env", {
 "useBuiltIns": "usage",
 "corejs": 3
 }]
 ],
 "plugins": [
 ["@babel/proposal-class-properties", {
 "loose": true
 }],
 "@babel/proposal-function-bind",
 "@babel/proposal-optional-chaining",
 "transform-remove-console",
 "@babel/transform-runtime"
 ]
 }
 
 | 
@babel/plugin-proposal-class-properties
该插件可以让你在类中书写初始化字段
| 12
 3
 4
 5
 6
 
 | class A {a = 1;
 constructor(){
 this.b = 3;
 }
 }
 
 | 
@babel/plugin-proposal-function-bind
该插件可以让你轻松的为某个方法绑定this
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | function Print() {console.log(this.loginId);
 }
 
 const obj = {
 loginId: "abc"
 };
 
 obj::Print();
 
 | 
@babel/plugin-proposal-optional-chaining
支持?.语法
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | const obj = {foo: {
 bar: {
 baz: 42,
 },
 },
 };
 
 const baz = obj?.foo?.bar?.baz;
 
 const safe = obj?.qux?.baz;
 
 | 
babel-plugin-transform-remove-console
该插件会移除源码中的控制台输出语句
| 12
 
 | console.log("foo");console.error("bar");
 
 | 
编译后
@babel/plugin-transform-runtime
用于提供一些公共的API,比如下面的代码
| 12
 3
 4
 5
 
 | class A {constructor(name) {
 this.name = name;
 }
 }
 
 | 
转化后
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | "use strict";
 require("core-js/modules/es.function.name.js");
 
 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
 
 
 var A = function A(name) {
 _classCallCheck(this, A);
 
 this.name = name;
 };
 
 | 
如果使用了这个库
转化后
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | "use strict";
 var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
 
 require("core-js/modules/es.function.name.js");
 
 var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
 
 var A = function A(name) {
 (0, _classCallCheck2.default)(this, A);
 this.name = name;
 };
 
 | 
可以看出来,需要的辅助函数都从外部引入了,这样就可以避免一些重复代码,比如如果你有10个类,不使用这个库的话,_classCallCheck这个函数是会重复出现在10个文件里的,就会影响打包后的代码大小
在webpack里使用
安装
| 1
 | npm install --save-dev babel-loader @babel/core
 | 
如果你是在新项目里使用,必须要安装@babel/core,因为babel-loader要调用它
配置一波
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 
 | const path = require("path");const {CleanWebpackPlugin} = require("clean-webpack-plugin");
 const HtmlWebpackPlugin = require('html-webpack-plugin');
 const CopyWebpackPlugin = require('copy-webpack-plugin');
 const MiniCssExtractPlugin = require("mini-css-extract-plugin")
 const webpack = require("webpack");
 const cssLoaderConfig = {
 loader: "css-loader",
 options: {
 modules : {
 localIdentName: "[local]-[hash:5]"
 }
 }
 };
 module.exports = {
 entry: {
 index: "./index.js"
 },
 mode: "development",
 
 output: {
 path: path.resolve(__dirname, "dist"),
 filename: "js/[name].[chunkhash:5].js",
 publicPath: "/"
 },
 devServer: {
 contentBase: path.resolve(__dirname, 'dist'),
 port: 9000,
 open : true,
 },
 context: path.resolve(__dirname, "src"),
 module: {
 rules: [
 {
 test: /\.m?js$/,
 exclude: /node_modules/,
 use: {
 loader: "babel-loader"
 }
 },
 {
 test: /\.s[ac]ss$/i,
 use: [
 MiniCssExtractPlugin.loader,
 cssLoaderConfig,
 "postcss-loader",
 "sass-loader",
 ]
 },
 {
 test: /\.less$/i,
 use: [
 MiniCssExtractPlugin.loader,
 cssLoaderConfig,
 "postcss-loader",
 "less-loader",
 ]
 },
 {
 test: /\.p?css$/i,
 use: [
 MiniCssExtractPlugin.loader,
 cssLoaderConfig,
 "postcss-loader",
 ]
 },
 {
 test: /\.(png)|(gif)|(jpg)$/,
 use: [{
 loader: "url-loader",
 options: {
 limit: 10 * 1024,
 name: "imgs/[name].[contenthash:5].[ext]"
 }
 }]
 }],
 noParse: /jquery/
 },
 plugins: [
 new CleanWebpackPlugin(),
 new HtmlWebpackPlugin({
 template: "./public/index.html",
 filename: "html/index.html",
 chunks: ["index"]
 }),
 new CopyWebpackPlugin({
 patterns: [
 {
 from: "./assets",
 to: "./assets"
 },
 ],
 }),
 new webpack.ProvidePlugin({
 $ : 'jquery'
 }),
 new MiniCssExtractPlugin({
 filename: "css/[name].[contenthash:5].css"
 })
 ],
 resolve: {
 alias: {
 "@": path.resolve(__dirname, 'src')
 }},
 externals: {
 jquery : "$"
 }
 }
 
 | 
好的,这样就可以让babel处理我们在项目中的js文件了
后记
我没咕咕咕,耶