获取全套webpack 4.x教程,请访问瓦力博客
为什么要处理ES6语法呢?当我们使用新语法来写代码,一些浏览器如果不支持那么就会报错,导致用户体验非常糟糕。我们使用babel来将ES6语法处理成ES5语法,就可以解决这个问题。
- Babel官网{:target="_blank"}
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语法,但是只转换了一部分,比如在低版本浏览中还是识别不了Promise
、Map
这样的语法。
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
//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打包输出的信息中可以看到,Promise
和Map
方法@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
当我们在.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?");
/***/ })
从打包的代码我们可以看到,向Promise
和Map
都帮助我们实现了。