继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

webpack 处理ES6语法(8)

瓦力博客
关注TA
已关注
手记 54
粉丝 26
获赞 78

获取全套webpack 4.x教程,请访问瓦力博客

为什么要处理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, // webpack@1.x
						disable: true,       // webpack@2.x 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都帮助我们实现了。

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP