关于webpack:从零学脚手架三webpack属性详解

54次阅读

共计 21654 个字符,预计需要花费 55 分钟才能阅读完成。

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

在上一篇中,介绍了 <font style=”color:cornflowerblue”>webpack</font> 的 entryoutputplugins 属性。

在这一篇,接着介绍其它配置属性。

mode

这个属性在上一篇中应用过一次:设置 <font style=”color:cornflowerblue”>webpack</font> 编译模式,那么这个属性到底是什么货色呢?

<font style=”color:cornflowerblue”> 打包器 </font> 是将 <font style=”color:#007FFF”> 开发环境代码 </font> 编译 为 <font style=”color:#007FFF”> 可部署环境代码 </font>

搭建的 <font style=”color:cornflowerblue”> 工程化 </font> 代码根本都无奈间接运行在浏览器,所以本地测试也都是应用打包编译后的代码预览。

然而本地开发预览又必须具备代码可读性、可调试性等条件。

<font style=”color:cornflowerblue”>webpack </font> 为了解决这个问题,就提供了两种 <font style=”color:cornflowerblue”> 打包模式 </font>:<font style=”color:cornflowerblue”> 开发模式(development)</font> 和 <font style=”color:cornflowerblue”> 公布模式(production)</font>

mode 属性设置

 {mode:'development'}

也能够应用 CLI 参数 进行设置

  • <font style=”color:cornflowerblue”>webpack</font> 默认应用的是 <font style=”color:cornflowerblue”> 公布模式(production)</font>,短少 mode 属性执行时,<font style=”color:cornflowerblue”>webpack</font> 会进行提醒
  • CLI 参数 设置 优先级要高于 webpack.config.js 文件设置。
  • 更好的计划是应用两个 webpack.config.js 文件,脚手架个别都是这样辨别,在之后介绍 <font style=”color:cornflowerblue”>webpack merge</font> 时解决

测试两种模式的区别时,最直观区别就是查看编译生成的代码是否进行了压缩:在 production 模式下,<font style=”color:cornflowerblue”>webpack</font> 会预设压缩 plugin

<font style=”color:cornflowerblue”>webpack</font> 中的 mode 属性值其实具备三个:developmentproductionnone

none 属性值与两者的区别只是没有预设任何 <font style=”color:#06f”> 插件 </font>

developmentproduction 两种模式只是针对不同场景下性能差异化的辨别,其实现具体的性能还是应用的 <font style=”color:#06f”> 插件 </font>

为了配置简单化,developmentproduction 两种模式都预设了一些根本 <font style=”color:#06f”> 插件 </font>。

上面来介绍下 developmentproduction 两种模式中的预设的局部性能

development

process.env.NODE_ENV

development 模式时,<font style=”color:cornflowerblue”>webpack</font> 应用内置 <font style=”color:cornflowerblue”>DefinePlugin</font>

预设了一个环境变量属性 process.env.NODE_ENV,属性值为 development

开发人员能够编写业务代码时依据 process.env.NODE_ENV 属性判断以后编译模式,以此执行不同环境中的代码。

process.env.NODE_ENV 属性和 <font style=”color:cornflowerblue”>DefinePlugin</font> 稍后具体介绍

设置模块和模块名称设置有效性

development 模式时,<font style=”color:cornflowerblue”>webpack</font> 会将 JS 模块 模块名称 设置为无效名称,用来不便调试

<font style=”color:cornflowerblue”>webpack@4.X</font> 版本设置代码可读性应用的是 <font style=”color:cornflowerblue”>webpack</font> 内置的 <font style=”color:cornflowerblue”>plugin</font>:<font style=”color:cornflowerblue”>NamedModulesPlugin</font> 和 <font style=”color:cornflowerblue”>NamedChunksPlugin</font>

<font style=”color:cornflowerblue”>webpack@5.X</font> 版本设置代码可读性应用的是 optimization.moduleIdsoptimization.chunkIds 两个属性。

