1.【Webpack进阶】less-loader、试源css-loader、源码style-loader源码解析
2.源码细读-深入了解terser-webpack-plugin的分析实现
3.webpack 4 源码主流程分析(十一):文件的生成
4.å¦ä½å¨WebStorm 2017ä¸è°è¯Vue.js + webpack
5.webpack之devtool详解
6.放弃 console.log 吧!用 Debugger 你能读懂各种源码
【Webpack进阶】less-loader、试源css-loader、源码style-loader源码解析
Webpack进阶学习中,分析精髓源码Loader的试源运用是关键环节。在深入理解Loader基础后,源码本文将解析less-loader、分析css-loader和style-loader的试源内部工作原理。
less-loader是源码专为处理Less样式文件设计的,它将Less代码转换为浏览器能识别的分析CSS。以less文件为例,试源其工作原理是源码调用less库的功能,将扩展了CSS特性的分析Less代码转化为CSS,如变量、Mixin和函数等。
css-loader的功能则更为复杂,它不仅处理@import和url语句,还支持css-modules,将样式文件内容合并并作为JavaScript模块输出。以多个样式文件(如a.css、b.css和c.css)为例,css-loader会将它们合并成一个JavaScript模块,输出包含所有样式内容的字符串。
style-loader的作用在于将css-loader转化后的CSS样式代码插入到DOM中。理论上,我们可能期望直接在JavaScript中插入CSS代码,但css-loader返回的是模块化的代码,不能直接放入style标签。javac源码style-loader的实现通过一种巧妙的方式,将这些模块代码适当地包装,确保样式能正确插入到文档中。
style-loader的设计思路独特,其内部逻辑涉及Loader调用链、执行顺序和模块化输出等多个层面,理解style-loader的运作机制,对于深化对Webpack和Loader的理解至关重要。深入研究这些Loader的源码,无疑能提升你对Webpack进阶应用的掌握程度。
源码细读-深入了解terser-webpack-plugin的实现
terser-webpack-plugin 是一个基于 webpack 的插件,它利用 terser 库对 JavaScript 代码进行压缩和混淆。其核心功能在于通过在 webpack 的运行时钩子 optimizeChunkAssets 中注册,实现了代码优化过程。在 apply 函数中,它获取 compilation 实例,并通过 tapPromise 注册一个异步任务,当 webpack 执行优化阶段时,每个 chunk 会触发这个任务,执行 minify 函数进行压缩处理。
optimise 函数是实际的任务处理入口,它负责具体的优化流程。函数内部,scheduleTask 负责并行处理,如果开启 parallel 模式,会利用jest-worker提供的线程池进行并发工作,线程池管理复杂,根据 node 版本不同采用 worker_threads 或 child_process。minify 函数则是dns 源码压缩和混淆代码的核心操作,它直接使用 terser 库完成任务。
总的来说,terser-webpack-plugin 的优化流程包括在 webpack 的优化阶段对代码进行压缩,使用 Jest 的 worker 线程池进行并行处理,以及通过 terser 库的实际压缩操作。理解这些核心环节,可以帮助开发者更深入地掌握该插件的使用和工作原理。
webpack 4 源码主流程分析(十一):文件的生成
本文深入分析了 Webpack 4 中文件生成的具体流程。在资源写入文件阶段,通过一系列优化和处理,最终返回到 Compiler.js 的 compile 方法,其中 Compiler 的属性 _lastCompilationFileDependencies 和 _lastCompilationContextDependencies 被赋予了 fileDependencies 和 contextDependencies。紧随其后的是创建目标文件夹的过程,该操作通过 outputPath 属性配置,结合 mkdirp 函数完成。
在创建目标文件并写入阶段,通过 asyncLib.forEachLimit 方法并行处理每个文件资源,实现路径拼接、源码转换为 buffer,最后写入真实路径的文件。对于不同类型的 source 实例,如 CachedSource、ConcatSource 和 ReplaceSource,其处理逻辑各不相同,但最终目标都是获取替换后的字符串并合并返回 resultStr。所有文件创建写入完成后,执行回调,触发Compiler.afterEmit:hooks,进一步设置 stats 并打印构建信息。集团源码
至此,构建流程全部结束。通过本文的分析,我们可以更直观地了解 Webpack 4 中文件生成的具体实现细节,为深入理解 Webpack 的工作原理和优化提供理论支持。本章小结,下章将解析打包后的文件,敬请期待。
å¦ä½å¨WebStorm ä¸è°è¯Vue.js + webpack
æ人è§å¾vue项ç®é¾è°è¯ï¼æ¯å 为ç¨äºwebpackãææ代ç æå¨äºä¸èµ·ï¼è¿å äºå¾å¤æ¡æ¶ä»£ç ï¼æ ¹æ¬ä¸ç¥éæä¹ä¸æãæ以vue+webpackè°è¯è¦ä»webpackå ¥æã
1.æ们å ä»ä¸è¬æ åµå¼å§è¯´ã
-sourcemap
webpacké ç½®æä¾äºdevtoolè¿ä¸ªé项ï¼å¦æ设置为 â#source-mapâï¼åå¯ä»¥çæ.mapæ件ï¼å¨chromeæµè§å¨ä¸è°è¯çæ¶åå¯ä»¥æ¾ç¤ºæºä»£ç ã
devtool: '#source-map'
2.ç¶èè¿ä¸ªè®¾ç½®å®é ä¸æ²¡è¿ä¹ç®åãwebpackå®æ¹ç»åºäº7个é 置项ä¾éæ©:
.devtoolä»ç»
è¿éä¸åçé ç½®æäºä¸åçææï¼æ¯å¦æ¯å¦ä¿ç注éãä¿çè¡ä¿¡æ¯çï¼å ·ä½æ¯ä¸æ¡ä»ä¹ææè¿éä¸è¯¦è§£éï¼æå ´è¶£çç«¥éå¯ä»¥åèè¿ç¯æç«
å®æ¹é»è®¤çæ¯ç¨ â#cheap-module-eval-source-mapâ
devtool: '#cheap-module-eval-source-map'
设置好ä¹åï¼å¨vue项ç®è°è¯çæ¶åï¼ä»£ç éé¢æ 注debuggerçæ¶åå°±è½çå°å¯¹åºç代ç äºï¼é常æ¹ä¾¿ã
.debugger
æè ï¼ç´æ¥æ¾å°å¯¹åºçæ件ãå¨chromeç¨ âctrl(command) + pâï¼è¾å ¥æ件åï¼å¯ä»¥æ¾å°å¯¹åºçæºä»£ç ã
command+p
ææç¹ï¼
æç¹
éè¦æ³¨æçæ¯ï¼è¿éæç¹ä¼æå¨ä¸ä¸è¡ãåæ¶ä¸è¡ä»£ç è¿è¡å¨å®çä¸ä¸è¡æç®æ§è¡ã
.-vue-cli
vue家ç项ç®èææ¶ï¼æ¨è使ç¨ãvue-cliè家å¨è¿é
vue-cliå¯ä»¥å¸®æ们èªå¨æ建项ç®ï¼é¦å npmå ¨å±å®è£
npm install -g vue-cli
ç¶åå建ä¸ä¸ªæ°ç项ç®
vue init webpack my-project
ä¸è·¯å车ï¼æå®ã(æ´å¤é 置项请åèä¸é¢ç»åºçvue-clié¾æ¥)
è¿éä»ç½ä¸ä¸è½½äºä¸ä¸ªå¸¦webpackçvue项ç®(è·ä¹åè®°å¾npm installä¸ä¸)
.vue-cli webpack
ä»bulidæ件夹éé¢å°±å¤§æ¦è½çåºï¼
•webpack.dev.conf: å¼å模å¼ç¨
•webpack.prod.conf: ç产模å¼ç¨
å ¶ä¸ï¼å¼å模å¼æä¾äºdevtool为â#cheap-module-eval-source-mapâï¼ç产模å¼æ ¹æ®configæ件夹ä¸çproductionSourceMapåéæ§å¶æ¯å¦ä½¿ç¨ã
è¥ä¸ºtrueï¼ådevtool为â#source-mapâ
å ¶ä»ä½¿ç¨æ¹æ³ä¸è´ãé常æ¹ä¾¿ã
3.线ä¸è°è¯
å¹³æ¶å¼åçæ¶åï¼æ们ç¨webpackççå è½½ï¼å¯ä»¥çå»æè½½è°è¯çæ¥éª¤ï¼é常æ¹ä¾¿ãä½æ¯åå¸åé¨ç½²å°æå¡å¨ä¸ï¼å°±å¤±å»äºè¿ä¸ªæ¬å°ä¼å¿ã
å¦æ使ç¨æè½½æ件æ¹å¼ä¼æ¯è¾éº»ç¦ãç±äºwebpackæåºæ¥çæ件æçæ¬å·è¿äºä¿¡æ¯ï¼èä¸åå¸ä¸ä¸ªå ç代ç éå¯è½éè¦çå¾ ä¸çï¼è¿ä¸ªæ¹æ¡ä¸å®é ãä½æ¯å¦ææè½½çæ¯çå è½½å°ç«¯å£ä¸çæ件çè¯ï¼è¿ä¸ªé®é¢å°±å¾å¥½åäºã
-çå è½½
å¨æ¤ä¹åï¼å æ¥åæä¸ä¸webpackççå è½½åçã
对项ç®æå å¯ä»¥åç°è¿ä¹ä¸ä¸ªæ件ï¼__webpack_hmr
__webpack_hmr
è¿æ¯webpackçå è½½çæå¡å¨æ¨éäºä»¶ï¼eventsourceç±»åï¼åè½åwebsocketæç¹ç±»ä¼¼ã大è´ä½ç¨æ¯å»ºç«ä¸ä¸ªä¸ä¼åæ¢çstreamæµé¾æ¥ï¼æå¡å¨åéæ´æ°æ°æ®åæ¥appendå°æµçæ«ç«¯ï¼å端读åææ°appendçæ°æ®ï¼ç¶åå¨æçæ´æ°é¡µé¢ä¸çä¸è¥¿ã
æ¥ä¸æ¥æ们è§å¯ä¸ä¸ææå°çæ´æ°æ°æ®æåªäºãé便æ´æ°ä¸ä¸ªæ件ï¼è§¦åçå è½½ï¼åæ个å ï¼åç°æ两个.hot-update.jsonåä¸ä¸ª.hot-update.jsæ件
çå è½½æ´æ°æ件
è¿äºå ·ä½åäºäºå¥æä¸ç¥éï¼è¿éå°±ä¸æ·±ç©¶äºãåºè¯¥æ¯æ ¹æ®jsonéé¢çæ°æ®ï¼è¾¾å°ä¸ä¸ªåç¡®æ´æ°çææã
æ以çæ´æ°å ¶å®å°±æ¯çå¬æå¡å¨ä¸çæ°æ®ï¼æä¿®æ¹çè¯æå¡å¨åéæ°æ®è¿æ¥ï¼å端ææ°æ®æ¿æ¥åæ¿æ¢å°é¡µé¢ä¸è¿ä¹ä¸ä¸ªè¿ç¨ã
-AutoResponder
æ¥ä¸æ¥è°è°çº¿ä¸æè½½æµè¯ï¼è¿éæ¨èä¸æ¬¾è½¯ä»¶ï¼fiddler
fiddleræä¸ä¸ªåè½å«åAutoResponderï¼å®å¯ä»¥å°ä¸ä¸ªå°åæåå¦ä¸ä¸ªå°åãä¹æ以ç¨è¿ä¸ªè½¯ä»¶ï¼æ¯å 为å®è½å¹é æ£åï¼é常æ¹ä¾¿ã
AutoResponder
ä¸ä¸è说å°ï¼webpackçå è½½ç¨å°äºè¿å ç±»æ件
•__webpack_hmr
•xxxxxxxxxxx.hot-update.json
•xxxxxxxxxxx.hot-update.js
webpack之devtool详解
Webpack的Devtool详解 Webpack的Devtool是开发者在开发和调试过程中重要的工具之一,它可以帮助开发者更好地理解和调试代码。Devtool提供了多种不同的配置选项,用于生成源代码映射,以便于开发者在浏览器控制台中直接查看源代码,从而更有效地定位和解决代码中的问题。 一、什么是Devtool? Webpack的Devtool是一个配置选项,允许开发者在构建过程中生成源代码映射。源代码映射是一种文件,它将编译后的代码映射回原始源代码,以便于开发者调试。Devtool的不同配置选项会生成不同类型的源代码映射,适用于不同的开发场景。 二、Devtool的主要配置选项 1. eval模式:这是最简单的源代码映射形式,它直接在控制台输出源代码。这种模式下,不需要生成额外的文件,但生成的源代码映射相对较小且不持久。 2. source-map模式:在这种模式下,仙剑源码Webpack会生成一个独立的.map文件来存储源代码映射信息。这种模式的源代码映射比较详细,但会增加构建时间。 3. inline-source-map模式:与source-map模式类似,但源代码映射信息会直接嵌入到构建后的文件中。这种模式便于传输和分发构建后的文件,但同样会增加文件大小。 4. cheap-module-eval-source-map模式:适用于模块化的项目,能够提供模块级别的调试信息。它在开发和调试阶段很有用,但生成的源代码映射相对较小。 三、如何选择适合的Devtool配置? 选择Devtool的配置取决于项目的需求和开发阶段。在开发阶段,为了快速迭代和调试代码,可以选择生成更详细的源代码映射;而在生产环境,为了优化性能和文件大小,可以选择生成较小的源代码映射或者不使用源代码映射。常见的做法是在开发阶段使用如eval或cheap-module-eval-source-map等详细的配置选项,而在生产环境使用source-map或inline-source-map等更精简的配置选项。 总之,Webpack的Devtool是开发者在开发和调试过程中的重要工具,通过合理配置Devtool,可以大大提高开发效率和代码质量。放弃 console.log 吧!用 Debugger 你能读懂各种源码
很多同学不清楚为什么要使用debugger进行调试,难道console.log不行吗?
即使学会了使用debugger,还是有很多代码看不懂,如何调试复杂的源码呢?
这篇文章将为你讲解为什么要使用这些调试工具:console.log vs Debugger。
相信绝大多数同学都会使用console.log进行调试,将想查看的变量值打印在控制台。
这种方法可以满足基本需求,但遇到对象打印时就无法胜任了。
比如,我想查看webpack源码中的compilation对象的值,我尝试打印了一下:
但你会发现,当对象的值也是对象时,它不会展开,而是打印一个[Object] [Array]这样的字符串。
更严重的是,打印的内容过长会超过缓冲区的大小,在terminal中显示不全:
而使用debugger来运行,在这里设置一个断点查看,就没有这些问题了:
有些同学可能会说,那打印一个简单的值时使用console.log还是很方便的。
比如这样:
真的吗?
那还不如使用logpoint:
代码执行到这里就会打印:
而且没有污染代码,使用console.log的话,调试完成后这个console也不得不删除掉。
而logpoint不需要,它就是一个断点的设置,不在代码中。
当然,最重要的是debugger调试可以看到调用栈和作用域!
首先是调用栈,它就是代码的执行路线。
比如这个App的函数组件,你可以看到渲染这个函数组件会经历workLoop、beginWork、renderWithHooks等流程:
你可以点击调用栈的每一帧,查看都执行了什么逻辑,用到了什么数据。比如可以看到这个函数组件的fiber节点:
再就是作用域,点击每一个栈帧就可以看到每个函数的作用域中的变量:
使用debugger可以看到代码的执行路径,每一步的作用域信息。而你使用console.log呢?
只能看到那个变量的值而已。
得到的信息量差距不是一点半点,调试时间长了,别人会对代码的运行流程越来越清晰,而你使用console.log呢?还是老样子,因为你看不到代码执行路径。
所以,不管是调试库的源码还是业务代码,不管是调试Node.js还是网页,都推荐使用debugger打断点,别再用console.log了,即使想打印日志,也可以使用LogPoint。
而且在排查问题的时候,使用debugger的话可以加一个异常断点,代码跑到抛异常的地方就会断住:
可以看到调用栈来理清出错前都走了哪些代码,可以通过作用域来看到每一个变量的值。
有了这些,排查错误就变得轻松多了!
而你使用console.log呢?
什么也没有,只能自己猜。
Performance
前面说debugger调试可以看到一条代码的执行路径,但是代码的执行路径往往比较曲折。
比如那个React会对每个fiber节点做处理,每个节点都会调用beginWork。处理完之后又会处理下一个节点,再次调用beginWork:
就像你走了一条小路,然后回到大路之后又走了另一条小路,使用debugger只能看到当前这条小路的执行路径,看不到其他小路的路径:
这时候就可以结合Performance工具了,使用Performance工具看到代码执行的全貌,然后用debugger来深入每一条代码执行路径的细节。
SourceMap
sourcemap非常重要,因为我们执行的都是编译打包后的代码,基本是不可读的,调试这种代码也没有什么意义,而sourcemap就可以让我们直接调试最初的源码。
比如vue,关联了sourcemap之后,我们能直接调试ts源码:
nest.js也是:
不使用sourcemap的话,想搞懂源码,但你调试的是编译后的代码,怎么读懂呢?
读懂一行
前面说的debugger、Performance、SourceMap只是调试代码的工具,那会了调试工具,依然读不懂代码怎么办呢?
我觉得这是不可能的。
为什么这么说呢?
就拿react源码来说:
switch case能读懂吧。三目运算符能读懂吧。函数调用能读懂吧。
每一行代码都能读懂,而全部的代码不就是由这一行行代码组成的么?
加上我们可以单步执行来知道代码执行路径。
为啥每行代码都能读懂,连起来就读不懂了呢?
那应该是代码太多了,而你花的时间不够而已。
先要读懂一行,一个函数,读懂一个小功能的实现流程,慢慢积累,之后了解的越来越多之后,你能读懂的代码就会越多。
总结
这篇文章讲了为什么要使用调试工具,如何读懂复杂代码。
console.log的弊端太多了,大对象打印不全,会超过terminal缓冲区,对象属性不能展开等等,不建议大家使用。即使要打印也可以使用LogPoint。
使用debugger可以看到调用栈,也就是代码的执行路径,每个栈帧的作用域,可以知道代码从开始运行到现在都经历了什么,而console.log只能知道某个变量的值。
此外,报错的时候也可以通过异常断点来梳理代码执行路径来排查报错原因。
但debugger只能看到一条执行路径,可以使用Performance录制代码执行的全流程,然后再结合debugger来深入其中一条路径的执行细节。
此外,只有调试最初的源码才有意义,不然调试编译后的代码会少很多信息。可以通过SourceMap来关联到源码,不管是Vue、React的源码还是Nest.js、Babel等的源码。
会了调试之后,就能调试各种代码了,不存在看不懂的源码,因为每一行代码都是基础的语法,都是能看懂的,如果看不懂,只可能是代码太多了,你需要更多的耐心去读一行行代码、一个个函数、理清一个个功能的实现,慢慢积累就好了。
掌握基于debugger、Performance、SourceMap等调试代码之后,各种网页和Node.js代码都能调试,各种源码都能读懂!