项目中常用的webpack插件

本文原创:linqiumei、huoyinghui
不同项目,使用webpack版本不同,对应的插件也不同。
如何查看项目中webpack的版本? 1.在package.json中的script脚本命令中,添加"webpack": "webpack --version",终端运行npm run webpack
2.项目目录的终端运行./node_modules/.bin/webpack –v
3.项目目录的终端运行npx webpack -v

npx会自动查找当前依赖包中的可执行文件,找不到会在PATH中寻找,找不到,就会自动安装。npm5.2起支持npx
webpack -v查询的是全局环境中的webpack版本
项目中webpack配置文件结构 项目中常用的webpack插件
文章图片
1.webpack_config_node.png webpack的重要属性 entry: 定义入口文件
output: 定义输出文件
module: 设置项目中不同类型模块的处理方式
resolve: 设置模块解析方式
plugins: 使用插件自定义webpack构建过程
webpack.base.js 项目中常用的webpack插件
文章图片
2.base_entry_oputput.png entry: 定义了webpack打包的入口文件
output:
-- path: 定义输出文件存储位置
-- publicPath: 用于配置异步加载/按需加载等线上资源的url前缀,默认为空字符串,为相对路径;const publicPath = path.join('/account/')
-- filename: 定义打包资源输出到path指定目录位置的文件名
? 其中,[name]指代entry中键值对的键值,[hash]为打包时会生成唯一的标志符,指代打包过程,同一打包过程的文件hash是一样的
-- chunkFilename: chunk是webpack进行模块依赖分析时,代码分割出来的代码块。用于配置没有入口起点的代码块输出的文件名
-- globalObject: 因为默认传入的参数是window,但是umd书写规范中,传入的参数应该是this
项目中常用的webpack插件
文章图片
3.base_module.png module:
-- loader在module.rules中配置,如使用vue-loader加载vue文件,使用css-loader加载.css文件。
项目中常用的webpack插件
文章图片
4.base_resolve.png resolve:
-- extensions: 如果有多个文件有相同的名字,但是后缀名不同,webpack会按数组顺序解析列在首位的文件,并跳过其他后缀
-- alias: 别名,简化模块引入的代码
-- symlinks: 是否将符号链接解析为真实路径,默认为true
项目中常用的webpack插件
文章图片
5.base_plugins.png plugins
-- vueLoaderPlugin: 必须插件,将定义的其他规则应用到.vue文件中相应语言块。
-- HtmlWebpackPlugin: 简化了HTML文件的创建
当使用webpack打包时,HtmlWebpackPlugin创建一个html文件,并把webpack打包后的静态文件自动插入到html文件中。默认会在output.path目录下创建一个index.html文件,并在文件中插入一个script标签,src为output.filename。css资源会包含在html头部的link标记中。

项目中常用的webpack插件
文章图片
6.base_htmlWebpackPlugin1.png -- DllReferencePlugin: 配合DllPlugin使用,webpack.dll.js中生成manifest.json文件,DllReferencePlugin打包时,不会打包manifest.json中的文件,而是使用相应的全局函数处理,用于提高构建速度。如第三方库vue、vue-loader等打包
-- DefinePlugin: 可以在编译时定义全局变量,打包的时候对这些变量进行替换
项目中常用的webpack插件
文章图片
7.base_DefinPlugin.png webpack.dll.js 将第三方库依赖打包到一个单独的dll文件目录下,并生成manifest.json文件
项目中常用的webpack插件
文章图片
8.dll.png optimization
-- minimize: 是否压缩
plugins
-- ProvidePlugin: 每当vue作为自由变量时,模块会自动用已加载vue的内容填充模块
-- CleanWebpackPlugin: 用于npm run dll时,清除之前打包的文件
-- AssetsPlugin: 生成一个记录版本号的文件
-- DllPlugin: 将第三方库代码分离,每次文件更改的时候,只打包项目自身的代码。将vue、vue-router第三方库单独打包
webpack.dev.js 项目中常用的webpack插件
文章图片
9.dev.png plugins:
-- HotModuleReplacementPlugin: 热加载模块,不能用于生产环境,因为watch状态消耗性能,生产环境中,代码稳定,更新几率小
webpack.prod.js 项目中常用的webpack插件
文章图片
10.prod.png devtool:
控制是否生成以及如何生成source map,有助于定位代码错误位置
performance:
展示性能提示,当加载影响性能的资源时,可以输出一个警告提醒。warning、error、 false
optimization:
-- minimizer: 用于压缩js文件,不支持es6语法
-- uglifyjs-webpack-plugin: 用于压缩js文件,不支持es6语法,可用terser-webpack-plugin替代
-- OptimizeCssAssetsPlugin: 用于优化css文件的输出,摈弃重复样式,去除样式规则中的多余参数,移除不必要的浏览器前缀等。autoprefixer是否去除浏览器前缀
plugins:
-- MiniCssExtractPlugin: 将css提取到单独的文件中,并支持按需加载
-- DefinePlugin: 定义全局变量
-- hashedModuleIdsPlugin: 根据模块的相对路径,生成四位数的hash作为模块id,用于生产环境。
-- CleanWebpackPlugin: 清除打包内容:verbose: 是否将日志输出到控制台,默认为false;dry: 默认为false,为true的时候,模拟删除,不会真的删除文件;exclude: 忽略不用删除的文件
-- CopyWebpackPlugin: 将单个文件或整个目录复制到构建目录中
webpack5
首先可以看一下当前webpack5的开发进度
项目中常用的webpack插件
文章图片
picture1.png 相较于webpack4,webpack5有了很大的变化,先简单列举一下新旧版本的几个不同点:
  1. webpack5清除webpack4标记即将过期的功能
  2. 通过持久缓存提高构建性能cache
  3. 确定性chunkId和moduleId,优化长期缓存
  4. 更好的Tree Shaking
  5. 支持生成es6/es2015的代码
  6. SplitChunk配置优化
