前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从零学脚手架(四)---babel

从零学脚手架(四)---babel

作者头像
莫问今朝
发布2021-03-16 15:26:46
1.2K0
发布2021-03-16 15:26:46
举报
文章被收录于专栏:博客园博客园

如果此篇对您有所帮助,在此求一个star。项目地址: OrcasTeam/my-cli

接下来介绍一个打包编译过程中一个极为重要的工具--babel。

ES6的枷锁

细心的朋友可以知道,在之前打包编译测试都是使用简单的ES5特性,

并没有使用过ES6(ES2015+)特性(import除外)

这是因为webpack本身不会处理代码中的ES6(ES2015+)特性,所以也就没有使用。

先来做一个测试

/src/index.js 文件使用部分ES6(ES2015+),查看打包编译代码会发现webpack并没有处理ES6(ES2015+)特性。

自从ES6(ES2015+)时代来临后,前端才具有了飞速发展。ES6(ES2015+)各种特性也给开发人员带来了便利。

毫不客气的说,没有人再想写ES5代码了。

但是,前端代码的执行环境(浏览器)是由用户决定的,如果用户一直使用旧版本浏览器,那么新特性就无法运行在用户浏览器中。

这时候就需要一种工具:将代码使用的ES6(ES2015+)特性转换为ES5特性

这个工具就叫做:babel

?? ? webpack作为一个打包器。为babel提供了扩展支持。

?? ES6是ES2015+所有版本统称 有的文章会写成ES7、ES8。但其实都是ES6。

? 上面代码使用到了ES6的 Promise类型块级声明(const)箭头函数for-of语法数组APIawait属性,不了解ES6的朋友可以学习阮一峰老师的ES6入门教程

babel

babel介绍

ES6来临后,前端开启了百花绽放的时代。从而也导致了ES6转ES5的工作并不仅仅局限于JS语言的原始特性。

例如:Typescript、JSX语法等等。

这些都可以使用babel进行处理。

babel的设计思想也与webpack一致:提供核心引擎 + 插件化的模式管理

babel提供了一个核心引擎库:@babel/core 和 扩展插件库配置。

@babel/cli

babel 其实并不是webpack一个扩展插件,它是一个独立的工具。可以进行单独配置、运行。

babel提供了一个@babel/cli库,与webpack-cli库一样,允许命令行直接运行babel

代码语言:javascript
复制
{
  "scripts": {
	"build": "babel src -d lib"
  }
}

在此就不介绍@babel/cli这一块的内容了,有兴趣的朋友可以去官网学习

??? babel作为一个独立工具,理论可以配置在所有打包器中。

babel-loader

babel作为一个独立的工具,那么肯定不能直接配置在webpack中。

那么想要babel执行在webpack,就必须提供一个适配器,来桥接两个库。

而这个适配器就是babel-loader

babel-loader在webpack执行时拦截需要转换文件,将文件先交给babel进行转换,然后再传回webpack执行接下来的操作。

而babel-loader只是调用了@babel/core库中的API。最后执行的还是@babel/core引擎

下面先安装babel-loader和@babel/core

yarn add -D babel-loader@8.2.2 @babel/core@7.13.1

然后在webpack.config.js中配置所有的js文件都使用babel-loader进行转换。

代码语言:javascript
复制
{
   module:{
    rules:[
      {
        //  所有的.js文件都走babel-loader
        test:/\.js$/,
        include: path.join(config.root,'src'),
        loader: "babel-loader",
      }
    ]
  },
}

? babel@6.X版本时,核心引擎库名为babel-core。从babel@7.X版本之后,官方对库名称做了统一的修改,官方提供的包都以@babel/冠名,所以babel-core和@babel/core实际上是一个库 。有兴趣朋友可以在NPM中对比下两个包的版本 :@babel/corebabel-core

?后面会陆续加入其它文件执行babel-loader。例如:.ts、.jsx

但是目前依然无法转换ES6(ES2015+)代码。因为只添加了引擎(@babel/core),并没有添加具体转换库。

@babel/preset-env

先来介绍一下@babel/preset-env库,来完成部分转换功能。

@babel/preset-env是babel 预设的一个plugin

yarn add -D @babel/preset-env@7.13.5

在配置loader时,可以设置当前loader使用的属性和依赖库。babel-loader具有一个presets属性来依赖的预设插件(preset)

