为什么要处理ES6语法呢?当我们使用新语法来写代码,一些浏览器如果不支持那么就会报错,导致用户体验非常糟糕。我们使用babel来将ES6语法处理成ES5语法,就可以解决这个问题。

1.安装Babel

yarn add babel-loader @babel/core

webpack.config.js

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');    //生成html文件
const CleanWebpackPlugin = require('clean-webpack-plugin');  //清除



module.exports = {
  mode:'development',
  entry:'./src/index.js',
  module:{
	rules:[
		{
			test:/\.css$/,
			use:[
				'style-loader',
				{
					loader:'css-loader',
					options:{
						importLoaders:1
					}					
				},
				'postcss-loader'
				
			]
		},
		{
			test:/\.scss$/,
			use:[
				'style-loader',
				{
					loader:'css-loader',
					options:{
						importLoaders:2
					}					
				},
				'sass-loader',
				'postcss-loader'
			]
		},
		{
			test: /\.less$/,
			use: [
				'style-loader',
				{
					loader:'css-loader',
					options:{
						importLoaders:2
					}					
				},
				'less-loader',
				'postcss-loader'
			]
		},
		{
			test:/\.(png|svg|jpeg|jpg|gif)$/,
			use:[		
				{
					loader:'file-loader',
					options:{
						name:'[name].[ext]',  //[path] 上下文环境路径
						publicPath:'./assets/image/',    //公共路径
						outputPath:'assets/image/',  //输出路径							
					}
				},
				{
					loader: 'image-webpack-loader',
					options: {
						bypassOnDebug: true, // [email protected]
						disable: true,       // [email protected] and newer
					},
				},
			]
		},
		{
			test: /\.html$/,
			use:[
				{
					loader:'html-loader',
					options:{
						arrts:['img:src','img:data-src'],
						minimize:false  //是否压缩html
					}
				}
			]
		},
		{
			test: /(iconfont.svg)|\.(woff|woff2|eot|ttf|otf)$/,
			use:[
				{
					loader:'file-loader',
					options:{
						name:'[name].[ext]',  //[path] 上下文环境路径
						publicPath:'./assets/iconfont/',    //公共路径
						outputPath:'assets/iconfont/',  //输出路径							
					}
				}				
			]
		},
+		{
+			test: /\.js$/,
+			exclude: /(node_modules|bower_components|lib)/,
+			loader: 'babel-loader'
+		}
	]
  },
  plugins: [
	new HtmlWebpackPlugin({
		title: '瓦力博客',
		template: './src/index.html'   //以src/index.html为编译模板
	}),
	new CleanWebpackPlugin(),
	new webpack.HotModuleReplacementPlugin()
  ],
  devServer:{
	contentBase: path.join(__dirname, 'dist'),
	clientLogLevel: 'info',
	open:true,  //启动时默认打开浏览器
	host:'localhost', //域名 0.0.0.0局域网可访问
	port:'9009',
	inline:true, //实时更新
	hot:true,    //热替换
	hotOnly:true,
	proxy:{
		'/':{
			target:'http://www.waliblog.com'
		},
		'/upload':{
			target:'http://www.waliblog.com'
		}
	}
  },
  output:{
    path: path.resolve(__dirname,'dist')
  }
}

文件结构

myProject
 |-dist
 |-node_modules
 |-src
     |-assets
        |-css
            |-index.css
        |-less
            |-index.less     
        |-sass
            |-index.scss
        |-images
            |-wali_logo.png
     |-index.html
     |-index.js
 |-package.json
 |-webpack.config.js
 |-postcss.config.js
+ |-.babelrc

安装@babel/preset-env

yarn add @babel/preset-env

.babelrc

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

src/index.js

const arr = [
    new Promise(() => {}),
    new Promise(() => {})
]


arr.map(val => {
    console.log(val)
})

package.json

{
  "scripts": {
    "dev": "npx webpack-dev-server --mode=development --colors",
    "dist": "npx webpack --mode=production",
+    "build": "npx webpack --mode=development --colors"
  }
}

运行webpack

yarn run build

打包完成后我们打开dist目录下main.js,最下面能后找到

/***/ "./src/index.js":
/*!**********************!*\
  !*** ./src/index.js ***!
  \**********************/
/*! no static exports found */
/***/ (function(module, exports) {

eval("var arr = [new Promise(function () {}), new Promise(function () {})];\narr.map(function (val) {\n  console.log(val);\n});\n\n//# sourceURL=webpack:///./src/index.js?");

/***/ })

我们看到ES6语法被转换成了ES5语法,但是只转换了一部分,比如在低版本浏览中还是识别不了PromiseMap这样的语法。

2.兼容低版本浏览器

安装babel/polyfill

yarn add @babel/polyfill

src/index.js

+ import "@babel/polyfill";
const arr = [
    new Promise(() => {}),
    new Promise(() => {})
]


arr.map(val => {
    console.log(val)
})

运行webpack

yarn run build

ssl

//dist/main.js
/***/ "./src/index.js":
/*!**********************!*\
  !*** ./src/index.js ***!
  \**********************/