但本源也是应用内置 <font style=”color:cornflowerblue”>plugin</font>:<font style=”color:cornflowerblue”>NamedModuleIdsPlugin</font> 和 <font style=”color:cornflowerblue”>NamedChunkIdsPlugin</font>

optimization: {
    moduleIds: 'named',
    chunkIds: 'named',
}

optimization 属性是 <font style=”color:cornflowerblue”>webpack</font> 提供的优化属性,与 mode 一样,只是为了方便管理,其本源还是应用 <font style=”color:#06f”> 插件 </font > 设置的。

设置 devtool 属性

development 模式时,<font style=”color:cornflowerblue”>webpack</font> 会将 devtool 属性设置为 eval

devtool 属性是管制 <font style=”color:cornflowerblue”>SourceMap </font> 文件如何生成的。<font style=”color:cornflowerblue”>SourceMap</font> 是用于将原始模块文件与打包后的代码映射文件。用于调试应用。具体稍候介绍

production

process.env.NODE_ENV

production 模式时,<font style=”color:cornflowerblue”>webpack</font> 应用内置 <font style=”color:cornflowerblue”>DefinePlugin</font>

预设一个环境变量属性 process.env.NODE_ENV,属性值为 production

开发人员能够编写业务代码时依据 process.env.NODE_ENV 属性判断以后编译模式,以此执行不同环境中的代码。

process.env.NODE_ENV 属性和 <font style=”color:cornflowerblue”>DefinePlugin</font> 稍后具体介绍

设置模块和模块名称混同

production 模式时,<font style=”color:cornflowerblue”>webpack</font> 将 JS 模块 模块名称 进行混同,以保障代码安全性

<font style=”color:cornflowerblue”>webpack@4.X </font> 版本设置代码可读性应用的是 <font style=”color:cornflowerblue”>webpack</font> 内置的 <font style=”color:cornflowerblue”>plugin</font>:<font style=”color:cornflowerblue”>NamedModulesPlugin</font> 和 <font style=”color:cornflowerblue”>NamedChunksPlugin</font>

<font style=”color:cornflowerblue”>webpack@5.X</font> 版本设置代码可读性应用的是 optimization.moduleIdsoptimization.chunkIds 两个属性,但本源也是应用内置 <font style=”color:cornflowerblue”>plugin</font>:<font style=”color:cornflowerblue”>DeterministicModuleIdsPlugin</font> 和 <font style=”color:cornflowerblue”>DeterministicChunkIdsPlugin</font>

optimization: {
    moduleIds: 'deterministic',
    chunkIds: 'deterministic',
}
代码压缩

production 模式时,<font style=”color:cornflowerblue”>webpack</font> 开启了代码压缩优化,应用 terser-webpack-plugin 库对打包生成代码进行压缩

<font style=”color:cornflowerblue”>webpack@5.X </font> 默认应用 terser-webpack-plugin 压缩代码,<font style=”color:cornflowerblue”>webpack@4.X </font> 版本及之前版本,默认应用的压缩库为 uglifyjs-webpack-plugin。但 uglifyjs-webpack-plugin 已进行保护

作用域晋升

production模式时,<font style=”color:cornflowerblue”>webpack</font> 会应用内置的 <font style=”color:cornflowerblue”>ModuleConcatenationPlugin</font> 对代码的作用域进行提醒。用于缩小打包生成的代码量和执行速度。

错误处理

production模式时,<font style=”color:cornflowerblue”>webpack</font> 会预设内置 <font style=”color:cornflowerblue”>NoEmitOnErrorsPlugin</font>。

打包编译时,如果呈现代码谬误,则不在生成代码。用于防止代码错误代码仍然打包胜利

<font style=”color:cornflowerblue”>webpack@5.X</font> 和 <font style=”color:cornflowerblue”>webpack@4.X</font> 对于 developmentproduction 预设性能具备肯定的差别,具体请参考 webpack5-mode、webpack4-mode、显微镜下的 webpack4 的新个性:mode 详解

DefinePlugin

developmentproduction 两种模式中,都设置了一个环境变量属性:process.env.NODE_ENV,只是属性值不雷同。