代码语言:javascript
复制
{
    module:{
        rules:[
            {
                //  所有的.js文件都走babel-loader
                test:/\.js$/,
                include: path.join(config.root,'src'),
                loader: "babel-loader",
                options: {
                    presets:[
                        "@babel/preset-env",
                    ]
                }
            }
        ]
    }  
}

?? presets的执行是从后往前执行的,官方说为了确保向后兼容

? presets配置可以设置短名称,

  1. preset库名称以 babel-preset- 前缀,可以省去前缀。 例如:babel-preset-my-custom,可以直接设置为:custom
  2. 短名称也适用于冠名,例如:@org/preset-env,可以设置为:@org/env

此时执行yarn build操作后生成的代码就会处理部分ES6(ES2015+)

生成代码中可以看到:awaitfor-ofconst 这些ES6代码被转换了。

? 代码中的那堆 case 语句,是await ES5的写法。await 本质只是一个 将异步同步化的状态机。不熟悉 await 机制的朋友可以忽略,只需知道代码为await语法ES5写法即可。

但细心的朋友可以发现,并不是所有的ES6特性被转换了。

还有部分ES6特性并没有被转换(promiseincludesfilter),并且代码被一个箭头函数包裹着。

代码被箭头函数包裹这个问题稍后在解决。

先来了解下为什么有的ES6特性没有被转换。

? @babel/preset-env取代了preset-es20系列的预设插件(preset)

目前生成代码还无法在浏览器运行,缺少regeneratorRuntime,这个稍后再说

Syntax和API

思考一个问题:刚才被转换的ES6特性与未被转换的ES6特性有何不同。

答案是被转换的ES6特性是Syntax(语法),而未被转换的则是:API(类型、函数)

babel处理ES6特性时将Syntax(语法)API(类型、函数)进行了分开处理。

为什么要这样做呢?

原因是两者本质的不同:Syntax(语法)一个语言本身客观存在的事实,而API(类型、函数),则只是对一系列操作的封装

当执行环境不支持Syntax(语法)时,那么就只能使用其它Syntax(语法)进行替换。

而执行环境中不存在API(类型、函数)时,可以编写自定义API(类型、函数)进行替换。

? JSSyntax(语法)错误提示是:Uncaught SyntaxError;API(类型、函数)错误提示是:Uncaught ReferenceError。

@babel/preset-env只是babel提供处理Syntax(语法)的预设插件(preset)

至于API(类型、函数)的处理,则是由其它插件处理,这个插件俗称:垫片、腻子

babel配置形式

在处理API(类型、函数)之前,先介绍下babel配置文件。

刚才在配置@babel/preset-env时,直接配置在了babel-loader中presets属性。

除了babel-loader,babel还支持其它方式配置

package.json

@babel/core支持在package.json文件设置

package.json文件babel属性设置babel 插件

@babel/core执行时会尝试读取此属性。

代码语言:javascript
复制
 "babel": {
   "presets": [
     "@babel/preset-env"
   ],
   "plugins": [
   ]
 }
配置文件

babel支持使用配置文件设置。

这种方式与webpack.config.js文件一样,使用.约定文件名称设置。@babel/core执行时会尝试读取.约定文件

约定文件名称 可以为 babel.config.js.babelrc.json 。 较为常用的是 .babelrc.json 。不过一般都会省略后缀, 名称叫做 .babelrc

package.json形式和配置文件形式 只能选择一种形式设置。如果同时存在会直接报错。

babel-loader配置方式优先级高于其他两种方式

参数设置

在使用plugin/preset时,可以设置属性。

不过参数形式有些奇葩。

plugin/preset与参数存在于一个数组内,第一个为plugin/preset,第二个为属性对象

代码语言:javascript
复制
{
  "presets": [
     ["@babel/preset-env", {
          "targets": "defaults"
     }]
  ],
  "plugins": [
  ]
}

??? 以下会使用配置文件方式,所以一定要把babel-loader中的设置删除掉。否则会因为优先级问题而失效。:我就因为这个疏漏曾经被耽误了一天

转换API(类型、函数)
设置低版本浏览器

在转换API(类型、函数)时要进行测试。

而开发人员基本上使用的都是新版浏览器,所以需要具有一个不支持ES6API(类型、函数)的浏览器。