/*! no exports provided */
/*! all exports used */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _babel_polyfill__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/polyfill */ \"./node_modules/@babel/polyfill/lib/index.js\");\n/* harmony import */ var _babel_polyfill__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_polyfill__WEBPACK_IMPORTED_MODULE_0__);\n\nvar arr = [new Promise(function () {}), new Promise(function () {})];\narr.map(function (val) {\n  console.log(val);\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvaW5kZXguanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvaW5kZXguanM/MzcwMCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgXCJAYmFiZWwvcG9seWZpbGxcIjtcbnZhciBhcnIgPSBbbmV3IFByb21pc2UoZnVuY3Rpb24gKCkge30pLCBuZXcgUHJvbWlzZShmdW5jdGlvbiAoKSB7fSldO1xuYXJyLm1hcChmdW5jdGlvbiAodmFsKSB7XG4gIGNvbnNvbGUubG9nKHZhbCk7XG59KTsiXSwibWFwcGluZ3MiOiJBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./src/index.js\n");

/***/ })

从webpack打包输出的信息中可以看到,PromiseMap方法@babel/polyfill自己帮我们做了实现。可是dist/mian.js文件突然增大到941kb,原因就是 main.js文件将整个polyfill都打包进来。我们想要的其实在main.js中用到的方法帮助我们实现,如果没有用到,就不需要打包进main.js。

3.精简代码

.babelrc

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

运行webpack

yarn run build

ssl

当我们在.babelrc文件中配置"useBuiltIns": "usage",我们发现打包出来的main.js文件大小变成29kb。"useBuiltIns": "usage"作用就是当polyfill去往低版本浏览器添加一些特性的时候,不是把所有的特性都加进了,而是根据你的业务代码来决定添加什么。

4.设置浏览器版本

.babelrc

{
  "presets": [
		[
			"@babel/preset-env",
+			{
+				"targets": {
+					"edge": "17",
+					"firefox": "60",
+					"safari": "11.1",
+					"chrome": "67"
+				},
+				"useBuiltIns": "usage"
			}
		]
	]
}

"chrome": "67"指编译的代码要运行在67版本的chrom浏览器上,如果67版本chrom支持promis等新语法,则不转换,否则进行转换。

运行webpack

yarn run build

5.插件开发

上面教程如果我们开发项目,完全够用了。但是当我们开发插件时就会有问题,因为上面是将promis等新特性的实现通过全局变量来注入,会污染全局环境。而且写代码还要在js前面添加import "@babel/polyfill"。所以小菜建议下面这种方式

安装pluginTransformRuntime

yarn add @babel/plugin-transform-runtime
yarn add @babel/runtime
yarn add @babel/runtime-corejs2

.babelrc

{
	"presets": [
		[
			"@babel/preset-env",
			{
				"targets": {
					"chrome": "67"
				},
				"useBuiltIns": "usage"
			}
		]
	],
+  "plugins": [
+    [
+      "@babel/plugin-transform-runtime",
+      {
+        "absoluteRuntime": false,
+        "corejs": 2,
+        "helpers": true,
+        "regenerator": true,
+        "useESModules": false
+      }
+    ]
+  ]
}

运行webpack

yarn run build

打开dist/main.js文件

/***/ "./src/index.js":
/*!**********************!*\
  !*** ./src/index.js ***!
  \**********************/
/*! no exports provided */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _babel_runtime_corejs2_core_js_promise__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime-corejs2/core-js/promise */ \"./node_modules/@babel/runtime-corejs2/core-js/promise.js\");\n/* harmony import */ var _babel_runtime_corejs2_core_js_promise__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_corejs2_core_js_promise__WEBPACK_IMPORTED_MODULE_0__);\n\nconst arr = [new _babel_runtime_corejs2_core_js_promise__WEBPACK_IMPORTED_MODULE_0___default.a(() => {}), new _babel_runtime_corejs2_core_js_promise__WEBPACK_IMPORTED_MODULE_0___default.a(() => {})];\narr.map(val => {\n  console.log(val);\n});\n\n//# sourceURL=webpack:///./src/index.js?");

/***/ })

从打包的代码我们可以看到,向PromiseMap都帮助我们实现了。

webpack4.x 教程

webpack 准备工作(1) webpack 手写最基本的配置(2) webpack 打包样式(3) webpack 让打包更便捷(4) webpack 打包图片(5) webpack iconfont打包(6) webpack devServer本地开发(7) webpack 处理ES6语法(8) webpack SourceMap配置(9) webpack Tree Shaking(10) webpack js代码分割(11) webpack 懒加载(12) webpack 打包分析,Preloading,Prefetching(13) webpack 模块化区分开发和生产(14) webpack 样式文件的代码分割(15) webpack 浏览器缓存(16) webpack shimming(17) webpack 环境变量(18) webpack Esline(19) webpack 解析resolve(20) webpack Library的打包(21) webpack dll(22) webpack 多页面打包配置(23) webpack 搭建vue脚手架(24)