- ES6的编译
ES6的编译需要安装的loader: npm install babel-loader @babel/core —save-dev
文件目录中app.js中,写一个箭头函数。
在config文件中配置loader如下,进行webpack打包,但是发现并没有编译(因为箭头函数依然存在),是因为webpack不知道要编译成满足什么规范的JS,所以也就是我们需要告诉webpack我们需要打包生成的js是什么规范 。
比如是:ES2015,
ES2016,
ES2017,
env, (通常采用这个规范)
babel-preset-stage
babel-preset:是存储JS不同标准的插件(babel的插件),通过正确使用presets,告诉babel按照哪个规范进行编译。
安装babel-preset: npm install @babel/preset-env —save-dev
module.exports = {
entry: {
app: './app.js'
},
output: {
filename: '[name].[hash:8].js'
},
module: {
rules: [
{
test: /\.js$/,
use: 'babel-loader'
}
]
}
}
修改webpack的config文件,配置babel-loader的presets:
presets使用 @babel/preset-env,编译 targets为市场占有率大于1%的浏览器。
module.exports = {
entry: {
app: './app.js'
},
output: {
filename: '[name].[hash:8].js'
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env',{
targets:{
browsers: ['>1%']
}
}]
]
}
}
}
]
}
}
基于以上配置,再次webpack打包,会发现箭头函数别编译成了普通函数。
Babel-preset的target配置:
Target是preset的核心配置,告诉preset编译的具体目标。Target可以是:
(1)以browser为目标;(通常情况)
(2)以node的版本为目标;
(3)以特定的浏览器为目标;
以node为目标和以特定浏览器为目标:例子中的node和chrome版本均已支持ES6,所以箭头函数不会被编译。
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env',{
targets:{
// browsers: ['>1%']
// node: "10"
// chrome: "59"
}
}]
]
}
}
}
]
}
babel-loader是只能编译ES6的语法,但是对于ES6的方法的无能为力的,比如ES6中有sort排序方法。这时候就需要另外两个模块的帮助:
babel-polyfill
babel-plugin-transform-runtime(需要同时安装 babel-runtime)
安装这两个库:
npm install babel-polyfill —save-dev
npm install babel-plugin-transform-runtime babel-runtime —save
babel-polyfill的生效方式:
在打包文件生成一个全局对象,将ES6的方法用ES5规范全部实现一遍,在运行的时候,实际上调用的babel-polyfill生成的ES5的方法。一般用于项目开发。
使用babel-polyfill,并不需要我们在配置文件中编写,只需要在js中 import 它就可以了。
import 'babel-polyfill';
setTimeout(() => {
console.log(1);
}, 200);
在使用babel-polyfill之前,可以注意一下打包出来的js文件大小:
使用babel-polyfill之后:
发现打包文件体积明显增大很多,是因为babel-polyfill 生成的全局对象里包含的方法,它包含了所有ES6的新方法的实现,所以体积变大很多。
app.js中,使用了Promise,可以在打包文件中发现Promise的实现,其实也就是使用的是babel-polyfill生成的方法。
import 'babel-polyfill';
new Promise(setTimeout(() => {
console.log(1);
}, 200));
也可以在config文件中引入babel-polyfill,使其生效,如下:
entry: {
app: ['babel-polyfill','./app.js']
},
babel-transform-runtime的生效方式:
它会生成一个局部对象,比如在上面的实例app.js中,这个局部对象只会在app.js中,并且只会包含使用了的ES6方法,并不会包含没有使用的ES6方法,如上面的Promise,则只会包含Promise的实现。它并不会特别明显的增加打包文件的体积,一般用于框架的开发。
在webpack4中,安装babel-transform-runtime:
npm install @babel/plugin-transform-runtime @babel/runtime
app.js如下:
new Promise(setTimeout(() => {
console.log(1);
}, 200));
async function a() {
console.log("Hello!");
}
config如下:配置在plugins下,需要将刚才的polyfill去掉。
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env',{
targets:{
browsers: ['>1%']
}
}]
],
plugins:[
["@babel/transform-runtime"]
]
}
}
}
]
}
打包后的文件大小并不是很大:
如果babelloader的options配置过于庞大的话,影响阅读,可以将这部分单独提取出来,在当前目录新建 .babelrc 文件,将options的配置移入到该文件中,wepack会自动去这个文件中去读取相关配置。
{
"presets": [
["@babel/preset-env",{
"targets":{
"browsers": [">1%"]
}
}]
],
"plugins":[
["@babel/transform-runtime"]
]
}
- 语法糖的编译
以typescript为例:
安装:
npm install typescript ts-loader —save-dev
const hello: string = "Hello world!";
console.log(hello);
import "./test.ts";
new Promise(setTimeout(() => {
console.log(1);
}, 200));
async function a() {
console.log("Hello!");
}
webpack.config.js文件:
module.exports = {
entry: {
app: ['./app.js']
},
output: {
filename: '[name].[hash:8].js'
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.tsx?$/,
use: "ts-loader"
}
]
}
}
另外还需要配置ts-loader具体的参数,增加tsConfig.json,如下所示:
{
"compilerOptions":{
"module":"commonjs",
"target":"es5"
},
"exclude":["./node_modules"]
}