一般ES6的新特性,都已经不再支持IE浏览器了。所以IE浏览器是一个天然的测试对象。

例如ES6Promise类型,就不再支持IE浏览器

win 10系统携带的IE浏览器版本一般都为IE11。IE浏览器支持对版本进行修改IE浏览器

F12-开发者模式--仿真--文档模式 可以修改IE浏览器版本,在这里使用的版本为IE9

处理箭头函数包裹

在刚才打包编译时,发现生成的代码使用了一个箭头函数包裹。

这个箭头函数函数怀疑是打包时webpack搞得鬼,具体原因没排查,在这里只介绍下处理方案。

package.json文件中添加browserslist属性,设置打包代码支持IE9浏览器。

代码语言:javascript
复制
"browserslist": [
 "ie 9"
]

? browserslist属性是browserslist库提供的一个属性,browserslist是提供浏览器版本支持的库。多个库中都依赖了browserslist。 browserslist库详情在下一篇介绍。

此时使用yarn build执行打包编译,生成代码就不再由箭头函数包裹

regenerator-runtime和core-js
regenerator-runtime

介绍下关于之前打包代码缺少 regeneratorRuntime() 问题。

regeneratorRuntime() 是由regenerator-runtime库提供的,

regenerator-runtime库是一个转换ES6中 generator函数await函数 功能的库。babel直接使用此库处理两种函数。

core-js

很多文章介绍时regenerator-runtime都与core-js一起介绍。所以在此也将这两个库放在一起介绍。

处理ES6 API(类型、函数)的解决方案在上面介绍过。

当执行环境中不存在API(类型、函数)时,可以使用自定义API(类型、函数)进行替代。

而core-js库就是一个自定义的API(类型、函数)库。也就是俗称的腻子

core-js是 个人开源项目,并不属于任何公司。

babel直接使用了core-js进行处理API(类型、函数)

core-js截至到编写文章时的最新版本为@3.9.0

core-js的@3.X与@2.X两个大版本间具有巨大的差异性,以至于影响到了babel。不过目前基本都是使用core-js@3.X版本。

? core-js开发者目前在开发core-js@4.X版本。可能到时候配置又会具有大变化。

@babel/polyfill

关于babel的文章中,有很多都会介绍@babel/polyfill。

@babel/polyfill库其实就是babel对core-js和regenerator-runtime的封装库。

不过在babel官网,这个库已经被弃用了。babel@7.4.0版本之后就建议直接使用core-js和regenerator-runtime

上面那段话的大致意思为:@babel@7.4.0开始,@babel/polyfill会被弃用,直接使用core-js和regenerator-runtime。

下面那段话的大致意思为:babel具有一个polyfill包含了core-js和regenerator-runtime。

??? 关于@babel/polyfill库被弃用的原因好像是因为:core-js@3.X版本和core-js@2.X版本的巨大差异 导致@babel/polyfill无法过渡适配

core-js、regenerator-runtime使用

yarn add regenerator-runtime@0.13.7 core-js@3.9.0 // 安装在dependencies

直接使用core-js和regenerator-runtime需要在代码中手动引用。babel当然也支持配置,慢慢来

index.js文件引用。

??

  1. 导入core-js库时,导入方式为:"core-js/stable",是为了只导入稳定版本特性, 关于stage请参考:[ECMAScript] TC39 process
  2. 导入regenerator-runtime时,导入方式为:regenerator-runtime/runtime,为了节省文件大小

此时执行yarn build打包 编译生成代码中会看到好多引用代码。这些都是core-js处理ES6 API(类型、函数)的垫片

例如promise类型,就可以在编译生成后的代码中找到core-js自定义的实现方式。

这时候使用IE9运行代码可以运行成功,也就是说ES6 API(类型、函数)被成功替代了。

@babel/preset-env 属性设置
按需加载

刚才加入core-js和regenerator-runtime后打包运行,可以知道ES6 API(类型、函数)被成功替代了。

但其实这里还具有一个非常严重的问题,那就是文件大小。

可以看到打包生成的文件现在高达428K。虽然打包代码压缩,但也不应该这个大小

在代码中仅写了两个函数。那么原因大概是引入core-js和regenerator-runtime导致。

core-js是ES6 API(类型、函数)的垫片。

core-js本身并不知道你使用哪些ES6 API(类型、函数),而babel默认情况会将所有的垫片引入,

