《四》Webpack 中处理 JavaScript 模块的 Loader 之 babel-loader

Webpack 已经内置了对 JavaScript 模块的处理,默认就可以加载 JS 文件,并且支持模块化开发。但是不是特别完备,并不会对 ES6+ 等代码进行转换。因此需要指定对应的 Loader 来完成想要的功能。

babel-loader:会自动使用 Babel 工具对加载的 JavaScript 文件进行转换。可以用来转换 ES6+ 语法和 JSX 语法。

使用 babel-loader 来转换 ES6+ 语法:

  1. 新建 src/index.js 并编写代码。
    // src/index.js
    setTimeout(() => {
      console.log('Hello')
    })
    
  2. 运行 webpack 命令进行打包,会发现,虽然能够正常打包,但是打包后生成的文件后并没有对箭头函数进行转换。如果运行在浏览器中,不认识箭头函数语法的浏览器将会报错。
    请添加图片描述

使用插件来转换 ES6+ 语法::

  1. 安装 Babel:npm install @babel/core --save-dev
  2. 安装 babel-loadernpm install babel-loader --save-dev
  3. 安装需要的 Babel 插件:npm install @babel/plugin-transform-arrow-functions --save-dev
  4. webpack.config.js 配置文件中进行配置。
    // webpack.config.js
    module.exports = {
      module: {
        rules: [
          // 使用 babael-loader 对 JS 文件进行转换
          {
            test: /\.js$/,
            use: {
              loader: 'babel-loader',
              options: {
                // 转换不同的功能就使用不同的插件。此处使用 Babel 中转换箭头函数的插件来转换箭头函数
                plugins: [
                  '@babel/plugin-transform-arrow-functions',
                ]
              }
            }
          }
        ]
      }
    }
    
  5. 此时,再去运行 webpack,会发现打包生成的文件中箭头函数被转换成 ES5 中的函数语法了。
    请添加图片描述

使用预设来转换 ES6+ 语法:

@babel/preset-env :是 Babel 提前预设好的一系列 Babel 中转换 ES6+ 语法的插件的组合,默认会根据目标浏览器来决定使用哪些插件。

  1. 安装 @babel/preset-env 预设:npm install @babel/preset-env --save-dev

  2. webpack.config.js 配置文件中进行配置。

    // webpack.config.js
    module.exports = {
      module: {
        rules: [
          // 使用 babael-loader 对 JS 文件进行转换
          {
            test: /\.js$/,
            use: {
              loader: 'babel-loader',
              options: {
                // 使用 Babel 中的 @babel/preset-env 预设
                presets: [
                  '@babel/preset-env',
                ]
              }
            }
          }
        ]
      }
    }
    
  3. 此时,运行 webpack,会发现打包生成的文件中箭头函数也被转换成 ES5 中的函数语法了。

    会转换哪些语法取决于项目的目标浏览器。

    请添加图片描述

设置 @babel/preset-env 预设的目标浏览器:
  1. 可以通过配置 @babel/preset-env 预设的 target 属性来修改目标浏览器。
    // webpack.config.js
    module.exports = {
        module: {
            rules: [
                {
                    test: /\.js$/,
                    use: {
                        loader: 'babel-loader',
                        options: {
                            presets: [
                                [
                                    '@babel/preset-env',
                                    // 设置 @babel/preset-env 预设的目标浏览器,优先级高于 Browserslist 中的设置
                                    {
                                        target: ['chrome 88'], 
                                    },
                                ]
                            ]
                        }
                    }
                }
            ]
        }
    }
    
  2. 也可以通过 Browserslist 来修改目标浏览器。更推荐这种方式,因为类似 PostCSS 也会使用 Browserslist ,以便全局统一目标浏览器。
Babel7 之前的 @babel/preset-env 预设的写法:
// webpack.config.js
module.exports = {
    module: {
        rules: [
            {
                test: /\.js$/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        // Babel7 之前 @babel/preset-env 预设的写法。含义是把 es2015、react、stage-3 的代码转换成目标浏览器支持的代码
                        // es2015 和 stage-3 对应的就是现在的 preset-env,react 对应的就是现在的 preset-react
                        presets: ['es2015', 'react', 'stage-3']
                    }
                }
            }
        ]
    }
}

从 Babel7 开始,建议使用新的预设来代替。