环境变量用于编写业务代码时 针对不同环境下的差异化代码。例如调用第三方 SDK 时:辨别 <font style=”color:cornflowerblue”> 开发环境 </font> 和 <font style=”color:cornflowerblue”> 正式环境 </font>。

当然能够抉择每次发版时手动批改配置,只有本人不会感觉麻烦。

做一个测试

/src/index.js 中输入 process.env.NODE_ENV 属性

在执行 yarn start 后查看打包生成代码会看到 process.env.NODE_ENV 替换为了 development 字符串

同样如果执行yarn build process.env.NODE_ENV 属性 会替换成 production 字符串

这就是 process.env.NODE_ENV 环境变量的作用,<font style=”color:cornflowerblue”>webpack</font> 在打包编译时会将设置的环境变量属性值进行替换,能够在编写业务代码时进行环境判断。

<font style=”color:cornflowerblue”>webpack</font> 应用了内置的 <font style=”color:cornflowerblue”>DefinePlugin</font> 设置 process.env.NODE_ENV

当然也能够应用 <font style=”color:cornflowerblue”>DefinePlugin</font> 设置自定义环境变量。具体详情请参考:官网

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

devtool

development 模式中会设置 devtool 属性。

devtool 属性也是 <font style=”color:cornflowerblue”>webpack</font> 提供的一个属性项。用于设置 <font style=”color:cornflowerblue”>javascript-source-map</font>

咱们都看过打包编译生成的代码,哪怕是 development 模式下生成的,也是超级凌乱。

而想要对这些代码调试排查谬误,那几乎是个噩梦。

对于这个问题,<font style=”color:cornflowerblue”>Google</font> 提供了一种工具叫做:<font style=”color:cornflowerblue”>javascript-source-map</font>

<font style=”color:cornflowerblue”>javascript-source-map </font> 提供一个映射信息,将 打包编译生成的代码 开发编写的代码文件 进行映射,调试时间接针对 开发编写的代码文件进行调试。

<font style=”color:cornflowerblue”>source-map</font> 具体介绍请参考阮一峰老师的:JavaScript Source Map 详解

<font style=”color:cornflowerblue”>webpack</font> 提供了 devtool 属性来设置 <font style=”color:cornflowerblue”>javascript-source-map</font>

development 模式 devtool 属性默认值为 eval

production 模式 devtool 属性默认值为 false(none)

eval 属性值生成的代码都是由 eval 语法编译,并提供了一个 sourceURL 属性用于指向文件源门路

devtool 属性具备十分多的属性值,不同的属性值 操作具备差别 和 打包耗费工夫不同。

有的属性值会生成一个 .map 文件,个文件中寄存映射信息,有的间接在生成文件中显示映射信息。

在此就不不具体介绍 devtool,有趣味的敌人能够参考官网自行测试

{
    //    属性能够设置为 false 和字符串
    devtool:false; // 'eval'
}

optimization

<font style=”color:cornflowerblue”>webpack</font> 针对代码优化治理,提供了 optimization 属性进行治理。

就像方才介绍的 optimization.moduleIdsoptimization.chunkIds 提供了对 模块 模块名称 治理。

但其本源还是应用了 <font style=”color:#06f”> 插件 </font> 进行治理,属性只是为了方便管理。

optimization 对象具备好多属性,在此也不具体介绍,

只介绍 optimization.minimizeoptimization.minimizer。这两个也是常常被应用到属性。

minimize 和 minimizer

minimize

先来做一个测试,将 optimization.minimize 手动改为 false

  optimization:{minimize:false}

此时应用 yarn build 执行打包能够看到代码并没有进行压缩

也就是 optimization.minimize 属性是控制代码压缩的。

production 模式只是将 optimization.minimize 设置为了 true

  optimization:{
    // 开启默认优化
    minimize:true
  }
minimizer

optimization 对象中还具备一个 minimizer 属性,这个属性和 plugins 属性性能雷同,都是用来设置 <font style=”color:cornflowerblue”>plugin</font> 的。

而两者的区别在于:optimization.minimizer 会受到 optimization.minimize 属性的治理