也就造成了这个恐怖的文件大小

前端对于文件大小非常敏感,文件大小直接影响到网站的加载速度。所以必须要做到按需加载垫片 (仅加载需要使用的垫片)

不同项目对浏览器支持版本需求不一样。

babel处理ES6 API(类型、函数)垫片时的按需加载垫片具有三种含义

  1. 按照浏览器版本加载垫片
  2. 按照代码中使用加载垫片
  3. 按照浏览器版本+代码中使用加载垫片

?浏览器支持版本需求 取决于项目的使用用户,例如有的项目只是公司管理项目,无须兼容老版本浏览器

babel中@babel/preset-env提供了两种按需加载配置方案:按照浏览器版本加载(1)按照浏览器版本+代码中使用加载(3)

@babel/preset-env 属性配置

设置浏览器版本(browserslist、targets)

按需加载垫片中有一个浏览器版本加载的含义,想要实现浏览器版本加载那就必须设置浏览器版本,

babel提供了两种设置浏览器版本的方案:

browserslist

browserslist方案在刚才处理函数包裹代码时使用到了,设置在package.json中的browserslist属性

代码语言:javascript
复制
"browserslist": [
    "ie 9"
]

browserslist是一个提供浏览器版本的一个库,提供了多种配置规则,好多库都使用到了browserslist,例如:babel。

browserslist属性是Array,允许设置多个浏览器版本。例如ie 9,便是支持IE9浏览器。

还可以设置范围版本,例如大于Chrome75版本。

代码语言:javascript
复制
"browserslist": [
    "Chrome > 75"
]

在这里只使用这两种规则测试,browserslist会在下一篇介绍

targets

targets属性是babel自身提供浏览器版本设置,配置在@babel/preset-env属性中

targets属性类型为 StringObject;支持browserslist格式规则。

targets属性的优先级高于browserslist

代码语言:javascript
复制
{
    "presets": [
        ["@babel/preset-env",{
            "targets": "chrome > 75",
        }]
    ],
    "plugins": [
    ]
}
代码语言:javascript
复制
{
    "presets": [
        ["@babel/preset-env",{
            "targets": {
                "chrome": "58",
                "ie": "11"
            }]
            ],
        "plugins": [
    ]
}

推荐使用browserslist设置,也就是package.jsonbrowserslist属性。

因为browserslist库已经被社区高度认可。好多库都依赖了browserslist,使用browserslist库可以做到:配置统一管理,利于项目维护

?:?? 浏览器版本设置也会影响Syntax(语法)的转换。 指定的浏览器版本支持的Syntax(语法)不会被转换ES5

corejs

在介绍按需加载垫片之前再说一个@babel/preset-env属性:corejs

corejs属性是babel@7.4.0时加入的,用于设置加载core-js版本。

corejs设置的类型为: StringObject

代码语言:javascript
复制
{
    "presets": [
        ["@babel/preset-env",{
            "corejs": {
                "version": "3.9",
                "proposals":true
            }
        }]
    ],
    "plugins": [
    ]
}
  • version:设置加载的core-js版本。 此属性可以设置任何受支持的core-js 参数类型为 String 默认值为:2.0
  • proposals:是否加载core-js支持的 提议API 参数类型为:Boolean 默认值为:false

?? corejs属性只有在启用按需加载垫片(useBuiltIns设置为entryusage才有效。

useBuiltIns

按需加载垫片是由@babel/preset-env库提供的useBuiltIns属性设置。

useBuiltIns属性可以设置三个属性值:

false

不启用按需加载垫片功能,全部加载core-js垫片。此值为默认值。

entry

按照浏览器版本加载垫片。

代码语言:javascript
复制
{
  "presets": [
    ["@babel/preset-env",{
      "useBuiltIns": "entry",
      "corejs": {
        "version": "3.9",
        "proposals":true
      }

    }]
  ],
"plugins": [
  ]
}

browserslist属性为 Chrome > 75 时 打包出来的文件大小就会小很多

代码语言:javascript
复制
"browserslist": [
    "Chrome > 75"
]

可以看到,此时文件大小与刚才是天壤之别。因为浏览器设置的为 Chrome > 75 ,几乎支持全部新特性

可以看到打包生成代码中没有提供filter垫片,并且 await 语法都没有转换。这些特性在新版Chrome都提供了。

如果将browserslist属性设置为 ie 9

那么文件大小依然会很大。因为ES6 新特性都不支持IE 9

代码语言:javascript
复制
"browserslist": [
    "ie 9"
]

usage

刚才使用entry属性值实现了按照浏览器版本加载垫片的功能。

不过并不能算是我们需要的真正按需加载垫片。

useBuiltIns属性的usage值提供了理论上真正的按需加载浏览器版本+代码中使用

代码语言:javascript
复制
{
  "presets": [
    	["@babel/preset-env",{
      "useBuiltIns": "usage",
      "corejs": {
        "version": "3.9",
        "proposals":true
      }
 	}]
  ],
  "plugins": [
  ]
}

在使用usage属性值时,就不需要手动引用core-js和regenerator-runtime库了

babel会自动加载。

此时哪怕设置ie 9。打包文件大小也不会像entry时那么大了。

代码语言:javascript
复制
"browserslist": [
    "ie 9"
]

而在Chrome > 75的情况下,代码都不需要进行处理了

代码语言:javascript
复制
"browserslist": [
    "Chrome > 75"
]

entry、usage有话说

  1. babel在处理entry属性值时,直接将按需加载处理逻辑做到了入口。而在处理usage时,则在用到时进行了单独引用,并且保证每一个API(类型、函数)只引用一次
  2. 在两者选择使用时,不要一味的追求usage,因为usage使用起来更为棘手

modules

@babel/preset-env配置项中有一个modules

modules属性表示是否将ES modules转换为指定模块类型处理。

modules属性值具有:amdsystemjsumdcommonjscjsautofalse

默认属性值为auto:默认情况下,使用ES modules来进行处理,但是会受到其它plugin的modules属性影响。

推荐使用ES modules,将属性值设置为false

因为ES6 modules 可以进行tree-shaking优化

代码语言:javascript
复制
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "modules":false
      }
    ]
  ]
}