TC39 是指技术委员会第 39 号,它是 ECMA 机构的一部分(ECMA 是 ECMAScript 规范下的 JavaScript 语言标准化的机构)。
TC39 遵循的原则是:分阶段加入不同的语言特性,新流程涉及四个不同的 Stage:

  1. Stage 0:strawman 稻草人。任何尚未提交作为正式方案的讨论、想法变更或者补充都被认为是第 0 阶段的稻草人。
  2. Stage 1:proposal 提案。提案已经被正式化,并期望解决此问题,还需要观察与其他提案的相互影响。
  3. Stage 2:draft 草稿。提案应提供规范的草稿,此时,语言的实现着开始观察 runtime 的具体实现是否合体。
  4. Stage 3:candidate 候补。提案成为被建议的候选提案,在这个阶段,规范的编辑人员和评审人员必须在最终规范上签字,提案不会有太大的改变,在对外发布之前只是修正一些问题。
  5. Stage 4:finished 完成。进入这个阶段的天将包含在 ECMAScript 的下一个修订版本中。

使用 Polyfill 来处理 ES6+ 语法::

  1. src/index.js 中编写代码。
    // src/index.js
    new Promise(function(resolve) {
      console.log('Hello')
      resolve()
    })
    
  2. 运行 webpack 命令进行打包,会发现,打包生成的文件中 Promise 仍然存在,但是显然有些浏览器是不认识 Promise 的,运行在那些浏览器上就会报错。
    请添加图片描述
通过配置 @babel/preset-env 预设的 useBuiltIns 属性来使用 Polyfill:

Babel7.4.0 之前,可以使用 @babel/polyfill 包,但是该包现在已经不推荐使用了。

Babel7.4.0 之后,可以通过单独引入 core-jsregenerator-runtime 来完成 Polyfill 的使用。

安装 @babel/prolyfill 时应该使用 npm install @babel/prolyfill,而不是 npm install @babel/prolyfill --save-dev,因为@babel/prolyfill 在生产环境下也需要使用。
但是如果安装到了本地依赖下,也不会出现问题,因为 Webpack 打包时会从入口文件开始将所有依赖的东西打包进去,因此即使安装到了本地依赖下,Webpack 在打包时也会将它打包进去。
但从规范上来讲,还是应该使用 npm install @babel/prolyfill 来安装 @babel/prolyfill
安装 core-jsregenerator-runtime 同理。

  1. 安装 core-jsregenarator-runtimenpm install core-js regenerator-runtime
  2. webpack.config.js 配置文件中进行配置。
    // webpack.config.js
    module.exports = {
      module: {
        rules: [
          {
            test: /\.js$/,
            // 某些第三方库可能本身已经实现了 Polyfill,因此不对这部分内容使用 Polyfill,避免产生冲突
            exclude: /node_modules/,
            use: {
              loader: 'babel-loader',
              options: {
                presets: [
                  ['@babel/preset-env', {
                  	// 设置预设以什么样的方式来使用 Polyfill
                    useBuiltIns: 'usage',
                    // 设置 corejs 的版本。不指定使用哪个版本的话,默认使用 V2。由于目前安装的 core-js 版本为 3.32.2,因此此处设置使用 V3
                    corejs: 3,
                  }]
                ]
              }
            }
          }
        ]
      }
    }
    
  3. 此时,运行 webpack 命令,会发现打包生成的文件中多了实现 Promise 的代码。
    请添加图片描述
通过配置 plugin-transform-runtime 插件来使用 Polyfill:

配置预设的 useBuiltIns 属性会将 Polyfill 特性放到全局作用域中;而配置 plugin-transform-runtime 插件不会将 Polyfill 特性放到全局作用域中。
因此,如果是编写一个第三方的工具库,推荐使用 plugin-transform-runtime 插件,以避免污染全局的代码。

  1. 安装 plugin-transform-runtime 插件:npm install @babel/plugin-transform-runtime --save-dev

  2. 安装 @babel/runtime-corejs3npm install @babel/runtime-corejs3 --save-dev

    @babel/runtime-corejs3 提供了一组与 ECMAScript 新特性相关的运行时支持和 Polyfill。

  3. webpack.config.js 配置文件中进行配置。

    // webpack.config.js
    module.exports = {
      module: {
        rules: [
          {
            test: /\.js$/,
            use: {
              loader: 'babel-loader',
              options: {
                plugins: [
                  // 配置 plugin-transform-runtime 插件。如果此处 corejs 设置的是 2,则需要 @babel/runtime-corejs2
                  ['@babel/plugin-transform-runtime', {corejs: 3}]
                ]
              }
            }
          }
        ]
      },
    }
    
  4. 此时,运行 webpack 命令,会发现打包生成的文件中多了实现 Promise 的代码。
    在这里插入图片描述

