转化ES6语法
本文开始看如何在webpack中处理js模块。
我们希望把ES6或者更高级的语法转换为ES5,就需要用到babel,babel就是用来转化我们的js的。
修改index.js文件,增加一些ES6的语法
js
// webpack-dev-1\src\index.js
let str = require('./a.js')
console.log('hello cheny');
console.log(str);
require('./index.css')
require('./index.less')
// 增加个箭头函数
let fn = () => {
console.log('cheny && xzz');
}
fn()
然后我们先什么也不配,打包一下来看看,现在的配置文件如下
js
// webpack-dev-1\webpack.config.js
// webpack是node写出来的,所以使用node的语法
let path = require('path')
let HtmlWebpackPlugin = require('html-webpack-plugin') // 引入插件
let MiniCssExtractPlugin = require('mini-css-extract-plugin') // 引入插件
let OptimizeCss = require('optimize-css-assets-webpack-plugin') // 引入插件 压缩css的
let UglifyJsPlugin = require('uglifyjs-webpack-plugin') // 压缩js文件的插件
module.exports = {
// 配置优化项
optimization: {
minimizer: [ // 是一个数组,还得优化js
new UglifyJsPlugin({
cache: true, // 是否用缓存
parallel: true, // 是否并发压缩
sourceMap: true,// 线上用来调试的映射文件
}),
new OptimizeCss(), // 开启优化css后,生产模式css文件也会被压缩,但是必须配置js压缩,如果不配置,js生产模式就不会被压缩了
]
},
devServer: { // 开发服务器的配置
port: 3000, // 默认端口是8080,这里可以改
progress: true, // 打包时候的进度条
contentBase: './build', // 以哪个文件夹作为服务的根目录
open: true, // 服务启动完毕后,直接打开浏览器
compress: true, // 启动gzip压缩
},
mode: 'development', // 模式,默认两种模式 production 和 development
entry: './src/index.js', // 入口
output: {
// 带hash戳的文件,:8限制一下hash戳的长度
filename: 'bundle.[hash:8].js', // 打包后的文件名
path: path.resolve(__dirname, 'build'), // 打包后的路径,必须是一个绝对路径
},
plugins: [ // 是一个数组,放着所有的webpack插件
// 插件是一个类,通过new的方式来引用
new HtmlWebpackPlugin({
template: './src/index.html', // 告诉插件,是以这个目录下的index.html为模板
filename: 'index.html', // 告诉插件,打包后的文件叫什么名字,这里也叫index.html
hash: true, // 引用的时候可以加一个hash戳
}),
// 插件的使用就没有先后顺序了,随便放就行
// 引入抽离css样式的插件,
new MiniCssExtractPlugin({
filename: 'main.css', // 告诉插件,抽离出的样式文件的名字叫什么,这里叫main.css
}),
],
module: { // 模块
rules: [ // 规则,在这里面配置各种loader
// css-loader 解析css文件,@import语法的
// style-loader 把解析后的css文件 插入到head标签中
// loader有个特点,希望单一,一个loader干一件事
/*
loader的用法
1. 只用字符串,就是只用一个loader
2. 多个loader,需要一个数组 [],数组里可以放字符串,或者对象,对象的话就可以配置loader的参数了
*/
// loader的顺序,默认是从右向左执行,从下往上执行
{
test: /\.css$/,
use: [
// 这个插件上有个loader,我们不想再用style-loader把样式放在style标签里了,所以就用它的loader
MiniCssExtractPlugin.loader,
'css-loader',
// 应该在解析css之前增加前缀
'postcss-loader',
]
},
{
test: /\.less$/,
use: [
// 这个插件上有个loader,我们不想再用style-loader把样式放在style标签里了,所以就用它的loader
MiniCssExtractPlugin.loader, // 若果想抽离多个文件,可以在new一个出来,一个抽离css一个抽离less都行
// 这里就用一个了
'css-loader', // 解析 @import语法 解析 css
// 应该在解析css之前增加前缀
'postcss-loader',
'less-loader' // 把less 转换为 css
]
},
],
}
}
开始打包,npm run build
我们发现打包出来的仍然是ES6语法,并没有做任何转换。
使用babel来转换
- 我们希望转换语法,肯定先需要一个loader,babel-loader
- 转化的时候肯定还需要用到我们的babel,核心模块的名字叫 @babel/core,这个babel的核心模块会调用transform方法来对代码进行转化。
- 那我们还必须知道该如何转化,所以还有一个转化模块,叫 @babel/preset-env,可以把一些高级的语法转换为低级的语法
我们先来安装一下:
shell
# @babel/core babel-loader @babel/preset-env -D
yarn add @babel/core@^7.4.5 babel-loader@^8.0.6 @babel/preset-env@^7.4.5 -D
修改配置文件webpack.config.js
js
// webpack-dev-1\webpack.config.js
// webpack是node写出来的,所以使用node的语法
let path = require('path')
let HtmlWebpackPlugin = require('html-webpack-plugin') // 引入插件
let MiniCssExtractPlugin = require('mini-css-extract-plugin') // 引入插件
let OptimizeCss = require('optimize-css-assets-webpack-plugin') // 引入插件 压缩css的
let UglifyJsPlugin = require('uglifyjs-webpack-plugin') // 压缩js文件的插件
module.exports = {
// 配置优化项
optimization: {
minimizer: [ // 是一个数组,还得优化js
new UglifyJsPlugin({
cache: true, // 是否用缓存
parallel: true, // 是否并发压缩
sourceMap: true,// 线上用来调试的映射文件
}),
new OptimizeCss(), // 开启优化css后,生产模式css文件也会被压缩,但是必须配置js压缩,如果不配置,js生产模式就不会被压缩了
]
},
devServer: { // 开发服务器的配置
port: 3000, // 默认端口是8080,这里可以改
progress: true, // 打包时候的进度条
contentBase: './build', // 以哪个文件夹作为服务的根目录
open: true, // 服务启动完毕后,直接打开浏览器
compress: true, // 启动gzip压缩
},
mode: 'development', // 模式,默认两种模式 production 和 development
entry: './src/index.js', // 入口
output: {
// 带hash戳的文件,:8限制一下hash戳的长度
filename: 'bundle.[hash:8].js', // 打包后的文件名
path: path.resolve(__dirname, 'build'), // 打包后的路径,必须是一个绝对路径
},
plugins: [ // 是一个数组,放着所有的webpack插件
// 插件是一个类,通过new的方式来引用
new HtmlWebpackPlugin({
template: './src/index.html', // 告诉插件,是以这个目录下的index.html为模板
filename: 'index.html', // 告诉插件,打包后的文件叫什么名字,这里也叫index.html
hash: true, // 引用的时候可以加一个hash戳
}),
// 插件的使用就没有先后顺序了,随便放就行
// 引入抽离css样式的插件,
new MiniCssExtractPlugin({
filename: 'main.css', // 告诉插件,抽离出的样式文件的名字叫什么,这里叫main.css
}),
],
module: { // 模块
rules: [ // 规则,在这里面配置各种loader
{
test: /\.js$/, // 匹配以js结尾的文件
use: {
loader: 'babel-loader',
options: { // 用babel-loader 需要把ES6转为ES5
// 配置可以写在这里,还可以写在外面
// 在这里添加一个预设
presets: [
'@babel/preset-env', // 这个插件就可以把ES6转ES5
]
}
}
},
// css-loader 解析css文件,@import语法的
// style-loader 把解析后的css文件 插入到head标签中
// loader有个特点,希望单一,一个loader干一件事
/*
loader的用法
1. 只用字符串,就是只用一个loader
2. 多个loader,需要一个数组 [],数组里可以放字符串,或者对象,对象的话就可以配置loader的参数了
*/
// loader的顺序,默认是从右向左执行,从下往上执行
{
test: /\.css$/,
use: [
// 这个插件上有个loader,我们不想再用style-loader把样式放在style标签里了,所以就用它的loader
MiniCssExtractPlugin.loader,
'css-loader',
// 应该在解析css之前增加前缀
'postcss-loader',
]
},
{
test: /\.less$/,
use: [
// 这个插件上有个loader,我们不想再用style-loader把样式放在style标签里了,所以就用它的loader
MiniCssExtractPlugin.loader, // 若果想抽离多个文件,可以在new一个出来,一个抽离css一个抽离less都行
// 这里就用一个了
'css-loader', // 解析 @import语法 解析 css
// 应该在解析css之前增加前缀
'postcss-loader',
'less-loader' // 把less 转换为 css
]
},
],
}
}
修改完配置文件后,把babel-loader给配置好,再来重新打包试一下 npm run build
我们发现,箭头函数已经被转换为普通函数了。
转换更高级的语法
我们再修改index.js
js
// webpack-dev-1\src\index.js
let str = require('./a.js')
console.log('hello cheny');
console.log(str);
require('./index.css')
require('./index.less')
// 增加个箭头函数
let fn = () => {
console.log('cheny && xzz');
}
fn()
class A { // let a = new A() a.a = 1
a = 1 // 相当于给实例加了一个属性
}
let a = new A()
console.log(a.a, '22');
添加一些预设的语法,会需要配置一些预设的插件。
(现在好像不需要了,这种语法应该已经通过提案了,不过可以学习一下配置)
安装插件 @babel/plugin-proposal-class-properties
shell
# @babel/plugin-proposal-class-properties -D
yarn add @babel/plugin-proposal-class-properties@^7.4.4 -D
修改webpack.config.js
js
// webpack-dev-1\webpack.config.js
// webpack是node写出来的,所以使用node的语法
let path = require('path')
let HtmlWebpackPlugin = require('html-webpack-plugin') // 引入插件
let MiniCssExtractPlugin = require('mini-css-extract-plugin') // 引入插件
let OptimizeCss = require('optimize-css-assets-webpack-plugin') // 引入插件 压缩css的
let UglifyJsPlugin = require('uglifyjs-webpack-plugin') // 压缩js文件的插件
module.exports = {
// 配置优化项
optimization: {
minimizer: [ // 是一个数组,还得优化js
new UglifyJsPlugin({
cache: true, // 是否用缓存
parallel: true, // 是否并发压缩
sourceMap: true,// 线上用来调试的映射文件
}),
new OptimizeCss(), // 开启优化css后,生产模式css文件也会被压缩,但是必须配置js压缩,如果不配置,js生产模式就不会被压缩了
]
},
devServer: { // 开发服务器的配置
port: 3000, // 默认端口是8080,这里可以改
progress: true, // 打包时候的进度条
contentBase: './build', // 以哪个文件夹作为服务的根目录
open: true, // 服务启动完毕后,直接打开浏览器
compress: true, // 启动gzip压缩
},
mode: 'development', // 模式,默认两种模式 production 和 development
entry: './src/index.js', // 入口
output: {
// 带hash戳的文件,:8限制一下hash戳的长度
filename: 'bundle.[hash:8].js', // 打包后的文件名
path: path.resolve(__dirname, 'build'), // 打包后的路径,必须是一个绝对路径
},
plugins: [ // 是一个数组,放着所有的webpack插件
// 插件是一个类,通过new的方式来引用
new HtmlWebpackPlugin({
template: './src/index.html', // 告诉插件,是以这个目录下的index.html为模板
filename: 'index.html', // 告诉插件,打包后的文件叫什么名字,这里也叫index.html
hash: true, // 引用的时候可以加一个hash戳
}),
// 插件的使用就没有先后顺序了,随便放就行
// 引入抽离css样式的插件,
new MiniCssExtractPlugin({
filename: 'main.css', // 告诉插件,抽离出的样式文件的名字叫什么,这里叫main.css
}),
],
module: { // 模块
rules: [ // 规则,在这里面配置各种loader
{
test: /\.js$/, // 匹配以js结尾的文件
use: {
loader: 'babel-loader',
options: { // 用babel-loader 需要把ES6转为ES5
// 配置可以写在这里,还可以写在外面
// 在这里添加一个预设
presets: [ // 这是一个大插件的集合
'@babel/preset-env', // 这个插件就可以把ES6转ES5
],
// 如果有一些预设的语法,还不是js标准时,需要配置一些小插件来转换
plugins: [
'@babel/plugin-proposal-class-properties'
]
}
}
},
// css-loader 解析css文件,@import语法的
// style-loader 把解析后的css文件 插入到head标签中
// loader有个特点,希望单一,一个loader干一件事
/*
loader的用法
1. 只用字符串,就是只用一个loader
2. 多个loader,需要一个数组 [],数组里可以放字符串,或者对象,对象的话就可以配置loader的参数了
*/
// loader的顺序,默认是从右向左执行,从下往上执行
{
test: /\.css$/,
use: [
// 这个插件上有个loader,我们不想再用style-loader把样式放在style标签里了,所以就用它的loader
MiniCssExtractPlugin.loader,
'css-loader',
// 应该在解析css之前增加前缀
'postcss-loader',
]
},
{
test: /\.less$/,
use: [
// 这个插件上有个loader,我们不想再用style-loader把样式放在style标签里了,所以就用它的loader
MiniCssExtractPlugin.loader, // 若果想抽离多个文件,可以在new一个出来,一个抽离css一个抽离less都行
// 这里就用一个了
'css-loader', // 解析 @import语法 解析 css
// 应该在解析css之前增加前缀
'postcss-loader',
'less-loader' // 把less 转换为 css
]
},
],
}
}
比如更高级的语法,装饰器,还是预设的语法,我们修改index.js
js
// webpack-dev-1\src\index.js
let str = require('./a.js')
console.log('hello cheny');
console.log(str);
require('./index.css')
require('./index.less')
// 增加个箭头函数
let fn = () => {
console.log('cheny && xzz');
}
fn()
@log
class A { // let a = new A() a.a = 1
a = 1 // 相当于给实例加了一个属性
}
let a = new A()
console.log(a.a, '22');
function log(target) {
console.log(target, '26');
}
这时候再运行会报错,提示
如果想支持这种扩展语法,需要安装 @babel/plugin-proposal-decorators 插件
安装一下
shell
# @babel/plugin-proposal-decorators -D
yarn add @babel/plugin-proposal-decorators@^7.4.4 -D
修改配置文件
json
{
test: /\.js$/, // 匹配以js结尾的文件
use: {
loader: 'babel-loader',
options: { // 用babel-loader 需要把ES6转为ES5
// 配置可以写在这里,还可以写在外面
// 在这里添加一个预设
presets: [ // 这是一个大插件的集合
'@babel/preset-env', // 这个插件就可以把ES6转ES5
],
// 如果有一些预设的属性,需要配置一些小插件来转换还不是标准的js语法
plugins: [
["@babel/plugin-proposal-decorators", { "legacy": true }],
['@babel/plugin-proposal-class-properties', { "loose": true }],
]
}
}
},
然后重新运行,发现可以了,浏览器成功打印
总结
因为打包后的文件需要跑在不同的浏览器上,所以很多高级语法不同的浏览器支持情况是不一样的。
所以就需要把高级语法转换为ES5的语法,这样就可以跑在各个浏览器上了,babel就是干这件事的。
- babel-loader 转换高级语法的js的loader
- @babel/core babel的核心模块,转换的时候就是这个核心模块去调用转换的方法
- @babel/preset-env 预设,告诉插件如何转换,转换的规则
- 如果有一些并未形成规范的语法,可以在预设中安装额外的babel插件来进行转换,比如装饰器语法,需要使用@babel/plugin-proposal-decorators插件来转换
参考
https://www.bilibili.com/video/BV1a4411e7Bz?p=7&spm_id_from=pageDriver