@babel/preset-env还有一些别的属性,在此就不赘述。有兴趣的朋友可以查询官网

@babel/plugin-transform-runtime

babel处理ES6特性时,还提供了一个解决全局污染的垫片库:@babel/plugin-transform-runtime

@babel/plugin-transform-runtime也是一个经常被使用到的库。

在日常开发中都应该遵守的一个原则:避免全局污染

全局污染是一件极为可怕的问题。在协同、代码运行时会出现不可预知的问题。

@babel/plugin-transform-runtime库就是将代码使用到的ES6 API(类型、函数)名称转换为自定义名称,从而避免污染运行环境自身API

? @babel/plugin-transform-runtime与usage属性值一样:按照浏览器版本+代码中使用加载垫片

开发第三方库,强烈建议使用@babel/plugin-transform-runtime

@babel/runtime-corejs3

@babel/plugin-transform-runtime库依赖了一个@babel/runtime-corejs3或@babel/runtime-corejs2库。

??? @babel/runtime-corejs3对应的core-js@3.X @babel/runtime-corejs2对应的core-js@2.X

@babel/runtime-corejs3是babel提供的core-js封装库,内部做了一些处理,具体可以参考这篇文章。不过此文章是基于@babel/runtime-corejs2版本,与@babel/runtime-corejs3具有一定差异。

yarn add -D @babel/plugin-transform-runtime@7.13.7 @babel/runtime-corejs3@7.13.7

?? 使用@babel/plugin-transform-runtime时,就不需要安装core-js和regenerator-runtime ,@babel/runtime-corejs3中会依赖这两个库

.babelrc文件中使用@babel/plugin-transform-runtime配置替代@babel/preset-env中配置。

不过注意的是@babel/plugin-transform-runtime属性中corejs.version不再是字符串,而是23。 因为加载的是@babel/runtime-corejs[3/2]

代码语言:javascript
复制
{
  "presets": [
    [
      "@babel/preset-env",
      {
        //  移除useBuiltIns设置
        //      "targets": "chrome > 75",
        //      "useBuiltIns": "usage",
        //      "corejs": {
        //        "version": "3.9",
        //        "proposals":true
        //      }
      }
    ]
  ],
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "corejs": {
          "version": 3,
          "proposals": true
        }
      }
    ]
  ]
}

配置完毕后,不再需要任何引用就可以进行打包生成。