使用 babel-loader 来转换 React 中的 JSX 语法:

  1. 安装 react 和 react-domnpm install react react-dom
  2. 新建 src/index.jsx 文件并编写代码。
    // src/index.jsx
    import React from 'react'
    import ReactDOM from 'react-dom'
    
    class App extends React.Component {
        state = {
            title: 'Hello World',
        }
        render() {
            return (
                <div>{this.state.title}</div>
            )
        }
    }
    
    ReactDOM.render(<App/>, document.getElementById('app'))
    
  3. 修改 Webpack 打包的入口文件。
    // webpack.config.js
    module.exports = {
        entry: './src/index.jsx',
    }
    
  4. 运行 webpack 命令进行打包,会发现报错了,Webpack 不认识 JSX 语法。
    在这里插入图片描述

使用插件来转换 React 中的 JSX 语法:

对 JSX 语法进行转换需要使用 @babel/plugin-syntax-jsx@babel/plugin-transform-react-jsx@babel/plugin-transform-react-display0name 这三个插件。

使用预设来转换 React 中的 JSX 语法:

一个一个安装配置插件比较繁琐,可以使用 Babel 中的预设 preset-react

  1. 安装 preset-react 预设:npm install @babel/preset-react --save-dev
  2. webpack.config.js 配置文件中进行配置。
    // webpack.config.js
    module.exports = {
        entry: './src/index.jsx',
        module: {
            rules: [
                {
                    test: /\.jsx$/,
                    use: {
                        loader: 'babel-loader',
                        options: {
                            presets: ['@babel/preset-react']
                        }
                    },
                }
            ]
        }
    }
    
  3. 此时,运行 webpack 命令进行打包,会发现打包成功了。

使用 babel-loader 来转换 TypeScript 语法:

使用 babel-loaderts-loader 都能转换 TypeScript 代码,它们之前的区别是:

  1. babel-loader 不依赖于 TypeScript Compiler,因此不需要安装 TypeScript ;ts-loader 依赖于 TypeScript Compiler ,因此需要安装 TypeScript。
  2. babel-loader 不会对类型进行校验,即使类型错误也能打包成功;ts-loader 会对类型进行校验,如果类型错误将会打包失败。
  3. 如果 TypeScript 代码中有 Promise 等新特性,babel-loader 可以通过使用 '@babel/preset-env' 预设方便添加对应的 Polyfill,但是 ts-loader 就无能为力了。
    TypeScript 官方的使用建议:
    请添加图片描述
  1. 新建 src/index.ts 并编写代码。
    // src/index.ts
    var title:string = 'Hello World'
    
    function getInfo (info: string) {
        console.log(info)
    }
    getInfo(title)
    
  2. 修改 Webpack 打包的入口文件。
    // webpack.config.js
    module.exports = {
        entry: './src/index.ts',
    }
    
  3. 运行 webpack 命令进行打包,会发现报错了,Webpack 不认识 TypeScript 语法。
    在这里插入图片描述

使用插件来处理 TypeScript 语法:

对 TypeScript 语法进行转换需要使用 @babel/transform-typescript 插件。

使用预设来处理 TypeScript 语法:

相比于插件,更推荐使用 Babel 中的 @babel/preset-typescript 预设来转换 TypeScript 语法。

  1. 安装 @babel/preset-typescript 预设:npm install @babel/preset-typescript --save-dev
  2. webpack.config.js 配置文件中进行配置。
    // webpack.config.js
    module.exports = {
      entry: './src/index.ts',
      module: {
        rules: [
          {
            test: /\.ts$/,
            use: {
              loader: 'babel-loader',
              options: {
                // 使用 @babel/preset-typescript 预设来对 ts 代码进行转换
                presets: ['@babel/preset-typescript']
              }
            }
          }
        ]
      },
    }
    
  3. 此时,运行 webpack 命令进行打包,会发现打包成功了。

Babel 的配置文件:

可以将 Babel 的配置信息放到独立的文件中,babel-loader 会自动去加载对应的配置文件。

Babel 提供了两种配置文件的写法:

  1. .babelrc.json.babelrc/ .js/.cjs/.mjs)文件:早期使用较多的配置方式。但是对于配置 Monorepos 项目是比较麻烦的。
  2. babel.config.json.js/.cjs/.mjs)文件:Babel7 中更加推荐这种方式。可以直接作用于 Monorepos 项目的子包。

    Monorepos:一个仓库中有多个包;Multirepos:多个仓库多个包。
    目前很多项目都采用了多包管理的方式。例如:Babel、element-llusumi 等。

使用 Babel 的配置文件:

  1. webpack.config.js 配置文件中配置使用 babale-loader
    // webpack.config.js
    module.exports = {
        module: {
            rules: [
                {
                    test: /\.js$/,
                    use: 'babel-loader',
                }
            ]
        }
    }
    
  2. babel.config.js 配置文件中进行 babale-loader 的具体配置。
    // babel.config.js
    module.exports = {
        presets: [
            '@babel/preset-env'
        ]
    }
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值