optimization.minimizer属性会受到 optimization.minimize 属性的管制:

如果 optimization.minimize 属性值为 false,那么就不加载设置在optimization.minimizer 属性中的 <font style=”color:cornflowerblue”>plugin</font>

也就是 optimization.minimize 是管制 optimization.minimizer 属性的开关。

<font style=”color:#f03d3d”>terser-webpack-plugin</font> 默认状况下是设置在 optimization.minimizer 属性中,所以 optimization.minimize 属性设置为false 代码会不压缩。

如果 <font style=”color:#f03d3d”>terser-webpack-plugin</font> 手动设置在 plugins 属性中,

那么就算 optimization.minimizefalse,代码仍然会压缩。

<font style=”color:#f03d3d”>webpack</font> 曾经依赖了 <font style=”color:#f03d3d”>terser-webpack-plugin</font>,所以就不须要再装置

<font style=”color:cornflowerblue”>webpack@4.X</font> 以下默认应用的压缩裤为 uglifyjs-webpack-plugin,好多文章都是以 uglifyjs-webpack-plugin 为根底解说的,不过 uglifyjs-webpack-plugin 目前不再保护,<font style=”color:cornflowerblue”>webpack@5.X</font> 开始改为了 terser-webpack-plugin

optimization.minimizeoptimization.minimizer 是 <font style=”color:cornflowerblue”>webpack</font> 为方便管理提供的属性。

在配置时能够将对于优化的 <font style=”color:cornflowerblue”>plugin</font> 设置在 optimization.minimizer 属性,由 optimization.minimize 对立治理。

而 <font style=”color:cornflowerblue”>webpack</font> 提供的一系列默认值提供了最小配置。

代价却进步了 <font style=”color:cornflowerblue”>webpack</font> 学习老本。让很多人对这些属性感到蛊惑。

terser-webpack-plugin

<font style=”color:#f03d3d”>terser-webpack-plugin</font> 作为 <font style=”color:cornflowerblue”>webpack@5.X</font> 默认的压缩工具。在此就间接介绍此库的属性

<font style=”color:#f03d3d”>terser-webpack-plugin</font> 压缩对 devtool 属性具备肯定的要求,只反对 nonesource-mapinline-source-maphidden-source-mapnosources-source-map。像eval 生成的是字符串。<font style=”color:#f03d3d”>terser-webpack-plugin</font> 就没方法进行解决

在方才手动设置 <font style=”color:#f03d3d”>terser-webpack-plugin</font> 时没有增加任何参数。

而 <font style=”color:#f03d3d”>terser-webpack-plugin</font> 是有很多配置项的,配置项通过构造函数传递。

<font style=”color:#f03d3d”>terser-webpack-plugin</font> 第一层参数次要对于文件多线程的设置。

const TerserPlugin = require('terser-webpack-plugin');

{
    optimization: {
    // 配置可优化
    minimize: true,
    minimizer: [
      new TerserPlugin({
        //  指定压缩的文件
        include: /\.js(\?.*)?$/i,
          
        // 排除压缩的文件
        // exclude:/\.js(\?.*)?$/i,
          
        //  是否启用多线程运行,默认为 true,开启,默认并发数量为 os.cpus()-1
        //  能够设置为 false(不应用多线程)或者数值(并发数量)parallel: true,

        //  能够设置一个 function,应用其它压缩插件笼罩默认的压缩插件,默认为 undefined,d,minify: undefined,

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

        //  压缩时的选项设置
        terserOptions: {}})
    ]
  }
}
  • include:指定压缩的文件

    属性可设置为:StringString[]Regex

    默认值为:undefined

  • exclude:排除压缩的文件

    属性可设置为:StringString[]Regex

    默认值为:undefined

  • parallel:是否启用多线程运行

    属性可设置为:BooleanNumber

    属性值为false:不启动多线程

    属性值为true:启动多线程,多线程数量为:os.cpus()-1

    属性值为Number:示意应用的多线程数量

    默认值为:true

  • minify:设置其它压缩工具笼罩 <font style=”color:#f03d3d”>terser-webpack-plugin</font>

    此属性能够设置一个函数,函数内容许应用其它压缩工具代替 <font style=”color:#f03d3d”>terser-webpack-plugin</font>,其实相当于做了一个拦挡,基本上不会应用此属性。具体介绍能够参考 官网

    属性可设置为:Function

    默认值为undefined

  • extractComments:是否将代码正文提取到一个独自的文件。

    通过压缩的代码都会去除正文,此属性就是设置是否提取正文,个人感觉这个属性也没什么用。具体介绍能够参考 官网

    属性可设置为:BooleanStringRegExpFunction<(node, comment) -> Boolean | Object>Object

    属性值为 false 或者函数返回false:示意不提取

    属性值为 String 时:all示意全副提取。some示意应用默认正则匹配:/^**!|@preserve|@license|@cc_on/i

    属性值为 true 或者函数返回 true 时:示意提取,应用默认正则匹配:/^**!|@preserve|@license|@cc_on/i

    属性值为 Regex 时:自定义提取规定。

    属性值为 Object 时:容许自定义提取条件。

    默认值为true

  • terserOptions:设置压缩选项

    此属性才是具体设置压缩选项的参数。

    属性可设置为:Object

