webpack中所用到的库与知识点(针对Vue框架)

常用配置项:

基础:

​ mode:默认'development','production',针对不同的模式,webpack打包时会采用不同的插件与打包行为,我们也能根据不同打包模式来自定义采用哪些plugins或loader。

​ context: 各配置项路径的上下文,context的默认值是 CWD。推荐将context修改为项目的根目录,这样可以使得项目配置独立于 CWD

​ output:

​ filename: 打包后的chunk的文件名字形式,一般涉及代码分割,多插件,多入口,多bundle时基本都要[name],一般为[name].bundle.js或[name].js

​ publicPath: 请求资源时的路径

​ resolve:

​ extensions(Array):对一些拓展类型的处理,可以在引用时无需加后缀

​ alias(Object):针对路径的别名

开发模式:

​ devtool: sourceMap方式

​ devServer:

​ hot: 热更新

​ proxy: 代理

​ open:打包后自动打开页面

​ quiet: true, // necessary for FriendlyErrorsPlugin

生产模式:

​ optimization.splitChunks:用于chunk打包分块配置,针对不同文件夹下的模块进行生成不同块。

常用库:

webpack-dev-server

​ 开发必备,内置在webpack中,通过devServer配置来调整

​ --inline:启用inline mode,构建消息将会在浏览器控制台显示,socket.io的client代码被打包进去,以此来同webpack-dev-server进行websocket通讯从而实现自动编译打包,页面自动刷新功能(默认为inline)

​ --iframe:与inline mode相对应,构建消息显示在页面中的一个iframe元素中

​ --quiet:不显示打包信息

​ --compress:开启gzip压缩

​ --progress:显示打包的进度

webpack-merge 用户合并打包配置,在遇到打包情况较多时候,善用配置合并会有很好的效果

rimraf 可用于删除之前的打包文件

ora 可用于在打包过程中在终端显示spin圈圈表示正在打包,同时还能设置字体颜色

chalk 可以对终端打印的文字进行样式修改,如修改颜色等

portfinder 端口设置 可用于自动设置端口且不会重复,vue-cli在开发模式下构建时使用的就是该库

​ 详见:https://zhuanlan.zhihu.com/p/...

modules

​ base:

eslint-loader (不久会被废弃,迁移到EslintWebpackPlugin上)

babel-loader:

​ 优化相关:use:‘babel-loader?cacheDirectory=true’即可开启缓存

​ 配置:

​ ”stage-2“: 支持到stage-2的语法标准

​ env:

​ modules:false为不讲esmodule转为commonjs,默认为true,如果为true会造成webpack的tree-shaking失效

