zoukankan      html  css  js  c++  java
  • Webpack & Babel学习

    初始化

    
    mkdir webpack-study && cd webpack-study    //创建并进入项目文件夹
    

    Babel

    概念

    Babel 是一个 JavaScript 编译器,主要用于把 ECMAScript 2015+ 版本语法的代码转换为 ECMAScript 5 及以下版本的语法,以便运行在当前和旧版本浏览器或其他环境中(node)

    一般编译器编译过程分为 4 个阶段输入、解析、转换和输出。Babel 本身不参与解析和转换阶段,这两个阶段需要 Plugins(插件)Presets(预设)来实现

    Plugins(插件) 用来告诉 babel 如何解析/转换代码。Presets(预设)用来告诉 babel 转换代码时要使用那些新语法特性,它的本质就是一组 Plugin的集合。

    Babel 插件分为两类:

    • 转换插件
    • 语法插件
      解析(parse)为特定类型的语法

    plugins/presets 路径
    如果插件用 npm 安装,那可以直接写插件的名称,babel 会自动检查 node_modules 目录里是否安装

    {
        "plugins":["babel-plugin-myPlugin"]
    }
    

    也可以指定插件的相对/绝对路径

    {
      "plugins": ["./myPlugin"]
    }
    

    还可以使用短名称

    {
      "plugins": [
        "myPlugin",
        "babel-plugin-myPlugin", // 两个插件实际是同一个
        "@org/babel-plugin-name",
        "@org/name" // 两个插件实际是同一个
      ]
    }
    

    plugins/presets 执行顺序:
    插件执行的顺序是按照书写顺序依次执行的

    • Plugin(插件)在 Presets 前运行
    • Plugin(插件)顺序从前往后
    • Preset 顺序是颠倒的(从后往前)
    {
      "plugins": ["transform-decorators-legacy", "transform-class-properties"]
    }
    

    如上所示,先执行 transform-decorators-legacy,再执行 transform-class-properties
    presets的顺序是颠倒的

    {
      "presets": ["es2015", "react", "stage-2"]
    }
    

    先执行 stage-2react然后是 es2015

    插件参数:
    插件参数由插件名和参数对象组成一个数组,可以在配置文件(.babelrc/babel.config.js)中设置

    如果不指定参数,下面这几种形式都是一样的:

    {
      "plugins": ["pluginA", ["pluginA"], ["pluginA", {}]]
    }
    

    如果指定参数,则传递一个对象

    {
      "plugins": [
        [
          "transform-async-to-module-method",
          {
            "module": "blubird"
          }
        ]
      ],
      "presets": [
        [
          "env",
          {
            "modules": false
          }
        ]
      ]
    }
    

    安装 Babel

    npm install --save-dev @babel/core @babel/cli @babel/preset-env
    npm install --save @babel/polyfill
    # 可选
    npm install --save @babel/runtime
    npm install --save-dev @babel/plugin-transform-runtime
    
    • @babel/core
      babel 的核心,必选
    • @babel/cli
      babel 命令行工具,执行 babel 编译
    • @babel/preset-env
      官方用于转换 ECMAScript 2015+语法的插件集合,可根据配置来按需加载插件 (向下支持维度)
    • @babel/polyfill
      官方用来创建一个当前和旧版本浏览器能支持 ECMAScript 2015+语法的环境,比如让 IE8 支持Promise。(向上支持维度)
    • @babel/runtime 和 @babel/plugin-transform-runtime
      有时候语法的转换相对复杂,可能会需要额外的辅助函数,比如转换 ECMA 2015 的class
    /* 源文件 */
    class Person {}
    
    /* 编译后文件 */
    function _classCallCheck(instance, Constructor) {
      if (!(instance instanceof Constructor)) {
        throw new TypeError("Cannot call a class as a function");
      }
    }
    
    var Person = function Person() {
      _classCallCheck(this, Person);
    };
    

    上面的转换需要一个_classCallCheck 辅助函数,试想假如我们多个文件中使用了class,那么每个文件都需要定义一遍
    _classCallCheck 函数,这样不止代码冗余,也会增加文件大小。假如将这些辅助函数抽离到一个包当中,由所有文件共同引用那该多好,而 @babel/runtime 就是做这件事的。
    我们已经知道 @babel/runtime 提供了各式各样的辅助函数,但是我们如何知道该引用那个辅助函数呢? Babel 提供了@babel/plugin-transform-runtime插件帮我们做这件事情
    同时@babel/plugin-transform-runtime插件还为我们提供了一个沙箱环境(sandboxed environment),创建一个自己的内部作用域,防止污染全局变量,这在编写一些类库等公共设施代码的时候尤为重要。
    需要注意的是:
    1、两个包引入的范围不一样:一个在运行时引入,一个在开发时引入
    2、plugin-transform-runtime 已经默认包括了 @babel/polyfill,因此不用在独立引入。

    Babel 配置

    Babel的配置文件有两种格式 .babelrcbabel.config.js
    .babelrcbable.config.js 区别是 babel.config.js 通过编程的方式来创建配置的,.babelrc就是一个配置文件, 相比 bable.config.js来说是静态的
    推荐使用 babel.config.js 来配置 Babel

    • @babel/preset-env
      指定运行环境,只有 IE8 及以上版本浏览器不支持的让ECMAScript 2015+语法才会被转换
    {
      "presets": [
        "@babel/preset-env",
        {
          "targets": {
            "browsers": "ie >= 8"
          },
          "modules": false // 将ES 2015模块转换为其他模块规范,可选 "amd" | "umd" | "systemjs" | "commonjs" | "cjs" | "auto" | false 默认是 "auto"
        }
      ]
    }
    
    • @babel/polyfill
      按需 polyfill 用useBuiltIns配置项来实现。
    {
      "presets": [
        [
          "@babel/preset-env",
          {
            "modules": false,
            "useBuiltIns": "entry",
            "targets": {
              "browsers": "ie >= 8"
            }
          }
        ]
      ]
    }
    

    useBuiltIns的值可以是entryusage
    entry:会在入口处把所有 IE8 及以上浏览器不支持 ECMAScript 2015 的特性 polyfill 引入进来。
    usage:会扫描要转换的代码,只有代码中用到哪个新特性,它才会引入响应的 polyfill

    • @babel/runtime 和 @babel/plugin-transform-runtime
    {
      "presets": [
        [
          "@babel/preset-env",
          {
            "modules": false,
            "targets": {
              "browsers": "ie >= 8"
            }
          }
        ]
      ],
      "plugins": [
        [
          "@babel/plugin-transform-runtime",
          {
            "corejs": 2
          }
        ]
      ]
    }
    

    注意:
    上面corejs的值可以设置为false2。为什么这样?
    大家都知道 corejs 是给低版本浏览器提供接口的库,如 Promise,map,set 等。在 Babel 中你设置为 false 或者不设置,就是引入 corjs 中的库,而且是全局引入,会污染全局变量。如果不想全局引入,不要让引入的库影响全局,那就需要把 corejs 的值设为 2
    还要注意一点,如果 corejs 值设为 2,那就需要再引入一个库

    npm install --save core-js@2
    npm install --save-dev @babel/runtime-corejs2
    

    执行 Babel 编译命令

    npx babel 源文件路径 --out-dir 编译后文件路径
    

    webpack

    概念

    webpack 是一个 JavaScript 应用程序的静态模块打包器(module bundler)。
    当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。

    entry(入口)

    entry 指示 webpack 应该使用哪个模块来作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点的依赖(直接和间接)。每个依赖项随机被处理,最后输出到称之为 bundules 的文件中
    入口点可以有一个或多个,默认值为 ./src

    output(出口)

    output 指示 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist
    注意,即使有多个 entry ,但只能有一个 output

    loader(加载器)

    loader 使 webpack 拥有处理那些非 JavaScript 文件的能力。loader 可以将所有类型的文件转换为 webpack 能够处理的模块,然后你就可以在 webpack 中处理这些模块

    plugins(插件)

    loader 被用于转换某些类型的模块,而 plugins 则可以用于执行范围更广的任务

    mode(模式)

    模式有两种,developmentproduction

    modules(模块)
    substitutions(文件名占位符)

    安装 webpack

    
    npm install --save-dev webpack
    npm install --save-dev webpack-cli    //webpack命令行工具
    
    

    webpack 配置

    webpack 通过 webpack.config.js 文件来进行配置

    // webpack。config.js
    
    module.exports = {};
    
    entry 配置

    entry 的值可以接受字符串、对象、字符串数组
    当值为字符串或对象(只有一个 key)或字符串数组时表示单个入口,如下所示

    // 字符串
    module.exports = {
      entry: "./src/index.js",
    };
    // 对象
    module.exports = {
      entry: {
        main: "./scr/index.js",
      },
    };
    // 字符串数组
    module.exports = {
      entry: ["./src/polyfill.js", "./src/index.js"],
    };
    

    entry 值为数组表示数组中的文件一般是没有相互依赖关系的,但是又处于某些原因需要将它们打包在一起,如上面的 polyfill.jsindex.js 会打包到一起

    多个入口

    实现多个入口配置只需要让 entry 属性值为对象就行了,一般会有两个应用场景

    1. 分离应用(app)和第三方库
    module.exports = {
      entry: {
        app: "./src/index.js",
        vendors: "./scr/lib/jquery.js",
      },
    };
    

    分离第三方库不推荐上面的方法,可以使用 webpack 的 DllPlugin 插件

    1. 多页面应用(app)
    module.exports = {
        entry:{
            pageOne:'./src/pageOne/index.js',
            pageTwo:'./src/pageTwo/index.js'.
            pageThree:'./src/pageThree/index.js'
        }
    }
    
    output 配置

    output 的值是一个对象,里面有

    未完待续……

    Babel 与 webpack 结合

    npm install babel-loader  -D
    

    未完待续……

  • 相关阅读:
    python 网络客户端编程端口,模块
    Python反转
    ASP.NET的路由系统
    yield 关键字
    C# Lock关键字
    C#中as和is关键字
    13.4 上下文对象
    请求生命周期
    ASP.NET常用的指令
    ASP.NET Page 指令
  • 原文地址:https://www.cnblogs.com/Khadron/p/14535330.html
Copyright © 2011-2022 走看看