今天给各位分享中考倒计时网站源码分享的知识,其中也会对中考倒计时启动小视频进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
作者:王平安
转发链接:https://mp.weixin.qq.com/s/Nd1bXGA5uacFN_guP0Gx3Q
目录
了不起的WebpackHMR学习指南(上)「含源码讲解」本篇
了不起的WebpackHMR学习指南(下)「含源码讲解」
一、HMR介绍
HotModuleReplacement(以下简称:HMR模块热替换)是Webpack提供的一个非常有用的功能,它允许在JavaScript运行时更新各种模块,而无需完全刷新。
HotModuleReplacement(orHMR)isoneofthemostusefulfeaturesofferedbywebpack.Itallowsallkindsofmodulestobeupdatedatruntimewithouttheneedforafullrefresh.–《HotModuleReplacement》
当我们修改代码并保存后,Webpack将对代码重新打包,HMR会在应用程序运行过程中替换、添加或删除模块,而无需重新加载整个页面。HMR主要通过以下几种方式,来显著加快开发速度:
保留在完全重新加载页面时丢失的应用程序状态;只更新变更内容,以节省宝贵的开发时间;调整样式更加快速-几乎相当于在浏览器调试器中更改样式。
需要注意:HMR不适用于生产环境,这意味着它应当只在开发环境使用。
二、HMR使用方式
在Webpack中启用HMR功能比较简单:
1.方式一:使用devServer
1.1设置devServer选项
只需要在webpack.config.js中添加devServer选项,并设置hot值为true,并使用HotModuleReplacementPlugin和NamedModulesPlugin(可选)两个Plugins:
//webpack.config.js\n\nconstpath=require(&39;)\nconstwebpack=require(&39;)\nmodule.exports={\nentry:&39;,\noutput:{\nfilename:&39;,\npath:path.join(__dirname,&39;)\n},\n+devServer:{\n+hot:true,//启动模块热更新HMR\n+open:true,//开启自动打开浏览器页面\n+},\nplugins:[\n+newwebpack.NamedModulesPlugin(),\n+newwebpack.HotModuleReplacementPlugin()\n]\n}
1.2添加scripts
然后再package.json中为scripts命令即可:
//package.json\n\n{\n//…\n&34;:{\n+&34;:&34;\n},\n//…\n}
2.方式二、使用命令行参数
另一种是通过添加–hot参数来实现。添加–hot参数后,devServer会告诉Webpack自动引入HotModuleReplacementPlugin,而不需要我们手动引入。另外常常也搭配–open来自动打开浏览器到页面。这里移除掉前面添加的两个Plugins:
//webpack.config.js\n\nconstpath=require(&39;)\nconstwebpack=require(&39;)\nmodule.exports={\n//…\n-plugins:[\n-newwebpack.NamedModulesPlugin(),\n-newwebpack.HotModuleReplacementPlugin()\n-]\n}
然后修改package.json文件中的scripts配置:
//package.json\n\n{\n//…\n&34;:{\n-&34;:&34;\n+&34;:&34;\n},\n//…\n}
3.简单示例
基于上述配置,我们简单实现一个场景:index.js文件中导入hello.js模块,当hello.js模块发生变化时,index.js将更新模块。模块代码如下实现:
//hello.js\nexportdefault()=>&39;;\n\n//index.js\nimporthellofrom&39;\nconstdiv=document.createElement(&39;);\ndiv.innerHTML=hello();\n\ndocument.body.appendChild(div);
然后再index.html中导入打包后的JS文件,并执行npmstart运行项目:
<!DOCTYPEhtml>\n<htmllang=&34;>\n<head>\n<metacharset=&34;>\n</head>\n<body>\n<div>了不起的WebpackHMR学习指南</div>\n<scriptsrc=&34;></script>\n</body>\n</html>
4.实现监听更新
当我们通过HotModuleReplacementPlugin插件启用了HMR,则它的接口将被暴露在全局module.hot属性下面。通常,可以先检查这个接口是否可访问,然后再开始使用它。举个例子,你可以这样accept一个更新的模块:
if(module.hot){\nmodule.hot.accept(&39;,function(){\n//使用更新过的library模块执行某些操作…\n})\n}
关于module.hot更多API,可以查看官方文档《HotModuleReplacementAPI》。回到上面示例,我们测试更新模块的功能。这时我们修改index.js代码,来监听hello.js模块中的更新:
importhellofrom&39;;\nconstdiv=document.createElement(&39;);\ndiv.innerHTML=hello();\ndocument.body.appendChild(div);\n\n+if(module.hot){\n+module.hot.accept(&39;,function(){\n+console.log(&39;);\n+div.innerHTML=hello();\n+})\n+}
然后修改hello.js文件内容,测试效果:
-exportdefault()=>&39;;\n+exportdefault()=>&39;;
当我们保存代码时,控制台输出&34;,并且页面中&34;也更新为&34;,证明我们监听到文件更新了。
简单WebpackHMR使用方式就介绍到这,更多介绍,还请阅读官方文档《HotModuleReplacement》。
5.devServer常用配置和技巧
5.1常用配置
根据目录结构的不同,contentBase、openPage参数要配置合适的值,否则运行时应该不会立刻访问到你的首页。同时要注意你的publicPath,静态资源打包后生成的路径是一个需要思考的点,取决于你的目录结构。
devServer:{\ncontentBase:path.join(__dirname,&39;),//告诉服务器从哪里提供内容(默认当前工作目录)\nopenPage:&39;,//指定默认启动浏览器时打开的页面\nindex:&39;,//指定首页位置\nwatchContentBase:true,//contentBase下文件变动将reload页面(默认false)\nhost:&39;,//默认localhost,想外部可访问用&39;\nport:8080,//默认8080\ninline:true,//可以监控js变化\nhot:true,//热启动\nopen:true,//启动时自动打开浏览器(指定打开chrome,open:&39;)\ncompress:true,//一切服务都启用gzip压缩\ndisableHostCheck:true,//true:不进行host检查\nquiet:false,\nhttps:false,\nclientLogLevel:&39;,\nstats:{//设置控制台的提示信息\nchunks:false,\nchildren:false,\nmodules:false,\nentrypoints:false,//是否输出入口信息\nwarnings:false,\nperformance:false,//是否输出webpack建议(如文件体积大小)\n},\nhistoryApiFallback:{\ndisableDotRule:true,\n},\nwatchOptions:{\nignored:/node_modules/,//略过node_modules目录\n},\nproxy:{//接口代理(这段配置更推荐:写到package.json,再引入到这里)\n&34;:{\n&34;:&34;,\n&34;:false,\n&34;:true,\n&34;:{//将url上的某段重写(例如此处是将api-dev替换成了空)\n&34;:&34;\n}\n}\n},\nbefore(app){},\n}
5.2技巧1:文件形式输出dev-server代码
dev-server输出的代码通常在内存中,但也可以写入硬盘,产出实体文件:
devServer:{\nwriteToDisk:true,\n}
通常可以用于代理映射文件调试,编译时会产出许多带hash的js文件,不带hash的文件同样也是实时编译的。
5.3技巧2:默认使用本地IP启动服务
有的时候,启动服务时,想要默认使用本地的ip地址打开:
devServer:{\ndisableHostCheck:true,//true:不进行host检查\n//useLocalIp:true,//建议不在这里配置\n//host:&39;,//建议不在这里配置\n}
同时还需要将host配置为0.0.0.0,这个配置建议在scripts命令中追加,而非在配置中写死,否则将来不想要这种方式往回改折腾,取巧一点,配个新命令:
&34;:&34;
5.4技巧3:指定启动的调试域名
有时启动的时候希望是指定的调试域名,例如:local.test.baidu.com:
devServer:{\nopen:true,\npublic:&39;,//需要带上端口\nport:8080,\n}
同时需要将127.0.0.1修改为指定的host,可以借助iHost等工具去修改,各个工具大同小异,格式如下:
127.0.0.1local.test.baidu.com
服务启动后将自动打开local.test.baidu.com:8080访问
5.5技巧4:启动gzip压缩
devServer:{\ncompress:true,\n}
三、HMR基本原理介绍
从前面介绍中,我们知道:HMR主要功能是会在应用程序运行过程中替换、添加或删除模块,而无需重新加载整个页面。那么,Webpack编译源码所产生的文件变化在编译时,替换模块实现在运行时,两者如何联系起来?带着这两个问题,我们先简单看下HMR核心工作流程(简化版):
HMR工作流程图.png
接下来开始HMR工作流程分析:
当Webpack(Watchman)监听到项目中的文件/模块代码发生变化后,将变化通知Webpack中的构建工具(Packager)即HMRPlugin;然后经过HMRPlugin处理后,将结果发送到应用程序(Application)的运行时框架(HMRRuntime);最后由HMRRuntime将这些发生变化的文件/模块更新(新增/删除或替换)到模块系统中。
其中,HMRRuntime是构建工具在编译时注入的,通过统一的ModuleID将编译时的文件与运行时的模块对应起来,并且对外提供一系列API供应用层框架(如React)调用。
注意:建议先理解上面这张图的大致流程,再进行后续阅读。放心,我等着大家~
四、HMR完整原理和源码分析
通过上一节内容,我们大概知道HMR简单工作流程,那么或许你现在可能还有很多疑惑:文件更新是什么通知HMRPlugin?HMRPlugin怎么发送更新到HMRRuntime?等等问题。
那么接下来我们开始详细结合源码分析整个HMR模块热更新流程,首先还是先看流程图,可以先不了解图中方法名称(红色字体黄色背景色部分):
WebpackHMR.png
上图展示了从我们修改代码,到模块热更新完成的一个HMR完整工作流程,图中已用红色阿拉伯数字符号将流程标识出来。
要了解上面工作原理,我们先理解图中这几个名称概念:
Webpack-dev-server:一个服务器插件,相当于express服务器,启动一个Web服务,只适用于开发环境;Webpack-dev-middleware:一个Webpack-dev-server的中间件,作用简单总结为:通过watchmode,监听资源的变更,然后自动打包。Webpack-hot-middleware:结合Webpack-dev-middleware使用的中间件,它可以实现浏览器的无刷新更新,也就是HMR;
下面一起学习HMR整个工作原理吧:
1.监控代码变化,重新编译打包
首先根据devServer配置,使用npmstart将启动Webpack-dev-server启动本地服务器并进入Webpack的watch模式,然后初始化Webpack-dev-middleware,在Webpack-dev-middleware中通过调用startWatch()方法对文件系统进行watch:
//webpack-dev-server\\bin\\webpack-dev-server.js\n//1.启动本地服务器Line386\nserver=newServer(compiler,options);\n\n//webpack-dev-server\\lib\\Server.js\n//2.初始化Webpack-dev-middlewareLine109\nthis.middleware=webpackDevMiddleware(compiler,Object.assign({},options,wdmOptions));\n\n//webpack-dev-middleware\\lib\\Shared.js\n//3.开始watch文件系统Line171\nstartWatch:function(){\n//…\n//startwatching\nif(!options.lazy){\nvarwatching=compiler.watch(options.watchOptions,share.handleCompilerCallback);\ncontext.watching=watching;\n}\n//…\n}\nshare.startWatch();\n//…
当startWatch()方法执行后,便进入watch模式,若发现文件中代码发生修改,则根据配置文件对模块重新编译打包。
2.保存编译结果
Webpack与Webpack-dev-middleware交互,Webpack-dev-middleware调用Webpack的API对代码变化进行监控,并通知Webpack将重新编译的代码通过JavaScript对象保存在内存中。
我们会发现,在output.path指定的dist目录并没有保存编译结果的文件,这是为什么?
其实,Webpack将编译结果保存在内存中,因为访问内存中的代码比访问文件系统中的文件快,这样可以减少代码写入文件的开销。
Webpack能将代码保存到内存中,需要归功于Webpack-dev-middleware的memory-fs依赖库,它将原本outputFileSystem替换成了MemoryFileSystem的实例,便实现代码输出到内存中。其中部分源码如下:
//webpack-dev-middleware\\lib\\Shared.jsLine108\n\n//storeourfilesinmemory\nvarfs;\nvarisMemoryFs=!compiler.compilers&&\ncompiler.outputFileSysteminstanceofMemoryFileSystem;\nif(isMemoryFs){\nfs=compiler.outputFileSystem;\n}else{\nfs=compiler.outputFileSystem=newMemoryFileSystem();\n}\ncontext.fs=fs;
上述代码先判断fileSystem是否是MemoryFileSystem的实例,若不是,则用MemoryFileSystem的实例替换compiler之前的outputFileSystem。这样bundle.js文件代码就作为一个简单JavaScript对象保存在内存中,当浏览器请求bundle.js文件时,devServer就直接去内存中找到上面保存的JavaScript对象并返回给浏览器端。
3.监控文件变化,刷新浏览器
Webpack-dev-server开始监控文件变化,与第1不不同的是,这里并不是监控代码变化重新编译打包。当我们在配置文件中配置了devServer.watchContentBase为true,Webpack-dev-server会监听配置文件夹中静态文件的变化,发生变化时,通知浏览器端对应用进行浏览器刷新,这与HMR不一样。
//webpack-dev-server\\lib\\Server.js\n//1.读取参数Line385\nif(options.watchContentBase){defaultFeatures.push(&39;);}\n\n//2.定义_watch方法Line697\nServer.prototype._watch=function(watchPath){\n//…\nconstwatcher=chokidar.watch(watchPath,options).on(&39;,()=>{\nthis.sockWrite(this.sockets,&39;);\n});\n\nthis.contentBaseWatchers.push(watcher);\n};\n\n//3.执行_watch()监听文件变化Line339\nwatchContentBase:()=>{\nif(/^(https?:)?\\/\\//.test(contentBase)||typeofcontentBase===&39;){\nthrownewError(&39;);\n}elseif(Array.isArray(contentBase)){\ncontentBase.forEach((item)=>{\nthis._watch(item);\n});\n}else{\nthis._watch(contentBase);\n}\n}
4.建立WS,同步编译阶段状态
这一步都是Webpack-dev-server中处理,主要通过sockjs(Webpack-dev-server的依赖),在Webpack-dev-server的浏览器端(Client)和服务器端(Webpack-dev-middleware)之间建立WebSocket长连接。
然后将Webpack编译打包的各个阶段状态信息同步到浏览器端。其中有两个重要步骤:
发送状态
Webpack-dev-server通过WebpackAPI监听compile的done事件,当compile完成后,Webpack-dev-server通过_sendStats方法将编译后新模块的hash值用socket发送给浏览器端。
保存状态
浏览器端将_sendStats发送过来的hash保存下来,它将会用到后模块热更新。
//webpack-dev-server\\lib\\Server.js\n\n//1.定义_sendStats方法Line685\n//sendstatstoasocketormultiplesockets\nServer.prototype._sendStats=function(sockets,stats,force){\n//…\nthis.sockWrite(sockets,&39;,stats.hash);\n};\n\n//2.监听done事件Line86\ncompiler.plugin(&39;,(stats)=>{\n//将最新打包文件的hash值(stats.hash)作为参数传入_sendStats()\nthis._sendStats(this.sockets,stats.toJson(clientStats));\nthis._stats=stats;\n});\n\n//webpack-dev-server\\client\\index.js\n//3.保存hash值Line74\nvaronSocketMsg={\n//…\nhash:functionhash(_hash){\ncurrentHash=_hash;\n},\n//…\n}\nsocket(socketUrl,onSocketMsg);
未完结,请看下一篇
推荐JavaScript经典实例学习资料文章
《10个打开了我新世界大门的WebAPI(上)「实践」》
《10个打开了我新世界大门的WebAPI(中)「实践」》
《10个打开了我新世界大门的WebAPI(下)「实践」》
《「图文」ESLint在中大型团队的应用实践》
《Deno是代码的浏览器,你认同吗?》
《前端存储除了localStorage还有啥?》
《Javascript多线程编程?的前世今生》
《微前端方案qiankun(实践及总结)》
《「图文」V8垃圾回收原来这么简单?》
《Webpack5模块联邦引发微前端的革命?》
《基于Web端的人脸识别身份验证「实践」》
《「前端进阶」高性能渲染十万条数据(时间分片)》
《「前端进阶」高性能渲染十万条数据(虚拟列表)》
《图解Promise实现原理(一):基础实现》
《图解Promise实现原理(二):Promise链式调用》
《图解Promise实现原理(三):Promise原型方法实现》
《图解Promise实现原理(四):Promise静态方法实现》
《实践教你从零构建前端Lint工作流「干货」》
《高性能多级多选级联组件开发「JS篇」》
《深入浅出讲解Node.jsCLI工具最佳实战》
《延迟加载图像以提高Web网站性能的五种方法「实践」》
《比较JavaScript对象的四种方式「实践」》
《使用ServiceWorker让你的Web应用如虎添翼(上)「干货」》
《使用ServiceWorker让你的Web应用如虎添翼(中)「干货」》
《使用ServiceWorker让你的Web应用如虎添翼(下)「干货」》
《前端如何一次性处理10万条数据「进阶篇」》
《推荐三款正则可视化工具「JS篇」》
《如何让用户选择是否离开当前页面?「JS篇」》
《JavaScript开发人员更喜欢Deno的五大原因》
《仅用18行JavaScript实现一个倒数计时器》
《图文细说JavaScript的运行机制》
《一个轻量级JavaScript全文搜索库,轻松实现站内离线搜索》
《推荐Web程序员常用的15个源代码编辑器》
《10个实用的JS技巧「值得收藏」》
《细品269个JavaScript小函数,让你少加班熬夜(一)「值得收藏」》
《细品269个JavaScript小函数,让你少加班熬夜(二)「值得收藏」》
《细品269个JavaScript小函数,让你少加班熬夜(三)「值得收藏」》
《细品269个JavaScript小函数,让你少加班熬夜(四)「值得收藏」》
《细品269个JavaScript小函数,让你少加班熬夜(五)「值得收藏」》
《细品269个JavaScript小函数,让你少加班熬夜(六)「值得收藏」》
《深入JavaScript教你内存泄漏如何防范》
《手把手教你7个有趣的JavaScript项目-上「附源码」》
《手把手教你7个有趣的JavaScript项目-下「附源码」》
《JavaScript使用mediaDevicesAPI访问摄像头自拍》
《手把手教你前端代码如何做错误上报「JS篇」》
《一文让你彻底搞懂移动前端和Web前端区别在哪里》
《63个JavaScript正则大礼包「值得收藏」》
《提高你的JavaScript技能10个问答题》
《JavaScript图表库的5个首选》
《一文彻底搞懂JavaScript中Object.freeze与Object.seal的用法》
《可视化的JS:动态图演示-事件循环EventLoop的过程》
《教你如何用动态规划和贪心算法实现前端瀑布流布局「实践」》
《可视化的js:动态图演示Promises&Async/Await的过程》
《原生JS封装拖动验证滑块你会吗?「实践」》
《如何实现高性能的在线PDF预览》
《细说使用字体库加密数据-仿58同城》
《Node.js要完了吗?》
《Pug3.0.0正式发布,不再支持Node.js6/8》
《纯JS手写轮播图(代码逻辑清晰,通俗易懂)》
《JavaScript20年中文版之创立标准》
《值得收藏的前端常用60余种工具方法「JS篇」》
《箭头函数和常规函数之间的5个区别》
《通过发布/订阅的设计模式搞懂Node.js核心模块Events》
《「前端篇」不再为正则烦恼》
《「速围」Node.jsV14.3.0发布支持顶级Await和REPL增强功能》
《深入细品浏览器原理「流程图」》
《JavaScript已进入第三个时代,未来将何去何从?》
《前端上传前预览文件image、text、json、video、audio「实践」》
《深入细品EventLoop和浏览器渲染、帧动画、空闲回调的关系》
《推荐13个有用的JavaScript数组技巧「值得收藏」》
《前端必备基础知识:window.location详解》
《不要再依赖CommonJS了》
《犀牛书作者:最该忘记的JavaScript特性》
《36个工作中常用的JavaScript函数片段「值得收藏」》
《Node+H5实现大文件分片上传、断点续传》
《一文了解文件上传全过程(1.8w字深度解析)「前端进阶必备」》
《【实践总结】关于小程序挣脱枷锁实现批量上传》
《手把手教你前端的各种文件上传攻略和大文件断点续传》
《字节跳动面试官:请你实现一个大文件上传和断点续传》
《谈谈前端关于文件上传下载那些事【实践】》
《手把手教你如何编写一个前端图片压缩、方向纠正、预览、上传插件》
《最全的JavaScript模块化方案和工具》
《「前端进阶」JS中的内存管理》
《JavaScript正则深入以及10个非常有意思的正则实战》
《前端面试者经常忽视的一道JavaScript面试题》
《一行JS代码实现一个简单的模板字符串替换「实践」》
《JS代码是如何被压缩的「前端高级进阶」》
《前端开发规范:命名规范、html规范、css规范、js规范》
《【规范篇】前端团队代码规范最佳实践》
《100个原生JavaScript代码片段知识点详细汇总【实践】》
《关于前端174道JavaScript知识点汇总(一)》
《关于前端174道JavaScript知识点汇总(二)》
《关于前端174道JavaScript知识点汇总(三)》
《几个非常有意思的javascript知识点总结【实践】》
《都2020年了,你还不会JavaScript装饰器?》
《JavaScript实现图片合成下载》
《70个JavaScript知识点详细总结(上)【实践】》
《70个JavaScript知识点详细总结(下)【实践】》
《开源了一个JavaScript版敏感词过滤库》
《送你43道JavaScript面试题》
《3个很棒的小众JavaScript库,你值得拥有》
《手把手教你深入巩固JavaScript知识体系【思维导图】》
《推荐7个很棒的JavaScript产品步骤引导库》
《Echa哥教你彻底弄懂JavaScript执行机制》
《一个合格的中级前端工程师需要掌握的28个JavaScript技巧》
《深入解析高频项目中运用到的知识点汇总【JS篇】》
《JavaScript工具函数大全【新】》
《从JavaScript中看设计模式(总结)》
《身份证号码的正则表达式及验证详解(JavaScript,Regex)》
《浏览器中实现JavaScript计时器的4种创新方式》
《Three.js动效方案》
《手把手教你常用的59个JS类方法》
《127个常用的JS代码片段,每段代码花30秒就能看懂-【上】》
《深入浅出讲解js深拷贝vs浅拷贝》
《手把手教你JS开发H5游戏【消灭星星】》
《深入浅出讲解JS中this/apply/call/bind巧妙用法【实践】》
《手把手教你全方位解读JS中this真正含义【实践】》
《书到用时方恨少,一大波JS开发工具函数来了》
《干货满满!如何优雅简洁地实现时钟翻牌器(支持JS/Vue/React)》
《手把手教你JS异步编程六种方案【实践】》
《让你减少加班的15条高效JS技巧知识点汇总【实践】》
《手把手教你JS开发H5游戏【黄金矿工】》
《手把手教你JS实现监控浏览器上下左右滚动》
《JS经典实例知识点整理汇总【实践】》
《2.6万字JS干货分享,带你领略前端魅力【基础篇】》
《2.6万字JS干货分享,带你领略前端魅力【实践篇】》
《简单几步让你的JS写得更漂亮》
《恭喜你获得治疗JSthis的详细药方》
《谈谈前端关于文件上传下载那些事【实践】》
《面试中教你绕过关于JavaScript作用域的5个坑》
《Jquery插件(常用的插件库)》
《【JS】如何防止重复发送ajax请求》
《JavaScript+Canvas实现自定义画板》
《Continuation在JS中的应用「前端篇」》
作者:王平安
转发链接:https://mp.weixin.qq.com/s/Nd1bXGA5uacFN_guP0Gx3Q
关于中考倒计时网站源码分享,中考倒计时启动小视频的介绍到此结束,希望对大家有所帮助。