清除webpack4标记即将过期的功能点就先掠过,其余几点下面我们一一介绍。
通过持久缓存提高构建性能 首先说明cache在构建中的作用,cache在首次打包构建项目时,会将编译结构缓存起来,二次构建时,会根据缓存判断当前哪些已经构建过并且没有改动,这些文件就不会被重新编译,从而减少项目构建时间。
在webpack4中,cache是这样设置的:
cache: true // 或false

通过cache-loader将编译结构写入硬盘缓存或者采用babel-loader并配置option.cacheDirectory将编译结果写入磁盘
而在webpack5中对cache做了升级,缓存默认是开启状态,缓存的文件存于内存中,我们也可以配置缓存的类型及存储的位置:
cache: { type: 'filesystem’, cacheDirectory: path, cacheLocation: path + name, buildDependencies: { config: [__filename], }, }

以上几个属性的含义可以简单理解为:
type: 缓存类型,值为 'memory'或‘filesystem’,分别代表基于内存的临时缓存,以及基于文件系统的持久化缓存。
cacheDirectory: 缓存目录,默认目录为 node_modules/.cache/webpack,也可以自定义设置
name: 缓存名称,同时也是 cacheDirectory 中的子目录命名,默认值为 Webpack配置中 的{config.mode}
cacheLocation: 缓存真正的存放地址, path.resolve(cache.cacheDirectory, cache.name), 该属性在赋值情况下将忽略 cacheDirectory 和 name 属性
优化长期缓存 我们都知道,webpack基本配置会有入口文件,类似的设置如下:
entry:{ app: './index.js'// 入口 }, output:{ filename:'./bundle.js'// 出口 }

但是有很多文件是不会配置entry的,这些未从entry打包的chunk文件,都会以0,1,2,3…加chunkhash的文件命名方式输出。这样就引发了一些问题,举个例子:
假设我们打包了page0.js、page1.js、page2.js,打包后的文件名暂时称为1.js、2.js、3.js,这样使用是不会有任何问题的,但现在如果我们删除或者暂时不使用1.js后,原来的2.js会变为1.js,3.js会变为2.js,此时再引用2.js就不对了,这就是出现了缓存失效问题。
出现的这种问题,目前有解决方案,就是使用import(/* webpackChunkName: “home” */ ‘./home’)这种魔术式注释来给打包文件命名,虽然命名问题解决了,可是打开文件内容会发现,chunkId仍然发生了变化。
page1.js第一次打包时的chuankId:
项目中常用的webpack插件
文章图片
14.page_chunkId_1.png page1.js第二次打包后的chunkId:
项目中常用的webpack插件
文章图片
15.page_chunkId_2.png 那么webpack5是怎么解决的呢 在webpack5中,有确定的 chunkId、moduleId 以及导出名称,生产模式下,默认是启用chunkIds、 moduleIds的,具体是以确定性的方式为模块和分块分配短的(3 或 5 位)数字 ID,使得生成的缓存失效频率降低,配置可以这样写:
optimization: { chunkIds: "deterministic", // 顾名思义,deterministic为确定性的 moduleIds: "deterministic" }

当然,chunkIds和moduleIds还有其他的配置选项
moduleId:
optimization 选项值
false 告诉webpack不应使用任何内置算法, 通过插件提供自定义算法
natural 按使用顺序的数字ID,沿用v4数值命名
named 方便调试的高可读性id,文件命名
deterministic 根据模块路径生成简短的hash值
size 根据模块大小生成的数字id,沿用v4
chunkId:
optimization 选项值
false 告诉webpack不应使用任何内置算法, 通过插件提供自定义算法
natural 按使用顺序的数字ID,沿用v4数值命名
named 方便调试的高可读性id,文件命名
deterministic 根据代码块内容决定,注意与moduleId的此选项区分
totalSize 根据请求到的解析资源size计算的id
减小Bundle体积
  1. 分析导入导出模块之间的依赖关系
webpack可以通过优化配置选项中的innerGraph启用模块依赖,具体如下:
optimization: { innerGraph: true }

依赖图的好处是可以理清各个模块之间从export到import是怎样的引用关系,webpack对模块中的符号进行分析以找出从export到import的依赖关系,举个:(内部依赖图可以记录到当前文件引用了something模块)
import {something} from './something' function usingSomething() { return something; } export function test() { return usingSomething(); }

  1. 嵌套tree-shaking
Tree-shaking,翻译过来就是树摇,一个文件就是一棵树,会有主干和分支,也会有叶子,如果树被晃动,就会有叶子落下。tree-shaking就是将文件中不需要的代码删除掉,用来减小文件的体积,在webpack5中,不仅可以做到摇无用代码,还可以嵌套查询是否有无用代码从而进行删除。
首先做这样的配置:
optimization: { sideEffects: false, usedExports: true }

// inner.js export const a = 1; export const b = 2; // module.js import * as inner from './inner' export {inner}// user.js import * as module from './module'; console.log(module.inner.a);

通过内部模块依赖图,检测到inner.js中的常量 b 没有被使用,就会将其删除掉,是不是很腻害:happy:
注意!tree-shaking虽然在减小文件体积方面做的很到位,但使用需谨慎,要保证被删除的代码没有副作用才行,因为只要是没有使用到的文件,都会被摇掉,那如果有些文件不使用也不想被优化呢,比如需要写一个组件,但在库里没有使用它,这就有可能在打包时被优化掉了。
SplitChunk配置优化 splitChunk是webpack优化配置中的一个配置项,可以将Node Modules中代码单独打包成一个chunk最终输出,配置成功的话,可以自动分析多入口chunk中,有没有公共的文件,如果有,就会打包成一个单独的chunk。
先在index文件里引入jquery库,简单写两行代码:
import $ from 'jquery'function sum(...args) { return args.reduce((a, b) => a + b, 0) } console.log(sum(1,2,3,4))

看一下不配置splitChunk的打包情况:
项目中常用的webpack插件
文章图片
17.splitchunk_2.png 项目中常用的webpack插件
文章图片
18.splitchunk_3.png 看第一张图,index.js中只写了几行代码,但体积却有852KiB,从第二张图可以得到答案,就是webpack将jquery和index中的代码打包到了一个文件里。
接下来配置一下splitchunk:
optimization: { splitChunks: { chunks: 'all', minSize: {// webpack5之前只可以设置 minSize: size javaScript: 2000, style: 10000 } } }

splitchunk不是webpack5才有的属性,但minSize的细化配置是webpack5升级的,可以在其中配置单独打包文件满足的条件,比如javaScript: 2000,如果文件体积小于2000,是不会单独抽离出来打包的。
再来看下同样代码的打包情况:
项目中常用的webpack插件
文章图片
20.splitchunk_5.png 可以看到,第三方组件库被单独打包了,虽然一个文件引用了jquery库,表现的作用不明显,但如果多个文件都引用了这个库,作用就很明显了,一个是每个文件中都会打包jquery,一个是jquery只打包一份。
webpack使用遇到的问题
1.本地绑定localhost.jd.com域名,然后通过绑定域名访问项目,但是页面会报Invalid Host header,如下图所示
项目中常用的webpack插件
文章图片
21.problem_one.png 问题原因:新版的webpack-dev-server增加了安全验证,默认检查hostname,如果hostname不是配置内的,将中断访问。
解决方法:在webapck配置中找到devServer配置项,添加{disableHostCheck: true},然后重启项目即可,如图
项目中常用的webpack插件
文章图片
solutionOne.png 2.debug模式启动项目报找不到localhost
问题原因: 本地代理时,没有指定本地host
解决方案:在host配置中添加上本地回环地址127.0.0.1 localhost的映射,例如: 127.0.0.1 localhost.test.com
3.设置div超出两行显示省略号,但因为css样式中有浏览器前缀,线上打包会将前缀去掉导致样式失效。
问题原因:webpack.prod.js文件配置压缩时,引入了OptimizeCSSAssetsPlugin插件,这个插件默认会将浏览器前缀去掉
解决方案:为该插件设置参数autoprefixer为false
【项目中常用的webpack插件】欢迎计算机前端相关领域小伙伴加入我们,具体的招聘信息可进入公众号查看,欢迎关注。
项目中常用的webpack插件
文章图片
关注我们吧.jpg

    推荐阅读