terserOptions 属性

先来做一个测试,在 index.js 中创立这么一个函数

应用默认压缩配置进行打包编译,后果能够看到生成的代码只有实在执行的代码。

默认 <font style=”color:#f03d3d”>terser-webpack-plugin</font> 配置基本上做到了最优解。

如果将 var a = 1 改为let a = 1,则后果有些不统一,这是因为 ES6 问题,有趣味的诸君能够测试一下

<font style=”color:#f03d3d”>terser-webpack-plugin</font> 配置属性中:terserOptions.compress属性才是管制压缩。

terserOptions.compress 设置类型为 BooleanObject

接下来将此属性设置为false。查看打包编译代码,能够发现,代码并没有被压缩,只是扭转了属性名称和函数函数

{
   optimization: {
    // 配置可优化
    minimize: true,
    minimizer: [
      new TerserPlugin({
        //  压缩时的选项设置
        terserOptions: {compress:false}
      })
    ]
  }
}

terserOptions这一层中的设置次要是对代码中 属性名称 函数名称。等一系列的设置

{
   optimization: {
    // 配置可优化
    minimize: true,
    minimizer: [
      new TerserPlugin({
          //  压缩时的选项设置
          terserOptions: {
              //  是否保留原始函数名称,true 代表保留,false 即保留
              //  此属性对应用 Function.prototype.name
              //  默认为 false
              keep_fnames:false,
              
              // 是否保留原始类名称
              keep_classnames:false,
            
              //  format 和 output 是同一个属性值,,名称不统一,output 不倡议应用了,被放弃
              // 指定压缩格局。例如是否保留 * 正文 *,是否始终为 *if*、*for* 等设置大括号。format: {comments:true},
              output: undefined,
              
              //  是否反对 IE8,默认不反对
              ie8:true,
              
                //  ·压缩配置
              compress: {},}
      })
    ]
  }
}
  • keep_fnames:是否保留原始函数名称

    方才测试看到了,默认状况下会更改函数名称,此属性就是设置是否保留函数名称。

    属性可设置为:Boolean

    属性值为false:示意不保留原始名称

    属性值为true:示意保留原始名称

    默认值为false

  • keep_classnames:是否保留原始类名称

    keep_fnames 属性相似,只不过设置的是类名称

    属性可设置为:Boolean

    属性值为false:示意不保留原始名称

    属性值为true:示意保留原始名称

    默认值为false

  • format/output:指定压缩格局。例如是否保留 正文 ,是否始终为iffor 等设置大括号。

    formatoutput 的配置雷同。output官网不再举荐应用。这个属性就不介绍,具体请参考官网

    属性可设置为:Object

    默认值为null

  • ie8:是否反对 IE8

    属性可设置为:Boolean

    默认值为false

  • compress:设置压缩选项

    属性可设置为:BooleanObject

    属性值为false:示意不压缩。

    属性值为object:自定义压缩设置。