代码语言:javascript
复制
"browserslist": [
    "ie 9"
]

在IE9环境yarn build

可以看到使用的ES6-API已经被转换为另外的API了,所以并不会再污染全局代码。至于打包的大小,并没有多大

至于在Chrome > 75的打包结果,有兴趣的朋友可以自行测试。

preset和plugin

在使用babel库时,发现有两种类型:

  1. preset:@babel/preset-env
  2. plugin:@babel/plugin-transform-runtime

配置时也是不同属性:

代码语言:javascript
复制
{
  "presets": [
    
  ],
  "plugins": [
  ]
}

preset的中文翻译为:预置。其实也就是babel提供的预置插件库,其本质也都是plugin

总结

???

  • babel来用来处理ES6特性的库
  • babel也是核心引擎 + 插件化的设计模式
  • babel-loader是babel的适配器,将babel提供webpack使用
  • babel使用不同的插件分别处理Syntax(语法)API(类型、函数)
  • babel提供不少的预设插件,配置在presets属性中。
  • @babel/preset-env中useBuiltIns属性用来设置按需加载垫片
  • @babel/plugin-transform-runtime提供了一种不污染全局情况下使用垫片方式。

本文参考

本文依赖

package.json

代码语言:javascript
复制
{
  "name": "my-cli",
  "version": "1.0.0",
  "main": "index.js",
  "author": "mowenjinzhao<yanzhangshuai@126.com>",
  "license": "MIT",
  "devDependencies": {
    "@babel/core": "7.13.1",
    "@babel/plugin-transform-runtime": "7.13.7",
    "@babel/preset-env": "7.13.5",
    "@babel/runtime-corejs3": "7.13.7",
    "babel-loader": "8.2.2",
    "clean-webpack-plugin": "3.0.0",
    "html-webpack-plugin": "5.2.0",
    "webpack": "5.24.0",
    "webpack-cli": "4.5.0"
  },
  "dependencies": {
    "jquery": "3.5.1",
  },
  "scripts": {
    "start": "webpack --mode=development  --config webpack.config.js",
    "build": "webpack --mode=production  --config webpack.config.js"
  },
  
  "browserslist": [
    "ie 9",
    "Chrome > 75"
    ]
}

webpack.config.js

代码语言:javascript
复制
const path = require('path')
const webpack = require("webpack");
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin')


const config = {
  root: path.join(__dirname, './'),
}

