-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
2165 lines (869 loc) · 85.3 KB
/
index.html
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
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html class="theme-next mist use-motion" lang="zh-Hans">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta name="theme-color" content="#222">
<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />
<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />
<link href="/css/main.css?v=5.1.3" rel="stylesheet" type="text/css" />
<link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.3">
<link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=5.1.3">
<link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=5.1.3">
<link rel="mask-icon" href="/images/logo.svg?v=5.1.3" color="#222">
<meta name="keywords" content="Hexo, NexT" />
<meta property="og:type" content="website">
<meta property="og:title" content="聆听群山的怒号">
<meta property="og:url" content="http://yoursite.com/index.html">
<meta property="og:site_name" content="聆听群山的怒号">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="聆听群山的怒号">
<script type="text/javascript" id="hexo.configurations">
var NexT = window.NexT || {};
var CONFIG = {
root: '/',
scheme: 'Mist',
version: '5.1.3',
sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
fancybox: true,
tabs: true,
motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
duoshuo: {
userId: '0',
author: '博主'
},
algolia: {
applicationID: '',
apiKey: '',
indexName: '',
hits: {"per_page":10},
labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
}
};
</script>
<link rel="canonical" href="http://yoursite.com/"/>
<title>聆听群山的怒号</title>
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-111538804-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-111538804-1');
</script>
</head>
<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">
<div class="container sidebar-position-left
page-home">
<div class="headband"></div>
<header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
<div class="header-inner"><div class="site-brand-wrapper">
<div class="site-meta ">
<div class="custom-logo-site-title">
<a href="/" class="brand" rel="start">
<span class="logo-line-before"><i></i></span>
<span class="site-title">聆听群山的怒号</span>
<span class="logo-line-after"><i></i></span>
</a>
</div>
<p class="site-subtitle"></p>
</div>
<div class="site-nav-toggle">
<button>
<span class="btn-bar"></span>
<span class="btn-bar"></span>
<span class="btn-bar"></span>
</button>
</div>
</div>
<nav class="site-nav">
<ul id="menu" class="menu">
<li class="menu-item menu-item-home">
<a href="/" rel="section">
<i class="menu-item-icon fa fa-fw fa-home"></i> <br />
首页
</a>
</li>
<li class="menu-item menu-item-about">
<a href="/about/" rel="section">
<i class="menu-item-icon fa fa-fw fa-user"></i> <br />
关于
</a>
</li>
<li class="menu-item menu-item-tags">
<a href="/tags/" rel="section">
<i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
标签
</a>
</li>
<li class="menu-item menu-item-categories">
<a href="/categories/" rel="section">
<i class="menu-item-icon fa fa-fw fa-th"></i> <br />
分类
</a>
</li>
<li class="menu-item menu-item-archives">
<a href="/archives/" rel="section">
<i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
归档
</a>
</li>
<li class="menu-item menu-item-sitemap">
<a href="/sitemap.xml" rel="section">
<i class="menu-item-icon fa fa-fw fa-sitemap"></i> <br />
站点地图
</a>
</li>
</ul>
</nav>
</div>
</header>
<main id="main" class="main">
<div class="main-inner">
<div class="content-wrap">
<div id="content" class="content">
<section id="posts" class="posts-expand">
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="http://yoursite.com/2019/08/24/service-worker-缓存原理/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="Fszer">
<meta itemprop="description" content="">
<meta itemprop="image" content="https://cloud.githubusercontent.com/assets/18730194/15146790/dd39acee-16ef-11e6-8ee7-093d1ce74fce.png">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="聆听群山的怒号">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2019/08/24/service-worker-缓存原理/" itemprop="url">service worker 缓存原理</a></h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建于" itemprop="dateCreated datePublished" datetime="2019-08-24T12:12:24+08:00">
2019-08-24
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h2 id="workbox-的-service-worker-缓存实现"><a href="#workbox-的-service-worker-缓存实现" class="headerlink" title="workbox 的 service worker 缓存实现"></a>workbox 的 service worker 缓存实现</h2><p>正如其名 workbox 是 google 封装的一个工具箱,旨在提供开箱即用的 service worker 相关特性。</p>
<p>precaching 缓存应该其中适用性最广的一个特性。正好最近在项目中使用的到,于是便去研究了一下其原理</p>
<h3 id="service-Worker-cache-api-precache"><a href="#service-Worker-cache-api-precache" class="headerlink" title="service Worker + cache api = precache"></a>service Worker + cache api = precache</h3><p>我们说 service worker 缓存其实并不正确,service worker 本身并不提供缓存功能,而是配合了 <code>Cache</code> 的 api 才提供完整的缓存功能。</p>
<p>在 workbox 中将这两者封装成一个 <em>workbox</em>-<em>precaching</em></p>
<h3 id="Service-Worker-生命周期"><a href="#Service-Worker-生命周期" class="headerlink" title="Service Worker 生命周期"></a>Service Worker 生命周期</h3><p>在缓存功能中 Service Worker 的作用主要有两个</p>
<ul>
<li>提供生命周期的钩子给 PrecacheController 进入执行缓存控制的相关逻辑</li>
<li>提供拦截请求的功能</li>
</ul>
<p>Service Worker 的生命周期包括</p>
<ul>
<li><strong>installing</strong> 每个 service worker 只触发一次,初始化和注册 Service Worker </li>
<li><strong>installed</strong> Service Worker 已经完成了安装,并且等待其他的 Service Worker 线程被关闭。</li>
<li><strong>activetaing</strong> 在这个状态下没有被其他的 Service Worker 控制的客户端,允许当前的 worker 完成安装,并且清除了其他的 worker 以及关联缓存的旧缓存资源,等待新的 Service Worker 线程被激活。</li>
<li><strong>activate</strong> 在这个状态会处理 <code>activate</code> 事件回调 (提供了更新缓存策略的机会)。并可以处理功能性的事件 <code>fetch (请求)</code>、<code>sync (后台同步)</code>、<code>push (推送)</code>。</li>
<li><strong>redundant</strong> 这个状态表示一个 Service Worker 的生命周期结束。</li>
</ul>
<p><img src="https://mdn.mozillademos.org/files/12636/sw-lifecycle.png" alt="img"></p>
<p>其中 precaching 用到的主要是 <strong>installing</strong> 和 <strong>activate</strong> 两个声明周期的钩子,分别对应了静态资源缓存的初始化,更新以及拦截请求</p>
<h3 id="Cache-API"><a href="#Cache-API" class="headerlink" title="Cache API"></a>Cache API</h3><p>precaching 的另一部分则是 Cache Api</p>
<p>Cache 的缓存机制可以直接对 <code>Request</code> / <code>Response</code> 对象对提供存储机制。有意思的是,虽然他定义在 service worker 的标准中,但是它直接暴露在 window 的作用域下,因此你实际上不一定需要配合 service worker 使用</p>
<p>cache 包括这样一些有趣的特性</p>
<ul>
<li>一个域可以有多个命名 Cache 对象</li>
<li>你需要自定义更新方式,除非明确地更新缓存,否则缓存将不会被更新</li>
<li>你需要自定义清理缓存逻辑,除非删除,否则缓存数据不会过期</li>
<li>Cache 的 <a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Cache/put" target="_blank" rel="external"><code>Cache.put</code></a>, <a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Cache/add" target="_blank" rel="external"><code>Cache.add</code></a>和<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Cache/addAll" target="_blank" rel="external"><code>Cache.addAll</code></a>只能在<code>GET</code>请求下使用。</li>
</ul>
<p>可以看到 Cache api 保存的直接就是一个 Request/ Response 的对象,因此可以直接其作为请求的返回。</p>
<p>另外,在写下这篇文章的节点, mdn 中 关于 Cache api 的部分文档和实际的 api 行为有不一致,我估计是没来得及更新。一个比较明显的差异在于 <code>Cache.keys()</code></p>
<p>根据文档的说明和示例, <code>Cache.keys()</code> 返回应该是一个<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise" target="_blank" rel="external"><code>Promise</code></a>对象,其 resolve 的结果是<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Cache" target="_blank" rel="external"><code>Cache</code></a>对象key值组成的数组</p>
<p>如果用 ts 类型标注出来应该是 <code>Promise<string[]|null></code> ,但是在 workbox 的源码中其标注的 types 是 <code>Promise<Request[] | null></code>,两者显然不可相比。</p>
<h4 id="额外的缓存清除机制"><a href="#额外的缓存清除机制" class="headerlink" title="额外的缓存清除机制"></a>额外的缓存清除机制</h4><p>虽然说除非主动删除,否则缓存数据不会过期一直缓存下来,但有一种额外的的情况,那就是浏览器上的可控制存储大小实际上受限于硬盘的大小。</p>
<p>而浏览器会根据可控制存储大小,硬性的限制每个域下缓存数据的大小。所以 cache 的容量是有上限。如果某个域配额不够,或者磁盘空间不够的话,浏览还是会根据 LRU 最近最少使用的规则,清除某个域下面的缓存信息。清除的时候会以整个域作为单位进行清除,而不是再深入细分清除。</p>
<p>因此一个 workbox 完整的缓存控制流程如下</p>
<ul>
<li>webpack 中 workbox 根据我们打包出来的 chunk 和相关的过滤配置,生成了 Manifest.js 记录所有要缓存的静态资源<ul>
<li>manfest 的结构 {revision:string, url:string}</li>
<li>revision 保存文件的 md5 hash 作为文件的版本</li>
<li>url 则是 Cache 的 key 值和请求地址</li>
</ul>
</li>
<li>在 <strong>installing</strong> 回调中读取 Manifest.js ,获取所需的静态资源索引,调用 cache api 进行缓存</li>
<li>在 <strong>activate</strong> 时根据 manifest ,对资源文件进行遍历检查,删除无用资源或者更新资源文件</li>
<li>在 <strong>fetch</strong> 事件中拦截 cache 中已经存在的静态资源文件请求直接返回缓存数据</li>
</ul>
<h3 id="对比其他缓存方式"><a href="#对比其他缓存方式" class="headerlink" title="对比其他缓存方式"></a>对比其他缓存方式</h3><h4 id="http-缓存"><a href="#http-缓存" class="headerlink" title="http 缓存"></a>http 缓存</h4><p>http 主要依赖 304 进行缓存,包括</p>
<ul>
<li>强缓存:通过 Cache-Control max-age 设定一个过期时间,再这个时间之前都不会再次发请求</li>
<li>协商缓存:强缓存失效之后,则可以通过 last-modified 或者 etag 向服务器请求判断是否需要更新缓存</li>
</ul>
<p>http 的问题在于用户主动刷新的时候,就会让强缓存失效,直接进行协商缓存。</p>
<h4 id="localstorage-缓存"><a href="#localstorage-缓存" class="headerlink" title="localstorage 缓存"></a>localstorage 缓存</h4><p>localstorage 缓存相比 http 缓存可以进一步控制资源,也可以缓存比较大的资源,不过 localstorage 也有其问题</p>
<ul>
<li>需要自己实现资源的请求管理的机制,管理资源文件的读取和写入。</li>
<li>localstorage 只能保存字符串数据,因此也需要自己实现对资源的序列化,反序列化,以及添加的逻辑</li>
<li>seo 不友好</li>
<li>版本更新机制</li>
</ul>
<p>所以相比之下 Cache + Service Worker 的优势就是对 localstorage 缓存方案的进一步改进</p>
<ul>
<li>不需要自己去维护资源的请求机制</li>
<li>service Worker 可以直接拦截请求,cache 直接保存 <code>Request</code> / <code>Response</code>不需要进行序列化</li>
<li>seo 优化</li>
<li>可控性更加的高</li>
</ul>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</div>
</article>
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="http://yoursite.com/2019/04/20/vue-Typescript问题两则/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="Fszer">
<meta itemprop="description" content="">
<meta itemprop="image" content="https://cloud.githubusercontent.com/assets/18730194/15146790/dd39acee-16ef-11e6-8ee7-093d1ce74fce.png">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="聆听群山的怒号">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2019/04/20/vue-Typescript问题两则/" itemprop="url">'vue/TypeScript问题两则'</a></h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建于" itemprop="dateCreated datePublished" datetime="2019-04-20T11:31:35+08:00">
2019-04-20
</time>
</span>
<span class="post-category" >
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-folder-o"></i>
</span>
<span class="post-meta-item-text">分类于</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/学习/" itemprop="url" rel="index">
<span itemprop="name">学习</span>
</a>
</span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p>最近尝试为 vue 项目配合 TypeScript 不过发现毕竟 vue 不是原生 TypeScript 开发,在对 TypeScript 支持方面显然还问题多多,这里稍微记录两则</p>
<h2 id="自动注入-h-问题"><a href="#自动注入-h-问题" class="headerlink" title="自动注入 h 问题"></a>自动注入 h 问题</h2><p>如果你在 vue 中是用 jsx 你会明显感受到和 react 有明显的一个差异就是 react 中你可以很方便的到处写下 jsx,而 vue 中则限定的比较死,要么写在组建的 render 函数中,要么主动传递 h 函数到你想要写 jsx 的地方比如</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 找不到 h 函数</span></div><div class="line"><span class="keyword">const</span> component = <span class="xml"><span class="tag"><<span class="name">button</span> /></span></span></div><div class="line">// ok</div><div class="line">export default {</div><div class="line"> render (h) {</div><div class="line"> return <span class="tag"><<span class="name">button</span> /></span></div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line">// 主动将 h 传递到需要的地方</div><div class="line">const component2 = h => <span class="tag"><<span class="name">button</span> /></span></div><div class="line"></div><div class="line">export default {</div><div class="line"> render (h) {</div><div class="line"> return component2(h)</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<p>由于 h 函数是在编译后才会被使用到,而每次都要写 h,但实际少主动用到,所以 vue 官方为了进一步简化使用,开发了一个 babel 插件<code>babel-sugar-inject-h</code>, 检测 jsx 自动插入 h 函数,比如这样</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// With @vue/babel-sugar-inject-h</span></div><div class="line"><span class="keyword">const</span> component =()=> <span class="xml"><span class="tag"><<span class="name">button</span> /></span></span></div><div class="line">export default {</div><div class="line"> render () {</div><div class="line"> return <span class="tag"><<span class="name">button</span> /></span></div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line">// 不需要写h,编译后自动注入 h 函数,等价于</div><div class="line">const component =(h)=> <span class="tag"><<span class="name">button</span> /></span></div><div class="line">export default {</div><div class="line"> render (h) {</div><div class="line"> return <span class="tag"><<span class="name">button</span> /></span></div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<p>这让看起来让 vue/jsx 更加接近 react/jsx ,还稍微减轻了开发的工作。但我个人认为这样有些自做主张,并且关键是做的并不完美。如果你用了 vue-cli 那么他是自带且默认启动的,如果你没有用 vue-cli 自己配的环境,那么就有可能就忽略了这的插件,就容易导致同一段代码在两个环境下有不同的表现。而这如果不是用户主动去看文档,是不会被感知到的,一但出了问题就特别令人摸不着头脑,</p>
<p>哦,跑题了,这篇文章应该说的是跟 TypeScript 相关的问题,其实也就是它做得不够好的一个体现,假如你要配合 TypeScript 使用,很有可能遇到以下代码</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">import { Component, Vue } from "vue-property-decorator";</div><div class="line">@Component</div><div class="line">export default class App extends Vue {</div><div class="line"> test = (h: any) => <div>123</div>;</div><div class="line">}</div></pre></td></tr></table></figure>
<p>其中 test 是你组件的内部变量,理论上这段代码应该等价于</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">export</span> <span class="keyword">default</span> {</div><div class="line"> data(){</div><div class="line"> <span class="keyword">return</span> {</div><div class="line"> test: (h)=><span class="xml"><span class="tag"><<span class="name">div</span>></span>123<span class="tag"></<span class="name">div</span>></span></span></div><div class="line"> }</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<p>然而假如你实际在 vue-cli 中跑这段代码,是可以跑起来的,但在浏览器中会报出类似以下错误,</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">Error in data(): "TypeError: Cannot read property '$createElement' of undefined"</div></pre></td></tr></table></figure>
<p>有了前面的铺垫,不用说问题的关键显然是出在 <code>babel-sugar-inject-h</code> 自动注入 h 的问题上,为了了解为什么,不妨看一下这段代码编译后的样子</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 略去前后无关代码</span></div><div class="line"><span class="function"><span class="keyword">function</span> (<span class="params">_Vue</span>) </span>{</div><div class="line"> <span class="built_in">Object</span>(inherits[<span class="string">"a"</span> <span class="comment">/* default */</span>])(App, _Vue);</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">App</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">var</span> _this;</div><div class="line"></div><div class="line"> <span class="built_in">Object</span>(classCallCheck[<span class="string">"a"</span> <span class="comment">/* default */</span>])(<span class="keyword">this</span>, App);</div><div class="line"> <span class="keyword">var</span> h = _this.$createElement;</div><div class="line"> _this = <span class="built_in">Object</span>(possibleConstructorReturn[<span class="string">"a"</span> <span class="comment">/* default */</span>])(<span class="keyword">this</span>, <span class="built_in">Object</span>(getPrototypeOf[<span class="string">"a"</span> <span class="comment">/* default */</span>])(App).apply(<span class="keyword">this</span>, <span class="built_in">arguments</span>));</div><div class="line"></div><div class="line"> _this.test = <span class="function"><span class="keyword">function</span> (<span class="params">h</span>) </span>{</div><div class="line"> <span class="keyword">return</span> h(<span class="string">"div"</span>, [<span class="string">"123"</span>]);</div><div class="line"> };</div><div class="line"></div><div class="line"> <span class="keyword">return</span> _this;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> App;</div><div class="line">}(vue_property_decorator[<span class="string">"c"</span> <span class="comment">/* Vue */</span>]);</div></pre></td></tr></table></figure>
<p>我撇去了无关的代码和不压缩,这里的问题就显而易见了。</p>
<p>尽管在 test 上我主动显式的传入了 h 函数,但是对于构造函数 data() 来说,似乎依然被判断为应当注入 h 的情况,这也其实没有关系,不过它注入 <code>var h = _this.$createElement;</code> 的位置就有些问题了 ,默认情况下,它一般事插入到 this 声明定义之后。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">App</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="comment">// 一般情况下编译后 _this 的声明和定义实在同一行的,因此注入后不会报错</span></div><div class="line"> <span class="keyword">var</span> _this = something;</div><div class="line"> <span class="keyword">var</span> h = _this.$createElement;</div><div class="line"> <span class="keyword">return</span> _this;</div><div class="line"> }</div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">App</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="comment">// 在 ts/vue-property-decorato 中的 this 是先声明后定义</span></div><div class="line"> <span class="keyword">var</span> _this;</div><div class="line"> <span class="keyword">var</span> h = _this.$createElement;</div><div class="line"> _this = something;</div><div class="line"> <span class="keyword">return</span> _this;</div><div class="line"> }</div></pre></td></tr></table></figure>
<p>然而由于用了ts和vue-property-decorator,_this 的是先声明后定义,导致插入在声明之后的 h 是找不到的 <code>_this.$createElement</code> 的</p>
<h3 id="解决方法"><a href="#解决方法" class="headerlink" title="解决方法"></a>解决方法</h3><p>最好的方法当然是这个插件更新并考虑 ts 这种 edge case ,不过在此之前我其实建议直接关掉自动注入 h 的功能,毕竟 vue/jsx 本身就不是可以到处写 jsx ,本来就需要 h 却隐蔽起来并不会解决太多问题,反而会造成一些认知问题。</p>
<p>不过这里牵扯到另一个问题,如何关闭这个插件。</p>
<p><a href="https://github.com/vuejs/jsx/tree/dev/packages/babel-preset-jsx" target="_blank" rel="external">vue/jsx</a> 的文档中写明的修改配置方法是在 babel config 中修改 <code>@vue/babel-preset-jsx</code> 的配置,假如你是自己配置环境那么直接如此就可以了。</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">{</div><div class="line"> <span class="attr">"presets"</span>: [</div><div class="line"> [</div><div class="line"> <span class="string">"@vue/babel-preset-jsx"</span>,</div><div class="line"> {</div><div class="line"> <span class="attr">"injectH"</span>: <span class="literal">false</span></div><div class="line"> }</div><div class="line"> ]</div><div class="line"> ]</div><div class="line">}</div></pre></td></tr></table></figure>
<p><strong>但是</strong>,假如你用 vue-cli 构建的项目的话,你会发现这样写并没有用,这是因为 vue-cli 非常“聪明”的封装了另一个 <code>@vue/babel-preset-app</code> ,这 preset 内部引入了 <code>@vue/babel-preset-jsx</code>自己包裹了一层配置的传递, <a href="https://github.com/vuejs/vue-cli/blob/dev/packages/%40vue/babel-preset-app/index.js#L37" target="_blank" rel="external">源码在这里</a></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">if</span> (options.jsx !== <span class="literal">false</span>) {</div><div class="line"> presets</div><div class="line"> .push([</div><div class="line"> <span class="built_in">require</span>(<span class="string">'@vue/babel-preset-jsx'</span>), </div><div class="line"> <span class="keyword">typeof</span> options.jsx === <span class="string">'object'</span> ? options.jsx : {}</div><div class="line"> ])</div><div class="line">}</div></pre></td></tr></table></figure>
<p>可以看到它根本不会去读取 babel config 中 <code>@vue/babel-preset-jsx</code> 的配置参数,因此正确的配置方法是</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">{</div><div class="line"> "presets": [</div><div class="line"> [</div><div class="line"> "@vue/babel-preset-app",</div><div class="line"> {</div><div class="line"> // 要扔到 @vue/babel-preset-app 的 jsx 字段上</div><div class="line"> jsx:{</div><div class="line"> "injectH": false</div><div class="line"> }</div><div class="line"> }</div><div class="line"> ]</div><div class="line"> ]</div><div class="line">}</div></pre></td></tr></table></figure>
<p>而关于 jsx 可配置 <code>@vue/babel-preset-jsx</code> 参数这一点,官方一开始并没有任何说明(现在有了),在<a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/babel-preset-app" target="_blank" rel="external">文档</a>中也只提到,<code>jsx</code> 是一个布尔值用于开启关闭 jsx 支持,如果不去看源码谁又知道,它还可以传入 object 来做进一步的配置?</p>
<p>所以说,为了搞清 <code>babel-sugar-inject-h</code> 这一个小问题,不得不跑去看 vue-cli/babel-preset-jsx/babel-preset-app 等一长串的相关源码配置方法才摸索清楚,这说不定就是封装之美?</p>
<p><strong>真有你的啊 vue-cli</strong></p>
<h2 id="tsx-中组件属性类型推断问题"><a href="#tsx-中组件属性类型推断问题" class="headerlink" title="tsx 中组件属性类型推断问题"></a>tsx 中组件属性类型推断问题</h2><p>tsx 中无法正确给出自定义 component 的属性类型定义,甚至会报错。相比之下这个问题更加简单也更加恼人,假如你定义了一个组件,比如</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div></pre></td><td class="code"><pre><div class="line">import Vue from "vue";</div><div class="line"></div><div class="line">const MyComponent = Vue.extend({</div><div class="line"> props: {</div><div class="line"> text: { type: String, required: true },</div><div class="line"> important: Boolean,</div><div class="line"> },</div><div class="line"> computed: {</div><div class="line"> className() {</div><div class="line"> return this.important ? "label-important" : "label-normal";</div><div class="line"> }</div><div class="line"> },</div><div class="line"> methods: {</div><div class="line"> onClick(event) { this.$emit("ok", event); }</div><div class="line"> },</div><div class="line"> template: "<span :class='className' @click='onClick'>{{ text }}</span>"</div><div class="line">});</div><div class="line"></div><div class="line">// 在别的组件中调用,则会报错</div><div class="line">// Compilation error(TS2339): Property `text` does not exist on type '...'</div><div class="line"><MyComponent text="foo" />;</div></pre></td></tr></table></figure>
<p>这个问题如果是从官方角度来说,几乎除了等待 vue3 重构以后得到 TypeScript 更好的支持以外,看来别无其他折中的办法,详情可参见这个 <a href="https://github.com/vuejs/vue-cli/issues/2417" target="_blank" rel="external">issue</a> 。</p>
<p>所幸这个 issue 中也给出了一个比较成熟的第三方解决方案 <a href="https://github.com/wonderful-panda/vue-tsx-support" target="_blank" rel="external">vue-tsx-support</a>,这个库的文档已经非常详细了,这里没有必要赘述。总而言之这个库可以相当好的解决目前的 tsx component prop 缺少类型推导的问题,不过,代价是引入了他自己的一套定义组件的方式。</p>
<h3 id="兼容?升级?"><a href="#兼容?升级?" class="headerlink" title="兼容?升级?"></a>兼容?升级?</h3><p>首先这个库虽然得到推荐,但官方对其的态度也停留在可以有的暧昧程度,不如 <code>**vue-property-decorator**</code> 那样得到官方认可并且整合到官方工具链中这个级别的对待。在这个问题上 vue 官方寄希望于 vue3 重构能解决,而没有给出现在的过度方案,显然你不可能寄希望于他们能去兼容现在的第三方过度方案……</p>
<p>因此另外一个不甚优雅的解决方案,那就是通过 d.ts 文件让 component 的参数允许任何属性</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">declare</span> <span class="keyword">module</span> 'vue/types/options' {</div><div class="line"> <span class="keyword">interface</span> ComponentOptions<V <span class="keyword">extends</span> Vue> {</div><div class="line"> [propName: <span class="built_in">string</span>]: <span class="built_in">any</span></div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<p>这样 component 实际上就可以接受任何参数而不报错,然而无法正确推导出对应的 component 有什么属性的问题并没有解决,所以依然的不到任何提示,这某种程度上就损失了 TypeScript 一个大优势。</p>
<p>而好处是,没有引入任何新的东西,也不需要魔改任何旧的代码,在兼容性上和其他的 vue2 代码处于一个级别。</p>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>目前来说,ts + vue 当然可用,但是依然相当多的问题,没法如丝般顺滑的相互配合。对于他们完全打算通过 vue3 去彻底(?)解决于 ts 共用的的问题,而不打算优化一下 2.x 当前存在问题的决定……我是比较不赞同的</p>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</div>
</article>
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="http://yoursite.com/2019/04/11/JavaScript函数式编程备忘录-上/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="Fszer">
<meta itemprop="description" content="">
<meta itemprop="image" content="https://cloud.githubusercontent.com/assets/18730194/15146790/dd39acee-16ef-11e6-8ee7-093d1ce74fce.png">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="聆听群山的怒号">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2019/04/11/JavaScript函数式编程备忘录-上/" itemprop="url">『JavaScript函数式编程』备忘录(上)</a></h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建于" itemprop="dateCreated datePublished" datetime="2019-04-11T22:55:11+08:00">
2019-04-11
</time>
</span>
<span class="post-category" >
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-folder-o"></i>
</span>
<span class="post-meta-item-text">分类于</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/学习/" itemprop="url" rel="index">
<span itemprop="name">学习</span>
</a>
</span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p><a href="https://imgchr.com/i/iz4o4I"><img src="https://s1.ax1x.com/2018/11/17/iz4o4I.jpg" alt="iz4o4I.jpg"></a></p>
<p>本文建议结合 <a href="https://github.com/Tk-archer/functional-javaScript-code-refactoring">https://github.com/Tk-archer/functional-javaScript-code-refactoring</a> 这个项目阅读查看</p>
<h2 id="起"><a href="#起" class="headerlink" title="起"></a>起</h2><p>『JavaScript函数式编程』这书其实在几年前我就入手了,但是当时并没能读下去,然后就一直尘封在书柜里面。</p>
<p>直到最近才偶然翻出来,打算好好读一下。本文说是读书笔记的话就过于正式了,所以就只能称之为备忘录了。</p>
<!--noindex-->
<div class="post-button text-center">
<a class="btn" href="/2019/04/11/JavaScript函数式编程备忘录-上/#more" rel="contents">
阅读全文 »
</a>
</div>
<!--/noindex-->
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</div>
</article>
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="http://yoursite.com/2019/01/09/2018-five-总结/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="Fszer">
<meta itemprop="description" content="">
<meta itemprop="image" content="https://cloud.githubusercontent.com/assets/18730194/15146790/dd39acee-16ef-11e6-8ee7-093d1ce74fce.png">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="聆听群山的怒号">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2019/01/09/2018-five-总结/" itemprop="url">2018 five总结</a></h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建于" itemprop="dateCreated datePublished" datetime="2019-01-09T23:16:10+08:00">
2019-01-09
</time>
</span>
<span class="post-category" >
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-folder-o"></i>
</span>
<span class="post-meta-item-text">分类于</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/杂谈/" itemprop="url" rel="index">
<span itemprop="name">杂谈</span>
</a>
</span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h2 id="序言"><a href="#序言" class="headerlink" title="序言"></a>序言</h2><p>不得不说,我实际上并没有正儿八经的为自己写过一篇年度总结。所以这某种意义上来说也是一种“新年新气象”的行为,尽管这实际上是在回顾过去。</p>
<h2 id="2018-我干了什么"><a href="#2018-我干了什么" class="headerlink" title="2018 我干了什么"></a>2018 我干了什么</h2><p>今年是我在我的第一家公司工作的第二年,也是我正式工作的第二年。工作上今年其实并不是很有意思。</p>
<h3 id="不上不下的组件库"><a href="#不上不下的组件库" class="headerlink" title="不上不下的组件库"></a>不上不下的组件库</h3><p>年初我完成了公司内部的一套统一的 ui 组件库,现在看来只是马马虎虎,不足之处也数不胜数。但是实现的过程中可以说是对我个人的提升最大的一项工作,这对让我对需对组件的整合设计逻辑,以及这个组件概念本身都有了更多的了解。</p>
<p>但是不得不说,一个要维护一个成熟的 ui 库其实是非常花费精力的,看似一个 ui 组件库的核心是他自己,然而有没有方便的使用方法,明确的文档,<strong>能否有一套成熟的管理协作开发流程</strong>都对这个 ui 组件最终能发展成怎么样,有着非常大的影响。</p>
<h3 id="ts-rx-react"><a href="#ts-rx-react" class="headerlink" title="ts/rx/react"></a>ts/rx/react</h3><p>不得不承认我还是一个相当跟风又懒的人,在周围各种大佬的案例下,我最终可喜可贺的有时间“入门”了一下以上提到的这三个东西,的确可以说是打开了一些新方向</p>
<p>不过,可惜的是这些依然处于一个“入门”的阶段,能看懂使用了这些库的项目的源码,并一定程度理解到其实现思路的特殊之处,甚至自己写一些小玩意也不是什么问题。</p>
<p>然而,实际工作中没还是能有机会使用到,因此在这几项东西中必然还有更多我所没有了解到的,水面下的东西。</p>
<h3 id="再一次,早上好,药丸市"><a href="#再一次,早上好,药丸市" class="headerlink" title="再一次,早上好,药丸市"></a>再一次,早上好,药丸市</h3><p>我是一个相对孤僻的人,求学时期虽然也缺钱,但更重要的的是我缺少那些能引领我到处出去玩的朋友,因此即使说我是在广州长大,对于这里的很多地方我也非常陌生。过去的一年里我依然还是蛮孤僻的,但是由于某种我已经忘记了的理由,我决定不再呆在室内孤僻。</p>
<p>因此这一年里我去了许多广州的许多地方,一般开始的目的是为了某一处的食物,最终总是会变成吃完以后漫无目的的到处晃,有很多我之前没有去过的地方,也有那些我很久没有去过的地方,或许对于许多真正意义上的“老广”来说,我去的那些地方或许还是相当的“大众化”,但无论如何工作后以一种新的角度游历这个城市,带给我非常新鲜的感觉。</p>
<h2 id="2018-我没干成什么"><a href="#2018-我没干成什么" class="headerlink" title="2018 我没干成什么"></a>2018 我没干成什么</h2><p>emmmm,要说这个,那可就太多了。</p>
<p>比如我现在依然没有减下体重到 70kg 以下,虽然也能维持在 70~71,偶尔因为生病脱水落到 70 以下,但毕竟没有到达目标。</p>
<p>工作上,就像我上一篇文章里面所说的,这个最终走到垃圾堆里的失败项目对我的打击实在不是一点半点,但是那篇也写得够多的了,这里不再赘述。</p>
<p>除了这个,上面提到的 ui 库某种程度上也应该列入到这一 part。虽然根据最初的计划,我确实是完成了一版 ui 可用的ui组件库,但是,完成可用只不过是一个开始。就像上面说的维护和不断的迭代才是决定了它能走多远的核心。</p>
<p>然而就公司而言,业务需求始终是优先,以及这个项目缺少良性的反馈参与,在后期维护上变的越发吃力,现在虽然我还能接着用,却无力在公司内部进一步推广,因为无法适应设计多变的要求,如果明年还是没有时间抽出做专门的维护,最终荒废掉的结局大概是不可避免的。</p>
<p>个人方面,在我的 blog 有两问题,一个是更新,连月更都算不上,每年年初都想着要写多一点,每次是败给自己的惰性。</p>
<p>更加可惜的是另一个,同样在年初定下的自建博客也没有能完成,大概只做到了 1/3 的代码就因为这样那样的借口最终没能坚持下来。再一次让我体会到自己的堕落之处。</p>
<p>尽管我大言不惭的把说我去年一年学了新的东西,但我真的有足够的提升到了自我了吗?</p>
<p>举个例子,在重复的业务开发中,我能有一些比较固定的套路来提升自己的工作效率,然而这这些套路也没有能到达随手捏出一个成型的辅助类库的地步,其中多多少少还是只不过是换种花样的复制粘贴。另一方面,有固定的套路真的好事吗,这某种意义上或者也可以说是一种思路的僵化。尤其是周遭环境缺少有效的参考让我很难意识到自己做的到底行不行,尽管网络如此发达总是能找到解决方法,但是总觉得隔了一层纱,让我难以得到及时的反馈。</p>
<h2 id="8102-年"><a href="#8102-年" class="headerlink" title="8102 年"></a>8102 年</h2><p>这一 part 就是纯粹的杂谈了,说不上是完成了什么,也没有搞砸了什么。只是想记录今年里面那些还能让我想起来的片段。</p>
<h3 id="姜维传"><a href="#姜维传" class="headerlink" title="姜维传"></a>姜维传</h3><p>游戏方面,下半年印象最深刻的莫过于【姜维传】这部神仙作品。尽管他是一个 mod ,尽管我的战旗水平很差以至于后期全靠修改器。但是这个游戏再一次为我展现了一个不同的三国世界,其中的考究和脑洞实在令人佩服。尤其是今年我还玩了 358 这部贫瘠得可怜的开放世界,相比之下你只会想要问候暗荣那一家子开发人员到底在搞什么飞机。</p>
<p>我怎么都没有想到我人生中屈指可数的通宵居然能有姜维传一席之地。</p>
<h3 id="社交媒体"><a href="#社交媒体" class="headerlink" title="社交媒体"></a>社交媒体</h3><p>我其实一直不习惯国内社交媒体,多数时候对我来说他们不过又是另一种通讯工具,而非社交。我这些年流连最多的是 A 岛这样一个“匿名”的地方,他给我一种个人隐藏于话题之后的安心感,可以专注于话题而非多数社交媒体上的角色扮演。</p>
<p>不过从前年开始,telegram 这个im软件走入我的社交圈子中,对我来说它有种当年 qq 的感觉,却更加自由,现在这个时代这个地方,能有一份自由相当难得。今年我花了更多的时间在这里,显然,它让我意识到我并没有我想象中那么不需要社交。如果你厌烦于国内吵杂的社交环境,不如尝试以下 telegram。</p>
<p>最后是 g+ ,嚷嚷了那么久的鬼城鬼城,一旦真到了要倒闭的时候,还是会感到不舍,毕竟是陪伴了我相当一段时间的地方,要关门了,理性上可以接受,情感上依然会感到失落,只能说有缘再见。</p>
<h3 id="“绝症”患者与现代医学"><a href="#“绝症”患者与现代医学" class="headerlink" title="“绝症”患者与现代医学"></a>“绝症”患者与现代医学</h3><p>已经不知道是什么时候开始的了,我居然会有耳鸣…我尤为记得,当我第一次在 A 岛看到有人描述他自己是耳鸣,我才突然意识到我也有耳鸣。那种出其不意的感觉,犹如凤雏突然意识到自己所在的地方叫落凤坡一样。从此耳鸣就成为我生活中并不能被舍弃的一环。</p>
<p>我所患上的是神经性耳鸣,这个东西非常简单,简单到谷歌一下可以理解是什么,然而它又非常复杂,复杂到发生的原因?不知道,耳鸣响在哪里?不清楚,耳鸣的感受?只能靠患者描述(无法有客观物理的设备检测到),也没有确实有效的缓解药物,更不要说根治方法方法了。各种意义上都可以说是“绝症”了。</p>
<p>我今年终于鼓起勇气去医院检查了一番。就结果而言,基本上跟我自己查得到的资料是一致的。与其说做了无用功,不如说被医生确认了长久萦绕在心头上的想法,反而落得轻松。毕竟已经相当接受了耳鸣的存在。不过遇上失眠的夜晚加上耳朵吱吱作响依然是令人倍感绝望。</p>
<p>值得一提的是,在我检查我的耳鸣的时候,其中最核心的一项检查是判断我到底是不是有耳鸣,其实就是按顺序播放不同频率的声音,直到有一个频率的声音被你的耳鸣覆盖住,你觉得你听不到了,那么你就是患上了这个频率附近的耳鸣。这个方法异常简单,甚至你自己都可以在家做。</p>
<p>整个过程的主观性质非常的强,到底听没听到都是患者说了算,比如说一个听力正常的人,完全可以故意作假而很难被医生看出来。不像验血结果有就有没有就没有,可以客观的检查到。</p>
<p>最终结果也有些哭笑不得,除了耳鸣这个问题以外,各项检查都表示我的听力水平居然属于相当优秀那一拨,人生真是充满黑色幽默。现代医学已经解决了相当多的问题,然而现代医学也依然有相当多的问题还不能解决。就像知道自己不能做什么和知道自己能做什么同样重要。</p>
<p>所以这个时候,除了微笑还有什么更好的方法吗?</p>
<h3 id="书籍的边界"><a href="#书籍的边界" class="headerlink" title="书籍的边界"></a>书籍的边界</h3><p>今年我在学 react/ts/rx 这一堆的东西的时候,也都找了一下相关的书籍来看,结果每一本都有相当程度的过气跟不上版本的部分,其中以 react 的书籍尤其严重,同时 react 相关书籍的复读程度也是最高的,几乎每本书都要把相同的东西复读一边。</p>
<p>所以就像《疯投圈》有一期提到的读书观点,并不是不喜欢读书,而是作为技术类书籍,除非是很学院派的知识内容,否则一般程度的技术资讯类都不值得出书,尤其是各种这个入门那个初见,大多数都很令人失望……因为滞后性实在太强了,这或许本身就是书籍这种载体的局限所在。</p>
<h3 id="报复性消费"><a href="#报复性消费" class="headerlink" title="报复性消费"></a>报复性消费</h3><p>根据支付宝记录,我去年花费并不低,可以说是新高了。其实我刚开始工作的时候对消费是很有负罪感的,即便那些钱是我自己的工资。结果在一次次面那些对由不得你的支出的时候,报复性消费的欲望最终盖过了所剩无几的负罪感,从此,消费水平直线上升。</p>
<h2 id="所以-2019-就这样来了"><a href="#所以-2019-就这样来了" class="headerlink" title="所以 2019 就这样来了"></a>所以 2019 就这样来了</h2><p>太多的事情让我对新的一年没有更多的好感,虽然还有那么一些期望的东西,整体来说却有些提不起兴致。</p>
<p>姑且也写下了,方便我明年这个时候回来打脸</p>
<ol>
<li><strong>更新更多的 blog 文章</strong>,至少要比去年多吧,缺少人际交流的时候其实适合发牢骚。</li>
<li><strong>把去年学到的东西用上</strong>,只有学以致用才能学到更多东西,不然这个入门那个尝鲜,和我看不起的那些无聊的书籍又有什么不一样呢?</li>
<li><strong>旅游</strong>,想去日本见识一下,自已一个人去……</li>
<li><strong>做出一些更加有意义的东西</strong>,那么,什么是有意义的东西呢?</li>
</ol>
<p>完</p>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</div>
</article>
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="http://yoursite.com/2018/10/26/npm 如何安装私有包/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="Fszer">
<meta itemprop="description" content="">
<meta itemprop="image" content="https://cloud.githubusercontent.com/assets/18730194/15146790/dd39acee-16ef-11e6-8ee7-093d1ce74fce.png">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="聆听群山的怒号">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2018/10/26/npm 如何安装私有包/" itemprop="url">npm 如何安装私有包</a></h1>