上面介绍下 terserOptions.compress 的配置。terserOptions.compress只介绍局部属性。其它设置,有趣味的敌人能够查看官网

{
   optimization: {
    // 配置可优化
    minimize: true,
    minimizer: [
      new TerserPlugin({
          //  压缩时的选项设置
          terserOptions: {
                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
              }
        }
      })
    ]
  }
}
  • defaluts:是否应用默认配置项

    此属性示意是否应用官网设置默认配置项

    属性可设置为:Boolean

    默认值为true

  • dead_code:是否移除无法访问的代码

    属性可设置为:Boolean

    默认值为true

  • collapse_vars:是否优化只应用一次的变量

    此属性示意是否将只应用一次的变量间接进行替换优化

    属性可设置为:Boolean

    默认值为true

  • drop_console:是否删除所有 console 语句

    此属性能够在公布时设置为true

    属性可设置为:Boolean

    默认值为false

  • drop_debugger:是否删除所有 debugger 语句

    属性可设置为:Boolean

    默认值为true

  • pure_funcs:移除指定的函数。

    此属性能够设置移除指定的函数,然而须要毛病要移除的函数没有任何 <font style=”color:cornflowerblue”> 副作用(没有应用)</font>,有趣味的敌人能够测试删除自定义函数

<font style=”color:#f03d3d”>terser-webpack-plugin</font> 配置项还有好多,然而个别应用默认属性即可,

会被应用到可能也就是:

terserOptions.compress.drop_console去除所有 consoleparallel来设置多线程

其它个别都是默认值即可。

临时先将 optimization.minimize 属性设置false,能够更不便的查看生成代码

loader

在上一篇文章说过:<font style=”color:cornflowerblue”>webpack</font> 是一个 <font style=”color:#06f”>JavaScript 应用程序</font> 的动态模块打包器,其自身并不反对非JS 模块

但 <font style=”color:cornflowerblue”>webpack</font> 提供了将 非 JS 模块 转换为JS 模块 的性能 —<font style=”color:cornflowerblue”>loader </font>

<font style=”color:cornflowerblue”>loader</font> 相当于一个 <font style=”color:cornflowerblue”> 拦截器 </font>,将 <font style=”color:#06f”>指定文件</font> 进行编译为JS 模块,再传递给 <font style=”color:cornflowerblue”>webpack</font>。

在这里先不学习具体的 <font style=”color:cornflowerblue”>loader </font>,只介绍下 <font style=”color:cornflowerblue”>loader </font> 的配置语法。

<font style=”color:cornflowerblue”>loader</font> 的配置是在 module.rules 属性,module.rules是一个 Array 类型属性。

数组每一项都能够设置 拦挡文件应用指定 <font style=”color:cornflowerblue”>loader </font>。

{
  module:{
    rules:[
      {
        // test:/\.css$/,
        // include:path.join(__dirname,'src'),
        // exclude:path.join(__dirname,'node_modules'),
        // //  字符串模式
        // use:'css-loader',
        //  数组模式,能够设置多个 loader
        // use:[
        //   {
        //     loader:'css-loader',
        //     options:{
        //
        //     }
        //   }
        // ]
      }
    ]
  }
}
  • test:设置拦挡文件

    应用此属性设置拦挡的文件。例如:/.css$ 示意拦挡所有的 [.css]() 文件。应用 Regex 能够拦挡多种文件类型应用同一 <font style=”color:cornflowerblue”>loader</font>

    属性可设置为:Regex

  • include:蕴含拦挡的文件目录。

    此属性能够设置拦挡指定目录的文件,个别应用此属性设置只拦挡 /src 目录中文件

    属性可设置为:String

  • exclude:排除拦挡的文件目录。

    此属性与 include 相似,只不过性能相同,指定要排除的目录。个别应用此属性排除 node_modules 目录。

    此属性与 include 只应用一种。

    属性可设置为:String

  • use:拦挡到的文件所应用的 <font style=”color:cornflowerblue”>loader</font>。

    属性可设置为:StringArray

    属性值为String:设置 <font style=”color:cornflowerblue”>loader </font> 名称

    属性值为Array:能够指定多个 <font style=”color:cornflowerblue”>loader </font> 解决,并且能够对每一个 <font style=”color:cornflowerblue”>loader </font> 设置属性配置。