const modules = {

  //  入口文件
  //  字符串形式
  entry: path.join(config.root, 'src/index.js'),
  //  对象形式
  // entry:{
  //   'index':  path.join(config.root, 'src/index.js'),
  // },

  //  输出文件
  //  字符串形式
  // output:path.join(config.root, './dist/[name].js')
  //对象形式
  output: {
    //  输出文件的目录地址
    path: path.join(config.root, 'dist'),
    //  输出文件名称,contenthash代表一种缓存,只有文件更改才会更新hash值,重新打包
    filename: '[name]_[contenthash].js'
  },

  //devtool:false, //'eval'

  module:{
    rules:[
      {
        //  所有的.js文件都走babel-loader
        test:/\.js$/,
        include: path.join(config.root,'src'),
        loader: "babel-loader"
      }
    ]
  },


  optimization: {
    minimize: false,
    minimizer: [
    new TerserPlugin({
          //  指定压缩的文件
          include: /\.js(\?.*)?$/i,

          // 排除压缩的文件
          // exclude:/\.js(\?.*)?$/i,

          //  是否启用多线程运行,默认为true,开启,默认并发数量为os.cpus()-1
          //  可以设置为false(不使用多线程)或者数值(并发数量)
          parallel: true,

          //  可以设置一个function,使用其它压缩插件覆盖默认的压缩插件,默认为undefined,
          minify: undefined,

          //  是否将代码注释提取到一个单独的文件。
          //  属性值:Boolean | String | RegExp | Function<(node, comment) -> Boolean|Object> | Object
          //  默认为true, 只提取/^\**!|@preserve|@license|@cc_on/i注释
          //  感觉没什么特殊情况直接设置为false即可
          extractComments: false,

          // 压缩时的选项设置
          terserOptions: {
            //  是否保留原始函数名称,true代表保留,false即保留
            //  此属性对使用Function.prototype.name
            //  默认为false
            keep_fnames: false,

            // 是否保留原始类名称
            keep_classnames: false,

            //  format和output是同一个属性值,,名称不一致,output不建议使用了,被放弃
            // 指定压缩格式。例如是否保留*注释*,是否始终为*if*、*for*等设置大括号。
            format: {
              comments: false,
            },
            output: undefined,

            //  是否支持IE8,默认不支持
            ie8: false,

            compress: {
              // 是否使用默认配置项,这个属性当只启用指定某些选项时可以设置为false
              defaults: false,

              // 是否移除无法访问的代码
              dead_code: false,

              // 是否优化只使用一次的变量
              collapse_vars: true,

              warnings: true,

              //  是否删除所有 console.*语句,默认为false,这个可以在线上设置为true
              drop_console: false,

              //  是否删除所有debugger语句,默认为true
              drop_debugger: true,

              //  移除指定func,这个属性假定函数没有任何副作用,可以使用此属性移除所有指定func
              // pure_funcs: ['console.log'], //移除console
            },
          },
    	})
    ]
  },

  plugins: [
    new HtmlWebpackPlugin({
       //  HTML的标题,
        //  template的title优先级大于当前数据
        title: 'my-cli',

        //  输出的html文件名称
        filename: 'index.html',

        //  本地HTML模板文件地址
        template: path.join(config.root, 'src/index.html'),

        // 引用JS文件的目录路径
        publicPath: './',

        //  引用JS文件的位置
        //  true或者body将打包后的js脚本放入body元素下,head则将脚本放到中
        //  默认为true
        inject: 'body',

        //  加载js方式,值为defer/blocking
        //  默认为blocking, 如果设置了defer,则在js引用标签上加上此属性,进行异步加载
        scriptLoading: 'blocking',

        //  是否进行缓存,默认为true,在开发环境可以设置成false
        cache: false,

        //  添加mate属性
        meta: {}
    }),

    new CleanWebpackPlugin({
 		// 是否假装删除文件
        //  如果为false则代表真实删除,如果为true,则代表不删除
        dry: false,

        //  是否将删除日志打印到控制台 默认为false
        verbose: true,

        //  允许保留本次打包的文件
        //  true为允许,false为不允许,保留本次打包结果,也就是会删除本次打包的文件
        //  默认为true
        protectWebpackAssets: true,

        //  每次打包之前删除匹配的文件
        cleanOnceBeforeBuildPatterns: ['**/*'],

        //  每次打包之后删除匹配的文件
        cleanAfterEveryBuildPatterns:["*.js"],
    }),


    new webpack.DefinePlugin({ "global_a": JSON.stringify("我是一个打包配置的全局变量") }),
  ],

  resolve: {
    alias:{
      //  设置路径别名
      '@': path.join(config.root, 'src') ,

      '~':  path.join(config.root, './src/assets') ,
    },
    //  可互忽略的后缀
    extensions:['.js', '.json'],
    //  默认读取的文件名
    mainFiles:['index', 'main'],
  }
}

//  使用node.js的导出,将配置进行导出
module.exports = modules

.babelrc

代码语言:javascript
复制
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "modules":false
        //  移除useBuiltIns设置
        //      "targets": "chrome > 75",
        //      "useBuiltIns": "usage",
        //      "corejs": {
        //        "version": 3,
        //        "proposals":true
        //      }
      }
    ]
  ],
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "corejs": {
          "version": 3,
          "proposals": true
        }
      }
    ]
  ]
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-03-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 如果此篇对您有所帮助,在此求一个star。项目地址: OrcasTeam/my-cli
  • ES6的枷锁
  • babel
    • babel介绍
      • @babel/cli
        • babel-loader
          • @babel/preset-env
            • Syntax和API
              • babel配置形式
                • package.json
                • 配置文件
                • 参数设置
              • 转换API(类型、函数)
                • 设置低版本浏览器
                • 处理箭头函数包裹
                • regenerator-runtime和core-js
                • @babel/polyfill
                • core-js、regenerator-runtime使用
              • @babel/preset-env 属性设置
                • 按需加载
              • @babel/plugin-transform-runtime
                • @babel/runtime-corejs3
              • preset和plugin
              • 总结
              • 本文参考
              • 本文依赖
              • package.json
              • webpack.config.js
              • .babelrc
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档