-
Notifications
You must be signed in to change notification settings - Fork 2
/
rss.xml
459 lines (413 loc) · 152 KB
/
rss.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
<?xml version="1.0"?>
<rss version="2.0">
<channel>
<title>Lete乐特 's Blog</title>
<link>https://blog.imlete.cn</link>
<description>我相信我可以,但我一直在路上,所以我有无限的可能!!</description>
<language>zh-CN</language>
<pubDate>Tue, 17 Oct 2023 20:00:29 +0000</pubDate>
<lastBuildDate>Tue, 17 Oct 2023 20:00:29 +0000</lastBuildDate>
<category>CSS</category>
<category>记录</category>
<category>JavaScript</category>
<category>Git</category>
<category>教程</category>
<category>HTML</category>
<category>CDN</category>
<category>Github</category>
<category>Jsdeliver</category>
<category>SEO</category>
<category>Hexo</category>
<category>Yilia</category>
<category>Valine</category>
<category>Live2d</category>
<category>Config</category>
<category>LeanCloud</category>
<category>IDEA</category>
<category>Maven</category>
<category>Java</category>
<category>SpringBoot</category>
<category>Thymeleaf</category>
<category>java</category>
<category>源码</category>
<category>软件</category>
<category>MyBatis</category>
<category>SSM</category>
<category>Gzip</category>
<category>JQuery</category>
<category>Node</category>
<category>Cache</category>
<category>Vue</category>
<category>TypeScript</category>
<category>Vercel</category>
<category>HTTP</category>
<category>Typecho</category>
<category>Blog</category>
<category>Webpack</category>
<category>Windows</category>
<category>Linux</category>
<category>PhotoShop</category>
<category>抠图</category>
<category>VSCode</category>
<category>jsdelivr</category>
<category>C#</category>
<category>Google Chrome</category>
<category>谷歌插件</category>
<category>Google-Chrome</category>
<item>
<guid isPermalink="true">https://blog.imlete.cn/article/Virtual-DOM-slower-real-DOM.html</guid>
<title>虚拟 DOM 比真 DOM 烂</title>
<link>https://blog.imlete.cn/article/Virtual-DOM-slower-real-DOM.html</link>
<category>JavaScript</category>
<pubDate>Tue, 17 Oct 2023 20:00:29 +0000</pubDate>
<description><![CDATA[ <h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>在开始之前,说明一下为什么写这篇文章吧。虚拟 DOM(本文后面统一 <code>vDOM</code>),这个词经常在面试、社区文章中出现,都在说 vDOM 快、至于快在哪里也没个人能说的清楚(当然,我也不一定是对的,主要是分享自己对 vDOM 和 DOM 的看法),从网上看到的资料我能了解到的就是使用 JavaScript 的普通对象<code>抽象</code>出一个 vDOM 树,当数据变化的时候重新生成 vDOM 树,再通过 <code>diif</code> 算法比较<code>新</code> vDOM 和<code>旧</code>的 vDOM 对比,看看是哪块的数据变动了,最后将变动的地方<code>映射</code>到 DOM 上,从而完成页面数据的展示。那么问题就来了,既然最后都要修改 DOM 为什么还要弄出一个 vDOM 呢?吃饱了没事干?还遍历对比新旧 vDOM 的差异,饶了一圈不还是要改 DOM 吗?我陷入了沉思…..</p>
<h2 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h2><p>什么是 vDOM 我就不多说了,基于<code>前言</code>最后一句话的思考,我更想了解 vDOM 它究竟带来什么优点,前端巨头 Vue、React 都在用,这究竟是为什么??</p>
<p>于是我打开了 Vue 的官网 <a href="https://web.archive.org/web/20231017125349/https://cn.vuejs.org/guide/extras/rendering-mechanism">Virtual DOM</a>,并未在文档长看到有任何地方描述 vDOM 效率高、速度快、内存占用低。</p>
<p>再来看看 React 官网 <a href="https://web.archive.org/web/20231017131640/https://zh-hans.legacy.reactjs.org/docs/faq-internals.html">Virtual DOM - 中文</a> <a href="https://web.archive.org/web/20231017131401/https://legacy.reactjs.org/docs/faq-internals.html">Virtual DOM - 英语</a>,和 Vue 一样,并未提起 vDOM 效率高、速度快、内存占用低等字眼。其中有一句话:在 React 的世界里,术语 “Virtual DOM” 通常与 React 元素关联在一起,因为它们都是代表了<code>用户界面的对象</code>。</p>
<p>因此 vDOM 并不是在提高效率,而是在消耗效率。为什么这么说?因为同样是前端框架,后起之秀 <a href="https://svelte.dev">Svelte.js</a> 和 <a href="https://www.solidjs.com">Solid.js</a> 都没有使用 vDOM 反而效率还吊打 Vue.js 和 React.js ,效率甚至直逼 Vanilla.js (原生 JS)</p>
<h3 id="为什么需要虚拟-DOM"><a href="#为什么需要虚拟-DOM" class="headerlink" title="为什么需要虚拟 DOM"></a>为什么需要虚拟 DOM</h3><p>那么问题来了,为什么需要 vDOM,vDOM 效率不是比 DOM 低吗?为什么还要用?整那么多判断和数据对比,最后不还是要改 DOM 吗?为什么不直接改 DOM?</p>
<p>我们先想想 vDOM 究竟带来了什么优势。</p>
<ol>
<li><p>跨平台:借助一些工具可以将 vDOM <code>转换</code>成对应平台可以认识的东西<br>例如在浏览器中 react 就需要 react-dom 这个库在实现将 vDOM 转换成真实 DOM。<br>还有 react-native 将 vDOM 转换成 <code>Android</code> 和 <code>iOS</code> 平台可以使用的用户界面。<br><br>再举个 🌰,国内 uniApp 很多前端开发多多少少都听过吧?做小程序,或 APP 的,它使用 Vue vDOM 转换成对应平台、iOS、Android、小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)</p>
</li>
<li><p>简单方便: 能让你轻松的操作 DOM,也不用你去维护 DOM 的状态。<br>不像浏览器中的 DOM 每次都要 document.querySelector,甚至还要判断获取的这个真实 DOM 到底存不存在,这样写代码就非常的恶心</p>
</li>
<li><p>性能提升: 不是说 vDOM 性能比不上 DOM 吗?为什么还说它性能提升?<br>在某些情况下,vDOM 性能确实是要比 DOM 性能好,如果有 1000 个 DOM 节点(举例 ul&gt;li),这是后端返回的数据,需要渲染到页面上(一般人谁没事后端返回你那么多数据干嘛,更何况你也不能一次性渲染那么多数据啊,用户又看不到那么多,基本上都是做分页处理),假如有某种业务需求,修改了 100 个 li 接下来看看 vDOM 和 DOM 是怎么运行的吧<br><br>vDOM 生成一个新的 vDOM 跟旧的 vDOM 对比,发现有 100 个 li 数据发生了变化,这时 vDOM 开始修改 DOM ,这个过程中只触发一次 DOM 修改<br><br>DOM 可能也会和 vDOM 一样最后只触发一次 DOM 修改,也可能触发 100 次左右的 DOM 修改,具体看代码是怎么实现</p>
</li>
</ol>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">!(<span class="function">() =&gt;</span> &#123;</span><br><span class="line"> <span class="keyword">const</span> ul = <span class="variable language_">document</span>.<span class="title function_">querySelector</span>(<span class="string">&#x27;ul&#x27;</span>)</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; <span class="number">100</span>; i++) &#123;</span><br><span class="line"> <span class="keyword">const</span> li = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;li&#x27;</span>)</span><br><span class="line"> li.<span class="property">textContent</span> = i</span><br><span class="line"> <span class="comment">// 关键点</span></span><br><span class="line"> <span class="comment">// 每次给 ul 的子元素都添加一个 li,就排版一次,100次循环结束后排版了100次,也绘制渲染了100次</span></span><br><span class="line"> <span class="comment">// 不知道我这样说是不是对的,因为我对浏览器渲染原理也不是很了解。重排、重绘</span></span><br><span class="line"> ul.<span class="title function_">appendChild</span>(li)</span><br><span class="line"> &#125;</span><br><span class="line">&#125;)()</span><br><span class="line"></span><br><span class="line">!(<span class="function">() =&gt;</span> &#123;</span><br><span class="line"> <span class="keyword">const</span> ul = <span class="variable language_">document</span>.<span class="title function_">querySelector</span>(<span class="string">&#x27;ul&#x27;</span>)</span><br><span class="line"> <span class="keyword">const</span> fragment = <span class="variable language_">document</span>.<span class="title function_">createDocumentFragment</span>()</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; <span class="number">100</span>; i++) &#123;</span><br><span class="line"> <span class="keyword">const</span> li = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;li&#x27;</span>)</span><br><span class="line"> li.<span class="property">textContent</span> = i</span><br><span class="line"> <span class="comment">// 关键点</span></span><br><span class="line"> <span class="comment">// 每次给文档碎片里添加一个 li 这只是在内存中,并没有添加到页面上,所以页面并会不会发生什么变化</span></span><br><span class="line"> fragment.<span class="title function_">appendChild</span>(li)</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">// 直到循环完毕后,将文档碎片里的所有 li 一次性添加到 ul 里,此时页面只触发一次重排、重绘</span></span><br><span class="line"> ul.<span class="title function_">appendChild</span>(fragment)</span><br><span class="line">&#125;)()</span><br></pre></td></tr></table></figure>
<h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>本文仅仅是乐特对 vDOM 的理解和感悟,并未真正的去翻看文中提到的框架源码,所以我希望大家看完这篇文章后能够有一些自己的看法和理解,并自己行动去寻找自己的答案,而不是在网上看到别人写的文章就真的以为别人说的就是对的,从而丧失自己的判断里。就像网上发的短视频,未知事情真伪,仅仅是看到了别人裁剪视频的一小部分,就在评论区跟风</p>
<p>总结(这才是真正的总结),vDOM 并没有提高效率,反而是在降低效率,继续上面所说的 1000 个 DOM 节点,如果我只修改了 1 个 li 呢?vDOM 还是会生成一个新的 vDOM 和旧的 vDOM 对比,白白跑了 1000 次</p>
<p>如果有哪写的不对的,还请各位大佬指出 😁😁</p>
]]></description>
</item>
<item>
<guid isPermalink="true">https://blog.imlete.cn/article/Beautify-Windows-Terminal-PowerShell.html</guid>
<title>美化 Windows 终端(Terminal + PowerShell)</title>
<link>https://blog.imlete.cn/article/Beautify-Windows-Terminal-PowerShell.html</link>
<category>记录</category>
<category>Windows</category>
<pubDate>Sat, 18 Mar 2023 12:11:03 +0000</pubDate>
<description><![CDATA[ <h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>废话不多说,这是我做的一个 Oh-My-Posh 终端主题,仓库地址: <a href="https://github.com/Lete114/oh-my-posh-themes">https://github.com/Lete114/oh-my-posh-themes</a></p>
<p>效果如下:<br><img src="/img/Beautify-Windows-Terminal-PowerShell/lete114.png" alt=""></p>
<h2 id="Windows-Terminal"><a href="#Windows-Terminal" class="headerlink" title="Windows Terminal"></a>Windows Terminal</h2><blockquote>
<p>安装需要 Win10 2004(内部版本 19041)或更高版本</p>
</blockquote>
<p>Windows Terminal 是微软开源一个终端工具,主要功能包括多个选项卡、窗格、Unicode、和 UTF-8 字符支持,GPU 加速文本渲染引擎以及自定义主题、样式和配置</p>
<p>总之比 cmd、powershell 那丑不拉几的窗口好使就对了</p>
<p>可以通过微软商店直接安装,或者到开源仓库取下载安装都可以</p>
<p><a href="https://github.com/microsoft/terminal">https://github.com/microsoft/terminal</a></p>
<h2 id="Oh-My-Posh"><a href="#Oh-My-Posh" class="headerlink" title="Oh My Posh"></a>Oh My Posh</h2><p>Oh My Posh 类似于 Oh My zsh 的一个命令行提示工具,具体的得看官网描述 <a href="https://ohmyposh.dev/docs/">Oh My Posh Docs</a></p>
<p>安装 Oh My Posh ,参考官网安装教程<br><a href="https://ohmyposh.dev/docs/installation/windows">https://ohmyposh.dev/docs/installation/windows</a></p>
<p>使用 <code>winget</code> 安装</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">winget install JanDeDobbeleer.OhMyPosh -s winget</span><br></pre></td></tr></table></figure>
<blockquote>
<p>建议使用 powershell</p>
</blockquote>
<p>使用 Oh My Posh,如果你不找到你当前使用的是什么终端,你可以执行这条命令查看,具体详细请看官网 <a href="https://ohmyposh.dev/docs/installation/prompt">https://ohmyposh.dev/docs/installation/prompt</a></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">oh-my-posh get shell</span><br></pre></td></tr></table></figure>
<p>使用记事本或 vscode 打开 powershell 的配置文件</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 记事本</span></span><br><span class="line">notepad <span class="variable">$PROFILE</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># vscode</span></span><br><span class="line">code <span class="variable">$PROFILE</span></span><br></pre></td></tr></table></figure>
<blockquote>
<p>当上述命令出现错误时,确保先创建配置文件</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">New-Item -Path <span class="variable">$PROFILE</span> -Type File -Force</span><br></pre></td></tr></table></figure>
</blockquote>
<p>在文件中添加如下代码使用 Oh My Posh</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 注意这仅仅只是使用了 Oh My Posh,你可能会发现终端有乱码</span></span><br><span class="line"><span class="comment"># 因为 Oh My Posh 使用了 Nerd Fonts 字体中的一些图标,如果你的电脑中没有 Nerd Fonts 字体就会出现乱码</span></span><br><span class="line"><span class="comment"># 自带的主题就使用了 Nerd Fonts 的图标</span></span><br><span class="line">oh-my-posh init pwsh | Invoke-Expression</span><br><span class="line"></span><br><span class="line"><span class="comment"># 自定义主题,使用 Oh My Posh 自带的一些开箱即用主题</span></span><br><span class="line"><span class="comment"># 这里是 Oh My Posh 自带的主题 https://ohmyposh.dev/docs/themes</span></span><br><span class="line">oh-my-posh init pwsh --config <span class="string">&quot;<span class="variable">$env</span>:POSH_THEMES_PATH/robbyrussell.omp.json&quot;</span> | Invoke-Expression</span><br><span class="line"></span><br><span class="line"><span class="comment"># 下载我做的主题,我主题不需要安装 Nerd Fonts 字体</span></span><br><span class="line"><span class="comment"># https://raw.githubusercontent.com/Lete114/oh-my-posh-themes/main/lete114/lete114.minimal.omp.yaml</span></span><br><span class="line">oh-my-posh init pwsh --config <span class="string">&quot;你下载的路径/lete114.minimal.omp.yaml&quot;</span> | Invoke-Expression</span><br><span class="line"></span><br><span class="line"><span class="comment"># 之后执行以下命令加载配置文件</span></span><br><span class="line">. <span class="variable">$profile</span></span><br></pre></td></tr></table></figure>
<h3 id="安装字体"><a href="#安装字体" class="headerlink" title="安装字体"></a>安装字体</h3><p>如果你使用的主题是含 <code>minimal</code> 的就不需要安装</p>
<p>参考官方: <a href="https://ohmyposh.dev/docs/installation/fonts#configuration">https://ohmyposh.dev/docs/installation/fonts#configuration</a></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">oh-my-posh font install</span><br><span class="line"></span><br><span class="line"><span class="comment"># 也可以直接手动下载</span></span><br><span class="line"><span class="comment"># 下载完成后解压,全选右键点击安装即可自动安装</span></span><br><span class="line"><span class="comment"># https://github.com/ryanoasis/nerd-fonts/releases/download/v2.1.0/Meslo.zip</span></span><br></pre></td></tr></table></figure>
<blockquote>
<p>以下操作是根据 Oh My Posh 官网教程搬过来的,但不知道为什么我的字体依然显示乱码<br>有知道是啥问题的小伙伴可以在评论区回复我<br>当然,设置字体也可以在 Windows Terminal 的设置中设置,不必打开配置文件 (但同样我也不知道为什么我的 Windows Terminal 里面没有设置字体的选项,就挺离谱 😅)</p>
</blockquote>
<p>安装完成后打开 Windows Terminal 然后按 <code>Ctrl+Shift+,</code>(逗号) 来打开 settings.json 配置文件</p>
<p>找到 <code>profiles-&gt;defaults</code> 设置 <code>font-&gt;face</code></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line"> &quot;profiles&quot;:</span><br><span class="line"> &#123;</span><br><span class="line"> &quot;defaults&quot;:</span><br><span class="line"> &#123;</span><br><span class="line"> &quot;font&quot;:</span><br><span class="line"> &#123;</span><br><span class="line"> &quot;face&quot;: &quot;MesloLGM NF&quot;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="posh-git"><a href="#posh-git" class="headerlink" title="posh-git"></a>posh-git</h2><p>提供完整的 git 命令行提示以及自动补全</p>
<p><a href="https://github.com/dahlbyk/posh-git">https://github.com/dahlbyk/posh-git</a></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 安装 posh-git</span></span><br><span class="line">Install-Module posh-git -Scope CurrentUser -Force</span><br></pre></td></tr></table></figure>
<p>然后打开 PowerShell 配置文件,添加一行导入命令 <code>Import-Module posh-git</code> 即可</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 记事本打开配置文件</span></span><br><span class="line">notepad <span class="variable">$PROFILE</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 或使用 vscode 打开配置文件</span></span><br><span class="line">code <span class="variable">$PROFILE</span></span><br></pre></td></tr></table></figure>
<h2 id="PSReadLine"><a href="#PSReadLine" class="headerlink" title="PSReadLine"></a>PSReadLine</h2><blockquote>
<p>PowerShell 官方的插件,可以放心使用</p>
</blockquote>
<p>提供输入提醒,类似于 zsh 中有个插件,具体叫什么名字我忘了,就是当你输入一个命令输入到一半后,控制台就会有灰色命令提示,之后按下方向键的右键(-&gt;)键就能不全的根据</p>
<p><a href="https://github.com/PowerShell/PSReadLine">https://github.com/PowerShell/PSReadLine</a></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 以下是搬运的官方的教程</span></span><br><span class="line"></span><br><span class="line">Install-Module -Name PowerShellGet -Force</span><br><span class="line">Install-Module PSReadLine -AllowPrerelease -Force</span><br></pre></td></tr></table></figure>
<p>之后</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment"># 记事本打开配置文件</span></span><br><span class="line">notepad <span class="variable">$PROFILE</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 或使用 vscode 打开配置文件</span></span><br><span class="line">code <span class="variable">$PROFILE</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># PSReadLine</span></span><br><span class="line">Import-Module PSReadLine</span><br><span class="line"><span class="comment"># Enable Prediction History</span></span><br><span class="line">Set-PSReadLineOption -PredictionSource History</span><br><span class="line"><span class="comment"># Advanced Autocompletion for arrow keys</span></span><br><span class="line">Set-PSReadlineKeyHandler -Key UpArrow -Function HistorySearchBackward</span><br><span class="line">Set-PSReadlineKeyHandler -Key DownArrow -Function HistorySearchForward</span><br></pre></td></tr></table></figure>
]]></description>
</item>
<item>
<guid isPermalink="true">https://blog.imlete.cn/article/nonuse-es6+-implements-call-apply-bind.html</guid>
<title>不使用 ES6+ 实现 call apply bind 方法</title>
<link>https://blog.imlete.cn/article/nonuse-es6+-implements-call-apply-bind.html</link>
<category>记录</category>
<category>JavaScript</category>
<pubDate>Fri, 04 Nov 2022 15:24:31 +0000</pubDate>
<description><![CDATA[ <p>使用 ES6+ 实现这三个方法其实非常简单,本文就来挑战一下,如果不适用 ES6+ 的情况下如何实现这三个方法</p>
<blockquote>
<p>难点: 不能使用扩展运算符(…)该如何接收参数和传入参数</p>
</blockquote>
<p>至于这三个方法有什么区别可以阅读我之前的这篇文章 <a href="/article/call-apply-bind-distinction.html">call()-apply()-bind()方法有什么不同?</a></p>
<h2 id="apply"><a href="#apply" class="headerlink" title="apply"></a>apply</h2><p>就不多说废话了,直接看代码</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="title class_">Function</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">myApply</span> = <span class="keyword">function</span> (<span class="params">_this, args</span>) &#123;</span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> _this = _this || <span class="variable language_">window</span></span><br><span class="line"> _this[<span class="string">&#x27;#function#&#x27;</span>] = <span class="variable language_">this</span></span><br><span class="line"> <span class="keyword">if</span> (!args) &#123;</span><br><span class="line"> <span class="keyword">return</span> _this[<span class="string">&#x27;#function#&#x27;</span>]()</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="keyword">var</span> params = <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(args)</span><br><span class="line"> <span class="comment">// 当 JSON.stringify 把一个数组解析成字符串是会多套一层 ‘[]’ ,所以需要裁切掉</span></span><br><span class="line"> params = params.<span class="title function_">slice</span>(<span class="number">1</span>, params.<span class="property">length</span> - <span class="number">1</span>)</span><br><span class="line"> <span class="comment">// 由于 Function 无法访问上级作用域,由于上层以及裁掉了首尾部分</span></span><br><span class="line"> <span class="comment">// 所以得到 _this[&quot;#function#&quot;](1,2) 这样就能实现扩展运算符(...)的操作了,关于 new Function 请自行查阅</span></span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Function</span>(<span class="string">&#x27;_this&#x27;</span>, <span class="string">&#x27;return _this[&quot;#function#&quot;](&#x27;</span> + params + <span class="string">&#x27;)&#x27;</span>)(_this)</span><br><span class="line"></span><br><span class="line"> <span class="comment">// ------ 上面这坨你也可以改为 eval() ------</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> params = []</span><br><span class="line"> <span class="comment">// 注意,这里的 i 初始值是 1 主要目的是为了去除第一个参数(也就是 _this)</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">1</span>; i &lt; <span class="variable language_">arguments</span>.<span class="property">length</span>; i++) &#123;</span><br><span class="line"> params.<span class="title function_">push</span>(<span class="string">&#x27;arguments[&#x27;</span> + i + <span class="string">&#x27;]&#x27;</span>)</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">// 这里解释一下,当引用类型与字符串拼接的时候会隐式调用 toString() ,数组调用 toString() 会返回如下结果</span></span><br><span class="line"> <span class="comment">// _this[&quot;#function#&quot;](arguments[1],arguments[2],arguments[3])</span></span><br><span class="line"> <span class="comment">// eval 执行后可以访问上级作用域的变量,这里就可以实现扩展运算符(...)的操作了</span></span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">eval</span>(<span class="string">&#x27;_this[&quot;#function#&quot;](&#x27;</span> + params + <span class="string">&#x27;)&#x27;</span>)</span><br><span class="line"> &#125;</span><br><span class="line"> &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line"> <span class="keyword">delete</span> _this[<span class="string">&#x27;#function#&#x27;</span>]</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="call"><a href="#call" class="headerlink" title="call"></a>call</h2><p>由于前面以及实现了 <code>myApply</code> 方法,再 <code>myCall</code> 即可直接调用,如果要完整写一个 <code>myCall</code> 也只是增加代码冗余而已</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="title class_">Function</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">myCall</span> = <span class="keyword">function</span> (<span class="params">_this</span>) &#123;</span><br><span class="line"> _this = _this || <span class="variable language_">window</span></span><br><span class="line"> <span class="keyword">var</span> params = []</span><br><span class="line"> <span class="comment">// 注意,这里的 i 初始值是 1 主要目的是为了去除第一个参数(也就是 _this)</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">1</span>; i &lt; <span class="variable language_">arguments</span>.<span class="property">length</span>; i++) &#123;</span><br><span class="line"> params.<span class="title function_">push</span>(<span class="variable language_">arguments</span>[i])</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="title function_">myApply</span>(_this, params)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="bind"><a href="#bind" class="headerlink" title="bind"></a>bind</h2><p>如上,可以继续复用已经封装好的</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="title class_">Function</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">myBind</span> = <span class="keyword">function</span> (<span class="params">_this</span>) &#123;</span><br><span class="line"> _this = _this || <span class="variable language_">window</span></span><br><span class="line"> <span class="keyword">var</span> self = <span class="variable language_">this</span></span><br><span class="line"> <span class="keyword">var</span> params = []</span><br><span class="line"> <span class="comment">// 注意,这里的 i 初始值是 1 主要目的是为了去除第一个参数(也就是 _this)</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">1</span>; i &lt; <span class="variable language_">arguments</span>.<span class="property">length</span>; i++) &#123;</span><br><span class="line"> params.<span class="title function_">push</span>(<span class="variable language_">arguments</span>[i])</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line"> <span class="comment">// 注意这里的 i 初始值是 0 ,因为它不需要移除 _this ,可能这有点乱,希望读者多多思考</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i &lt; <span class="variable language_">arguments</span>.<span class="property">length</span>; i++) &#123;</span><br><span class="line"> params.<span class="title function_">push</span>(<span class="variable language_">arguments</span>[i])</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> self.<span class="title function_">myApply</span>(_this, params)</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>以上就是本文的全部内容,可能会存在一些小瑕疵,希望各位读者留言评论或优化</p>
]]></description>
</item>
<item>
<guid isPermalink="true">https://blog.imlete.cn/article/webpack-on-demand-loading-principle.html</guid>
<title>webpack 按需加载原理</title>
<link>https://blog.imlete.cn/article/webpack-on-demand-loading-principle.html</link>
<category>JavaScript</category>
<category>教程</category>
<pubDate>Sat, 15 Oct 2022 10:45:51 +0000</pubDate>
<description><![CDATA[ <blockquote>
<p>本文不会带你去阅读 <code>build</code> 后的源码,而是告诉你它是怎么做到的,原理是什么,怎么实现,如何自己动手做一个按需加载模块,如果不想听本文 BB,可直接一步到页脚,获取完整代码 <a href="#完整的按需加载代码">#完整的按需加载代码</a></p>
</blockquote>
<h2 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h2><p>如果你想阅读源码,你可以根据下面的结构去创建,然后自己打包阅读源码</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// webpack.config.js</span></span><br><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">&#x27;path&#x27;</span>)</span><br><span class="line"><span class="keyword">const</span> mode = <span class="string">&#x27;production&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line"> mode,</span><br><span class="line"> <span class="attr">entry</span>: <span class="string">&#x27;./src/index.js&#x27;</span>,</span><br><span class="line"> <span class="attr">output</span>: &#123;</span><br><span class="line"> <span class="attr">path</span>: path.<span class="title function_">join</span>(__dirname, <span class="string">&#x27;dist&#x27;</span>),</span><br><span class="line"> <span class="attr">filename</span>: <span class="string">&#x27;main.js&#x27;</span>,</span><br><span class="line"> <span class="attr">chunkFilename</span>: <span class="string">&#x27;[name].js&#x27;</span>,</span><br><span class="line"> <span class="attr">libraryTarget</span>: <span class="string">&#x27;umd&#x27;</span></span><br><span class="line"> &#125;,</span><br><span class="line"> <span class="attr">optimization</span>: &#123;</span><br><span class="line"> <span class="attr">minimize</span>: <span class="literal">false</span></span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// src/test.js</span></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = <span class="string">&#x27;test&#x27;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// src/index.js</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 当调用 window 的 init 方法时触发加载 test.js ,加载完成后输出结果</span></span><br><span class="line"><span class="variable language_">window</span>.<span class="property">init</span> = <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line"> <span class="title function_">import</span>(<span class="comment">/* webpackChunkName: &quot;test&quot; */</span> <span class="string">&#x27;./test&#x27;</span>).<span class="title function_">then</span>(<span class="function">(<span class="params">r</span>) =&gt;</span> &#123;</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(r)</span><br><span class="line"> &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="import-干了什么"><a href="#import-干了什么" class="headerlink" title="import() 干了什么"></a>import() 干了什么</h2><p>其实 webpack 就是把 <code>import()</code> 动态导入的模块打包成了一个文件,而其中的 <code>webpackChunkName</code> 注释就是定义打包后这个动态模块的 js 文件,上方指定命名为 <code>test</code>,则打包结果为 <code>test.js</code>,如果没有写 <code>webpackChunkName</code> 那么 webpack 会自动定义随机的文件名(当然这不是随机的,它是根据文件中的内容进行 hash 推算的,只要内容没变,他就一直是这个名字,这段感兴趣的可以自己去阅读源码)</p>
<h2 id="如何获取-url"><a href="#如何获取-url" class="headerlink" title="如何获取 url"></a>如何获取 url</h2><p>我在没看打包结果的源码时,我是这样想的,既然要加载,那么一定是通过 <code>script</code> 标签<br>因为引入是多变的,比如通过本地引入,或是 cdn 引入,又或者是其它方式,而 webpack 它是无法判断引入方式的,那么该如何获取 js 文件的 url 地址呢?</p>
<p>拦截请求:<br>不过 <code>script</code> 发出的请求是浏览器发送的,并不像 <code>xhr</code> 一样可以包装一层进行 hook 拦截<br>于是我又想到了 <code>Service Workers</code> 的 <code>fetch</code> 事件,不过 webpack 怎么可能干这种事,这就属于入侵式修改了,不合理</p>
<p>思来想去,我实在是想不到有啥办法了,于是我就去看了源码,万万没想到啊,居然是用 <a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Document/currentScript">document.currentScript</a> 属性,我居然把这给忘了:(</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 获取当前 script 标签的 src 属性</span></span><br><span class="line"><span class="variable language_">document</span>.<span class="property">currentScript</span>.<span class="property">src</span></span><br></pre></td></tr></table></figure>
<p>webpack 源码里还写了一个获取当前 script 标签的代码</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 获取到所有的 script 标签</span></span><br><span class="line"><span class="keyword">var</span> scripts = <span class="variable language_">document</span>.<span class="title function_">getElementsByTagName</span>(<span class="string">&#x27;script&#x27;</span>)</span><br><span class="line"><span class="comment">// 如果有,这通过下表获取</span></span><br><span class="line"><span class="keyword">if</span> (scripts.<span class="property">length</span>) scriptUrl = scripts[scripts.<span class="property">length</span> - <span class="number">1</span>].<span class="property">src</span></span><br></pre></td></tr></table></figure>
<p>原理是什么呢?,大家都知道,html 是从上往下解析的,当解析到 script 标签时,浏览器会阻塞页面渲染,等待下载完当前 js 并执行完成后才会继续往下解析,(除非你给当前 script 标签使用了 <code>async</code> 或 <code>defer</code> 属性,至于这俩属性的作用,可自行网上搜索)这时使用 <code>document.getElementsByTagName(&#39;script&#39;)</code> 获取页面上的 script 标签则只会获取到已经解析的 script 标签,所以当前的 script 标签它一定是最后一个 script 标签,就可以通过 <code>length - 1</code> 获取啦</p>
<p>既然得到了 url,那么就可以加载 js 了,只需要把当前的 js 文件名改成需要加载的 js 文件名,也就是前面所说的 <code>webpackChunkName</code></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> scriptUrl</span><br><span class="line"><span class="keyword">if</span> (<span class="variable language_">document</span>.<span class="property">currentScript</span>) scriptUrl = <span class="variable language_">document</span>.<span class="property">currentScript</span>.<span class="property">src</span></span><br><span class="line"><span class="keyword">if</span> (!scriptUrl) &#123;</span><br><span class="line"> <span class="keyword">const</span> scripts = <span class="variable language_">document</span>.<span class="title function_">getElementsByTagName</span>(<span class="string">&#x27;script&#x27;</span>)</span><br><span class="line"> <span class="keyword">if</span> (scripts.<span class="property">length</span>) scriptUrl = scripts[scripts.<span class="property">length</span> - <span class="number">1</span>].<span class="property">src</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (!scriptUrl) <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">&#x27;Automatic publicPath is not supported in this browser&#x27;</span>)</span><br><span class="line"><span class="comment">// 结果以下几个 replace() 即可得到 url</span></span><br><span class="line">scriptUrl = scriptUrl</span><br><span class="line"> .<span class="title function_">replace</span>(<span class="regexp">/#.*$/</span>, <span class="string">&#x27;&#x27;</span>) <span class="comment">// 去除锚点</span></span><br><span class="line"> .<span class="title function_">replace</span>(<span class="regexp">/\?.*$/</span>, <span class="string">&#x27;&#x27;</span>) <span class="comment">// 去除参数</span></span><br><span class="line"> .<span class="title function_">replace</span>(<span class="regexp">/\/[^/]+$/</span>, <span class="string">&#x27;/&#x27;</span>) <span class="comment">// 去除文件名</span></span><br></pre></td></tr></table></figure>
<h2 id="如何加载"><a href="#如何加载" class="headerlink" title="如何加载"></a>如何加载</h2><p>因为在上一步我们已经得到 url,此时只需要拼接上 <code>webpackChunkName</code> 的文件名就可以加载指定的 js 了</p>
<p>那么<code>webpackChunkName</code>是怎么来的呢?<br>如果你用的是 webpack,那么它已经帮你做好了,反之则得自己写,其实很简单</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 定义一个对象,里面写好动态加载的js文件名即可</span></span><br><span class="line"><span class="keyword">const</span> map = &#123; <span class="attr">admin</span>: <span class="string">&#x27;discuss.admin.js&#x27;</span> &#125;</span><br></pre></td></tr></table></figure>
<p>然后通过 js 动态创建 script 标签加载 js 即可,最后加上一个 <code>onload</code> 事件,等待加载成功后自行代码即可</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// chunk: js 文件名</span></span><br><span class="line"><span class="comment">// callback: 回调函数,当js加载完成后执行</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">loadScript</span> = (<span class="params">chunk, callback</span>) =&gt; &#123;</span><br><span class="line"> <span class="keyword">const</span> script = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;script&#x27;</span>)</span><br><span class="line"> script.<span class="property">src</span> = scriptUrl + map[chunk]</span><br><span class="line"> script.<span class="property">onload</span> = <span class="function">() =&gt;</span> &#123;</span><br><span class="line"> <span class="comment">// 执行完成后及时释放,让系统回收内存,毕竟我们只需要加载一次即可</span></span><br><span class="line"> script.<span class="property">onload</span> = <span class="literal">null</span></span><br><span class="line"> <span class="title function_">callback</span>()</span><br><span class="line"> <span class="comment">// 删掉动态加载的 script 标签 dom 元素(不会对程序照成影响)</span></span><br><span class="line"> script.<span class="property">parentNode</span> &amp;&amp; script.<span class="property">parentNode</span>.<span class="title function_">removeChild</span>(script)</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="variable language_">document</span>.<span class="property">head</span>.<span class="title function_">appendChild</span>(script)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>最后还有一个问题需要解决,那就是避免在多次执行<code>window.init()</code>时触发多次加载,导致多次请求,照成不必要的请求,以及浪费流量带宽</p>
<p>既然已经加载,那么就留个标记,表示这个 url 已经加载过了,下载执行不要不要继续创建 script 标签即可</p>
<p>定义一个数组用来储存已经加载过的动态 js,<code>const chunks = []</code> 在动态创建 script 标签之前将文件名<code>push()</code>进去数组里即可</p>
<h2 id="完整的按需加载代码"><a href="#完整的按需加载代码" class="headerlink" title="完整的按需加载代码"></a>完整的按需加载代码</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// source: https://github.com/discussjs/discuss/blob/dc345810e6696f1282fca65df039b2186b1f34d1/src/client/lib/import.js</span></span><br><span class="line"><span class="keyword">let</span> scriptUrl</span><br><span class="line"><span class="keyword">if</span> (<span class="variable language_">document</span>.<span class="property">currentScript</span>) scriptUrl = <span class="variable language_">document</span>.<span class="property">currentScript</span>.<span class="property">src</span></span><br><span class="line"><span class="keyword">if</span> (!scriptUrl) &#123;</span><br><span class="line"> <span class="keyword">const</span> scripts = <span class="variable language_">document</span>.<span class="title function_">getElementsByTagName</span>(<span class="string">&#x27;script&#x27;</span>)</span><br><span class="line"> <span class="keyword">if</span> (scripts.<span class="property">length</span>) scriptUrl = scripts[scripts.<span class="property">length</span> - <span class="number">1</span>].<span class="property">src</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (!scriptUrl) <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">&#x27;Automatic publicPath is not supported in this browser&#x27;</span>)</span><br><span class="line">scriptUrl = scriptUrl</span><br><span class="line"> .<span class="title function_">replace</span>(<span class="regexp">/#.*$/</span>, <span class="string">&#x27;&#x27;</span>) <span class="comment">// 去除锚点</span></span><br><span class="line"> .<span class="title function_">replace</span>(<span class="regexp">/\?.*$/</span>, <span class="string">&#x27;&#x27;</span>) <span class="comment">// 去除参数</span></span><br><span class="line"> .<span class="title function_">replace</span>(<span class="regexp">/\/[^/]+$/</span>, <span class="string">&#x27;/&#x27;</span>) <span class="comment">// 去除文件名</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 未来避免于其它js产生全局变量冲突,你可以定义为一个其它比较复杂的变量名</span></span><br><span class="line"><span class="variable language_">window</span>.<span class="property">chunks</span> = []</span><br><span class="line"><span class="keyword">const</span> map = &#123; <span class="attr">admin</span>: <span class="string">&#x27;discuss.admin.js&#x27;</span> &#125;</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">loadScript</span> = (<span class="params">chunk, callback</span>) =&gt; &#123;</span><br><span class="line"> <span class="comment">// 如果存在,则直接执行回调</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="variable language_">window</span>.<span class="property">chunks</span>.<span class="title function_">includes</span>(chunk)) <span class="keyword">return</span> <span class="title function_">callback</span>()</span><br><span class="line"> <span class="comment">// 如果上方判断没有成立,则push到数组里,下次执行就会立即执行回调不必再向下执行代码</span></span><br><span class="line"> <span class="variable language_">window</span>.<span class="property">chunks</span>.<span class="title function_">push</span>(chunk)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> script = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;script&#x27;</span>)</span><br><span class="line"> script.<span class="property">src</span> = scriptUrl + map[chunk]</span><br><span class="line"> script.<span class="property">onload</span> = <span class="function">() =&gt;</span> &#123;</span><br><span class="line"> script.<span class="property">onload</span> = <span class="literal">null</span></span><br><span class="line"> <span class="title function_">callback</span>()</span><br><span class="line"> script.<span class="property">parentNode</span> &amp;&amp; script.<span class="property">parentNode</span>.<span class="title function_">removeChild</span>(script)</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="variable language_">document</span>.<span class="property">head</span>.<span class="title function_">appendChild</span>(script)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> loadScript</span><br></pre></td></tr></table></figure>
]]></description>
</item>
<item>
<guid isPermalink="true">https://blog.imlete.cn/article/CardLink.html</guid>
<title>使用 CardLink 库生产卡片式链接</title>
<link>https://blog.imlete.cn/article/CardLink.html</link>
<category>JavaScript</category>
<pubDate>Mon, 11 Jul 2022 09:52:21 +0000</pubDate>
<description><![CDATA[ <script async src="/js/cardlink.js" ></script>
<p>有时候经常看到知乎的文章,或者问题中的链接是卡片式的</p>
<p>将卡片式链接与普通的链接相比,卡片式链接不仅美观,还展示更多信息,如:标题、图片、网址等</p>
<p>效果如下 <a href="https://github.com/Lete114/CardLink">CardLink</a></p>
<h2 id="CardLink"><a href="#CardLink" class="headerlink" title="CardLink"></a>CardLink</h2><p>一些使用方法请见 <a href="https://github.com/Lete114/CardLink">https://github.com/Lete114/CardLink</a></p>
<p>通过 CDN 的方式引入 CardLink</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 建议放在head标签里 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.jsdelivr.net/npm/cardlink&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 建议放在 &lt;/body&gt; 之前 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"> <span class="comment">// 为&lt;article&gt;&lt;/article&gt;(文章)标签下所有打开新标签窗口的a标签生成卡片链接</span></span></span><br><span class="line"><span class="language-javascript"> <span class="title function_">cardLink</span>(<span class="variable language_">document</span>.<span class="title function_">querySelectorAll</span>(<span class="string">&#x27;article a[target=_blank]&#x27;</span>))</span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>当你想让特定的链接变成卡片式链接时你可以为它添加上 <code>cardlink</code> 属性</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 建议放在 &lt;/body&gt; 之前 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"> <span class="comment">// CardLink 默认会对页面上所有a[cardlink]生成卡片链接</span></span></span><br><span class="line"><span class="language-javascript"> <span class="title function_">cardLink</span>()</span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>或者如果你使用 <code>markdown</code> 写内容的时候,可以直接在内容中写 <code>HTML</code></p>
<figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">## 标题 1</span></span><br><span class="line"></span><br><span class="line">其它内容...</span><br><span class="line"></span><br><span class="line">正常 markdown 语法</span><br><span class="line">[<span class="string">https://Lete114.github.io/CardLink</span>](<span class="link">https://Lete114.github.io/CardLink</span>)</span><br><span class="line"></span><br><span class="line">html 语法</span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;https://Lete114.github.io/CardLink/&quot;</span> <span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="section">## 标题 2</span></span><br><span class="line"></span><br><span class="line">其它内容...</span><br></pre></td></tr></table></figure>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 建议放在 &lt;/body&gt; 之前 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"> <span class="comment">// CardLink 默认会对页面上所有a[cardlink]生成卡片链接</span></span></span><br><span class="line"><span class="language-javascript"> <span class="title function_">cardLink</span>()</span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h3 id="跨域请求"><a href="#跨域请求" class="headerlink" title="跨域请求"></a>跨域请求</h3><ol>
<li>搭建代理服务器,将目标链接传给代理服务器,让代理服务器去请求 HTML 文本并返回<br><a href="https://github.com/Lete114/CardLink/tree/server">CardLink-Server</a></li>
<li>使用在线免费的跨域代理<br>(前者是博主自己搭建的跨域请求服务,后者是网上找的免费跨域请求服务)<br><code>https://api.allorigins.win/raw?url=</code></li>
</ol>
]]></description>
</item>
<item>
<guid isPermalink="true">https://blog.imlete.cn/article/build-ts-doc.html</guid>
<title>如何为自己的js项目生成API文档</title>
<link>https://blog.imlete.cn/article/build-ts-doc.html</link>
<category>JavaScript</category>
<category>TypeScript</category>
<pubDate>Mon, 06 Jun 2022 15:52:50 +0000</pubDate>
<description><![CDATA[ <p>如题,当自己写完了一个第三方库,准备发布时,总不能直接把一些使用方法以及传参说明写在<code>README.md</code>里吧</p>
<p>看到许多第三方库都有一个<code>.d.ts</code>文件,当我们使用这些第三方库时,在方法上安装<code>ctrl+鼠标左键</code>时就会跳转到对应<code>.d.ts</code>说明文档中</p>
<p>那么这个是咱们做的呢?难道是手动创建并编写的吗?不是吧?如果是手动创建的话,哪些大型项目那么多方法和文件模块,并且还是多人协作开发,不可能同步如此庞大的<code>.d.ts</code>文件,那么这个是怎么做的呢?</p>
<p>这个是使用<code>TypeScript</code>生成的,不是吧?那我用的不是<code>TypeScript</code>写的库不就不能生成了?</p>
<p>非也非也,即使不是用<code>TypeScript</code>写的项目也能生成<code>.d.ts</code>文件</p>
<p>只要你写的时候在方法上添加注释即可,注释关键字必须遵循<a href="https://jsdoc.app/">JSDoc</a></p>
<p>JSDoc 中有很多关键字,这些关键字想必你多多少少会在其它第三方库的<code>.d.ts</code>文件中见过,如: <code>@param</code> <code>@returns</code> <code>@author</code>等,更多具体的请自行在<a href="https://jsdoc.app/">JSDoc</a>中查看</p>
<p>说了那么多,那么到底如何生成<code>.d.ts</code>文档呢?</p>
<p>举例我目前有一个<code>/src/main.js</code>,其中代码如下</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 代码来源于: https://github.com/Lete114/CardLink/blob/f4ab08b78625244d9515743e41c7e04f839e149f/src/main.js#L12</span></span><br><span class="line"><span class="comment"> * Determine if it is a [&#x27;https://&#x27;, &#x27;http://&#x27;, &#x27;//&#x27;] protocol</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">String</span>&#125; url Website url</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@returns</span> &#123;<span class="type">Boolean</span>&#125;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">isHttp</span>(<span class="params">url</span>) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="regexp">/^(https?:)?\/\//g</span>.<span class="title function_">test</span>(url)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>只需一行命令即可,使用 npx 临时安装<code>typescript</code>,并调用<code>typescript</code>的命令生成<code>.d.ts</code>文档</p>
<blockquote>
<p>注意其中<code>-p</code>是 npx 的命令,原名<code>--package</code>,具体请看官网<a href="https://docs.npmjs.com/cli/v8/commands/npx">https://docs.npmjs.com/cli/v8/commands/npx</a></p>
</blockquote>
<ul>
<li><code>src/**/*.js</code>: 对 src 目录下的所有 js 文件生成<code>.d.ts</code>文件</li>
<li><code>--declaration</code>: 生成相应的<code>.d.ts</code>文件</li>
<li><code>--allowJs</code>: 允许编译 javascript 文件</li>
<li><code>--emitDeclarationOnly</code>: 只输出 <code>.d.ts</code> 文件,不输出 JavaScript 文件</li>
<li><code>--outDir</code>: 输出到指定的目录</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npx -p typescript tsc src/**.js --declaration --allowJs --emitDeclarationOnly --outDir types</span><br></pre></td></tr></table></figure>
<p>执行如上命令后就会先下载<code>typescript</code>,然后执行 tsc 命令,构建生成<code>.d.ts</code> 文件到<code>types/main.d.ts</code></p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 代码来源于: https://github.com/Lete114/CardLink/blob/f4ab08b78625244d9515743e41c7e04f839e149f/src/main.js#L12</span></span><br><span class="line"><span class="comment"> * Determine if it is a [&#x27;https://&#x27;, &#x27;http://&#x27;, &#x27;//&#x27;] protocol</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">String</span>&#125; url Website url</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@returns</span> &#123;<span class="type">Boolean</span>&#125;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">function</span> <span class="title function_">isHttp</span>(<span class="params">url: <span class="built_in">string</span></span>): <span class="built_in">boolean</span></span><br></pre></td></tr></table></figure>
]]></description>
</item>
<item>
<guid isPermalink="true">https://blog.imlete.cn/article/Static-resource-cache-control.html</guid>
<title>前端优化之静态资源缓存控制</title>
<link>https://blog.imlete.cn/article/Static-resource-cache-control.html</link>
<category>CSS</category>
<category>JavaScript</category>
<category>HTML</category>
<category>Cache</category>
<pubDate>Thu, 12 May 2022 11:51:45 +0000</pubDate>
<description><![CDATA[ <blockquote>
<p>本文转自<a href="https://www.zhihu.com/question/20790576/answer/32602154">@张云龙</a>,于 2014 年 10 月在知乎上的一个问题回答,博主觉得这位大佬写的很好,也很详细,于是就把内容搬到了自己的博客上,便于以后自己查阅</p>
</blockquote>
<h2 id="太长不想看"><a href="#太长不想看" class="headerlink" title="太长不想看"></a>太长不想看</h2><p>使用强制缓存如何,如何让用户能够及时使用最新修改后的静态资源?</p>
<ol>
<li>修改资源文件名<code>index-v1.css</code></li>
<li>修改资源文件名,并且对文件内容生成 hash 值(内容改变,则 hash 改变反之不改变)(<code>index.v1tg6l.css</code>)</li>
<li>为资源添加请求参数(该参数没有任何作用,只是为了修改 url 地址)与第二条一样生成 hash(<code>index.css?v=qb6l0p</code>)</li>
</ol>
<blockquote>
<p>总结: 只要修改了资源请求的 url 地址,那么就会获取最新修改的静态资源,从而主动弃用旧静态资源<br>很多大网站都会使用这种方式,例如 baidu,taobao</p>
</blockquote>
<h2 id="什么是-HTTP-缓存"><a href="#什么是-HTTP-缓存" class="headerlink" title="什么是 HTTP 缓存"></a>什么是 HTTP 缓存</h2><p>HTTP 缓存分为两种(本文不会深究响应头的众多参数)</p>
<ul>
<li>强制缓存: (状态码始终 200)在规定时间内,不用向服务器发送请求,直接使用本地缓存(超过规定时间后才会重新向服务器发送请求获取资源)</li>
<li>协商缓存: (状态码过期 200,未过期 304)每次都会向服务器确认,这个本地资源有没有过期,过期: 服务器返回新资源。未过期: 让浏览器使用本地缓存</li>
</ul>
<h2 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h2><p>使用强制缓存如何,如何让用户能够及时使用最新修改后的静态资源?</p>
<p>这是一个普通网站的结构<br><img src="/img/Static-resource-cache-control/1.png" alt=""></p>
<p>访问这个网站,可以看到网络请求状态,响应状态 200,这是在正常不过的事了<br>那就看看<code>a.css</code>的请求吧,如果每次用户访问页面都要加载,是不是很影响性能,很浪费带宽啊<br><img src="/img/Static-resource-cache-control/2.png" alt=""></p>
<p>我们希望最好这样,利用 304,让浏览器使用本地缓存。但,这样就够了吗?不成!<strong>304 叫协商缓存</strong>,这玩意儿还是需要向浏览器发送一个请求,问问服务器这个资源有没有更新</p>
<blockquote>
<p>更新: 返回新资源<br>没更新: 告诉浏览器使用本地缓存</p>
</blockquote>
<p><img src="/img/Static-resource-cache-control/3.png" alt=""></p>
<p>使用<strong>强制缓存(cache-control/expires)</strong>让浏览器不要向服务器发送请求了<br>所以必须彻底灭掉这个请求,变成这样<br><img src="/img/Static-resource-cache-control/4.png" alt=""></p>
<p>那问题来了:这都不让浏览器发资源请求了,这缓存咋更新?<br>可以通过更新页面中引用的资源路径,让浏览器主动放弃缓存,加载新资源<br><img src="/img/Static-resource-cache-control/5.png" alt=""></p>
<p>下次上线资源的时候,把链接地址改成新的版本,这就能更新资源了<br><img src="/img/Static-resource-cache-control/6.png" alt=""></p>
<p>页面引用了 3 个 css,而某次上线只改了其中的 a.css,如果所有链接都更新版本(当然你如果只改 a 的链接地址就可以了,不过我们还是要继续讨论后续问题),就会导致 b.css,c.css 的缓存也失效,那岂不是又有浪费了?!<br>要解决这种问题,必须让 url 的修改与文件内容关联,也就是说,只有文件内容变化,才会导致相应 url 的变更,从而实现文件级别的精确缓存控制。</p>
<p>可以使用<strong>数据摘要算法</strong>,摘要信息与文件内容一一对应,就有了一种可以精确到单个文件粒度的缓存控制依据了</p>
<p>这回再有文件修改,就只更新那个文件对应的 url 了,想到这里貌似很完美了<br><img src="/img/Static-resource-cache-control/7.png" alt=""></p>
<p>现代互联网企业,为了进一步提升网站性能,会把静态资源和动态网页分集群部署,静态资源会被部署到 CDN 节点上,网页中引用的资源也会变成对应的部署路径<br><img src="/img/Static-resource-cache-control/8.png" alt=""></p>
<p>好了,当我要更新静态资源的时候,同时也会更新 html 中的引用吧,就好像这样<br><img src="/img/Static-resource-cache-control/9.png" alt=""></p>
<p>但是这会产生一个问题,如何保证页面与资源保持一致呢?</p>
<ul>
<li>先部署页面,再部署资源<ul>
<li>在二者部署的时间间隔内,如果有用户访问页面,就会在新的页面结构中加载旧的资源,并且把这个旧版本的资源当做新版本缓存起来,其结果就是:用户访问到了一个样式错乱的页面,除非手动刷新,否则在资源缓存过期之前,页面会一直执行错误。</li>
</ul>
</li>
<li>先部署资源,再部署页面<ul>
<li>在部署时间间隔之内,有旧版本资源本地缓存的用户访问网站,由于请求的页面是旧版本的,资源引用没有改变,浏览器将直接使用本地缓存,这种情况下页面展现正常;但没有本地缓存或者缓存过期的用户访问网站,就会出现旧版本页面加载新版本资源的情况,导致页面执行错误,但当页面完成部署,这部分用户再次访问页面又会恢复正常了。</li>
</ul>
</li>
</ul>
<blockquote>
<p>简而言之: 先部署谁都不成!都会导致部署过程中发生页面错乱的问题。<br>所以,访问量不大的项目,可以让研发同学苦逼一把,等到半夜偷偷上线,先上静态资源,再部署页面,看起来问题少一些。</p>
</blockquote>
<p>但是如果你现在正在维护一个用户访问量比较大的网站,改怎么办,你打算不解决了吗?</p>
<p>可以采用<strong>非覆盖式发布</strong>,前面我们说了那么多都是<strong>覆盖式发布</strong><br><img src="/img/Static-resource-cache-control/10.png" alt=""></p>
<p>全套做下来,就是相对比较完整的静态资源缓存控制方案了,而且,还要注意的是,静态资源的缓存控制要求在前端所有静态资源加载的位置都要做这样的处理。是的,所有!什么 js、css 自不必说,还要包括 js、css 文件中引用的资源路径,由于涉及到摘要信息,引用资源的摘要信息也会引起引用文件本身的内容改变,从而形成级联的摘要变化,大概就是如下图<br><img src="/img/Static-resource-cache-control/11.png" alt=""></p>
]]></description>
</item>
<item>
<guid isPermalink="true">https://blog.imlete.cn/article/Use-lint-staged.html</guid>
<title>使用 Lint-staged 校验 Git 暂存区代码是否符合标准</title>
<link>https://blog.imlete.cn/article/Use-lint-staged.html</link>
<category>JavaScript</category>
<category>Git</category>
<pubDate>Tue, 12 Apr 2022 16:57:17 +0000</pubDate>
<description><![CDATA[ <h2 id="什么是-Lint-staged"><a href="#什么是-Lint-staged" class="headerlink" title="什么是 Lint-staged"></a>什么是 Lint-staged</h2><p>在 Git 暂存区执行相关的操作,如对暂存区进行<code>eslint</code>或是<code>prettier</code>,也可以自定义一些脚本</p>
<p>官方写着很有趣的一段话:</p>
<blockquote>
<p>Run linters against staged git files and don’t let 💩 slip into your code base!<br>对暂存区进行代码校验,不要让 💩(便便)溜进你的代码库!</p>
</blockquote>
<h2 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h2><p>有些人可能会问,我都有<code>eslint</code>和<code>prettier</code>为什么还要用<code>lint-staged</code>?</p>
<blockquote>
<p>简而言之: <code>lint-staged</code>只对已修改的或是将要提交到仓库的文件进行校验</p>
</blockquote>
<p>因为<code>lint-staged</code>仅对暂存区的文件进行校验,而<code>eslint</code>和<code>prettier</code>则是全局或是指定某个目录下的的所有文件进行校验,在执行效率上肯定是<code>lint-staged</code>更胜一筹</p>
<h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install lint-staged -D</span><br></pre></td></tr></table></figure>
<p>编辑<code>package.json</code>文件</p>
<blockquote>
<p>如果同时校验<code>.vue</code>则可以这么写<code>&quot;*.&#123;js,vue&#125;&quot;: &quot;npx eslint --fix&quot;</code><br>其内部使用的匹配规则是<a href="https://github.com/micromatch/micromatch">micromatch</a></p>
</blockquote>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line"> <span class="attr">&quot;lint-staged&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line"> <span class="attr">&quot;*.js&quot;</span><span class="punctuation">:</span> <span class="string">&quot;npx eslint --fix&quot;</span></span><br><span class="line"> <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>
<p>完整<code>package.json</code>文件</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line"> <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;study-notes&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;version&quot;</span><span class="punctuation">:</span> <span class="string">&quot;1.0.0&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;description&quot;</span><span class="punctuation">:</span> <span class="string">&quot;&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;main&quot;</span><span class="punctuation">:</span> <span class="string">&quot;index.js&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;scripts&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line"> <span class="attr">&quot;test&quot;</span><span class="punctuation">:</span> <span class="string">&quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;prepare&quot;</span><span class="punctuation">:</span> <span class="string">&quot;npx husky install&quot;</span></span><br><span class="line"> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;keywords&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;author&quot;</span><span class="punctuation">:</span> <span class="string">&quot;&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;license&quot;</span><span class="punctuation">:</span> <span class="string">&quot;ISC&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;devDependencies&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line"> <span class="attr">&quot;@commitlint/cli&quot;</span><span class="punctuation">:</span> <span class="string">&quot;^16.2.3&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;@commitlint/config-conventional&quot;</span><span class="punctuation">:</span> <span class="string">&quot;^16.2.1&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;eslint&quot;</span><span class="punctuation">:</span> <span class="string">&quot;^8.13.0&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;husky&quot;</span><span class="punctuation">:</span> <span class="string">&quot;^7.0.4&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;lint-staged&quot;</span><span class="punctuation">:</span> <span class="string">&quot;^12.3.7&quot;</span></span><br><span class="line"> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;commitlint&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line"> <span class="attr">&quot;extends&quot;</span><span class="punctuation">:</span> <span class="string">&quot;@commitlint/config-conventional&quot;</span></span><br><span class="line"> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;lint-staged&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line"> <span class="attr">&quot;*.js&quot;</span><span class="punctuation">:</span> <span class="string">&quot;npx eslint --fix&quot;</span></span><br><span class="line"> <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>
<p>配置好后,当你执行<code>git add .</code>后就可以使用<code>npx lint-staged</code>命令来校验暂存区的代码文件了</p>
<p>有些人可能会说,这么麻烦,那我还不如直接在<code>git add .</code>之前使用<code>npx eslint --fix .</code>这也不是更好吗?</p>
<p>文章开头一句说了,<code>lint-staged</code>只对暂存区的代码文件进行 lint,执行效率远超<code>npx eslint --fix .</code>命令,该命令会对全局的文件进行校验,不过有没有问题都要校验一遍(如果项目很大,那么这个差距就显现了)</p>
<p>如果一个项目有<code>几百</code>或<code>上千</code>个文件,而我只是修改了一个文件,比如说一个标点符号或者是其它修改,那么<code>npx eslint --fix .</code>可能需要校验很久,而使用<code>npx lint-staged</code>则只需要校验这个文件即可</p>
<h3 id="配合-Husky-使用"><a href="#配合-Husky-使用" class="headerlink" title="配合 Husky 使用"></a>配合 Husky 使用</h3><p>关于如何使用 husky 可以参考这篇文章: <a href="/article/Use-husky-manage-git-project.html">使用 Husky(哈士奇)管理 Git 项目</a></p>
<p>添加 hook 后执行<code>git commit</code>之前就会对暂存区的文件进行校验了</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npx husky add .husky/pre-commit <span class="string">&#x27;npx lint-staged&#x27;</span></span><br></pre></td></tr></table></figure>
]]></description>
</item>
<item>
<guid isPermalink="true">https://blog.imlete.cn/article/Commitlint-lint-commit-messages.html</guid>
<title>使用 commitlint 来检查提交的信息是否符合规范</title>
<link>https://blog.imlete.cn/article/Commitlint-lint-commit-messages.html</link>
<category>Git</category>
<pubDate>Tue, 12 Apr 2022 15:39:56 +0000</pubDate>
<description><![CDATA[ <h2 id="什么是-commitlint"><a href="#什么是-commitlint" class="headerlink" title="什么是 commitlint"></a>什么是 commitlint</h2><p>commitlint 用来校验你提交的信息是否符合规范,它和<code>commitizen</code>很类似,它们都做一件事,那就是让你提交的信息更规范</p>
<h2 id="commitlint-和-commitizen-的区别"><a href="#commitlint-和-commitizen-的区别" class="headerlink" title="commitlint 和 commitizen 的区别"></a>commitlint 和 commitizen 的区别</h2><blockquote>
<p>commitlint: 校验 git commit 信息是否符合规范(就像 eslint 一样)</p>
</blockquote>
<blockquote>
<p>commitizen: 辅助 git commit 信息更加规范(就像代码提示一样)</p>
</blockquote>
<p>所以你可以把它们两个结合起来使用效果更佳哦~</p>
<h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --save-dev @commitlint/config-conventional @commitlint/cli</span><br></pre></td></tr></table></figure>
<p>创建配置文件,可以手动创建,也可以使用命令创建</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&quot;module.exports = &#123;extends: [&#x27;@commitlint/config-conventional&#x27;]&#125;&quot;</span> &gt; commitlint.config.js</span><br></pre></td></tr></table></figure>
<p>然后就会生成<code>commitlint.config.js</code>文件,其中包含<code>module.exports = &#123;extends: [&#39;@commitlint/config-conventional&#39;]&#125;</code>代码</p>
<blockquote>
<p>这个配置也可以写在<code>package.json</code>文件中</p>
</blockquote>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line"> <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;study-notes&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;version&quot;</span><span class="punctuation">:</span> <span class="string">&quot;1.0.0&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;description&quot;</span><span class="punctuation">:</span> <span class="string">&quot;&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;main&quot;</span><span class="punctuation">:</span> <span class="string">&quot;index.js&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;scripts&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line"> <span class="attr">&quot;test&quot;</span><span class="punctuation">:</span> <span class="string">&quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;prepare&quot;</span><span class="punctuation">:</span> <span class="string">&quot;husky install&quot;</span></span><br><span class="line"> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;keywords&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;author&quot;</span><span class="punctuation">:</span> <span class="string">&quot;&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;license&quot;</span><span class="punctuation">:</span> <span class="string">&quot;ISC&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;devDependencies&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line"> <span class="attr">&quot;@commitlint/cli&quot;</span><span class="punctuation">:</span> <span class="string">&quot;^16.2.3&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;@commitlint/config-conventional&quot;</span><span class="punctuation">:</span> <span class="string">&quot;^16.2.1&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;husky&quot;</span><span class="punctuation">:</span> <span class="string">&quot;^7.0.4&quot;</span></span><br><span class="line"> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;commitlint&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line"> <span class="attr">&quot;extends&quot;</span><span class="punctuation">:</span> <span class="string">&quot;@commitlint/config-conventional&quot;</span></span><br><span class="line"> <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>
<h2 id="配合commitizen使用"><a href="#配合commitizen使用" class="headerlink" title="配合commitizen使用"></a>配合commitizen使用</h2><blockquote>
<p>配合 commitizen 可以参考这篇文章: <a href="/article/Normalizing-git-commit-messages.html">使用commitizen规范化git提交信息</a></p>
</blockquote>
<h2 id="配合husky使用"><a href="#配合husky使用" class="headerlink" title="配合husky使用"></a>配合husky使用</h2><p>关于如何使用husky可以参考这篇文章: <a href="/article/Use-husky-manage-git-project.html">使用Husky(哈士奇)管理Git项目</a></p>
<p>添加hook</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">npx husky add .husky/commit-msg <span class="string">&#x27;npx --no -- commitlint --edit &quot;$1&quot;&#x27;</span></span><br><span class="line"><span class="comment"># 因为有些命令行不支持上面这条命令</span></span><br><span class="line"><span class="comment"># 如果上面这条对你的项目不管用,可以试试以下其它命令</span></span><br><span class="line">npx husky add .husky/commit-msg \&quot;npx --no -- commitlint --edit <span class="string">&#x27;$1&#x27;</span>\&quot;</span><br><span class="line"><span class="comment"># 或者</span></span><br><span class="line">npx husky add .husky/commit-msg <span class="string">&quot;npx --no -- commitlint --edit <span class="variable">$1</span>&quot;</span></span><br></pre></td></tr></table></figure>
<h2 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h2><p>不符合规范的提交信息</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">$ git commit -m <span class="string">&quot;abc&quot;</span></span><br><span class="line">⧗ input: abc</span><br><span class="line">✖ subject may not be empty [subject-empty]</span><br><span class="line">✖ <span class="built_in">type</span> may not be empty [type-empty]</span><br><span class="line"></span><br><span class="line">✖ found 2 problems, 0 warnings</span><br><span class="line">ⓘ Get <span class="built_in">help</span>: https://github.com/conventional-changelog/commitlint/<span class="comment">#what-is-commitlint</span></span><br><span class="line"></span><br><span class="line">husky - commit-msg hook exited with code 1 (error)</span><br></pre></td></tr></table></figure>
]]></description>
</item>
<item>
<guid isPermalink="true">https://blog.imlete.cn/article/Use-husky-manage-git-project.html</guid>
<title>使用Husky(哈士奇)管理Git项目</title>
<link>https://blog.imlete.cn/article/Use-husky-manage-git-project.html</link>
<category>Git</category>
<pubDate>Tue, 12 Apr 2022 14:16:02 +0000</pubDate>
<description><![CDATA[ <h2 id="什么是-Husky-哈士奇"><a href="#什么是-Husky-哈士奇" class="headerlink" title="什么是 Husky(哈士奇)"></a>什么是 Husky(哈士奇)</h2><p>Husky 就是狗,没错就是拆家的那家伙,也不知道<a href="https://github.com/typicode">@typicode</a>是怎么想的,尽然起了这么<strong>有趣</strong>的一个项目名字</p>
<p>Husky 可以方便快速的使用<code>Git hooks</code>,帮你简单的配置项目,同时 Husky 可以将<code>Git hooks</code>同步到仓库,让整个团队能使用相同的<code>Git hooks</code></p>
<h2 id="什么是-Git-Hooks"><a href="#什么是-Git-Hooks" class="headerlink" title="什么是 Git Hooks"></a>什么是 Git Hooks</h2><blockquote>
<p>文档说明中文: <a href="https://git-scm.com/book/zh/v2/%E8%87%AA%E5%AE%9A%E4%B9%89-Git-Git-%E9%92%A9%E5%AD%90">https://git-scm.com/book/zh/v2/自定义-Git-Git-钩子</a><br>文档说明英文: <a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks">https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks</a></p>
</blockquote>
<p>因为提交到仓库后<code>.git</code>文件是不存在仓库中的,而<code>Git hooks</code>却在<code>.git/hooks</code>目录下</p>
<p>现在假设你是项目组长,一些项目需要使用的技术和库,需要你来配置,然后让小组成员去使用,那么当你使用了<code>Git hooks</code>后,只有你本地这台电脑能使用<code>Git hooks</code>,其它人<strong>Clone(克隆)</strong>或<strong>Pull(拉取)</strong>,都不会得到你配置的<code>Git hooks</code>,这时就可以使用<code>Husky</code>来同步<code>Git hooks</code></p>
<h2 id="安装-Husky"><a href="#安装-Husky" class="headerlink" title="安装 Husky"></a>安装 Husky</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install husky -D</span><br></pre></td></tr></table></figure>
<blockquote>
<p>为什么使用<code>prepare</code>当作 key?<br>因为<code>prepare</code>是 npm 的生命周期命令,它会在<code>npm install</code>完成后执行,所以当如果有人克隆了项目并执行了<code>npm install</code>后就会自动初始化 husky 来管理 hook</p>
</blockquote>
<p>编辑<code>package.json</code>的<code>scripts</code>并并运行</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm set-script prepare <span class="string">&quot;npx husky install&quot;</span></span><br><span class="line">npm run prepare</span><br></pre></td></tr></table></figure>
<p>其中<code>npm set-script</code>命令仅限 npm 版本是 7.x 版本以上,如果不是则需要手动编辑</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line"> <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;study-notes&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;version&quot;</span><span class="punctuation">:</span> <span class="string">&quot;1.0.0&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;description&quot;</span><span class="punctuation">:</span> <span class="string">&quot;&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;main&quot;</span><span class="punctuation">:</span> <span class="string">&quot;index.js&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;scripts&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line"> <span class="attr">&quot;test&quot;</span><span class="punctuation">:</span> <span class="string">&quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;prepare&quot;</span><span class="punctuation">:</span> <span class="string">&quot;husky install&quot;</span></span><br><span class="line"> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;keywords&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;author&quot;</span><span class="punctuation">:</span> <span class="string">&quot;&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;license&quot;</span><span class="punctuation">:</span> <span class="string">&quot;ISC&quot;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;devDependencies&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line"> <span class="attr">&quot;husky&quot;</span><span class="punctuation">:</span> <span class="string">&quot;^7.0.4&quot;</span></span><br><span class="line"> <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>
<h2 id="添加-hook"><a href="#添加-hook" class="headerlink" title="添加 hook"></a>添加 hook</h2><p>举例:如果在进行 git commit 之前对代码进行<code>eslint</code>检查,那么可以使用<code>pre-commit</code>(这仅仅是个例子,你可以灵活的使用 hook 完成一些你想要完成的事情)</p>
<p>关于<code>pre-commit</code>的说明可以在官方文档查阅或是直接打开<code>.git\hooks\pre-commit.sample</code>查看注释说明</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npx husky add .husky/pre-commit <span class="string">&quot;npx eslint --fix&quot;</span></span><br></pre></td></tr></table></figure>
<p>当你执行<code>git commit -m &quot;xxx&quot;</code>提交代码之前就会自动执行 eslint</p>
<p>例如添加 hook 让他在提交代码前执行<code>package.json</code>中的 test 脚本</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npx husky add .husky/pre-commit <span class="string">&quot;npm test&quot;</span></span><br><span class="line">git commit -m <span class="string">&quot;test husky pre-commit&quot;</span></span><br></pre></td></tr></table></figure>
<p>test 脚本输出一段内容 <strong>“Error: no test specified”</strong> 后还行了<code>exit 1</code>结束命令如下,由于执行了<code>exit 1</code>结束了命令(相当于我们按了ctrl+c一样)所以并未提交</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">$ git commit -m <span class="string">&quot;test husky pre-commit&quot;</span></span><br><span class="line"></span><br><span class="line">&gt; [email protected] <span class="built_in">test</span></span><br><span class="line">&gt; <span class="built_in">echo</span> <span class="string">&quot;Error: no test specified&quot;</span> &amp;&amp; <span class="built_in">exit</span> 1</span><br><span class="line"></span><br><span class="line"><span class="string">&quot;Error: no test specified&quot;</span></span><br><span class="line">husky - pre-commit hook exited with code 1 (error)</span><br></pre></td></tr></table></figure>
]]></description>
</item>
</channel>
</rss>