当指定多个 <font style=”color:cornflowerblue”>loader </font> 时,<font style=”color:cornflowerblue”>loader </font> 加载程序为从右往左。具体请参考 Webpack 的 Loader 为什么是从右往左写?

resolve

resolve是 <font style=”color:cornflowerblue”>webpack</font> 提供的一个属性,用来配置打包编译时的模块解析规定。

resolve是一个 Object 类型,具备不少的属性配置。

在此只介绍三个罕用的属性。其它属性,有趣味的敌人能够去参考中武官网

alias

应用 <font style=”color:cornflowerblue”>vue-cli</font> 这类脚手架,开发时引入本地文件模块,通常能够应用一个 <font style=”color:cornflowerblue”> 符号(@)</font> 来代替 /src 工作目录。

这个性能就是 resolve.alias 提供的。

resolve.alias属性能够对一个指定门路设置别名。打包编译时会将设置别名替换为配置的实在门路

{
   resolve: {
    alias:{
      //  设置门路别名
      '@':path.join(__dirname,'src'),
      '~': path.resolve(__dirname, '../src/assets')
    },
  }
}

此时在援用文件模块时,就能够应用 @ 来代替 /src 工作目录(工作根目录)

<font style=”color:cornflowerblue”>webpack</font> 容许设置除关键字外的任意符号作为别名。<font style=”color:cornflowerblue”>vue-cli</font> 这类脚手架个别都预设 <font style=”color:cornflowerblue”> 符号(@)</font> 代替 /src 工作目录。

extensions

应用 <font style=”color:cornflowerblue”>vue-cli</font> 这类脚手架,开发时引入本地文件模块。很常见的一种行为就是不须要增加后缀名称。

这个性能就是 resolve.extensions 提供的。

resolve.extensions性能容许设置多个后缀名称。导入文件模块时能够疏忽文件后缀名称,

打包编译时依照配置缀程序顺次匹配,直到寻到第一个匹配文件或报错(找不到匹配文件)。

resolve.extensions属性类型为 Array,默认值为:[‘.js’, ‘.json’],也就是能够疏忽JS 文件和 JSON 文件后缀

上面将 resolve.extensions 设置为 [‘.json’] 做一个测试

{
   resolve: {extensions:['.json']
  }
}

此时因为援用 index2.js 时还是没有增加后缀,打包编译时就间接报错了。

而援用 index2.js 增加 .js 后缀名称才能够打包胜利。。

<font style=”color:cornflowerblue”>vue-cli</font>、<font style=”color:cornflowerblue”>react-cli</font> 这类脚手架都会在 resolve.extensions 属性配置本人文件类型的后缀名称。

在此以 <font style=”color:cornflowerblue”>react-cli</font> 为例

打包编译时匹配 resolve.extensions,应用的是队列模式。Array 从先到后

mainFiles

应用 <font style=”color:cornflowerblue”>vue-cli</font> 这类脚手架,开发时引入本地文件模块,有一种常见形式只指定其文件所在目录,并没有指定文件名称。

这种形式常见于以 目录为组件单元的代码格调。例如 <font style=”color:cornflowerblue”>antd</font>,就是以目录为组件单元。

这个性能是由 resolve.mainFiles 属性提供的。

resolve.mainFiles容许设置多个文件名称,导入文件模块时能够疏忽此文件名称。

打包编译时依照配置缀程序顺次匹配,直到寻到第一个匹配文件或报错(找不到匹配文件)。

resolve.extensions属性类型为 Array,默认值为:[‘index’],也就是能够疏忽index 名称的文件。

应用 resolve.mainFiles 时须要设置resolve.extensions,目录是没有后缀的,须要设置疏忽后缀,否则会报错:

上面将 resolve.mainFiles 设置为 [‘index’,’main’] 做测试