{
  "presets": [
    ["env", {
      "modules": false,
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    "stage-2"
  ],
  "plugins": ["transform-vue-jsx", "transform-runtime"],
  "env": {
    "development":{
      "plugins": ["dynamic-import-node"]
    }
  }
}

url-loader 将大小低于某一范围的各种媒体文件转为dataURL来避免过多的http请求

​ 注:v5 后弃用,请考虑使用 asset modules 代替。

svg-sprite-loader 用于处理icon图标,生成雪碧图,一方面可以减少http请求,另一方面能够使用<svg><use>的方式简单引入icon

vue-loader(注意,使用该loader需要加上对应的vue-loader-plugin)

json5-loader(将json转为js object对象)

style相关:

​ (style-,MiniCssExtractPlugin.loader,vue-style-),css-,postcss-,less-,sass-,stylus-(注意顺序,从右往左,加粗部分随意)

​ 注:style-loader,MiniCssExtractPlugin.loader,vue-style-loader三者的区别

​ 1 MiniCssExtractPlugin.loader多用于生产模式中获取单独的css文件,而style-loader则多用于开发模式因为它将多个css注入到dom中且更快,vue-style-loader则是基于style-loader并支持vue的ssr

​ 2 MiniCssExtractPlugin.loader与style-loader冲突

​ 3 当存在htmlWebpackPlungin时可以不考虑style-loader插件,它会将MiniCssExtractPlugin.loader抽离的文件通过script节点注入html中,建议使用插件

​ 可选:

cache-loader(vue重要) 在一些性能开销较大的 loader 之前添加 cache-loader,以便将结果缓存到磁盘里,效果还是挺不错的。

​ 1 关于babel-loader优化:

​ babel自身也可以通过缓存优化,所以在效果差不多的情况下,使用自身的就好

​ 2 关于vue-loader的优化:

​ vue-loader官方有提过关于cache-loader的使用,但未提起具体使用详情。具体如下:

      {
        test: /\.vue$/,
        loader: 'vue-loader',
        exclude: /node_modules/,
        include: resolve('src'),
        options: {
          cacheDirectory: resolve('./cache-loader'), // 缓存
          cacheIdentifier: 'cache-loader:{version} {process.env.NODE_ENV}'
        }
      },
      {
        test: /\.js$/,
        use: [
          {
            loader: 'cache-loader',
            options: {
              cacheDirectory: resolve('cache-loader'), // 缓存
            }
          }
        ],
        exclude: /node_modules/,
        include: resolve('src')
      }

thread-loader(可尝试) 对于项目庞大,文件较多的可使用该loader进行多进程打包

exports-loader 可以导出一切可以访问的变量,主要还是用于处理之前旧的无法通过模块化引入的库api。

plugins

DefinePlugin

​ 允许定义全局常量

HotModuleReplacementPlugin(HRM)

​ 1 当你更新代码后,webpack会监听到并自动刷新浏览器。但是这样你刚才的一些操作记录都会丢失,为了不丢失原来的操作,只是改变页面显示,使用HMR

​ 2 永远不要在生产模式下启用HRM

​ 3 开发模式下可直接通过hot控制热模块开关

Friendly-errors-webpack-plugin

​ 识别某些类别的webpack错误,并清理,聚合和优先级,以提供更好的开发人员体验

HtmlWebpackPlugin

​ 在打包过程中将生成的bundle以script标签引入到指定html文件中,包括css抽离插件抽离出的css文件

​ 详见:https://github.com/jantimon/h...

SplitChunksPlugin(webpack自带):十分重要,等价于optimization.splitChunks)

​ 从v4开始,移除了CommonsChunkPlugin取而代之的是SplitChunksPlugin

​ 1 核心属性cacheGroup,其他属性都是围绕着该属性配置的group来生效的。通过group拆分合并。

​ 合理划分公共模块

​ 进行如下划分:

​ 库和工具 - libs

​ 定制ui库与工具 - vender

​ 低频库/工具/代码 - chunk

​ 业务模块 - entries

​ 2 但是注意cacheGroup会与MinChunkSizePlugin插件冲突,如果二者都进行配置,会以MinChunkSizePlugin为优先。

HashedModuleIdsPlugin与NamedChunkPlugin:(重要)

module与chunk

​ module是指将代码按照功能拆分,分解成离散功能块。拆分后的代码块就叫做 module。可以简单的理解为一个 export/import 就是一个 module。

​ chunk是指代码中引用的文件(如:js、css、图片等)会根据配置合并为一个或多个包,我们称一个包为 chunk。

HashedModuleIdsPlugin

​ 我们每次在打包完之后,有时候会发现,即便内容没有变更,但是打包完文件对应hash仍然改变了。

​ 这是因为webpack 内部维护了一个自增的 id,每个 module 都有一个 id。所以当增加或者删除 module 的时候,id 就会变化,导致其它文件虽然没有变化,但由于 id 被强占,只能自增或者自减,导致整个 id 的顺序都错乱了。

​ 所以即便有些包对应的代码未改变,但是分配的id发生了变化,所以最后生成的包的内容中也发生了变化,造成了chunkhash的改变。

​ HashedModuleIdsPlugin它的原理是基于文件的相对路径生成moduleId,默认为4位。当然也可以自自设定长度等一些配置。这样就避免了上面的情况。

​ 注: NamedModulesPlugin 和 HashedModuleIdsPlugin 原理是相同的,将文件路径作为 id,只不过没有把路径 hash 而已,适用于开发环境方便调试。不建议在生产环境配置,因为这样不仅会增加文件的大小(路径一般偶读比较长),更重要的是会暴露你的文件路径。

NamedChunkPlugin

​ 同理,chunk id也需要单独处理,需要加上对应的插件,但是该插件比较坑的是对于懒加载无效,所幸该插件能够传入一个函数

new webpack.NamedChunksPlugin(chunk => {
      if (chunk.name) {
        return chunk.name
      }
      const modules = Array.from(chunk.modulesIterable)
      if (modules.length > 1) {
        const hash = require('hash-sum')
        const joinedHash = hash(modules.map(m => m.id).join('_'))
        let len = nameLength
        while (seen.has(joinedHash.substr(0, len))) len++
        seen.add(joinedHash.substr(0, len))
        return `chunk-${joinedHash.substr(0, len)}`
      } else {
        return modules[0].id
      }
    })

​ v5版本的处理:

​ v5版本自然不会对这个问题不闻不问,早在2015年这个问题就开始存在并一直讨论持续了很久的时间,v5版本将上面的配置都简化为了如下情况:

​ 默认情况下为这样:

​ v5的module与chunk命名:

​ 在开发模式下,默认启用的新命名代码块 ID 算法为模块提供了可读的名称。 模块 ID 由其路径决定,相对于 context。 代码块 ID 由代码块的内容决定。

​ 所以你不再需要使用import(/* webpackChunkName: "name" */ "module")来调试。 但如果你想控制生产环境的文件名,还是有意义的。

​ 可以在生产环境中使用 chunkIds: "named" 在生产环境中使用,但要确保不要不小心暴露模块名的敏感信息。

TerserWebpackPlugin:(v5用7以下的版本)(v4用5以下的版本^4.2.3)

​ 该插件使用terser来压缩js,推荐使用terser而不是uglify插件,主要是由于uglify对于es6以上支持成都不够且对于存在的较多bug不在维护,所以不宜再使用

MiniCssExtractPlugin

​ 用于将css单独抽离成文件,需要配合MiniCssExtractPlugin.loader使用

​ 注:关于MiniCssExtractPluginextract-text-webpack-plugin,二者都是将css抽离成文件,官方已经说明extract-text-webpack-plugin插件不支持v4版本的webpack,所以v4需要抽离css请使用MiniCssExtractPlugin

compressionwebpackplugin:(v4用7以下的版本)

​ 目前相对于gzip压缩有更好的Zopfli压缩,同样兼容gzip格式,但是损耗更低,速度更快。还有一个叫brotil压缩,但是目前该模式在服务端的支持不容易实现,且对于node版本要求在11以上

​ 注:开启压缩会对打包时间有影响

CssMinimizerWebpackPlugin(v4用2以下的版本)

​ 1 这个插件使用 cssnano 优化和压缩 CSS

​ 2 就像 optimize-css-assets-webpack-plugin 一样,但在 source maps 和 assets 中使用查询字符串会更加准确,支持缓存和并发模式下运行

EslintWebpackPlugin

​ 从eslint-loader迁移而来,且eslint-loader不久将会被废弃。

​ 相对于eslint-loader,该插件:

​ 1更易于配置

​ 2生成独特的输出报告

​ 3直接从eslint使用缓存

​ 4只对修改过的文件进行lint检查

ImageMinimizerWebpackPlugin(可尝试)

​ 图片压缩插件

PrefetchPlugin

​ 预加载普通的模块请求(module request),可以让这些模块在他们被 import 或者是 require 之前就解析并且编译

speed-measure-webpack-plugin:(可选)

​ 模块打包时间分析,使用该插件会在打包后显示各包所花费时间

BundleAnalyzerPlugin:(可选)

​ 模块打包大小分析,使用该插件在打包完后会弹出一个页面分析各bundle各模块的空间占比

EvalSourceMapDevToolPlugin/sourceMapDevToolPlugin:(可选)

​ 1 对sourceMap源码映射提供更细粒度的控制

​ 2 你可以直接使用 SourceMapDevToolPlugin/EvalSourceMapDevToolPlugin 来替代使用 devtool 选项,因为它有更多的选项。

I18nWebpackPlugin:(可选)

​ 该插件会在 bundle 的生成过程中进行文案翻译,因此你可以直接将翻译后的 bundle 交付给用户。

LimitChunkCountPlugin(可选,可尝试)

​ 限制包文件最大数量,且现在不再支持最小打包文件限制功能,需要的话使用MinChunkSizePlugin

MinChunkSizePlugin(可选,可尝试)

​ 使每个打包的文件至少都在某一大小之上(建议50kb以上:50000),但是使用该插件会与splitChunk冲突造成splitChunk文件失效

NormalModuleReplacementPlugin(可选)

​ 允许匹配的文件在构建中被替换,可根据不同行为进行不同替换

NpmInstallWebpackPlugin(可选)

​ 自动安装使用者无需关心的npm包,且能够通过require与import在工作时自动安装那些缺失的包,推荐开发模式

StylelintWebpackPlugin(可选,可尝试)

​ webpack官方提供的Stylelint 插件

ProgressPlugin (观察,可尝试):

​ 暴露webpack打包构建进度插件

ProvidePlugin(可选)

​ 自动加载配置的模块而无须通过import或者require引入便可在全局使用该模块,该插件还支持对模块的部分api进行导出,这样能很好的利用tree shaking。

<img src="/Users/liuliuziyang/Desktop/WeChat6ca5fa5fb2dae0e52feefdcc618145b4.png" alt="WeChat6ca5fa5fb2dae0e52feefdcc618145b4" style="zoom:50%;" />

dllPlugin

​ 提起该插件目的是为了引出后续的两个插件,dll插件原理就是缓存,空间换时间。但是该插件配置繁琐,所以推荐AutoDllPlugin,不过实际上webpack4的性能已经足够好了,像是vue以及react都已经移除了dll插件,所以用不用还是看个人。

​ 第二个要提及的插件是 hard-source-webpack-plugin,该插件比dll更具性能优势且易于配置,但是只能由webpack5支持。

03-05 16:32