Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

由浅入深webpack - 04.02 使用babel-loader编译ES6 #6

Open
Pasoul opened this issue Mar 25, 2018 · 0 comments
Open

由浅入深webpack - 04.02 使用babel-loader编译ES6 #6

Pasoul opened this issue Mar 25, 2018 · 0 comments
Labels

Comments

@Pasoul
Copy link
Owner

Pasoul commented Mar 25, 2018

babel

安装babel-core babel-loader转义es6语法
npm i -D babel-loader babel-core
创建一个webpack.config.js

module.exports = {
	entry: {
		app: './app.js'
	},
	output: {
		filename: '[name].[hash:5].js'
	},
	module: {
		rules: [
			{
				test: /\.js$/,
				exclude: /node_modules/,
				use: 'babel-loader'
			}
		]
	}
}

test定义一个规则,匹配所有以.js结尾的文件,对这些文件用babel-loader进行es6的转义,exclude表示不需要对node_modules中的第三方库进行转义

babel-preset

虽然定义好了loader,但是babel-loader不知道以什么规范进行转义,这时候需要用到babel的presets,presets其实是对babel规范的汇总,一般有一下几类:

  • es2015/es2016/es2017/latest
    使用es2015也就是我们常说的es6,编译箭头函数、编译const、let、编译class等待,更多细节查看文档
    使用es2016也就是es7,涉及到幂运算符,更多细节可看文档
    使用es2017也就是es8,包含我们经常使用的async/await语法糖,更多细节可看文档
    latest是个特殊的presets,包含了es2015、es2016、es2017一直到目前为止正式发布(不包括stage0-stage3)的规范

  • env
    babel-preset-es20xx和babel-preset-lastest的问题在于它们太过于庞大,即包含了过多在某些情况下不需要的功能,比如大多数浏览器已经支持generator,如果你使用babel-preset-es2015,它仍然会将generator函数编译成复杂的es5代码,这是没有必要的

解决方案:

babel-preset-env和babel-preset-lastest功能相似,但是使用babel-preset-env我们可以声明环境,然后该preset只会编译该环境下缺少的特性的代码
比如我们根据browserslist针对某些浏览器环境进行转义:
比如:

  1. 支持大部分浏览器最新的两个版本以及IE 7+:
"babel": {
"presets": [
    [
      "env",
      {
        "targets": {
          "browsers": ["last 2 versions", "ie >= 7"]
        }
      }
    ]
  ]
},

2.支持超过市场份额5%的浏览器

"targets": {
  "browsers": "> 5%"
}
  1. 某个固定版本的浏览器
"targets": {
  "chrome": 56
}

如何安装: npm install --save-dev babel-preset-env,如果安装的是最新的babel-loader,需要安装最新的preset-env:npm install "babel-loader@^8.0.0-beta" @babel/core @babel/preset-env
更多配置可以参考官方文档
要注意:这也意味着我们需要安装一些插件或preset以处理某些实验特性(stage0-stage3),这些往往不是babel-preset-lastest的一部分
使用babel-preset-env的好处就是你不再需要使用babel-preset-esxxxx

  • babel-preset-react
    与react相关的
  • babel-preset-stage 0 - 3
    实验特性,未正式被发布的

继续对我们的webpack.config.js做修改,增加preset预设

module.exports = {
	entry: {
		app: './app.js'
	},
	output: {
		filename: '[name].[hash:5].js'
	},
	module: {
		rules: [
			{
				test: /\.js$/,
				exclude: /node_modules/,
				use: {
					loader: 'babel-loader',
					options: { // 给这个loader指定参数
						presets: [ // 给babel-preset-env设置参数
							[
								'env',
								{
									targets: {
										browsers: ['>1%', 'last 2 versions']
									}
								}
							]
						]
					}
				}
			}
		]
	}
}

对app.js进行修改,增加一些es6的代码

let func = () => {}
const NUM = 40
let arr = [1, 2, 3]
let arrB = arr.map(item => item * 4)

console.log(arrB)

执行webpack打包,观察打包后生成的文件把es6的代码成功转义成es5:
image

如果把target改成只针对chome浏览器版本为52:

target: {
   chrome: '52'
}

image

babel-plugin

如果给app.js增加一些es6的方法,比如includes和new Set()

let func = () => {}
const NUM = 40
let arr = [1, 2, 3]
let arrB = arr.map(item => item * 4)

console.log(arrB.includes(8))
console.log('new set', new Set(arrB))

打开编译后的文件,发现并没有对includes和set进行转义,而低版本浏览器显然是没有这些方法的,其实babel-preset-env只会针对语法进行转义,而不会对函数和方法(Set、Map、Promise、Generator、Array.from、Object.assign等等)进行转义,因此我们需要babel-polyfill和babel-runtime

  • babel-polyfill
    全局垫片,为应用准备,不适用于框架,相当于对全局的变量进行污染,把没有的方法定义到全局
    安装:npm install --save babel-polyfill

  • babel-runtime
    局部垫片,为开发框架准备,使用es6语法,又不想污染全局变量
    安装:npm install --save babel-plugin-transform-runtime npm install --save babel-runtime

解决babel-preset-env无法转义部分es6的函数和方法:

  1. 应用级

app.js引入安装的babel-polyfill:

import 'babel-polyfill'
let func = () => {}
const NUM = 40
let arr = [1, 2, 3]
let arrB = arr.map(item => item * 4)

console.log(arrB.includes(8))
console.log(arrB)
console.log('new set', new Set(arrB))

发现打包后的文件增大了到了265kb,因为引入了全局垫片
image
同时babel-polyfill给全局定义了includes方法和set函数
image
image
image

2.非应用级:如开发框架
修改webpack.config.js配置,新建.babelrc文件,把options的配置放在.babelrc中

module.exports = {
	entry: {
		app: './app.js'
	},
	output: {
		filename: '[name].[hash:5].js'
	},
	module: {
		rules: [
			{
				test: /\.js$/,
				exclude: /node_modules/,
				use: {
					loader: 'babel-loader',
				}
			}
		]
	}
}

.babelrc:

{
	"presets": [ 
		[
			"env",
			{
				"targets": {
					"browsers": ['>1%', 'last 2 versions']
				}
			}
		]
	],
	plugins: ["transform-runtime"]
}

观察打包后的文件,发现run-time仅仅是对es6的方法进行了修改,没有增加全局变量
image
image
同时文件也仅仅增加到了40+kb
image

@Pasoul Pasoul added enhancement New feature or request webpack labels Mar 25, 2018
@Pasoul Pasoul removed the enhancement New feature or request label Jan 9, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant