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优化性能大概有三种方式:

代码压缩、代码分割、去除无用代码,主要的方向是减少请求体积,代码分割有的情况下还可以利用浏览器缓存,减少请求次数

  1. 代码压缩(主要就减少请求体积)

    我们可以对optimization下的minimize和minimizer配置项进行设置,配置TerserPlugin对js代码进行压缩处理,还可以使用插件如HTMLWebpackPlugin对html文件进行压缩。
  2. 代码分割(既减少一次的请求体积,使请求返回更快,有的情况还可以利用浏览器缓存,减少请求次数)

    我了解的大概几种方式,第一种是设置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引用文件就可以,通常可以用来处理不太变动的第三方库,可以看出来这样不仅可以利用浏览器缓存,还能提高开发效率。
  3. 去除无用代码(减少请求体积)

    可以利用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相关知识点的更多相关文章

  1. UITableView相关知识点

    //*****UITableView相关知识点*****// 1 #import "ViewController.h" // step1 要实现UITableViewDataSou ...

  2. Android开发涉及有点概念&相关知识点(待写)

    前言,承接之前的 IOS开发涉及有点概念&相关知识点,这次归纳的是Android开发相关,好废话不说了.. 先声明下,Android开发涉及概念比IOS杂很多,可能有很多都题不到的.. 首先由 ...

  3. IOS开发涉及有点概念&相关知识点

    前言,IOS是基于UNIX的,用C/C+/OC直通系统底层,不想android有个jvm. 首先还是系统架构的分层架构 1.核心操作系统层 Core OS,就是内存管理.文件系统.电源管理等 2.核心 ...

  4. IOS之UI--小实例项目--添加商品和商品名(使用xib文件终结版) + xib相关知识点总结

    添加商品和商品名小项目(使用xib文件终结版) 小贴士:博文末尾有项目源码在百度云备份的下载链接. xib相关知识点总结 01-基本使用 一开始使用xib的时候,如果要使用自定义view的代码,就需要 ...

  5. 学习记录013-NFS相关知识点

    一.NFS相关知识点 1.NFS常用的路径/etc/exports NFS服务主配置文件,配置NFS具体共享服务的地点/usr/sbin/exportfs NFS服务的管理命令,exportfs -a ...

  6. TCP/IP 相关知识点与面试题集

    第一部分:TCP/IP相关知识点 对TCP/IP的整体认 链路层知识点 IP层知识点 运输层知识点 应用层知识点 (这些知识点都可以参考:http://www.cnblogs.com/newwy/p/ ...

  7. Python开发一个csv比较功能相关知识点汇总及demo

    Python 2.7 csv.reader(csvfile, dialect='excel', **fmtparams)的一个坑:csvfile被csv.reader生成的iterator,在遍历每二 ...

  8. Caffe学习系列(二)Caffe代码结构梳理,及相关知识点归纳

    前言: 通过检索论文.书籍.博客,继续学习Caffe,千里之行始于足下,继续努力.将自己学到的一些东西记录下来,方便日后的整理. 正文: 1.代码结构梳理 在终端下运行如下命令,可以查看caffe代码 ...

  9. php正则相关知识点

    关于正则,其实简单就是搜索和匹配.php,java,python等都是支持正则的,php正则兼容perl.好多同学觉得正则比较难,比较抽象,其实正则是非常简单的,主要是一个熟悉和反复练习的结果,还有一 ...

  10. MySQL自增列(AUTO_INCREMENT)相关知识点总结

      MySQL的自增列(AUTO_INCREMENT)和其它数据库的自增列对比,有很多特性和不同点(甚至不同存储引擎.不同版本也有一些不同的特性),让人感觉有点稍微复杂.下面我们从一些测试开始,来认识 ...

随机推荐

  1. 我真的不想再用mybatis和其衍生框架了选择自研亦是一种解脱

    我真的不想再用mybatis和其衍生框架了选择自研亦是一种解脱 文档地址 https://xuejm.gitee.io/easy-query-doc/ GITHUB地址 https://github. ...

  2. 犯得一些zz错误

    本文用于警戒自己,不要再犯以前的傻逼错误 noip没建子文件夹导致爆零 知道关同步流之后还用endl,导致超时 使用'\n'代替endl 3.多组测试数据使用for循环占用了 i 变量名,后面在for ...

  3. Promise的理解与使用(一)

    一.Promise是什么?Promise是JS中进行异步操作的新的解决方案(旧的方案是回调函数的形式,回调函数里嵌套函数)从语法上来说,Promise是一个构造函数.从功能上来说,用Promise的实 ...

  4. 记一次 .NET某报关系统 非托管泄露分析

    一:背景 1. 讲故事 前段时间有位朋友找到我,说他的程序内存会出现暴涨,让我看下是怎么事情?而且还告诉我是在 Linux 环境下,说实话在Linux上分析.NET程序难度会很大,难度大的原因在于Li ...

  5. 服务端不回应客户端的syn握手,连接建立失败原因排查

    背景 测试环境有一个后台服务,部署在内网服务器A上(无外网地址),给app提供接口.app访问这个后台服务时,ip地址是公网地址,那这个请求是如何到达我们的内网服务器A呢,这块我咨询了网络同事,我画了 ...

  6. Linux 主机磁盘繁忙度监控实战shell脚本

    Linux 磁盘繁忙度是指磁盘的使用率和活动水平.可以通过一些工具来监测磁盘繁忙度,如 iostat.iotop.sar 等. 其中,iostat 是一个常用的工具,可以提供关于磁盘活动的详细统计信息 ...

  7. 深入理解Linux内核——内存管理(4)——伙伴系统(1)

    提要:本系列文章主要参考MIT 6.828课程以及两本书籍<深入理解Linux内核> <深入Linux内核架构>对Linux内核内容进行总结. 内存管理的实现覆盖了多个领域: ...

  8. 给你的 SpringBoot 工程部署的 jar 包瘦瘦身吧!

    之前有写过一篇有关maven插件的文章:spring-boot-maven-plugin插件详解 一.需求背景 我们知道Spring Boot项目,是可以通过java -jar 包名 启动的. 那为什 ...

  9. 有Root与无Root安装git-lfs

    有Root与无Root安装git-lfs 直接安装 先查看arm还是AMD 例如当前使用Rocky Linux 8.8版本的内核.因此,应该下载适用于Rocky Linux 8.x的Git LFS安装 ...

  10. 再聊Java Stream的一些实战技能与注意点

    大家好,又见面了. 在此前我的文章中,曾分2篇详细探讨了下JAVA中Stream流的相关操作,2篇文章收获了累计 10w+阅读.2k+点赞以及 5k+收藏的记录.能够得到众多小伙伴的认可,是技术分享过 ...