- 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"]}
