Webpack相关知识点
webpack的优点
webpack从配置的入口出发,可以打包所有前端资源,同时可以配置多种loader来处理不同类型文件的转换,并且可以配置plugin来扩展模块打包流程,满足更多构建中特殊的需求,开发过程中还可以使用HMR提升本地开发效率和体验,生产环境中可以利用代码压缩和代码分割来提升前端加载性能,总之就是既可以提升开发效率,又可以提升应用性能。
webpack中loader和plugin的区别
webpack中loader主要用于处理非JavaScript模块的转换,在固定的阶段中使用,本身只是一个函数,返回转换后的结果,因为webpack只能处理js;而plugin是用于处理特殊的构建需求,比如将css代码单独输出为一个文件、定义环境中的变量等,利用了webpack的hooks介入构建过程中不同的阶段,可以定制项目的构建流程。
开始编译,读取webpack配置,创建NormalModuleFactory,创建NormalModule(使用resolveLoader解析loader路径),开始编译模块(loader-runner)
如何利用webpack提升应用性能
webpack优化性能大概有三种方式:
代码压缩、代码分割、去除无用代码,主要的方向是减少请求体积,代码分割有的情况下还可以利用浏览器缓存,减少请求次数
- 代码压缩(主要就减少请求体积)
我们可以对optimization下的minimize和minimizer配置项进行设置,配置TerserPlugin对js代码进行压缩处理,还可以使用插件如HTMLWebpackPlugin对html文件进行压缩。 - 代码分割(既减少一次的请求体积,使请求返回更快,有的情况还可以利用浏览器缓存,减少请求次数)
我了解的大概几种方式,第一种是设置optimization下的splitChunks配置项、第二种css代码利用MiniCssExtractPlugin插件单独生成文件、第三是利用webpack的dllPlugin插件将第三方库打包成独立的文件。
splitChunks可以将模块抽离为单独的文件,chunks可以设置为all/async/inital三个值的其中一个,all就是所有的模块都打包到一个chunk,async是把异步加载的模块打包到chunk中,如通过动态import加载的模块,initial是把同步加载的模块打包到chunk中。可以配合按需加载使用,按需加载使用ES动态加载语法import来加载模块,webpack会自动处理使用这种语法编写的模块,把模块单独分离成文件,可以减少大型应用初始化时需要加载的前端资源,提升用户体验。
css代码利用plugin插件生成单独的文件,可以在后续请求中,利用浏览器缓存,如果是多页面应用,优点更明显,不用多次加载css。
dllPlugin也是将部分模块抽离成单独的文件,但是它和splitChunks不同,在代码不变的情况下不用重复打包,可以单独写一个配置文件,运行打包,在后续项目的构建流程直接使用DLLReferencePlugin引用文件就可以,通常可以用来处理不太变动的第三方库,可以看出来这样不仅可以利用浏览器缓存,还能提高开发效率。 - 去除无用代码(减少请求体积)
可以利用tree-shaking、还有sideEffects,将未使用的代码移除。
要利用到tree-shaking就要使用分别导入、而不是整体导入,未引入和未使用的模块方法就不会被打包,sideEffects对没有副作用的模块也可以将模块中未使用到的代码不进行打包。
还有webpack的IgnorePlugin插件,可以在打包中忽略掉某些依赖包中体积大但又不太需要的文件,如react脚手架生成的项目中就默认将moment的locale文件夹整个忽略掉,这个语言包会非常大,但是通常实际中不需要这些多语言的配置,单独引入需要的语言就可以。
webpack的热更新原理
热更新HMR就是不用刷新页面而将新变更的模块替换掉旧的模块,避免了频繁手动刷新页面、应用状态丢失,也减少了页面刷新时的等待。它的核心是客户端去服务端拉取更新后的文件。在DevServer开启hot后,webpack会往应用代码中添加websocket相关的代码,用于和服务器保持连接,等待更新动作,本地代码变更时通知浏览器做相应的处理;webpack还会往应用代码中添加HMR运行时的代码,用于定义应用更新时的API。当有更新时,webpack-dev-server发送更新信号给HMR运行时,然后HMR再请求所需要的更新数据,服务端返回一个json包含所有要更新的模块的hash值,对应模块再次请求获取到最新的模块代码,没有问题的话就进行应用更新。
应用更新的API常见的有module.hot.accept、module.hot.decline、module.hot.dispose等,accept是在应用特定代码模块更新时执行相应的callback;decline是对于指定的代码模块,拒绝进行更新;dispose用于添加一个处理函数,在模块代码被替换时运行(可用于移除之前添加的持久化资源或者相关状态)。
如何优化webpack的构建速度
总的来说方向就是减少webpack的工作量。
- 首先在开发环境下使用配置mode为develpment,webpack本身就默认不配置一些压缩优化的插件,这样可以减少在优化操作上的时间消耗;
- 其次提前处理一些文件资源,如使用imagemin或者其他工具提前压缩好图片,可以减少在图片处理上的耗时,一些不频繁更新的第三方库使用dllPlugin打包,在项目中直接引用,不打包到应用代码中,也可以大大减少构建所用时间;
- 还可以通过配置resolve,设置适合的extensions、modules、mainFields、mainFiles的值,减少模块解析时路径的查询范围,配置module的rules使用loader处理不同的文件时,通过include和exclude限制处理范围,减少耗时;
- 另外还可以使用thread-loader利用多进程加速loader执行,利用tree-shaking减少webpack处理打包的代码量,利用缓存提升二次构建速度,像babel-loader、terser-webpack-plugin都可以开启缓存。
- 生产环境还可以配置devtool不输出sourcemap。
- 如果项目非常大,涉及代码模块过多,在合适的情况下也可以根据一定的粒度,把不同的业务代码拆分到不同的代码库去维护和管理,减少webpack处理的代码量。
如何开发一个webpack的plugin
plugin的实现可以是一个类或者函数,使用时传入相关配置来创建一个实例,plugin实例最重要的方法就是apply,在webpack compiler安装插件时会被调用,接收webpack的compiler对象实例的引用作为参数,在compiler对象实例上我们可以注册各种事件钩子函数hooks,在compiler的有些hooks中,还可以获取到compilation对象实例,在compilation对象实例上注册各种hooks,我们可以通过注册各种hooks来影响webpack的所有构建流程,以便完成更多其他构建任务。
hooks可以简单分为同步和异步两种,同步类型的hooks只能使用tap来注册事件,异步的还可以使用tapPromise和tapAsync来注册。
本地开发plugin,可以使自定义plugin对外暴露一个类,然后在webpack配置文件中引入,运行webpack构建查看结果就可以,可以使用node命令进行调试。
compiler一些hooks:entryOption、beforeRun、emit、compilation、thisCompilation、make(compilation完成编译后执行)、shouldEmit(控制是否输出对应的构建结果)、assetEmitted(在构建结果输出之后执行,可以获取输出内容的相关信息)、done、failed(构建失败时执行)
compilation一些hooks:buildModule、finishModules、chunkAsset(chunk 对应的一个输出资源添加到compilation时执行)、processAssets
如何开发一个webpack的loader
webpack loader本质就是一个实现转换功能的函数,接收content、map、meta三个参数。content就是要进行转化的资源内容,可以是字符串或者buffer,如图片、字体等文件,map是sourcemap对象。
通常webpack loader都是基于一个实现核心功能的类库来开发的,如果直接return一个值,这个值就是转换后的内容,如果要返回sourcemap对象或者其他数据,或是抛出一个异常,需要使用this.callback(err, content, map, meta)来传递这些数据;有些loader在执行过程中可能依赖外部I/O的结果,就需要使用异步的方式来处理,在loader执行时调用this.async()来标识该loader是异步处理的,this.async()会返回一个函数,然后我们可以调用这个函数用于返回loader的处理结果。
使用本地开发的loader有两种方式:一种是配置loader时使用本地的路径;另一种是在loader路径解析中加入本地开发loader的目录,具体是在loader所在目录下添加package.json文件并配置name字段,然后配置resolveLoader的modules将loader所在目录的路径添加进去,并在配置loader时使用package.json中name的值,这种比较适合多个loader的情况。
官方提供的一个工具库loader-utils可以帮助我们获取给loader传递的options,我们还可以使用官方提供的schema-utils对传入的options进行校验。
Webpack相关知识点的更多相关文章
- UITableView相关知识点
//*****UITableView相关知识点*****// 1 #import "ViewController.h" // step1 要实现UITableViewDataSou ...
- Android开发涉及有点概念&相关知识点(待写)
前言,承接之前的 IOS开发涉及有点概念&相关知识点,这次归纳的是Android开发相关,好废话不说了.. 先声明下,Android开发涉及概念比IOS杂很多,可能有很多都题不到的.. 首先由 ...
- IOS开发涉及有点概念&相关知识点
前言,IOS是基于UNIX的,用C/C+/OC直通系统底层,不想android有个jvm. 首先还是系统架构的分层架构 1.核心操作系统层 Core OS,就是内存管理.文件系统.电源管理等 2.核心 ...
- IOS之UI--小实例项目--添加商品和商品名(使用xib文件终结版) + xib相关知识点总结
添加商品和商品名小项目(使用xib文件终结版) 小贴士:博文末尾有项目源码在百度云备份的下载链接. xib相关知识点总结 01-基本使用 一开始使用xib的时候,如果要使用自定义view的代码,就需要 ...
- 学习记录013-NFS相关知识点
一.NFS相关知识点 1.NFS常用的路径/etc/exports NFS服务主配置文件,配置NFS具体共享服务的地点/usr/sbin/exportfs NFS服务的管理命令,exportfs -a ...
- TCP/IP 相关知识点与面试题集
第一部分:TCP/IP相关知识点 对TCP/IP的整体认 链路层知识点 IP层知识点 运输层知识点 应用层知识点 (这些知识点都可以参考:http://www.cnblogs.com/newwy/p/ ...
- Python开发一个csv比较功能相关知识点汇总及demo
Python 2.7 csv.reader(csvfile, dialect='excel', **fmtparams)的一个坑:csvfile被csv.reader生成的iterator,在遍历每二 ...
- Caffe学习系列(二)Caffe代码结构梳理,及相关知识点归纳
前言: 通过检索论文.书籍.博客,继续学习Caffe,千里之行始于足下,继续努力.将自己学到的一些东西记录下来,方便日后的整理. 正文: 1.代码结构梳理 在终端下运行如下命令,可以查看caffe代码 ...
- php正则相关知识点
关于正则,其实简单就是搜索和匹配.php,java,python等都是支持正则的,php正则兼容perl.好多同学觉得正则比较难,比较抽象,其实正则是非常简单的,主要是一个熟悉和反复练习的结果,还有一 ...
- MySQL自增列(AUTO_INCREMENT)相关知识点总结
MySQL的自增列(AUTO_INCREMENT)和其它数据库的自增列对比,有很多特性和不同点(甚至不同存储引擎.不同版本也有一些不同的特性),让人感觉有点稍微复杂.下面我们从一些测试开始,来认识 ...
随机推荐
- 我真的不想再用mybatis和其衍生框架了选择自研亦是一种解脱
我真的不想再用mybatis和其衍生框架了选择自研亦是一种解脱 文档地址 https://xuejm.gitee.io/easy-query-doc/ GITHUB地址 https://github. ...
- 犯得一些zz错误
本文用于警戒自己,不要再犯以前的傻逼错误 noip没建子文件夹导致爆零 知道关同步流之后还用endl,导致超时 使用'\n'代替endl 3.多组测试数据使用for循环占用了 i 变量名,后面在for ...
- Promise的理解与使用(一)
一.Promise是什么?Promise是JS中进行异步操作的新的解决方案(旧的方案是回调函数的形式,回调函数里嵌套函数)从语法上来说,Promise是一个构造函数.从功能上来说,用Promise的实 ...
- 记一次 .NET某报关系统 非托管泄露分析
一:背景 1. 讲故事 前段时间有位朋友找到我,说他的程序内存会出现暴涨,让我看下是怎么事情?而且还告诉我是在 Linux 环境下,说实话在Linux上分析.NET程序难度会很大,难度大的原因在于Li ...
- 服务端不回应客户端的syn握手,连接建立失败原因排查
背景 测试环境有一个后台服务,部署在内网服务器A上(无外网地址),给app提供接口.app访问这个后台服务时,ip地址是公网地址,那这个请求是如何到达我们的内网服务器A呢,这块我咨询了网络同事,我画了 ...
- Linux 主机磁盘繁忙度监控实战shell脚本
Linux 磁盘繁忙度是指磁盘的使用率和活动水平.可以通过一些工具来监测磁盘繁忙度,如 iostat.iotop.sar 等. 其中,iostat 是一个常用的工具,可以提供关于磁盘活动的详细统计信息 ...
- 深入理解Linux内核——内存管理(4)——伙伴系统(1)
提要:本系列文章主要参考MIT 6.828课程以及两本书籍<深入理解Linux内核> <深入Linux内核架构>对Linux内核内容进行总结. 内存管理的实现覆盖了多个领域: ...
- 给你的 SpringBoot 工程部署的 jar 包瘦瘦身吧!
之前有写过一篇有关maven插件的文章:spring-boot-maven-plugin插件详解 一.需求背景 我们知道Spring Boot项目,是可以通过java -jar 包名 启动的. 那为什 ...
- 有Root与无Root安装git-lfs
有Root与无Root安装git-lfs 直接安装 先查看arm还是AMD 例如当前使用Rocky Linux 8.8版本的内核.因此,应该下载适用于Rocky Linux 8.x的Git LFS安装 ...
- 再聊Java Stream的一些实战技能与注意点
大家好,又见面了. 在此前我的文章中,曾分2篇详细探讨了下JAVA中Stream流的相关操作,2篇文章收获了累计 10w+阅读.2k+点赞以及 5k+收藏的记录.能够得到众多小伙伴的认可,是技术分享过 ...