{
   resolve: {extensions:['.js','.json'],
    mainFiles:['index','main'],
  }
}

能够看到,能够看到导入 /demo/main.js 时,疏忽了文件名称,然而仍然打包编译、导入胜利

打包编译时匹配 resolve.mainFiles,应用的也是队列模式。Array 从先到后

集体倡议应用目录构造形式组织组件

context

配置 <font style=”color:cornflowerblue”>webpack</font> 时,应用文件目录时都应用了相对地址:path.join(__dirname, …)

<font style=”color:cornflowerblue”>webpack</font> 其实提供了一个 context 属性:在配置项中容许 以此目录为基准 设置 绝对目录。

不过 context 属性个人感觉并不太好用。

context属性 String 类型,设置一个绝对路径的目录地址

context默认值为以后我的项目根目录,也就是 package.json 文件所在目录

context属性默认值为以后我的项目根目录,所以能够间接应用相对路径

{entry: './src/index.js' ,}

此时执行 yarn build 打包也能够进行打包胜利。

也能够应用 context 指定其它目录为基准目录

{context: path.join(__dirname, './src'),
  //  入口文件
  //  字符串模式
  entry: './index.js' ,
}

context 属性具备肯定的缺点

output 不容许相对路径

并不是所有的属性都能够设置为相对路径

例如 output 属性就只容许应用绝对路径。

配置属性中既有相对路径又有绝对路径,对于我这个强迫症来说感觉怪怪的。

output属性只容许应用绝对路径应该是为了保障输入地址的精确安全性。

基准绝对路径

集体比拟喜爱的计划就是自定义一个 root 目录。

在配置文件中 root目录 去设置门路

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

const {entry: path.join(config.root, 'src/index.js'),
  output: {path: path.join(config.root, 'dist'),
    filename: '[name]_[contenthash].js'
  },
}

至于自定义 root 属性而不间接应用 __dirname 起因是:

个人感觉自定义属性不便管制。例如更换配置文件目录,间接应用 __dirname,所有目录地址都须要更改,而自定义绝对路径基准就只须要更改 root 目录即可

当然实在开发不会呈现此类情况。

应用 context 属性还是绝对路径都无伤大雅,集体习惯罢了,只有文件门路正确即可

总结

  • <font style=”color:cornflowerblue”>webpack</font> 提供了两种 <font style=”color:cornflowerblue”> 打包模式 </font>:* 开发测试打包编译 (development)* 线上公布打包编译 (production)。两种打包模式可能更加方便管理 <font style=”color:cornflowerblue”> 插件 </font>
  • <font style=”color:cornflowerblue”>webpack</font> 对 developmentproduction 都预设了一些根底性能,大大减少了开发时的配置
  • <font style=”color:cornflowerblue”>source-map</font> 是 <font style=”color:cornflowerblue”>Google</font> 提供的打包编译后代码与开发代码的一种映射文件,主要用途是不便开发人员调试
  • optimization属性是 <font style=”color:cornflowerblue”>webpack</font> 提供的管制优化的属性,optimization只是一系列优化性能的汇合,次要是为了方便管理,实质还是由 <font style=”color:cornflowerblue”> 插件 </font> 实现性能
  • resolve属性提供了打包编译时的解析规定,

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

本文参考

  • webpack 官网
  • webpack5-mode
  • webpack4-mode
  • webpack4 的新个性:mode 详解
  • uglifyjs-webpack-plugin
  • terser-webpack-plugin
  • terser Github
  • terser-webpack-plugin Github
  • Webpack 的 Loader 为什么是从右往左写?

webpack.config.js

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:[
  //     {
  //       test:/\.css$/,
  //       include: ath.join(config.root,'src'),
  //       exclude: path.join(config.root,'node_modules'),
  //       ////  字符串模式
  //       // use:'css-loader',
  //       //  数组模式,能够设置多个 loader
  //       // use:[
  //       //   {
  //       //     loader:'css-loader',
  //       //     options:{
  //       //
  //       //     }
  //       //   }
  //       // ]
  //     }
  //   ]
  // }


  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

正文完
 0