-
Notifications
You must be signed in to change notification settings - Fork 0
/
feed.xml
936 lines (607 loc) · 90.9 KB
/
feed.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
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
<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.6.2">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2018-05-07T22:45:25+08:00</updated><id>/</id><title type="html">满大哈哈</title><subtitle>花名:满大哈哈,前端工程师,目标就是技术工程师,专注在所有的兴趣范围内</subtitle><entry><title type="html">利用canvas将html生成为图片</title><link href="/html5/2018/04/29/posterGenerater.html" rel="alternate" type="text/html" title="利用canvas将html生成为图片" /><published>2018-04-29T00:00:00+08:00</published><updated>2018-04-29T00:00:00+08:00</updated><id>/html5/2018/04/29/posterGenerater</id><content type="html" xml:base="/html5/2018/04/29/posterGenerater.html"><h2 id="需求">需求</h2>
<ol>
<li>HTML内容定制编辑后,把完整的HTML块生成成图片</li>
<li>提供预览</li>
<li>图片清晰</li>
</ol>
<h2 id="选型">选型</h2>
<ol>
<li>
<p>现成库直接上的原则:<a href="https://github.com/niklasvh/html2canvas">html2canvas</a>,star 10k+
需求1完美解决</p>
</li>
<li>
<p>造轮子,自己定制一个简单的生成工具</p>
</li>
</ol>
<h2 id="实现">实现</h2>
<p>html2canvas就不细说了,google/baidu的出来很多采坑方案,总体使用没问题,稍微看一下官方的特性说明,一些css属性是不支持的。</p>
<h3 id="下面是造轮子时间">下面是造轮子时间:</h3>
<p>提供思路,细节还需慢慢完善</p>
<p>html/css:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;style&gt;</span>
<span class="nc">.demo</span><span class="p">{</span>
<span class="nl">position</span><span class="p">:</span> <span class="nb">relative</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">300px</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">500px</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">0</span> <span class="nb">auto</span> <span class="m">10px</span><span class="p">;</span>
<span class="nl">border</span><span class="p">:</span> <span class="m">1px</span> <span class="nb">solid</span> <span class="m">#333</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.rect1</span><span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">30%</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">40%</span><span class="p">;</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">lightblue</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.rect2</span><span class="p">{</span>
<span class="nl">position</span><span class="p">:</span> <span class="nb">absolute</span><span class="p">;</span>
<span class="nl">top</span><span class="p">:</span> <span class="m">20%</span><span class="p">;</span>
<span class="nl">right</span><span class="p">:</span> <span class="m">30%</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">30%</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">40%</span><span class="p">;</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">lightcoral</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.rect3</span><span class="p">{</span>
<span class="nl">position</span><span class="p">:</span> <span class="nb">absolute</span><span class="p">;</span>
<span class="nl">top</span><span class="p">:</span> <span class="m">40%</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">100%</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">40%</span><span class="p">;</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">lightgreen</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.btns</span><span class="p">{</span>
<span class="nl">text-align</span><span class="p">:</span> <span class="nb">center</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.preview</span><span class="p">{</span>
<span class="nl">text-align</span><span class="p">:</span> <span class="nb">center</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">&lt;/style&gt;</span>
<span class="nt">&lt;section</span> <span class="na">class=</span><span class="s">"demo"</span><span class="nt">&gt;</span>
<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"rect1"</span><span class="nt">&gt;&lt;/div&gt;</span>
<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"rect2"</span><span class="nt">&gt;&lt;/div&gt;</span>
<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"rect3"</span><span class="nt">&gt;&lt;/div&gt;</span>
<span class="nt">&lt;/section&gt;</span>
</code></pre></div></div>
<p>布局上涉及了基础定位,position定位,为了简化造轮子的过程,我把布局按层叠进行了顺序调整,有需要的在布局阶段需要额外的增加元素的层级排序。</p>
<p>预览:</p>
<p><img src="/assets/images/20180429/html-preview.jpg" alt="img" /></p>
<h3 id="javascript片段">javascript片段</h3>
<h4 id="初始化">初始化</h4>
<ol>
<li>需要根据目标HTML块的大小来设置canvas的大小</li>
<li>将初始化好的canvas插入到body中,必要时设置隐藏
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">init</span><span class="p">(</span><span class="nx">target</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">targetDOMTree</span><span class="p">.</span><span class="nx">target</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="nx">target</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">canvas</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">'canvas'</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">canvas</span><span class="p">.</span><span class="nx">width</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">targetDOMTree</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">offsetWidth</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">canvas</span><span class="p">.</span><span class="nx">height</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">targetDOMTree</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">offsetHeight</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ctx</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">canvas</span><span class="p">.</span><span class="nx">getContext</span><span class="p">(</span><span class="s1">'2d'</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s1">'body'</span><span class="p">).</span><span class="nx">appendChild</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">canvas</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div> </div>
</li>
</ol>
<h3 id="画到canvas">画到canvas</h3>
<ol>
<li>取出html块的元素</li>
<li>根据内容判断画图,画文字还是继续查找</li>
<li>取得需要画到canvas的元素的必要css信息,如背景色,高宽,位置等</li>
<li>画起来</li>
</ol>
<p>代码片段提供简单的是否有文字的判断</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">renderToCanvas</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">allChildren</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">targetDOMTree</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">children</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">l</span> <span class="o">=</span> <span class="nx">allChildren</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">l</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">allChildren</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">innerTEXT</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ctx</span><span class="p">.</span><span class="nx">save</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ctx</span><span class="p">.</span><span class="nx">fillStyle</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">getComputedStyle</span><span class="p">(</span><span class="nx">allChildren</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span> <span class="kc">null</span><span class="p">).</span><span class="nx">backgroundColor</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ctx</span><span class="p">.</span><span class="nx">fillRect</span><span class="p">(</span><span class="nx">allChildren</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">offsetLeft</span><span class="p">,</span> <span class="nx">allChildren</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">offsetTop</span><span class="p">,</span> <span class="nx">allChildren</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">offsetWidth</span><span class="p">,</span> <span class="nx">allChildren</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">offsetHeight</span><span class="p">)</span>
<span class="k">this</span><span class="p">.</span><span class="nx">ctx</span><span class="p">.</span><span class="nx">restore</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="生成图片">生成图片</h3>
<p>canvas.toDataURL(type, quality):</p>
<p>返回值:</p>
<ul>
<li>图片数据地址</li>
</ul>
<p>参数:</p>
<ul>
<li>type: 可以指定image/jpeg或者image/png,默认: image/png</li>
<li>quality: 图片质量,设置范围: 0~1.0</li>
</ul>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">saveToImage</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">canvas</span><span class="p">.</span><span class="nx">toDataURL</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="结语">结语</h3>
<p>这是思路,因为项目比较赶,有些渲染部分都是写死的,有兴趣的可以直接参看html2canvas的源码,或者自己尝试。</p>
<h4 id="tips">TIPS</h4>
<p>提供几条在实际项目中遇到的问题:</p>
<ol>
<li>需求2的图片预览:
<ul>
<li>pc无问题</li>
<li>android无问题</li>
<li>ios有问题:ios的安全机制,不允许直接使用修改<code class="highlighter-rouge">img src</code>的方式来改变图片,新建img标签也会有这个问题,hack方法:设置<code class="highlighter-rouge">background-image</code>来替代img,不同尺寸的高宽变化就需要专门解决一下</li>
</ul>
</li>
<li>
<p>图片生成会出现模糊:</p>
<ul>
<li>
<p>问题的本质是在高清屏的显示实现精度不同:</p>
</li>
<li>
<p>解决方案: 不管当前的devicePixelRatio的值是多少,统一将canvasDOM节点的width属性设置为其csswidth属性的两倍,同理将height属性也设置为cssheight属性的两倍</p>
</li>
</ul>
</li>
</ol>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="kd">var</span> <span class="nx">getPixelRatio</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">context</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">backingStore</span> <span class="o">=</span> <span class="nx">context</span><span class="p">.</span><span class="nx">backingStorePixelRatio</span> <span class="o">||</span>
<span class="nx">context</span><span class="p">.</span><span class="nx">webkitBackingStorePixelRatio</span> <span class="o">||</span>
<span class="nx">context</span><span class="p">.</span><span class="nx">mozBackingStorePixelRatio</span> <span class="o">||</span>
<span class="nx">context</span><span class="p">.</span><span class="nx">msBackingStorePixelRatio</span> <span class="o">||</span>
<span class="nx">context</span><span class="p">.</span><span class="nx">oBackingStorePixelRatio</span> <span class="o">||</span>
<span class="nx">context</span><span class="p">.</span><span class="nx">backingStorePixelRatio</span> <span class="o">||</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">return</span> <span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">devicePixelRatio</span> <span class="o">||</span> <span class="mi">1</span><span class="p">)</span> <span class="o">/</span> <span class="nx">backingStore</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>
<p>参考:
<a href="https://blog.csdn.net/qyaroon/article/details/51916150">Canvas 在高清屏下绘制图片变模糊的解决方法</a></p></content><author><name></name></author><summary type="html">需求 HTML内容定制编辑后,把完整的HTML块生成成图片 提供预览 图片清晰</summary></entry><entry><title type="html">meta标签的常用设置项</title><link href="/html/2018/04/29/meta.html" rel="alternate" type="text/html" title="meta标签的常用设置项" /><published>2018-04-29T00:00:00+08:00</published><updated>2018-04-29T00:00:00+08:00</updated><id>/html/2018/04/29/meta</id><content type="html" xml:base="/html/2018/04/29/meta.html"><div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;!DOCTYPE html&gt;</span><span class="c">&lt;!-- 使用 HTML5 doctype,不区分大小写 --&gt;</span>
<span class="nt">&lt;html</span> <span class="na">lang=</span><span class="s">"zh-cmn-Hans"</span><span class="nt">&gt;</span><span class="c">&lt;!-- 更加标准的 lang 属性写法 http://zhi.hu/XyIa --&gt;</span>
<span class="nt">&lt;head&gt;</span>
<span class="c">&lt;!-- 声明文档使用的字符编码 --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">charset=</span><span class="s">'utf-8'</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- 优先使用 IE 最新版本和 Chrome --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">http-equiv=</span><span class="s">"X-UA-Compatible"</span> <span class="na">content=</span><span class="s">"IE=edge,chrome=1"</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- 页面描述 --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"description"</span> <span class="na">content=</span><span class="s">"不超过150个字符"</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- 页面关键词 --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"keywords"</span> <span class="na">content=</span><span class="s">""</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- 网页作者 --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"author"</span> <span class="na">content=</span><span class="s">"name, [email protected]"</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- 搜索引擎抓取 --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"robots"</span> <span class="na">content=</span><span class="s">"index,follow"</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- 为移动设备添加 viewport --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"viewport"</span> <span class="na">content=</span><span class="s">"initial-scale=1, maximum-scale=3, minimum-scale=1, user-scalable=no"</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- `width=device-width` 会导致 iPhone 5 添加到主屏后以 WebApp 全屏模式打开页面时出现黑边 http://bigc.at/ios-webapp-viewport-meta.orz --&gt;</span>
<span class="c">&lt;!-- iOS 设备 begin --&gt;</span>
<span class="nt">&lt;metan</span> <span class="na">ame=</span><span class="s">"apple-mobile-web-app-title"</span> <span class="na">content=</span><span class="s">"标题"</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- 添加到主屏后的标题(iOS 6 新增) --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"apple-mobile-web-app-capable"</span> <span class="na">content=</span><span class="s">"yes"</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- 是否启用 WebApp 全屏模式,删除苹果默认的工具栏和菜单栏 --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"apple-itunes-app"</span> <span class="na">content=</span><span class="s">"app-id=myAppStoreID, affiliate-data=myAffiliateData, app-argument=myURL"</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- 添加智能 App 广告条 Smart App Banner(iOS 6+ Safari) --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"apple-mobile-web-app-status-bar-style"</span> <span class="na">content=</span><span class="s">"black"</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- 设置苹果工具栏颜色 --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"format-detection"</span> <span class="na">content=</span><span class="s">"telphone=no, email=no"</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- 忽略页面中的数字识别为电话,忽略email识别 --&gt;</span>
<span class="c">&lt;!-- 启用360浏览器的极速模式(webkit) --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"renderer"</span> <span class="na">content=</span><span class="s">"webkit"</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- 避免IE使用兼容模式 --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">http-equiv=</span><span class="s">"X-UA-Compatible"</span> <span class="na">content=</span><span class="s">"IE=edge"</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- 针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓 --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"HandheldFriendly"</span> <span class="na">content=</span><span class="s">"true"</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- 微软的老式浏览器 --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"MobileOptimized"</span> <span class="na">content=</span><span class="s">"320"</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- uc强制竖屏 --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"screen-orientation"</span> <span class="na">content=</span><span class="s">"portrait"</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- QQ强制竖屏 --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"x5-orientation"</span> <span class="na">content=</span><span class="s">"portrait"</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- UC强制全屏 --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"full-screen"</span> <span class="na">content=</span><span class="s">"yes"</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- QQ强制全屏 --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"x5-fullscreen"</span> <span class="na">content=</span><span class="s">"true"</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- UC应用模式 --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"browsermode"</span> <span class="na">content=</span><span class="s">"application"</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- QQ应用模式 --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"x5-page-mode"</span> <span class="na">content=</span><span class="s">"app"</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- windows phone 点击无高光 --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"msapplication-tap-highlight"</span> <span class="na">content=</span><span class="s">"no"</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- iOS 图标 begin --&gt;</span>
<span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">"apple-touch-icon-precomposed"</span> <span class="na">href=</span><span class="s">"/apple-touch-icon-57x57-precomposed.png"</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- iPhone 和 iTouch,默认 57x57 像素,必须有 --&gt;</span>
<span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">"apple-touch-icon-precomposed"</span> <span class="na">sizes=</span><span class="s">"114x114"</span> <span class="na">href=</span><span class="s">"/apple-touch-icon-114x114-precomposed.png"</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- Retina iPhone 和 Retina iTouch,114x114 像素,可以没有,但推荐有 --&gt;</span>
<span class="nt">&lt;linkr</span> <span class="na">el=</span><span class="s">"apple-touch-icon-precomposed"</span> <span class="na">sizes=</span><span class="s">"144x144"</span> <span class="na">href=</span><span class="s">"/apple-touch-icon-144x144-precomposed.png"</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- Retina iPad,144x144 像素,可以没有,但推荐有 --&gt;</span>
<span class="c">&lt;!-- iOS 图标 end --&gt;</span>
<span class="c">&lt;!-- iOS 启动画面 begin --&gt;</span>
<span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">"apple-touch-startup-image"</span> <span class="na">sizes=</span><span class="s">"768x1004"</span> <span class="na">href=</span><span class="s">"/splash-screen-768x1004.png"</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- iPad 竖屏 768 x 1004(标准分辨率) --&gt;</span>
<span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">"apple-touch-startup-image"</span> <span class="na">sizes=</span><span class="s">"1536x2008"</span> <span class="na">href=</span><span class="s">"/splash-screen-1536x2008.png"</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- iPad 竖屏 1536x2008(Retina) --&gt;</span>
<span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">"apple-touch-startup-image"</span> <span class="na">sizes=</span><span class="s">"1024x748"</span> <span class="na">href=</span><span class="s">"/Default-Portrait-1024x748.png"</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- iPad 横屏 1024x748(标准分辨率) --&gt;</span>
<span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">"apple-touch-startup-image"</span> <span class="na">sizes=</span><span class="s">"2048x1496"</span> <span class="na">href=</span><span class="s">"/splash-screen-2048x1496.png"</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- iPad 横屏 2048x1496(Retina) --&gt;</span>
<span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">"apple-touch-startup-image"</span> <span class="na">href=</span><span class="s">"/splash-screen-320x480.png"</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- iPhone/iPod Touch 竖屏 320x480 (标准分辨率) --&gt;</span>
<span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">"apple-touch-startup-image"</span> <span class="na">sizes=</span><span class="s">"640x960"</span> <span class="na">href=</span><span class="s">"/splash-screen-640x960.png"</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- iPhone/iPod Touch 竖屏 640x960 (Retina) --&gt;</span>
<span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">"apple-touch-startup-image"</span> <span class="na">sizes=</span><span class="s">"640x1136"</span> <span class="na">href=</span><span class="s">"/splash-screen-640x1136.png"</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- iPhone 5/iPod Touch 5 竖屏 640x1136 (Retina) --&gt;</span>
<span class="c">&lt;!-- iOS 启动画面 end --&gt;</span>
<span class="c">&lt;!-- iOS 设备 end --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"msapplication-TileColor"</span> <span class="na">content=</span><span class="s">"#000"</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- Windows 8 磁贴颜色 --&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"msapplication-TileImage"</span> <span class="na">content=</span><span class="s">"icon.png"</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- Windows 8 磁贴图标 --&gt;</span>
<span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">"alternate"</span> <span class="na">type=</span><span class="s">"application/rss+xml"</span> <span class="na">title=</span><span class="s">"RSS"</span> <span class="na">href=</span><span class="s">"/rss.xml"</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- 添加 RSS 订阅 --&gt;</span>
<span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">"shortcut icon"</span> <span class="na">type=</span><span class="s">"image/ico"</span> <span class="na">href=</span><span class="s">"/favicon.ico"</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- 添加 favicon icon --&gt;</span>
<span class="nt">&lt;title&gt;</span>标题<span class="nt">&lt;/title&gt;</span>
</code></pre></div></div>
<h2 id="参考">参考</h2>
<ul>
<li><a href="https://github.com/yisibl/blog/issues/1">网红一丝</a></li>
<li><a href="http://fex.baidu.com/blog/2014/10/html-head-tags/">百度FEX</a></li>
<li><a href="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/meta">MDN-meta</a></li>
</ul></content><author><name></name></author><summary type="html">```html &lt;!DOCTYPE html&gt;</summary></entry><entry><title type="html">在windows上安装Jekyll</title><link href="/jekyll/2018/04/26/installJekyllOnWindows.html" rel="alternate" type="text/html" title="在windows上安装Jekyll" /><published>2018-04-26T00:00:00+08:00</published><updated>2018-04-26T00:00:00+08:00</updated><id>/jekyll/2018/04/26/installJekyllOnWindows</id><content type="html" xml:base="/jekyll/2018/04/26/installJekyllOnWindows.html"><h2 id="准备">准备</h2>
<p>windows 10 X64</p>
<p>Ruby环境:</p>
<ul>
<li><a href="https://rubyinstaller.org/downloads/">Ruby</a> ,官方推荐安装<strong>Ruby+Devkit 2.4.X</strong>,保证扩展库的可用性</li>
</ul>
<p>Python环境(安装python环境是为了提供代码高亮的支持,没需求的可以忽略):</p>
<ul>
<li><a href="https://www.python.org/downloads/windows/">Python</a>, 根据自己系统,我选择的是<strong>Windows x86-64 executable installer</strong></li>
</ul>
<h2 id="步骤">步骤</h2>
<ol>
<li>
<p>打开下载的Ruby的包,选下路径,一路下一步</p>
</li>
<li>
<p>安装Jekyll:</p>
</li>
</ol>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gem install Jekyll <span class="nt">--version</span><span class="o">=[</span>version]
</code></pre></div></div>
<p>版本号根据需要选择,不加就安装最新的</p>
<ol>
<li>安装bundle:</li>
</ol>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gem install bundle <span class="nt">--version</span><span class="o">=[</span>version]
</code></pre></div></div>
<p>Jekyll官方文档已经明确说明,版本大于3.8的需要安装bundle</p>
<ol>
<li>安装成功,更新gem</li>
</ol>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gem update
</code></pre></div></div>
<p>这里是我在安装的时候遇到的,Jekyll的依赖出现各种版本不匹配或者缺失的问题</p>
<ol>
<li>gem更新完成,可以使用Jekyll的命令,例如:</li>
</ol>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>jekyll serve
</code></pre></div></div>
<p>如果还会出现报错,可以使用:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bundle <span class="nb">exec </span>jekyll serve
</code></pre></div></div>
<p>后续其他命令也会需要加上<strong>bundle exec</strong></p>
<p>到这里Jekyll已经可以使用了,如果还需要增加代码高亮的支持,那么:</p>
<ol>
<li>
<p>安装python,安装包一路下一步,顶多改改安装路径</p>
</li>
<li>
<p>安装Pygments:</p>
</li>
</ol>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip install Pygments
</code></pre></div></div>
<p>到此安装结束,可以愉快的写博客了。</p>
<h2 id="参考">参考</h2>
<ul>
<li><a href="https://jekyllrb.com/docs/windows/">Jekyll官方文档</a>,官方推荐的是on Ubuntu on Windows,要硬装在windows上就按上面的步骤来吧</li>
<li><a href="http://yanhaijing.com/jekyll/2011/12/30/run-jekyll-on-window/">颜大大的文档</a>,年份久了点</li>
<li><a href="https://github.com/jekyll/jekyll/issues/6227">官方ISSUE</a>,主要就是会遇到需要利用bundle exec的命令的问题</li>
<li><a href="https://blog.csdn.net/orangleliu/article/details/25080309">Gem指令</a>,可以了解一下</li>
<li><a href="http://istoney.github.io/jekyll/2016/03/10/set-markdown-hightlighter">markdown代码高亮</a>,我是不喜欢minia(Jekyll默认主题)的高亮样式,所以找了一个修改方案</li>
</ul></content><author><name></name></author><summary type="html">准备</summary></entry><entry><title type="html">2018 书单</title><link href="/2018/04/08/2018-BookList.html" rel="alternate" type="text/html" title="2018 书单" /><published>2018-04-08T00:00:00+08:00</published><updated>2018-04-08T00:00:00+08:00</updated><id>/2018/04/08/2018-BookList</id><content type="html" xml:base="/2018/04/08/2018-BookList.html"><p>2018-04</p>
<ul>
<li>《你不知道的 JavaScript(上卷)》 作者:Kyle Simpson</li>
</ul>
<blockquote>
<blockquote>
<p>真正理解 js 的好书,包括编译机制,词法机制,原型链,this 出坑指南。在上卷除了 this 的出坑指南很有助于前端解决 this 的指向问题,让我真正理解了为什么 this 会出现指向问题的根本原因;另一个推荐反复阅读的是关于 JS 的‘类’,js 本身就是一个巨大的对象,我们在使用的时候都是依照原型链来调用,‘类’这个东西是面向对象里很重要的点,很多语言也有,引入到 js 里,通过模拟出‘类’的使用,这样带来的最严重的问题就是混淆了 js 本身的机制,不利于真正的用好 js,看完才明白,js 的调用机制到底需不需要去使用其他语言的特性,动态语言就要发挥动态语言的特性,而不是强行引入静态写法来符合大众的口味。</p>
</blockquote>
</blockquote></content><author><name></name></author><summary type="html">2018-04</summary></entry><entry><title type="html">2017读掉的书</title><link href="/2017/12/15/2017Read.html" rel="alternate" type="text/html" title="2017读掉的书" /><published>2017-12-15T00:00:00+08:00</published><updated>2017-12-15T00:00:00+08:00</updated><id>/2017/12/15/2017Read</id><content type="html" xml:base="/2017/12/15/2017Read.html"><blockquote>
<p>倒序整理</p>
</blockquote>
<h3 id="在读">在读</h3>
<p>《深入浅出 React 和 Redux》 作者:程墨</p>
<blockquote>
<blockquote>
<p>React 和 Redux 的入门很好的一本书,我是边看 ant-design 的代码,边看这本书,快速入门和上手。</p>
</blockquote>
</blockquote>
<h3 id="已读">已读</h3>
<p>2017-11</p>
<ul>
<li>《深入浅出 Node.js》 作者:朴灵</li>
</ul>
<blockquote>
<blockquote>
<p>朴灵这本书涉及到了 C/C++的层面,看起来会有点生涩,阅读的人可能对 C/C++并没有什么了解,但是对深层次的机制进行描述,其实有助于开阔 Node 入门时的视野,不再是局限在单纯的 js 或者服务端开发里面,值得反复推敲。</p>
</blockquote>
</blockquote>
<ul>
<li>《Node.js 实战》 作者:Mike Cantelon,Marc Harter, T.J.Holowaychuk,Nathan Rajlich</li>
</ul>
<blockquote>
<blockquote>
<p>看作者里面有 TJ,对于了解过 Node 的人都知道,TJ 给 Node 社区贡献超级多的高质量模块,Node 的社区的偶像级人物。这本实战写的时间比较早了,如果要照着里面的例子往下走,要注意一下书中 node 的版本和引入的模块的版本,我针对几个例子也做了一些实践,放在<a href="https://github.com/Myu1533/NodeInAction.git">NodeInAction</a>里面,欢迎查看和指正。跟着这本书走完,后续能持续巩固的话,开发个人 Node 的项目已经不是什么问题了,推荐指数无数星。</p>
</blockquote>
</blockquote>
<p>2017-10</p>
<ul>
<li>《智能时代》 作者:吴军</li>
</ul>
<blockquote>
<blockquote>
<p>打通眼界的一本书,智能到底是什么,现在的智能做到了什么,在做什么,能做什么,都做了说明,易于理解。各行业的人都能在书里找到自己行业的因为智能将会怎么变化,行业革命的驱动怎么来,为了不被淘汰,可以做准备了。</p>
</blockquote>
</blockquote>
<p>2017-08</p>
<ul>
<li>《图解 HTTP》作者:上野宣</li>
</ul>
<blockquote>
<blockquote>
<p>HTTP 的入门书,通俗易懂,我借这本书解决了几个 http 问题,打基础的好书</p>
</blockquote>
</blockquote>
<p>2017-05</p>
<ul>
<li>《JavaScript 设计模式与开发实践》 作者:曾探</li>
</ul>
<blockquote>
<blockquote>
<p>推荐必读。看起来可能不会很好理解,结合自己开发的过程,codereview 以后会发现其实用过,书里给了命名,再去看其他源码的话,从好的源码中遍地都是各种模式,阅读源码的理解效率也会高很多,对技术有追求的人,值得反复阅读</p>
</blockquote>
</blockquote></content><author><name></name></author><summary type="html">倒序整理</summary></entry><entry><title type="html">Jekyll Blog 上线</title><link href="/2017/11/27/welcome-to-jekyll.html" rel="alternate" type="text/html" title="Jekyll Blog 上线" /><published>2017-11-27T17:30:01+08:00</published><updated>2017-11-27T17:30:01+08:00</updated><id>/2017/11/27/welcome-to-jekyll</id><content type="html" xml:base="/2017/11/27/welcome-to-jekyll.html"><p>从 Hexo 跳到 jekyll</p>
<p>更喜欢 Jekyll 的简洁</p>
<p>过去的文章都没有做迁移</p>
<p>重新出发专注的写点东西</p>
<p>学习的心得/技术的分享/翻译</p>
<p>总之,记录起来</p></content><author><name></name></author><summary type="html">从 Hexo 跳到 jekyll</summary></entry><entry><title type="html">vue ssr 简介(译)</title><link href="/translate/2017/05/31/vue-ssr-introduce.html" rel="alternate" type="text/html" title="vue ssr 简介(译)" /><published>2017-05-31T00:00:00+08:00</published><updated>2017-05-31T00:00:00+08:00</updated><id>/translate/2017/05/31/vue-ssr-introduce</id><content type="html" xml:base="/translate/2017/05/31/vue-ssr-introduce.html"><h3 id="vuejs-server-side-rendering-guide">Vue.js Server-Side Rendering Guide</h3>
<h3 id="vuejs-服务端渲染指南">Vue.js 服务端渲染指南</h3>
<h6 id="note-this-guide-requires-the-following-minimum-versions-of-vue-and-supporting-libraries"><strong>Note:</strong> this guide requires the following minimum versions of Vue and supporting libraries:</h6>
<h6 id="注该指南至少需要的最低版本的-vue-核心库和支持库"><strong>注:</strong>该指南至少需要的最低版本的 Vue 核心库和支持库:</h6>
<h6 id="vue--vue-server-renderer--230">vue &amp; vue-server-renderer &gt;= 2.3.0</h6>
<h6 id="vue-router--250">vue-router &gt;= 2.5.0</h6>
<h6 id="vue-loader--1200--vue-style-loader--300">vue-loader &gt;= 12.0.0 &amp; vue-style-loader &gt;= 3.0.0</h6>
<p>If you have previously used Vue 2.2 with SSR, you will notice that the recommended code structure is
now <a href="https://ssr.vuejs.org/en/structure.html">a bit different</a> (with the new <a href="https://ssr.vuejs.org/en/api.html#runinnewcontext">runInNewContext</a> option set to false
).</p>
<p>若你已经用 Vue 2.2 做服务端渲染(SSR), 你会发现建议代码实践的提示现在<a href="https://ssr.vuejs.org/en/structure.html">有些不同</a>了(当<a href="https://ssr.vuejs.org/en/api.html#runinnewcontext">runInNewContext</a>选项设置为 false 的时候)</p>
<p>Your existing app should continue to work, but it’s recommended to migrate to the new recommendations.</p>
<p>你的应用会继续工作,但是规范将会迁移到新的推荐规范。</p>
<h3 id="what-is-server-side-rendering-ssr">What is Server-Side Rendering (SSR)?</h3>
<h3 id="什么是服务端渲染ssr">什么是服务端渲染(SSR)?</h3>
<p>Vue.js is a framework for building client-side applications.</p>
<p>Vue.js 是构建客户端应用的框架。</p>
<p>By default, Vue components produce and manipulate DOM in the browser as output.</p>
<p>默认,Vue 组件在浏览器端输出和操作 DOM。</p>
<p>However, it is also possible to render the same components into HTML strings on the server,send them directly to the browser,and finally “hydrate” the static markup into a fully interactive app on the client.</p>
<p>然而,同样可以在服务端渲染相同组件到 HTML 里面,把他们直接发送到浏览器,最后在客户端把静态标签变为富交互的应用。</p>
<p>A server-rendered Vue.js app can also be considered “isomorphic” or “universal”,in the sense that the majority of your app’s code runs on both the server <strong>and</strong> the client.</p>
<p>一个服务端渲染的 Vue.js 应用能被认为是同构的或者是通用的,你应用的大部分代码是运行在服务端和客户端的。</p>
<h3 id="why-ssr">Why SSR?</h3>
<h3 id="为什么要用-ssr">为什么要用 SSR?</h3>
<p>Compared to a traditional SPA (Single-Page Application),the advantage of SSR primarily lies in:</p>
<p>和传统的单页应用相比,SSR 的主要优势有:</p>
<p>Better SEO, as the search engine crawlers will directly see the fully rendered page.</p>
<p>更好的 SEO,搜索引擎的爬虫能直接看到完整的渲染页面。</p>
<p>Note that as of now, Google and Bing can index synchronous JavaScript applications just fine.</p>
<p>到目前为止,google 和 bing 可以很好的索引和同步 JavaScript 应用。</p>
<p>Synchronous being the key word there.</p>
<p>同步是关键。</p>
<p>If your app starts with a loading spinner, then fetches content via Ajax,the crawler will not wait for you to finish.</p>
<p>如果你的应用在启动的时候有个载入列表,通过 AJAX 获取内容,爬虫可不会等着你完成。</p>
<p>This means if you have content fetched asynchronously on pages where SEO is important,SSR might be necessary.</p>
<p>这意味着在重点 SEO 的页面是异步加载的,那么服务器渲染是必然的。</p>
<h4 id="faster-time-to-content">Faster time-to-content,</h4>
<h4 id="更快的内容加载">更快的内容加载,</h4>
<h4 id="especially-on-slow-internet-or-slow-devices">especially on slow internet or slow devices.</h4>
<h4 id="特别是在低速网络或者运行慢的设备上">特别是在低速网络或者运行慢的设备上。</h4>
<p>Server-rendered markup doesn’t need to wait until all JavaScript has been downloaded and executed to be
displayed, so your user will see a fully-rendered page sooner.</p>
<p>服务器端显示不需要等到所有 js 下载完成和执行才显示,所以你的用户将很快看到整个页面。</p>
<p>This generally results in better user experience, and can be critical for applications where time-to-content is directly associated with conversion rate.</p>
<p>这个结果在用户体验方面是更好的,也能用于评定渲染时间直接关系到转换率的应用。</p>
<h3 id="there-are-also-some-trade-offs-to-consider-when-using-ssr">There are also some trade-offs to consider when using SSR:</h3>
<h3 id="在用-ssr-的时候有几点需要权衡">在用 SSR 的时候,有几点需要权衡:</h3>
<p>Development constraints. Browser-specific code can only be used inside certain lifecycle hooks;some external libraries may need special treatment to be able to run in a server-rendered app.</p>
<p>开发限制。依赖浏览器特性的代码只能在内部关键的生命周期钩子上;一些外部库在服务端渲染应用上也需要特殊处理。</p>
<p>More involved build setup and deployment requirements.</p>
<p>更多的构建设置和发布需求的耦合。</p>
<p>Unlike a fully static SPA that can be deployed on any static file server,a server-rendered app requires an environment where a Node.js server can run.</p>
<p>不在像完整个的静态单页应用该可以被发布在任何静态服务器上,服务端渲染应用更需要一个 node 服务环境。</p>
<h3 id="more-server-side-load">More server-side load.</h3>
<h3 id="更多的服务端加载">更多的服务端加载。</h3>
<p>Rendering a full app in Node.js is obviously going to be more CPU-intensive than just serving static files,so if you expect high traffic, be prepared for corresponding server load and wisely employ caching strategies.</p>
<p>node 渲染一个完整应用,光服务静态文件就需要更多的密集型 CPU。因此如果你期望有高通信,就需要准备相应的服务载入和合理的使用缓存策略。</p>
<p>Before using SSR for your app, the first question you should ask it whether you actually need it.</p>
<p>在应用 SSR 之前,先问问自己是否真的需要。</p>
<p>It mostly depends on how important time-to-content is for your app.</p>
<p>主要依赖于渲染时间对应用的重要程度。</p>
<p>For example, if you are building an internal dashboard where an extra few hundred milliseconds on initial load doesn’t matter that much, SSR would be an overkill.</p>
<p>例如,你在做一个内部仪表盘,额外初始化的时候额外多几百号面也没什么影响,用 SSR 就过分了。</p>
<p>However, in cases where time-to-content is absolutely critical, SSR can help you achieve the best possible initial load performance.</p>
<p>然而,渲染时间是必要的评定标准,SSR 将帮助你在初始化表现上达到最好的可能。</p>
<h3 id="ssr-vs-prerendering">SSR vs Prerendering</h3>
<p>If you’re only investigating SSR to improve the SEO of a handful of marketing pages (e.g. /
, /about
, /contact
, etc), then you probably want <strong>prerendering</strong> instead.</p>
<p>如果你只是需要 SSR 在少数交易页面的 SEO 提升,那么预加载是替代方案。</p>
<p>Rather than using a web server to compile HTML on-the-fly, prerendering simply generates static HTML files for specific routes at build time.</p>
<p>相比于网页编译即时 HTML,在构建的时候预加载可以以简单方式生成特殊路由的静态 HTML 文件。</p>
<p>The advantage is setting up prerendering is much simpler and allows you to keep your frontend as a fully static site.</p>
<p>设置预加载的优势是更简单,允许你保持前端是一个完整的前端站点。</p>
<p>If you’re using Webpack, you can easily add prerendering with the <a href="https://github.com/chrisvfritz/prerender-spa-plugin">prerender-spa-plugin</a>.</p>
<p>如果你用 Webpack,你用 <a href="https://github.com/chrisvfritz/prerender-spa-plugin">prerender-spa-plugin</a>就可以轻易的增加预加载功能。</p>
<p>It’s been extensively tested with Vue apps - and in fact, <a href="https://github.com/chrisvfritz">the creator</a> is a member of the Vue core team.</p>
<p>事实上,这已经被广泛的应用在 Vue 应用上,<a href="https://github.com/chrisvfritz">创造者</a>来自于 Vue 核心代码团队。</p>
<h3 id="about-this-guide">About This Guide</h3>
<h3 id="关于这份指南">关于这份指南</h3>
<p>This guide is focused on server-rendered Single-Page Applications using Node.js as the server.</p>
<p>这份指南专注于用 Node 作为服务器的服务器端渲染的单页应用。</p>
<p>Mixing Vue SSR with other backend setups is a topic of its own and is not covered in this guide.</p>
<p>在其他后端服务用 Vue SSR 是另外一个话题,本指南将不会包含这方面的内容。</p>
<p>This guide will be very in-depth and assumes you are already familiar with Vue.js itself, and have decent working knowledge of Node.js and webpack.</p>
<p>这份指南非常深入解析 Vue SSR,是你以已经熟悉 Vue.js,掌握 node 和 webpack 的相关知识为前提。</p>
<p>If you prefer a higher-level solution that provides a smooth out-of-the-box experience, you should probably give <a href="http://nuxtjs.org/">Nuxt.js</a> a try.</p>
<p>如果你更倾向于用过更高级的,提供封装完好的体验的解决方案,你应该试试 <a href="http://nuxtjs.org/">Nuxt.js</a> 。</p>
<p>It’s built upon the same Vue stack but abstracts away a lot of the boilerplate, and provides some extra features such as static site generation.</p>
<p>它同样建立在 Vue 的堆栈上面,但是抽了很多引用,并提供一些额外特性,例如静态站点迭代器。</p>
<p>However, it may not suit your use case if you need more direct control of your app’s structure.</p>
<p>然而,如果你对你的应用该结构需要更多直接操作,<a href="http://nuxtjs.org/">Nuxt.js</a> 可能不适合。</p>
<p>Regardless, it would still be beneficial to read through this guide to better understand how things work together.</p>
<p>无论如何,通过阅读本指南有助于理解所有事务是如何一起共工作的。</p>
<p>As you read along, it would be helpful to refer to the official <a href="https://github.com/vuejs/vue-hackernews-2.0/">HackerNews Demo</a>, which makes use of most of the techniques covered in this guide.</p>
<p>就像你看到的,参考官方案例<a href="https://github.com/vuejs/vue-hackernews-2.0/">HackerNews Demo</a>,因为里面对指南里涉及的大多数技术的用法都有包含。</p>
<p>Finally, note that the solutions in this guide are not definitive - we’ve found them to be working well for us, but that doesn’t mean they cannot be improved.</p>
<p>最后,注意指南里的解决方案不是一定的,虽然对于我们来说他们工作的很好,并不意味着它们是不可改进的。</p>
<p>They might get revised in the future - and feel free to contribute by submitting pull requests!</p>
<p>他们在未来可能会被修改,欢迎提交 pr 来提交贡献。</p></content><author><name></name></author><summary type="html">Vue.js Server-Side Rendering Guide</summary></entry><entry><title type="html">vue ssr 基本用法(译)</title><link href="/translate/2017/05/31/vue-ssr-guide.html" rel="alternate" type="text/html" title="vue ssr 基本用法(译)" /><published>2017-05-31T00:00:00+08:00</published><updated>2017-05-31T00:00:00+08:00</updated><id>/translate/2017/05/31/vue-ssr-guide</id><content type="html" xml:base="/translate/2017/05/31/vue-ssr-guide.html"><h3 id="installation">Installation</h3>
<h3 id="安装">安装</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>npm install vue vue-server-renderer <span class="nt">--save</span>
</code></pre></div></div>
<p>We will be using NPM throughout the guide, but feel free to use <a href="https://yarnpkg.com/en/">Yarn</a> instead.</p>
<p>整个指南我们都用 NPM,不过也可以用 <a href="https://yarnpkg.com/en/">Yarn</a> 代替。</p>
<h4 id="notes">Notes</h4>
<h4 id="注意">注意</h4>
<p>It’s recommended to use Node.js version 6+.
vue-server-renderer
and vue
must have matching versions.</p>
<p>建议 Node v6 以上。
vue-server-renderer
和 vue
必须用对应的版本。
vue-server-renderer
relies on some Node.js native modules and therefore can only be used in Node.js.</p>
<p>vue-server-renderer 依赖 Node 本身的模块,因此只能应用在 node 上面。</p>
<p>We may provide a simpler build that can be run in other JavaScript runtimes in the future.</p>
<p>我们在未来会提供可以跑在其他 js 解析器的更简单的构建。</p>
<h3 id="rendering-a-vue-instance">Rendering a Vue Instance</h3>
<h3 id="渲染-vue-实例">渲染 Vue 实例</h3>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Step 1: Create a Vue instance</span>
<span class="c1">// 第一步: 创建Vue实例</span>
<span class="kd">const</span> <span class="nx">Vue</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'vue'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Vue</span><span class="p">({</span>
<span class="na">template</span><span class="p">:</span> <span class="s2">`&lt;div&gt;Hello World&lt;/div&gt;`</span>
<span class="p">});</span>
<span class="c1">// Step 2: Create a renderer</span>
<span class="c1">// 第二步:创建渲染器</span>
<span class="kd">const</span> <span class="nx">renderer</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'vue-server-renderer'</span><span class="p">).</span><span class="nx">createRenderer</span><span class="p">();</span>
<span class="c1">// Step 3: Render the Vue instance to HTML</span>
<span class="c1">// 第三步:把Vue实例渲染到HTML</span>
<span class="nx">renderer</span><span class="p">.</span><span class="nx">renderToString</span><span class="p">(</span><span class="nx">app</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">html</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="k">throw</span> <span class="nx">err</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">html</span><span class="p">);</span>
<span class="c1">// =&gt; &lt;div data-server-rendered="true"&gt;hello world&lt;/div&gt;</span>
<span class="p">});</span>
</code></pre></div></div>
<h3 id="integrating-with-a-server">Integrating with a Server</h3>
<h3 id="服务端集成">服务端集成</h3>
<p>It is pretty straightforward when used inside a Node.js server, for example <a href="https://expressjs.com/">Express</a>:</p>
<p>在 Node 里面使用相当的简单,例如<a href="https://expressjs.com/">Express</a>:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>npm install express <span class="nt">--save</span>
</code></pre></div></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">Vue</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'vue'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">server</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'express'</span><span class="p">)();</span>
<span class="kd">const</span> <span class="nx">renderer</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'vue-server-renderer'</span><span class="p">).</span><span class="nx">createRenderer</span><span class="p">();</span>
<span class="nx">server</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="s1">'*'</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Vue</span><span class="p">({</span>
<span class="na">data</span><span class="p">:</span> <span class="p">{</span> <span class="na">url</span><span class="p">:</span> <span class="nx">req</span><span class="p">.</span><span class="nx">url</span> <span class="p">},</span>
<span class="na">template</span><span class="p">:</span> <span class="s2">`&lt;div&gt;The visited URL is: &lt;/div&gt;`</span>
<span class="p">});</span>
<span class="nx">renderer</span><span class="p">.</span><span class="nx">renderToString</span><span class="p">(</span><span class="nx">app</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">html</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">status</span><span class="p">(</span><span class="mi">500</span><span class="p">).</span><span class="nx">end</span><span class="p">(</span><span class="s1">'Internal Server Error'</span><span class="p">);</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span>
<span class="s2">` &lt;!DOCTYPE html&gt; &lt;html lang="en"&gt; &lt;head&gt;&lt;title&gt;Hello&lt;/title&gt;&lt;/head&gt; &lt;body&gt;</span><span class="p">${</span><span class="nx">html</span><span class="p">}</span><span class="s2">&lt;/body&gt; &lt;/html&gt; `</span>
<span class="p">);</span>
<span class="p">});</span>
<span class="p">});</span>
<span class="nx">server</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">8080</span><span class="p">);</span>
</code></pre></div></div>
<h3 id="using-a-page-template">Using a Page Template</h3>
<h3 id="使用页面模板">使用页面模板</h3>
<p>When you render a Vue app, the renderer only generates the markup of the app.</p>
<p>当你渲染 Vue 应用的时候,渲染器只生成应用的标记。</p>
<p>In the example we had to wrap the output with an extra HTML page shell.</p>
<p>在案例里,我们用一个额外的 HTML 页面可以包裹输出。</p>
<p>To simplify this, you can directly provide a page template when creating the renderer.</p>
<p>为简化这步操作,你可以在创建渲染器的时候直接提供页面模板。</p>
<p>Most of the time we will put the page template in its own file, e.g. index.template.html:</p>
<p>大多数时候我们把页面模板放在它自己的文件里,例如 index.template.html:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;!DOCTYPE html&gt;</span>
<span class="nt">&lt;html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">&gt;</span>
<span class="nt">&lt;head&gt;</span>
<span class="nt">&lt;title&gt;</span>Hello<span class="nt">&lt;/title&gt;</span>
<span class="nt">&lt;/head&gt;</span>
<span class="nt">&lt;body&gt;</span>
<span class="c">&lt;!--vue-ssr-outlet--&gt;</span>
<span class="nt">&lt;/body&gt;</span>
<span class="nt">&lt;/html&gt;</span>
</code></pre></div></div>
<p>Notice the <!--vue-ssr-outlet--> comment – this is where your app’s markup will be injected.</p>
<h4 id="注意语句这里将是应用标记要注入的地方">注意<!--vue-ssr-outlet-->语句,这里将是应用标记要注入的地方。</h4>
<p>We can then read and pass the file to the Vue renderer:</p>
<p>我们将读取并传送文件给 Vue 的渲染器:</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">renderer</span> <span class="o">=</span> <span class="nx">createRenderer</span><span class="p">({</span>
<span class="na">template</span><span class="p">:</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'fs'</span><span class="p">).</span><span class="nx">readFileSync</span><span class="p">(</span><span class="s1">'./index.template.html'</span><span class="p">,</span> <span class="s1">'utf-8'</span><span class="p">)</span>
<span class="p">});</span>
<span class="nx">renderer</span><span class="p">.</span><span class="nx">renderToString</span><span class="p">(</span><span class="nx">app</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">html</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">html</span><span class="p">);</span>
<span class="c1">// will be the full page with app content injected.</span>
<span class="p">});</span>
</code></pre></div></div>
<h3 id="template-interpolation">Template Interpolation</h3>
<h3 id="模板插入">模板插入</h3>
<p>The template also supports simple interpolation.</p>
<p>模板支持简单插入</p>
<p>Given the following template:</p>
<p>上例子:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;html&gt;</span>
<span class="nt">&lt;head&gt;</span>
<span class="nt">&lt;title&gt;</span>title<span class="nt">&lt;/title&gt;</span>
<span class="c">&lt;!-- meta --&gt;</span>
<span class="nt">&lt;/head&gt;</span>
<span class="nt">&lt;body&gt;</span>
<span class="c">&lt;!--vue-ssr-outlet--&gt;</span>
<span class="nt">&lt;/body&gt;</span>
<span class="nt">&lt;/html&gt;</span>
</code></pre></div></div>
<p>We can provide interpolation data by passing a “render context object” as the second argument to renderToString
:</p>
<p>我们提供通过传递‘渲染上下文对象’作为第二参数的插入数据:</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">context</span> <span class="o">=</span> <span class="p">{</span> <span class="na">title</span><span class="p">:</span> <span class="s1">'hello'</span><span class="p">,</span> <span class="na">meta</span><span class="p">:</span> <span class="s2">` &lt;meta ...&gt; &lt;meta ...&gt; `</span> <span class="p">};</span>
<span class="nx">renderer</span><span class="p">.</span><span class="nx">renderToString</span><span class="p">(</span><span class="nx">app</span><span class="p">,</span> <span class="nx">context</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">html</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
<span class="c1">// page title will be "hello"</span>
<span class="c1">// with meta tags injected</span>
<span class="p">});</span>
</code></pre></div></div>
<p>The context object can also be shared with the Vue app instance, allowing components to dynamically register data for template interpolation.</p>
<p>上下文对象可以和 Vue 应用实例共享,允许组件动态的给模板插入注册数据。</p>
<p>In addition, the template supports some advanced features such as:</p>
<p>此外,模板支持一些高级特性,例如:</p>
<p>Auto injection of critical CSS when using *.vue components;</p>
<p>在使用 vue 单页组件的时候自动注入 css</p>
<p>Auto injection of asset links and resource hints when using clientManifest;</p>
<p>当使用 clientManifest 的时候,自动注入资源链接和资源提示;</p>
<p>Auto injection and XSS prevention when embedding Vuex state for client-side hydration.</p>
<p>当在客户端混合 Vuex 买点的时候,自动注入和阻止 XSS。</p>
<p>We will discuss these when we introduce the associated concepts later in the guide.</p>
<p>在指南里,我们将在介绍聚合概念的时候继续讨论。</p></content><author><name></name></author><summary type="html">Installation</summary></entry></feed>