<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>支付寶體驗科技 Archives - 成長駭客交流第一站 - HyperGrowths™</title>
	<atom:link href="https://hypergrowths.com/tag/%E6%94%AF%E4%BB%98%E5%AF%B6%E9%AB%94%E9%A9%97%E7%A7%91%E6%8A%80/feed/" rel="self" type="application/rss+xml" />
	<link>https://hypergrowths.com/tag/支付寶體驗科技/</link>
	<description>用SEO內容行銷加速增長? 企業發展遇到增長瓶頸？加入 HyperGrowths，學習突破性增長策略，優化行銷方案，助力企業飛躍式發展</description>
	<lastBuildDate>Sat, 30 Jan 2021 18:23:45 +0000</lastBuildDate>
	<language>zh-TW</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.3.5</generator>

<image>
	<url>https://hypergrowths.com/wp-content/uploads/2020/11/cropped-?.png</url>
	<title>支付寶體驗科技 Archives - 成長駭客交流第一站 - HyperGrowths™</title>
	<link>https://hypergrowths.com/tag/支付寶體驗科技/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>SEE Conf 大會邀請函&#124; 體驗美好，玩轉數據</title>
		<link>https://hypergrowths.com/software-engineering/front-end-dev/14930/topic-96380739/</link>
		
		<dc:creator><![CDATA[marketer]]></dc:creator>
		<pubDate>Sat, 30 Jan 2021 18:23:45 +0000</pubDate>
				<category><![CDATA[前端開發]]></category>
		<category><![CDATA[支付寶體驗科技]]></category>
		<guid isPermaLink="false">https://hypergrowths.com/software-engineering/front-end-dev/14930/topic-96380739/</guid>

					<description><![CDATA[<p>螞蟻金服體驗科技大會（SEE Conf），是由螞蟻金服體驗科技舉辦的，集專業分享、產品展台、Workshop 等內容於一身的科技盛筵。 SEE 是Seeking Experience &#38; Engineering 的縮寫，意為探索用戶體驗與工程實踐。 …</p>
<p>The post <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com/software-engineering/front-end-dev/14930/topic-96380739/" data-wpel-link="internal">SEE Conf 大會邀請函| 體驗美好，玩轉數據</a> appeared first on <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com" data-wpel-link="internal">成長駭客交流第一站 - HyperGrowths™</a>.</p>
]]></description>
										<content:encoded><![CDATA[<article class="Post-Main Post-NormalMain" tabindex="-1">
<header class="Post-Header">
<h1 class="Post-Title">SEE Conf 大會邀請函| 體驗美好，玩轉數據</h1>
<div class="Post-Author">
<div class="AuthorInfo" itemprop="author" itemscope="" itemtype="http://schema.org/Person"><meta itemprop="name" content="Jothy"><meta itemprop="image" content="https://pic1.zhimg.com/v2-c3aa87e8ed8dceec22af099a5edf5c9f_l.jpg?source=172ae18b"><meta itemprop="url" content="https://www.zhihu.com/people/jothy1023"><meta itemprop="zhihu:followerCount"></div>
</div>
</header>
<div class="Post-RichTextContainer">
<div class="RichText ztext Post-RichText">
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-a221f158c97d7dc541d04e34d45b7602_r.jpg" data-rawwidth="1440" data-rawheight="686" data-size="normal" data-caption="" class="origin_image zh-lightbox-thumb" width="1440" data-original="https://pic3.zhimg.com/v2-a221f158c97d7dc541d04e34d45b7602_b.jpg" title="v2-a221f158c97d7dc541d04e34d45b7602_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-a221f158c97d7dc541d04e34d45b7602_r.jpg" data-rawwidth="1440" data-rawheight="686" data-size="normal" data-caption="" class="origin_image zh-lightbox-thumb lazy" width="1440" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1440'%20height='686'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-a221f158c97d7dc541d04e34d45b7602_b.jpg" title="v2-a221f158c97d7dc541d04e34d45b7602_r"></figure>
<p>螞蟻金服體驗科技大會（SEE Conf），是由螞蟻金服體驗科技舉辦的，集專業分享、產品展台、Workshop 等內容於一身的科技盛筵。 SEE 是Seeking Experience &amp; Engineering 的縮寫，意為探索用戶體驗與工程實踐。我們希望通過SEE Conf, 與業界同行一起分享交流體驗科技的當前進展，探討切磋體驗科技的未來發展，共同努力促進體驗設計與技術的開放，讓生態繁榮共贏。</p>
<p> SEE Conf 是個年輕、嚮往美好的「少年」，它的前兩屆分別於2018、2019 年在螞蟻金服的Z 空間大樓順利舉辦，明年，它將迎來第三個年頭。</p>
<p>第三屆SEE Conf計劃於2020年1月4日（週六）在杭州西湖文體中心舉辦，會議時長為一天，上午主會場，下午將設置<b>技術</b>與<b>設計</b>兩個分會場。</p>
<p>現在，請跟隨我一起了解下主會場吧！</p>
<h2>體驗技術與設計之美</h2>
<p>隨著軟件開發成本的降低，越來越多的軟件產品不斷地豐富我們的生活，社會變得更加簡單便捷，但同時，各種產品的體驗問題也愈加凸顯。</p>
<p>這時候，體驗與技術的結合，顯得尤為重要。只有二者緊密結合起來，才能變「可用」為「好用」，從而帶來更好的體驗——這是SEE Conf 極力推崇的，也是SEE Conf 每位講師所追求的。</p>
<h2>講師介紹</h2>
<p>他，曾說過「 <a href="https://link.zhihu.com/?target=http%3A//baijiahao.baidu.com/s%3Fid%3D1604355682396162224%26wfr%3Dspider%26for%3Dpc" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">為人服務是所有設計師的出發點</a>」，相信設計能為人創造美好的生活。</p>
<figure data-size="small"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-1c91b32a3c8423ccd87d198c10cca25e_r.jpg" data-rawwidth="600" data-rawheight="600" data-size="small" data-caption="" class="origin_image zh-lightbox-thumb" width="600" data-original="https://pic3.zhimg.com/v2-1c91b32a3c8423ccd87d198c10cca25e_b.jpg" title="v2-1c91b32a3c8423ccd87d198c10cca25e_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-1c91b32a3c8423ccd87d198c10cca25e_r.jpg" data-rawwidth="600" data-rawheight="600" data-size="small" data-caption="" class="origin_image zh-lightbox-thumb lazy" width="600" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='600'%20height='600'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-1c91b32a3c8423ccd87d198c10cca25e_b.jpg" title="v2-1c91b32a3c8423ccd87d198c10cca25e_r"></figure>
<p><b>何人可，</b>湖南大學設計藝術學院院長、博士生導師何教授是教育部工業設計教學指導分委員會主任，國務院學位委員會設計學學科評議組成員，台灣工業設計協會特邀副會長，紅點、 IF、Gmark、紅星等國際設計大賽評委會主席或委員。</p>
<p>這一次，他將為我們帶來「<b>基於地域文化的設計創新</b>」主題分享，以新通道設計與社會創新項目為例，介紹湖南大學設計藝術學院十年來在台灣少數民族地區針對非物質文化遺產的數位化、當代化、國際化和商品化所作的研究及設計工作，並在此基礎上實現貧困地區的精準扶貧以及台灣文化的國際傳播。</p>
<hr>
<p>他，數次引用並踐行喬布斯名言「設計不止於好看，更關乎好用」，率先做起了螞蟻金服中後台「冰山之下的體驗」。</p>
<figure data-size="normal"><noscript><img decoding="async" src="" data-rawwidth="249" data-rawheight="246" data-size="normal" data-caption="" class="content_image" width="249" data-original="https://pic3.zhimg.com/v2-d06bfd84d87ca7e8b9ef9502de52517a_b.jpg"></noscript><img decoding="async" src="" data-rawwidth="249" data-rawheight="246" data-size="normal" data-caption="" class="content_image lazy" width="249" data-actualsrc="https://pic3.zhimg.com/v2-d06bfd84d87ca7e8b9ef9502de52517a_b.jpg" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='249'%20height='246'&gt;&lt;/svg&gt;"></figure>
<p><b>玉伯</b>，螞蟻金服體驗技術部負責人</p>
<p>在第一屆SEE Conf 上，玉伯講了「體驗雲」的故事，介紹了什麼是「體驗科技」——技術與設計的融合，服務與用戶的鏈接，以及重點介紹體驗雲可以帶給用戶什麼服務。<br />在第二屆SEE Conf 上，玉伯發表了「體驗科技與好的社會」主題致辭，表達了希望通過體驗從業者的發展、體驗的普惠與創新，讓社會變得更好的願景。</p>
<p>本屆SEE Conf,玉伯又將圍繞「<b>體驗科技</b>」帶來什麼樣的分享，讓我們拭目以待！</p>
<hr>
<p>他，在入職設計師的第一周，就畫下了Ant Design 站點的第一張訊息架構圖，後期雖然經過微調，但基本結構沿用至今。</p>
<figure data-size="normal"><noscript><img decoding="async" src="" data-rawwidth="264" data-rawheight="264" data-size="normal" data-caption="" class="content_image" width="264" data-original="https://pic2.zhimg.com/v2-f72e952e66efa9dee338b01deeb66ec5_b.jpg"></noscript><img decoding="async" src="" data-rawwidth="264" data-rawheight="264" data-size="normal" data-caption="" class="content_image lazy" width="264" data-actualsrc="https://pic2.zhimg.com/v2-f72e952e66efa9dee338b01deeb66ec5_b.jpg" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='264'%20height='264'&gt;&lt;/svg&gt;"></figure>
<p><b>林外</b>，螞蟻金服高級體驗設計專家</p>
<p>他，以樂高為創意來源，設計了Ant Design 第一個Logo，並用剛剛學會的C4D 軟件完成首頁模型的渲染。</p>
<figure data-size="normal"><noscript><img decoding="async" src="" data-rawwidth="265" data-rawheight="265" data-size="normal" data-caption="" class="content_image" width="265" data-original="https://pic4.zhimg.com/v2-a9a30d27a45c1a07c43a6e78aa9e243f_b.jpg"></noscript><img decoding="async" src="" data-rawwidth="265" data-rawheight="265" data-size="normal" data-caption="" class="content_image lazy" width="265" data-actualsrc="https://pic4.zhimg.com/v2-a9a30d27a45c1a07c43a6e78aa9e243f_b.jpg" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='265'%20height='265'&gt;&lt;/svg&gt;"></figure>
<p><b>線絲</b>，螞蟻金服高級創意設計師</p>
<p>他們將為我們帶來「 <b>Ant Design 4.0：創造快樂工作</b>」主題分享。</p>
<p>隨著Ant Design 的不斷成長，不可避免遇到傳承和發展的問題，所以我們需要建立一套核心價值體系，去總結Ant Design 過往的基因和內核，並指引一代又一代的Ant Designers 去進化、去創造一個有生命力的設計體系。本次主題，將全面介紹Ant Design 在過去兩年的積累和思考，總結成設計價值觀、設計資產、設計策略等多個部分，協助企業級設計者創造全新的工作體驗。</p>
<hr>
<p>她，是螞蟻金服圖形與藝術實驗室的專業產品經理，深諳圖形與藝術相結合的產品策略。</p>
<figure data-size="normal"><noscript><img decoding="async" src="" data-rawwidth="300" data-rawheight="300" data-size="normal" data-caption="" class="content_image" width="300" data-original="https://pic1.zhimg.com/v2-64871453467acf68862eb862ca6bb2dc_b.jpg"></noscript><img decoding="async" src="" data-rawwidth="300" data-rawheight="300" data-size="normal" data-caption="" class="content_image lazy" width="300" data-actualsrc="https://pic1.zhimg.com/v2-64871453467acf68862eb862ca6bb2dc_b.jpg" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='300'%20height='300'&gt;&lt;/svg&gt;"></figure>
<p><b>可言</b>，螞蟻金服高級產品經理</p>
<p>她，是螞蟻金服圖形與藝術實驗室的美女設計師，通過專業的視覺傳達方式極致地表現作品。</p>
<figure data-size="normal"><noscript><img decoding="async" src="" data-rawwidth="300" data-rawheight="300" data-size="normal" data-caption="" class="content_image" width="300" data-original="https://pic2.zhimg.com/v2-7ebc3b18dbcc9b55f912dfd9e35b0b31_b.jpg"></noscript><img decoding="async" src="" data-rawwidth="300" data-rawheight="300" data-size="normal" data-caption="" class="content_image lazy" width="300" data-actualsrc="https://pic2.zhimg.com/v2-7ebc3b18dbcc9b55f912dfd9e35b0b31_b.jpg" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='300'%20height='300'&gt;&lt;/svg&gt;"></figure>
<p><b>十喜</b>，螞蟻金服高級體驗設計師</p>
<p>他，是螞蟻金服圖形與藝術實驗室的前端專家，將可言與十喜的理念完美地實現了出來。</p>
<figure data-size="normal"><noscript><img decoding="async" src="" data-rawwidth="300" data-rawheight="300" data-size="normal" data-caption="" class="content_image" width="300" data-original="https://pic1.zhimg.com/v2-624e4702cd4bc9d823cb363eb13d328c_b.jpg"></noscript><img decoding="async" src="" data-rawwidth="300" data-rawheight="300" data-size="normal" data-caption="" class="content_image lazy" width="300" data-actualsrc="https://pic1.zhimg.com/v2-624e4702cd4bc9d823cb363eb13d328c_b.jpg" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='300'%20height='300'&gt;&lt;/svg&gt;"></figure>
<p><b>逸達</b>，螞蟻金服前端技術專家幻鸚中台負責人</p>
<p>他們共同研發了<b>幻鸚數字駕駛艙系統</b>，將為我們帶來「<b>決策機構體驗科技：數字駕駛艙</b>」分享。</p>
<p>幻鸚數字駕駛艙是新一代的數字指揮系統，以宏大場景的渲染能力與藝術化的表現力，結合多種控制交互方式，創造出令人驚嘆的沉浸式體驗，用以輔助管理者進行日常決策。<br />憑藉豐富的項目實戰經驗沉澱，我們推出了幻鸚中台1.0，以藝術化的啟發，定義數字駕駛艙，並向前探索體驗科技的未來。<br />該主題將正式發布幻鸚中台1.0，介紹數字駕駛艙的定義以及其如何成為社會數位化升級的牽引力，並給出市場，賦能和生態三位一體的解決方案。同時正式成立生態聯盟，借助生態的力量共創未來。</p>
<hr>
<p>他，最熟悉也最擅長和技術打交道，這一次，他將體驗科技與數據技術結合了起來！</p>
<figure data-size="normal"><noscript><img decoding="async" src="" data-rawwidth="300" data-rawheight="300" data-size="normal" data-caption="" class="content_image" width="300" data-original="https://pic3.zhimg.com/v2-c68dc4852bb95f4936cc1ea55d90cf82_b.jpg"></noscript><img decoding="async" src="" data-rawwidth="300" data-rawheight="300" data-size="normal" data-caption="" class="content_image lazy" width="300" data-actualsrc="https://pic3.zhimg.com/v2-c68dc4852bb95f4936cc1ea55d90cf82_b.jpg" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='300'%20height='300'&gt;&lt;/svg&gt;"></figure>
<p><b>步茗</b>，螞蟻金服數據技術專家、AVA負責人</p>
<p>他，是前端開發領域的專家，同時也熱愛和數據打交道，對數據十分有sense.</p>
<figure data-size="normal"><noscript><img decoding="async" src="" data-rawwidth="300" data-rawheight="300" data-size="normal" data-caption="" class="content_image" width="300" data-original="https://pic1.zhimg.com/v2-96108e41fd199b364446fd9b44facafc_b.jpg"></noscript><img decoding="async" src="" data-rawwidth="300" data-rawheight="300" data-size="normal" data-caption="" class="content_image lazy" width="300" data-actualsrc="https://pic1.zhimg.com/v2-96108e41fd199b364446fd9b44facafc_b.jpg" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='300'%20height='300'&gt;&lt;/svg&gt;"></figure>
<p><b>璆鳴</b>，螞蟻金服前端技術專家、DataWizard負責人</p>
<p>他們自主研發了<b>智能可視化體系AVA</b> ,將在本次SEE Conf中詳細與我們分享。</p>
<p>數據可視化在體驗科技中扮演著重要角色。但是對於設計和開發來說，仍然存在著學習成本高、圖表類型選擇有誤等問題。智能可視化技術如何幫助我們解決這些問題？是否會顛覆可視化生產和使用的方式？螞蟻金服體驗科技的智能可視化體系AVA 將為你解答這些問題。</p>
<hr>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-7e5656a8c2ce1f6419043f55baa18d73_r.jpg" data-rawwidth="740" data-rawheight="373" data-size="normal" data-caption="" class="origin_image zh-lightbox-thumb" width="740" data-original="https://pic4.zhimg.com/v2-7e5656a8c2ce1f6419043f55baa18d73_b.jpg" title="v2-7e5656a8c2ce1f6419043f55baa18d73_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-7e5656a8c2ce1f6419043f55baa18d73_r.jpg" data-rawwidth="740" data-rawheight="373" data-size="normal" data-caption="" class="origin_image zh-lightbox-thumb lazy" width="740" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='740'%20height='373'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-7e5656a8c2ce1f6419043f55baa18d73_b.jpg" title="v2-7e5656a8c2ce1f6419043f55baa18d73_r"></figure>
<p>SEE Conf最令人期待的，除了各式分享之外，還有有趣好玩的<b>Workshop</b> !</p>
<h2>玩轉數據可視化工作坊</h2>
<p><b>用數據講故事</b>&lt;br&gt;今天，數據可視化已無處不在。如果你需要可視化你的工作成果、用數據驅動的方式進行溝通，或者你想讀懂可視化作品中的玄機，那麼此次工作坊就是為你準備的。此次工作坊圍繞數據、圖表展示如何用故事化的設計思維與方法進行可視化的體驗設計。同時提供真實應用場景練習如何去探析數據背後的洞察。在這個工作坊，你將得到圖表決策模型、可視化通用設計方法、分析模型，以及數據可視化設計指南。</p>
<div class="highlight">
<pre><code class="language-text">注：工作坊人数有限，将通过现场规则进行抽取。</code></pre>
</div>
</div>
</div>
</article>
<p>The post <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com/software-engineering/front-end-dev/14930/topic-96380739/" data-wpel-link="internal">SEE Conf 大會邀請函| 體驗美好，玩轉數據</a> appeared first on <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com" data-wpel-link="internal">成長駭客交流第一站 - HyperGrowths™</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>從VSCode 看大型IDE 技術架構</title>
		<link>https://hypergrowths.com/software-engineering/front-end-dev/14899/topic-96041706/</link>
		
		<dc:creator><![CDATA[marketer]]></dc:creator>
		<pubDate>Sat, 30 Jan 2021 18:22:43 +0000</pubDate>
				<category><![CDATA[前端開發]]></category>
		<category><![CDATA[支付寶體驗科技]]></category>
		<guid isPermaLink="false">https://hypergrowths.com/software-engineering/front-end-dev/14899/topic-96041706/</guid>

					<description><![CDATA[<p>零、前言為什麼要去看VSCode？因為我們團隊在做的中後台快速研發平台雲鳳蝶也是一款類似Web IDE 形態的產品：而談起Web IDE，沒人能繞開VSCode，它非常流行，同時又完全開源，總共350000 行TypeScript代碼…</p>
<p>The post <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com/software-engineering/front-end-dev/14899/topic-96041706/" data-wpel-link="internal">從VSCode 看大型IDE 技術架構</a> appeared first on <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com" data-wpel-link="internal">成長駭客交流第一站 - HyperGrowths™</a>.</p>
]]></description>
										<content:encoded><![CDATA[<article class="Post-Main Post-NormalMain" tabindex="-1">
<header class="Post-Header">
<h1 class="Post-Title">從VSCode 看大型IDE 技術架構</h1>
<div class="Post-Author">
<div class="AuthorInfo" itemprop="author" itemscope="" itemtype="http://schema.org/Person"><meta itemprop="name" content="paranoidjk"><meta itemprop="image" content="https://pic4.zhimg.com/7767136d381ec3e5da22e406ffdec79f_l.jpg?source=172ae18b"><meta itemprop="url" content="https://www.zhihu.com/people/paranoidjk"><meta itemprop="zhihu:followerCount"></div>
</div>
</header>
<div class="Post-RichTextContainer">
<div class="RichText ztext Post-RichText">
<h2>零、前言</h2>
<p>為什麼要去看VSCode？<br />因為我們團隊在做的中後台快速研發平台<a href="https://zhuanlan.zhihu.com/p/90238943" class="internal" data-wpel-link="external" rel="nofollow external noopener noreferrer">雲鳳蝶</a>也是一款類似Web IDE形態的產品：</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-d6c2ca9f6c1aa2b3b4fa6dffa10d9903_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1590" class="origin_image zh-lightbox-thumb" width="2880" data-original="https://pic4.zhimg.com/v2-d6c2ca9f6c1aa2b3b4fa6dffa10d9903_b.jpg" title="v2-d6c2ca9f6c1aa2b3b4fa6dffa10d9903_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-d6c2ca9f6c1aa2b3b4fa6dffa10d9903_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1590" class="origin_image zh-lightbox-thumb lazy" width="2880" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='2880'%20height='1590'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-d6c2ca9f6c1aa2b3b4fa6dffa10d9903_b.jpg" title="v2-d6c2ca9f6c1aa2b3b4fa6dffa10d9903_r"></figure>
<p>而談起Web IDE，沒人能繞開VSCode，它非常流行，同時又完全開源，總共350000 行TypeScript 代碼的巨大工程，使用了142 個開源庫。市面上選擇基於VSCode去修改定制的IDE比比皆是： <a href="https://link.zhihu.com/?target=http%3A//emas.weex.io/zh/tools/ide.html" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Weex Studio</a> 、 <a href="https://link.zhihu.com/?target=https%3A//www.egret.com/products/wing.html" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">白鷺Egret Wing</a> 、 <a href="https://link.zhihu.com/?target=https%3A//www.quickapp.cn/docCenter/IDEPublicity" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">快應用IDE</a> ...</p>
<p>我希望從VSCode 身上看到什麼？</p>
<ul>
<li>大型複雜GUI 軟件（如IDE 類）如何組織功能模塊代碼</li>
<li>如何使用Electron 技術將Web 軟件桌面化</li>
<li>如何在打造插件化開放生態的同時保證軟件整體質量與性能</li>
<li>如何打造一款好用的、流行的工具軟件</li>
</ul>
<h2>一、VSCode 是什麼</h2>
<h3>官方定義</h3>
<blockquote><p><a href="https://link.zhihu.com/?target=https%3A//code.visualstudio.com/" class=" external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external"><span class="invisible">https://</span> <span class="visible">code.visualstudio.com/</span></a></p></blockquote>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-523f8344af863033a704bc30eb6ec26d_r.jpg" data-caption="" data-size="normal" data-rawwidth="902" data-rawheight="384" class="origin_image zh-lightbox-thumb" width="902" data-original="https://pic2.zhimg.com/v2-523f8344af863033a704bc30eb6ec26d_b.jpg" title="v2-523f8344af863033a704bc30eb6ec26d_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-523f8344af863033a704bc30eb6ec26d_r.jpg" data-caption="" data-size="normal" data-rawwidth="902" data-rawheight="384" class="origin_image zh-lightbox-thumb lazy" width="902" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='902'%20height='384'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-523f8344af863033a704bc30eb6ec26d_b.jpg" title="v2-523f8344af863033a704bc30eb6ec26d_r"></figure>
<p>關鍵詞：</p>
<ul>
<li>代碼編輯（工具屬性）</li>
<li>跨平台運行、開源</li>
<li>核心功能：</li>
<ul>
<li> IntelliSense（代碼提示）、 debugging（代碼調試）、 git（代碼管理） 都是圍繞代碼編輯的核心鏈路</li>
<li>extensions （插件）則肩負著打造開放生態的責任</li>
</ul>
</ul>
<p class="ztext-empty-paragraph"></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-f52caf2eef3e231024a798d67f2ac989_r.jpg" data-caption="" data-size="normal" data-rawwidth="2248" data-rawheight="268" class="origin_image zh-lightbox-thumb" width="2248" data-original="https://pic2.zhimg.com/v2-f52caf2eef3e231024a798d67f2ac989_b.png" title="v2-f52caf2eef3e231024a798d67f2ac989_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-f52caf2eef3e231024a798d67f2ac989_r.jpg" data-caption="" data-size="normal" data-rawwidth="2248" data-rawheight="268" class="origin_image zh-lightbox-thumb lazy" width="2248" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='2248'%20height='268'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-f52caf2eef3e231024a798d67f2ac989_b.png" title="v2-f52caf2eef3e231024a798d67f2ac989_r"></figure>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-7a762f1833fa3b9638bf9fee562ae16f_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb" width="2880" data-original="https://pic4.zhimg.com/v2-7a762f1833fa3b9638bf9fee562ae16f_b.jpg" title="v2-7a762f1833fa3b9638bf9fee562ae16f_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-7a762f1833fa3b9638bf9fee562ae16f_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb lazy" width="2880" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='2880'%20height='1800'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-7a762f1833fa3b9638bf9fee562ae16f_b.jpg" title="v2-7a762f1833fa3b9638bf9fee562ae16f_r"></figure>
<div class="highlight">
<pre><code class="language-text">点评：对于工具软件而言，需要内心能想清楚边界。哪些是自己应该专注去做的，哪些可以外溢到交给第三方扩展来满足。</code></pre>
</div>
<h3>發展歷程</h3>
<ul>
<li>2015-04 （4年前） 發布</li>
<li>2015-11 （發布之後半年）開源</li>
<li>2019-05 發布VSCode Remote Development</li>
</ul>
<p>團隊負責人： <a href="https://link.zhihu.com/?target=https%3A//zh.wikipedia.org/zh/%25E5%259F%2583%25E9%2587%258C%25E5%25B8%258C%25C2%25B7%25E4%25BC%25BD%25E7%2591%25AA" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Erich Gamma</a> . <a href="https://link.zhihu.com/?target=https%3A//junit.org/junit5/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">JUnit</a>作者之一， <a href="https://link.zhihu.com/?target=https%3A//book.douban.com/subject/1052241//" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">《設計模式》</a>作者之一， Eclipse架構師。 2011 加入微軟，在瑞士蘇黎世組建團隊開發基於web 技術的編輯器，也就是後來的monaco-editor。 VSCode 開發團隊從10 來個人開始，早期成員大多有Eclipse 開發團隊的背景。</p>
<p class="ztext-empty-paragraph"></p>
<blockquote><p><a href="https://zhuanlan.zhihu.com/p/35303567" class="internal" data-wpel-link="external" rel="nofollow external noopener noreferrer">Visual Studio Code有哪些工程方面的亮點</a><br /><a href="https://www.zhihu.com/question/36292298" class="internal" data-wpel-link="external" rel="nofollow external noopener noreferrer">維護一個大型開源項目是怎樣的體驗？</a><br /><a href="https://link.zhihu.com/?target=https%3A//rebornix.com/work/2019/10/18/Shape-Up/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">「Shape Up」適合中小團隊的一種工作方式</a></p></blockquote>
<p class="ztext-empty-paragraph"></p>
<figure data-size="normal"><noscript><img decoding="async" src="" data-caption="" data-size="normal" data-rawwidth="408" data-rawheight="576" class="content_image" width="408" data-original="https://pic4.zhimg.com/v2-86c0a7a713e88ffe4319eccc898099ff_b.jpg"></noscript><img decoding="async" src="" data-caption="" data-size="normal" data-rawwidth="408" data-rawheight="576" class="content_image lazy" width="408" data-actualsrc="https://pic4.zhimg.com/v2-86c0a7a713e88ffe4319eccc898099ff_b.jpg" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='408'%20height='576'&gt;&lt;/svg&gt;"></figure>
<p class="ztext-empty-paragraph"></p>
<p>Erich Gamma在GOTO 2016發表了主題為《 <a href="https://link.zhihu.com/?target=https%3A//www.youtube.com/watch%3Fv%3DuLrnQtAq5Ec" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">The journey of visual studio code: Building an App Using JS/TypeScript, Node, Electron &amp; 100 OSS Components</a> 》的演講，詳細講解了這個項目的發展歷程：</p>
<blockquote><p>沒時間觀看視頻的同學可以選擇下載完整<a href="https://link.zhihu.com/?target=https%3A//gotocon.com/dl/goto-amsterdam-2016/slides/ErichGamma_TheJourneyOfALargeScaleApplicationBuiltUsingJavaScriptTypeScriptNodeElectron100OSSComponentsAtMicrosoft.pdf" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">PDF</a></p></blockquote>
<p>PPT 的第一頁，就是Erich Gamma 截取自己正式加入微軟之後收到的工作內容描述的郵件：</p>
<p><b>”探索一種全新的和桌面IDE一樣成功的在線開發工具模式“</b></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-63e14f0cde2caad9d629729de43ea230_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb" width="2880" data-original="https://pic1.zhimg.com/v2-63e14f0cde2caad9d629729de43ea230_b.jpg" title="v2-63e14f0cde2caad9d629729de43ea230_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-63e14f0cde2caad9d629729de43ea230_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb lazy" width="2880" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='2880'%20height='1800'&gt;&lt;/svg&gt;" data-actualsrc="https://pic1.zhimg.com/v2-63e14f0cde2caad9d629729de43ea230_b.jpg" title="v2-63e14f0cde2caad9d629729de43ea230_r"></figure>
<p class="ztext-empty-paragraph"></p>
<p>整個團隊從大致10 個人開始，混合老中新三代不同水平的程序員，在微軟這個巨無霸的商業公司裡面想要落地這樣一個宏大的願景是不容易的，團隊一開始定下的思路就是像start up 一樣工作，每月每年都要ship 東西。</p>
<p>同時他也提出早期會瘋狂的在公司內部尋找落地場景，比如Visual Studio Online 的在線Code DIff 頁面，TypeScript 的官網的Playground 編輯器，OneDrive 代碼文件，Edge 瀏覽器Dev Tool 的代碼瀏覽等。</p>
<p>一個重要轉折點是微軟本身發生的巨大變化：</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-52240d39a606774d099119e184ac13f1_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb" width="2880" data-original="https://pic2.zhimg.com/v2-52240d39a606774d099119e184ac13f1_b.jpg" title="v2-52240d39a606774d099119e184ac13f1_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-52240d39a606774d099119e184ac13f1_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb lazy" width="2880" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='2880'%20height='1800'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-52240d39a606774d099119e184ac13f1_b.jpg" title="v2-52240d39a606774d099119e184ac13f1_r"></figure>
<p>伴隨微軟整個的開放開源跨平颱風潮，Erich Gamma 敏銳的決定將產品從Browser Based IDE 轉向跨平台的Desktop IDE，但仍然使用Web 技術，於是electron 完美契合，VSCode 團隊花了六個月使用Electron 將Web編輯器桌面化，又花了六個月將整個IDE 插件化，最終VSCode 成為一個流行的產品同時也成為一個典型的Electron 客戶端開源項目。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-6239a769fc0573f2d38c717b3d05829d_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb" width="2880" data-original="https://pic2.zhimg.com/v2-6239a769fc0573f2d38c717b3d05829d_b.jpg" title="v2-6239a769fc0573f2d38c717b3d05829d_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-6239a769fc0573f2d38c717b3d05829d_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb lazy" width="2880" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='2880'%20height='1800'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-6239a769fc0573f2d38c717b3d05829d_b.jpg" title="v2-6239a769fc0573f2d38c717b3d05829d_r"></figure>
<h3>產品定位</h3>
<p>Erich Gamma在2017 SpringOne Platform上有一個<a href="https://link.zhihu.com/?target=https%3A//www.youtube.com/watch%3Fv%3DVs3AGfeuNKU" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">關於VSCode的分享</a>，講解了在他開發Eclipse的過往經驗基礎上，對VSCode進行頂層設計時的諸多思路與決策，其中提到過對於VSCode的產品定位：</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-623a63be2fde7b549a3c471d48fc585b_r.jpg" data-caption="" data-size="normal" data-rawwidth="720" data-rawheight="422" class="origin_image zh-lightbox-thumb" width="720" data-original="https://pic4.zhimg.com/v2-623a63be2fde7b549a3c471d48fc585b_b.jpg" title="v2-623a63be2fde7b549a3c471d48fc585b_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-623a63be2fde7b549a3c471d48fc585b_r.jpg" data-caption="" data-size="normal" data-rawwidth="720" data-rawheight="422" class="origin_image zh-lightbox-thumb lazy" width="720" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='720'%20height='422'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-623a63be2fde7b549a3c471d48fc585b_b.jpg" title="v2-623a63be2fde7b549a3c471d48fc585b_r"></figure>
<p>從圖中可以看出VSCode 定位是處於編輯器和IDE 的中間並且偏向輕量編輯器一側的。<br /> VSCode 的核心是“編輯器+ 代碼理解+ 調試“，圍繞這個關鍵路徑做深做透，其他東西非常克制，產品保持輕量與高性能。</p>
<div class="highlight">
<pre><code class="language-text">点评：生产力工具类的软件一定要守住主线，否则很可能会变成不收门票的游乐园牛逼的产品背后一定有牛逼的团队，比如微软挖到Anders Hejlsberg，接连创造了C# 和TypeScript挖到Erich Gamma，接连诞生了monaco 和vscode 这些明珠</code></pre>
</div>
<h2>二、Electron 是什麼</h2>
<p>上文提到VSCode 有一個特性是跨平台，它的跨平台實質是通過electron 實現的。所以我們需要先簡單了解下<a href="https://link.zhihu.com/?target=https%3A//electronjs.org/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">electron</a></p>
<h3>官方定義</h3>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-79183b4f575ddecdef23f9f56fbb84f6_r.jpg" data-caption="" data-size="normal" data-rawwidth="1994" data-rawheight="988" class="origin_image zh-lightbox-thumb" width="1994" data-original="https://pic3.zhimg.com/v2-79183b4f575ddecdef23f9f56fbb84f6_b.jpg" title="v2-79183b4f575ddecdef23f9f56fbb84f6_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-79183b4f575ddecdef23f9f56fbb84f6_r.jpg" data-caption="" data-size="normal" data-rawwidth="1994" data-rawheight="988" class="origin_image zh-lightbox-thumb lazy" width="1994" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1994'%20height='988'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-79183b4f575ddecdef23f9f56fbb84f6_b.jpg" title="v2-79183b4f575ddecdef23f9f56fbb84f6_r"></figure>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-27d89c4e9a9ad4321faee9b405773c24_r.jpg" data-caption="" data-size="normal" data-rawwidth="2028" data-rawheight="728" class="origin_image zh-lightbox-thumb" width="2028" data-original="https://pic1.zhimg.com/v2-27d89c4e9a9ad4321faee9b405773c24_b.jpg" title="v2-27d89c4e9a9ad4321faee9b405773c24_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-27d89c4e9a9ad4321faee9b405773c24_r.jpg" data-caption="" data-size="normal" data-rawwidth="2028" data-rawheight="728" class="origin_image zh-lightbox-thumb lazy" width="2028" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='2028'%20height='728'&gt;&lt;/svg&gt;" data-actualsrc="https://pic1.zhimg.com/v2-27d89c4e9a9ad4321faee9b405773c24_b.jpg" title="v2-27d89c4e9a9ad4321faee9b405773c24_r"></figure>
<h3>核心技術</h3>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-82d6cdeaed40a3dcb4dacc7c6f737454_r.jpg" data-caption="" data-size="normal" data-rawwidth="1920" data-rawheight="1080" class="origin_image zh-lightbox-thumb" width="1920" data-original="https://pic1.zhimg.com/v2-82d6cdeaed40a3dcb4dacc7c6f737454_b.jpg" title="v2-82d6cdeaed40a3dcb4dacc7c6f737454_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-82d6cdeaed40a3dcb4dacc7c6f737454_r.jpg" data-caption="" data-size="normal" data-rawwidth="1920" data-rawheight="1080" class="origin_image zh-lightbox-thumb lazy" width="1920" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1920'%20height='1080'&gt;&lt;/svg&gt;" data-actualsrc="https://pic1.zhimg.com/v2-82d6cdeaed40a3dcb4dacc7c6f737454_b.jpg" title="v2-82d6cdeaed40a3dcb4dacc7c6f737454_r"></figure>
<ul>
<li>使用Web 技術來編寫UI，用chrome 瀏覽器內核來運行</li>
<li>使用NodeJS 來操作文件系統和發起網絡請求</li>
<li>使用NodeJS C++ Addon 去調用操作系統的native API</li>
</ul>
<h3>應用架構</h3>
<blockquote><p><a href="https://link.zhihu.com/?target=https%3A//electronjs.org/docs/tutorial/application-architecture" class=" external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external"><span class="invisible">https://</span> <span class="visible">electronjs.org/docs/tut</span> <span class="invisible">orial/application-architecture</span></a></p></blockquote>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-61635f60c7335c9e732bc209f61bb1ff_r.jpg" data-caption="" data-size="normal" data-rawwidth="539" data-rawheight="648" class="origin_image zh-lightbox-thumb" width="539" data-original="https://pic4.zhimg.com/v2-61635f60c7335c9e732bc209f61bb1ff_b.jpg" title="v2-61635f60c7335c9e732bc209f61bb1ff_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-61635f60c7335c9e732bc209f61bb1ff_r.jpg" data-caption="" data-size="normal" data-rawwidth="539" data-rawheight="648" class="origin_image zh-lightbox-thumb lazy" width="539" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='539'%20height='648'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-61635f60c7335c9e732bc209f61bb1ff_b.jpg" title="v2-61635f60c7335c9e732bc209f61bb1ff_r"></figure>
<ul>
<li>1 個主進程：一個Electron App 只會啟動一個主進程，它會運行package.json 的main 字段指定的腳本</li>
<li>N 個渲染進程：主進程代碼可以調用Chromium API 創建任意多個web 頁面，而Chromium 本身是多進程架構，每個web 頁面都運行在屬於它自己的渲染進程中</li>
</ul>
<p>進程間通訊：</p>
<ul>
<li>Render 進程之間的通訊本質上和多個Web 頁面之間通訊沒有差別，可以使用各種瀏覽器能力如localStorage</li>
<li> Render 進程與Main 進程之間也可以通過API 互相通訊(ipcRenderer/ipcMain)</li>
</ul>
<div class="highlight">
<pre><code class="language-text">点评：普通web 页面无法调用native api，因此缺少一些能力electron 的web 页面所处的Render 进程可以将任务转发至运行在NodeJS 环境的Main 进程，从而实现native API这套架构大大扩展了electron app 相比web app 的能力丰富度但同时又保留了web 快捷流畅的开发体验，再加上web 本身的跨平台优势结合起来让electron 成为性价比非常高的方案</code></pre>
</div>
<h2>三、VSCode 技術架構</h2>
<h3>多進程架構</h3>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-a93ba02c5d94b4d0d37cc59e6821e907_r.jpg" data-caption="" data-size="normal" data-rawwidth="720" data-rawheight="445" class="origin_image zh-lightbox-thumb" width="720" data-original="https://pic4.zhimg.com/v2-a93ba02c5d94b4d0d37cc59e6821e907_b.jpg" title="v2-a93ba02c5d94b4d0d37cc59e6821e907_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-a93ba02c5d94b4d0d37cc59e6821e907_r.jpg" data-caption="" data-size="normal" data-rawwidth="720" data-rawheight="445" class="origin_image zh-lightbox-thumb lazy" width="720" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='720'%20height='445'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-a93ba02c5d94b4d0d37cc59e6821e907_b.jpg" title="v2-a93ba02c5d94b4d0d37cc59e6821e907_r"></figure>
<ul>
<li>主進程：VSCode 的入口進程，負責一些類似窗口管理、進程間通信、自動更新等全局任務</li>
<li>渲染進程：負責一個Web 頁面的渲染</li>
<li>插件宿主進程：每個插件的代碼都會運行在一個獨屬於自己的NodeJS 環境的宿主進程中，插件不允許訪問UI</li>
<li> Debug 進程：Debugger 相比普通插件做了特殊化</li>
<li>Search 進程：搜索是一類計算密集型的任務，單開進程保證軟件整體體驗與性能</li>
</ul>
<h3>開發流程</h3>
<ul>
<li>開發文檔： <a href="https://link.zhihu.com/?target=https%3A//github.com/Microsoft/vscode/wiki/How-to-Contribute" class=" external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external"><span class="invisible">https://</span> <span class="visible">github.com/Microsoft/vs</span> <span class="invisible">code/wiki/How-to-Contribute</span></a></li>
<li>主倉庫： <a href="https://link.zhihu.com/?target=https%3A//github.com/microsoft/vscode" class=" external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external"><span class="invisible">https://</span> <span class="visible">github.com/microsoft/vs</span> <span class="invisible">code</span></a></li>
<li>其它關聯項目： <a href="https://link.zhihu.com/?target=https%3A//github.com/Microsoft/vscode/wiki/Related-Projects" class=" external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external"><span class="invisible">https://</span> <span class="visible">github.com/Microsoft/vs</span> <span class="invisible">code/wiki/Related-Projects</span></a></li>
</ul>
<div class="highlight">
<pre><code class="language-bash"><span class="c1"># 检出代码</span>git clone git@github.com:microsoft/vscode.git <span class="nb">cd</span> vscode <span class="c1"># 安装依赖</span>yarn <span class="c1"># 启动web 版</span>yarn watch <span class="o">&amp;&amp;</span> yarn web <span class="c1"># 启动桌面版</span>yarn watch <span class="o">&amp;&amp;</span> ./scripts/code.sh <span class="c1"># 打包</span>yarn run gulp vscode- <span class="o">[</span> platform <span class="o">]</span> yarn run gulp vscode- <span class="o">[</span> platform <span class="o">]</span> -min <span class="c1"># platforms: win32-ia32 | win32-x64 | darwin | linux-ia32 | linux-x64 | linux-arm</span></code></pre>
</div>
<h3>源碼組織</h3>
<blockquote><p><a href="https://link.zhihu.com/?target=https%3A//github.com/microsoft/vscode/wiki/Source-Code-Organization" class=" external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external"><span class="invisible">https://</span> <span class="visible">github.com/microsoft/vs</span> <span class="invisible">code/wiki/Source-Code-Organization</span></a></p></blockquote>
<p>下面是整個VSCode project 的一些頂級的重點文件夾，後文會重點關注src 與extensions:</p>
<div class="highlight">
<pre><code class="language-bash">├── build <span class="c1"># 构建脚本</span>├── extensions <span class="c1"># 内置插件</span>├── scripts <span class="c1"># 工具脚本</span>├── out <span class="c1"># 产物目录</span>├── src <span class="c1"># 源码目录</span>├── <span class="nb">test</span> <span class="c1"># 测试代码</span></code></pre>
</div>
<p>VSCode 的代碼架構也是隨著產品階段演進而不斷更迭的：</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-1d4cb252c8f25a349a5bea7970a10da1_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb" width="2880" data-original="https://pic2.zhimg.com/v2-1d4cb252c8f25a349a5bea7970a10da1_b.jpg" title="v2-1d4cb252c8f25a349a5bea7970a10da1_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-1d4cb252c8f25a349a5bea7970a10da1_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb lazy" width="2880" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='2880'%20height='1800'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-1d4cb252c8f25a349a5bea7970a10da1_b.jpg" title="v2-1d4cb252c8f25a349a5bea7970a10da1_r"></figure>
<p>下文會分享一些整個VScode 源碼組織的一些亮點與特色：</p>
<h3>1. 隔離內核(src) 與插件(extensions)，內核分層模塊化</h3>
<ul>
<li>/src/vs：分層和模塊化的core</li>
<li> /src/vs/base: 通用的公共方法和公共視圖組件</li>
<li>/src/vs/code: VSCode 應用主入口</li>
<li>/src/vs/platform：可被依賴注入的各種純服務</li>
<li>/src/vs/editor: 文本編輯器</li>
<li>/src/vs/workbench：整體視圖框架</li>
<li>/src/typings: 公共基礎類型</li>
<li>/extensions：內置插件</li>
</ul>
<h3>2. 每層按環境隔離</h3>
<p>內核裡面每一層代碼都會遵守electron 規範，按不同環境細分文件夾:</p>
<ul>
<li>common: 公共的js 方法，在哪裡都可以運行的</li>
<li>browser: 只使用瀏覽器API 的代碼，可以調用common</li>
<li> node: 只使用NodeJS API 的代碼，可以調用common</li>
<li> electron-browser: 使用electron 渲染線程和瀏覽器API 的代碼，可以調用common，browser，node</li>
<li> electron-main: 使用electron 主線程和NodeJS API 的代碼，可以調用common， node</li>
<li> test: 測試代碼</li>
</ul>
<div class="highlight">
<pre><code class="language-text">点评：云凤蝶也遇到了类似问题，作为一个低代码+ 可视化的研发平台，许多功能模块的实现都需要横跨编辑态和运行态如果代码不加以限制和区分，很容易导致错误的依赖关系和预期之外的bug因此云凤蝶最终也决定采用(editor/runtime/common) 类似的隔离架构</code></pre>
</div>
<h3>3. 內核代碼本身也採用擴展機制: Contrib</h3>
<p>可以看到/src/vs/workbench/contrib 這個目錄下存放著非常多的VSCode 的小的功能單元：</p>
<div class="highlight">
<pre><code class="language-bash">├── backup ├── callHierarchy ├── cli ├── codeActions ├── codeEditor ├── comments ├── configExporter ├── customEditor ├── debug ├── emmet ├──....中间省略无数.... ├── watermark ├── webview └── welcome</code></pre>
</div>
<p>Contrib 有一些特點：</p>
<ul>
<li>Contrib 目錄下的所有代碼不允許依賴任何本文件夾之外的文件</li>
<li>Contrib 主要是使用Core 暴露的一些擴展點來做事情</li>
<li>每一個Contrib 如果要對外暴露，將API 在一個出口文件裡面導出eg: contrib/search/common/search.ts</li>
<li>一個Contrib 如果要和另一個Contrib 發生調用，不允許使用除了出口API 文件之外的其它文件</li>
<li>接上一條，即使Contrib 事實上可以調用另一個Contrib 的出口API，也要審慎的考慮並儘量避免兩個Contrib 互相依賴</li>
</ul>
<p>VSCode 開發團隊做這個設計的目的我猜大概是因為重型的工具軟件功能點實在太多，而且非常多的地方都是採用相似的模式去橫向擴展，如果這些功能代碼直接採用原始的模塊引用的方式在core 裡面硬編碼聚合拼裝起來，是一個自頂向下的架構，對維護性的挑戰比較大。</p>
<p>而採用暴露擴展點的方式，可以將依賴關係反轉，依附於擴展點協議，獨立的小功能的代碼實現可以單獨聚合，核心模塊無需硬編碼和集成所有判斷，整體是一個鬆散式的架構，降低了代碼訊息密度與提升維護性，也更好擴展。</p>
<p>但是VSCode Contrib 的具體業務代碼組織其實看起來沒有太多範式，而且這個內核代碼的擴展機制Contrib 和VSCode 開放給外界的插件化機制extension 是有差異的，讀起來十分頭疼。</p>
<p>通過和兄弟團隊CloudIDE 開發組的專家交流，我得到兩條主要差異性：</p>
<ul>
<li>extension 每一個都是運行在歸宿於自己的獨立宿主進程，而contrib 的功能基本是要運行在主進程的</li>
<li>extension 只能依附於core 開放的擴展點而活，但是contrib 可以通過依賴注入拿到所有core 內部實現的class （雖然官方不推薦）</li>
</ul>
<h3>4. 依賴注入</h3>
<p>上一小節提到了VSCode 的代碼大量使用了依賴注入，這項技術的具體實現細節本文不會展開細講，感興趣的可以閱讀一些好的實現：</p>
<ul>
<li>雲鳳蝶團隊同學寫的<a href="https://link.zhihu.com/?target=https%3A//github.com/zhang740/power-di" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">power-di</a></li>
<li>社區開源的強大的<a href="https://link.zhihu.com/?target=http%3A//inversify.io/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">http://inversify.io</a></li>
</ul>
<p>TS依賴注入常見的實現原理是使用<a href="https://link.zhihu.com/?target=https%3A//www.npmjs.com/package/reflect-metadata" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">reflect-metadata</a>設置與獲取元訊息，從而可以實現在運行時拿到本來屬於編輯態的TypeScript類型相關元訊息，具體來說就是下面這些API：</p>
<ul>
<li>Reflect.getMetadata("design:type", , target, key): 獲取class 屬性類型元訊息</li>
<li>Reflect.getMetadata("design:paramtypes", target, key): 獲取class 方法參數元訊息</li>
<li>Reflect.getMetadata("design:returntype", target, key)：獲取class 方法返回值元訊息</li>
<li>Reflect.defineMetadata(metadataKey, metadataValue, target, propertyKey)：設置元訊息</li>
<li>Reflect.getMetadata(metadataKey, target, propertyKey): 獲取元訊息</li>
</ul>
<p>不過具體到VSCode的依賴注入，它沒有使用reflect-metadata這一套，而是基於decorator去標註元訊息，整個實現了一套自己的依賴注入方式，具體可以參考<a href="https://zhuanlan.zhihu.com/p/96902077" class="internal" data-wpel-link="external" rel="nofollow external noopener noreferrer">vscode源碼解析-依賴注入</a>這篇文章，大致包含如下幾類角色：</p>
<ul>
<li>Service：服務的實現邏輯</li>
<li>Interface：服務的接口描述</li>
<li>Client：服務使用方</li>
<li>Manger：服務管理器</li>
</ul>
<p>舉個例子來看，在/src/core/platform 裡面定義了大量service，其他地方消費者Client 都可以用依賴注入的方式使用到，偽代碼如下：</p>
<div class="highlight">
<pre><code class="language-text">class Client { // 构造函数参数注入（依赖注入方式的一种） constructor( // 必选@IModelService modelService: IModelService, // 可选@optional(IEditorService) editorService: IEditorService ) { // use services } } // 实例化instantiationService.createInstance(Client);</code></pre>
</div>
<h3>5. 絕對路徑import</h3>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-42015bdc46638edb1598a8bd676b41af_r.jpg" data-caption="" data-size="normal" data-rawwidth="977" data-rawheight="739" class="origin_image zh-lightbox-thumb" width="977" data-original="https://pic4.zhimg.com/v2-42015bdc46638edb1598a8bd676b41af_b.jpg" title="v2-42015bdc46638edb1598a8bd676b41af_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-42015bdc46638edb1598a8bd676b41af_r.jpg" data-caption="" data-size="normal" data-rawwidth="977" data-rawheight="739" class="origin_image zh-lightbox-thumb lazy" width="977" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='977'%20height='739'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-42015bdc46638edb1598a8bd676b41af_b.jpg" title="v2-42015bdc46638edb1598a8bd676b41af_r"></figure>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-334803ebf39803a9a514a763f5504c6b_r.jpg" data-caption="" data-size="normal" data-rawwidth="513" data-rawheight="504" class="origin_image zh-lightbox-thumb" width="513" data-original="https://pic4.zhimg.com/v2-334803ebf39803a9a514a763f5504c6b_b.jpg" title="v2-334803ebf39803a9a514a763f5504c6b_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-334803ebf39803a9a514a763f5504c6b_r.jpg" data-caption="" data-size="normal" data-rawwidth="513" data-rawheight="504" class="origin_image zh-lightbox-thumb lazy" width="513" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='513'%20height='504'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-334803ebf39803a9a514a763f5504c6b_b.jpg" title="v2-334803ebf39803a9a514a763f5504c6b_r"></figure>
<div class="highlight">
<pre><code class="language-text">点评：绝对路径import 是一个非常值得学习的技巧，具体的方式是配置TypeScript compilerOptions.paths相对路径import 对阅读者的大脑负担高，依赖当前文件位置上下文訊息才能理解假设修改代码的时候移动文件位置，相对路径需要修改本文件的所有import，绝对路径不需要</code></pre>
</div>
<h3>6. 命令系統</h3>
<p>VSCode和monaco-editor都有自己的命令系統，螞蟻<a href="https://zhuanlan.zhihu.com/p/83860143" class="internal" data-wpel-link="external" rel="nofollow external noopener noreferrer">CloudIDE</a>團隊的同學也曾經對命令系統的優勢做過總結：</p>
<p>傳統的模塊調用是個網狀，不太好找到一個切面來理解或治理：</p>
<p class="ztext-empty-paragraph"></p>
<figure data-size="normal"><noscript><img decoding="async" src="" data-caption="" data-size="normal" data-rawwidth="306" data-rawheight="237" class="content_image" width="306" data-original="https://pic4.zhimg.com/v2-fa176e771960177b8f64e334b9dc50e7_b.jpg"></noscript><img decoding="async" src="" data-caption="" data-size="normal" data-rawwidth="306" data-rawheight="237" class="content_image lazy" width="306" data-actualsrc="https://pic4.zhimg.com/v2-fa176e771960177b8f64e334b9dc50e7_b.jpg" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='306'%20height='237'&gt;&lt;/svg&gt;"></figure>
<p class="ztext-empty-paragraph"></p>
<p>而命令系統是中心化的，各功能末端變成了扁平化的結構：</p>
<p class="ztext-empty-paragraph"></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-7602adba2fbbe628aa434294ecfc3ca5_r.jpg" data-caption="" data-size="normal" data-rawwidth="471" data-rawheight="176" class="origin_image zh-lightbox-thumb" width="471" data-original="https://pic2.zhimg.com/v2-7602adba2fbbe628aa434294ecfc3ca5_b.jpg" title="v2-7602adba2fbbe628aa434294ecfc3ca5_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-7602adba2fbbe628aa434294ecfc3ca5_r.jpg" data-caption="" data-size="normal" data-rawwidth="471" data-rawheight="176" class="origin_image zh-lightbox-thumb lazy" width="471" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='471'%20height='176'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-7602adba2fbbe628aa434294ecfc3ca5_b.jpg" title="v2-7602adba2fbbe628aa434294ecfc3ca5_r"></figure>
<p class="ztext-empty-paragraph"></p>
<div class="highlight">
<pre><code class="language-text">点评：云凤蝶编辑器也遇到这类问题，云凤蝶的自由画布编辑器有非常多的功能，参见《打造媲美Sketch 的自由画布》而且很多情况下一个功能的触发方式是多种多样的，比如大纲树右键菜单触发，顶部工具栏触发，画布右键菜单触发，键盘快捷键触发等这就要求该功能的实现函数能跨区域在多个位置调用，这很容易导致代码依赖关系异常混乱。而命令系统就是一种解决这个问题的很好思路</code></pre>
</div>
<h3>7. TypeScript</h3>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-5070889f8d325a06422e52c405b98384_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb" width="2880" data-original="https://pic1.zhimg.com/v2-5070889f8d325a06422e52c405b98384_b.jpg" title="v2-5070889f8d325a06422e52c405b98384_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-5070889f8d325a06422e52c405b98384_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb lazy" width="2880" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='2880'%20height='1800'&gt;&lt;/svg&gt;" data-actualsrc="https://pic1.zhimg.com/v2-5070889f8d325a06422e52c405b98384_b.jpg" title="v2-5070889f8d325a06422e52c405b98384_r"></figure>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-a93f633f70613d12d4c713986d93803b_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb" width="2880" data-original="https://pic4.zhimg.com/v2-a93f633f70613d12d4c713986d93803b_b.jpg" title="v2-a93f633f70613d12d4c713986d93803b_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-a93f633f70613d12d4c713986d93803b_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb lazy" width="2880" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='2880'%20height='1800'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-a93f633f70613d12d4c713986d93803b_b.jpg" title="v2-a93f633f70613d12d4c713986d93803b_r"></figure>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-d506fecd8cf2fc681aca4de5dda360eb_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb" width="2880" data-original="https://pic4.zhimg.com/v2-d506fecd8cf2fc681aca4de5dda360eb_b.jpg" title="v2-d506fecd8cf2fc681aca4de5dda360eb_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-d506fecd8cf2fc681aca4de5dda360eb_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb lazy" width="2880" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='2880'%20height='1800'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-d506fecd8cf2fc681aca4de5dda360eb_b.jpg" title="v2-d506fecd8cf2fc681aca4de5dda360eb_r"></figure>
<h3>啟動流程（TLDR）</h3>
<p>上文初步了解了vscode 的技術架構與源碼組織，手癢的同學估計有點等不及嘗試走一遍vscode 的啟動流程了。</p>
<p>然後在正式發車之前，我需要給大家一點友情提醒，如果你沒耐心看完下面的VSCode 的啟動流程，應該知道，人生得過且過o(╥﹏╥)o</p>
<p>總體來看，VSCode 的啟動代碼真正show 給我們看了一個複雜的客戶端軟件的代碼會工程化到什麼地步，這其中摻雜了大量的基於TypeScript 的OOP 式的代碼組織，各種對邊界，宿主環境，上下文的處理，本來簡單的啟動APP 渲染一個頁面流程變得極其複雜。</p>
<p>下面精簡抽取核心啟動鏈路的文件和方法看一看：</p>
<ul>
<li>入口：package.json { "main": "./out/main" } : electron 的標準啟動入口</li>
<li>'/out/main.js': 是構建產物的入口文件，它對應源碼'/src/main.js'</li>
</ul>
<div class="highlight">
<pre><code class="language-text">// /src/main.js 的精簡核心鏈路const { app, protocol } = require('electron'); app.once('ready', function () { // electron 啟動好之後，調用vscode 的入口onReady(); }); async function onReady() { // 獲取緩存文件目錄地址和語言配置，執行啟動const [cachedDataDir, nlsConfig] = await Promise.all([nodeCachedDataDir.ensureExists(), resolveNlsConfiguration()]) ; startup(cachedDataDir, nlsConfig); } function startup(cachedDataDir, nlsConfig) { // 先加載vscode 自己開源的AMD Loader https://github.com/Microsoft/vscode-loader/ // 再使用這個loader 去加載VSCode的主入口文件require('./bootstrap-amd').load('vs/code/electron-main/main'); } // /src/vs/code/electron-main/main.ts 精簡核心鏈路// 初始化主類const code = new CodeMain(); // 執行主入口函數code.main(); class CodeMain { main() { // vscode 的class public 入口一般只是空殼，真正的都在private邏輯裡面this.startUp(); } private async startup() { // 先創建依賴的初始化service const [instantiationService, instanceEnvironment] = this.createServices(); // 創建編輯器實例並調用startUp 方法return instantiationService.createInstance (CodeApplication).startup(); } } // /src/vs/code/el ectron-main/app.ts export class CodeApplication extends Disposable { async startup(): Promise&lt;void&gt; { // IPC Server const electronIpcServer = new ElectronIPCServer(); // SharedProcess const sharedProcess = this.instantiationService.createInstance(SharedProcess, machineId , this.userEnv); // 創建一大堆依賴的service // IUpdateService IWindowsMainService IDialogMainService IMenubarService IStorageMainService...... const appInstantiationService = await this.createServices(machineId, trueMachineId, sharedProcess, sharedProcessClient); // 打開一個窗口const windows = appInstantiationService.invokeFunction(accessor =&gt; this.openFirstWindow(accessor, electronIpcServer, sharedProcessClient)); } private openFirstWindow() { const windowsMainService = this.windowsMainService = accessor.get(IWindowsMainService); return windowsMainService.open(); } } // /src/vs/platform/windows/electron-main/windowsMainService.ts export class WindowsMainService extends Disposable implements IWindowsMainService { open() { // 執行open this.doOpen(); } private doOpen() { // 打開瀏覽器窗口this.openInBrowserWindow(); } private openInBrowserWindow() { // 創建窗口const createdWindow = window = this.instantiationService.createInstance(CodeWindow, { state, extensionDevelopmentPath: configuration.extensionDevelopmentPath, isExtensionTestHost: !!configuration.extensionTestsPath }) ; } private doOpenInBrowserWindow() { // 加載頁面window.load(configuration); } } // /src/vs/code/electron-main/window.ts export class CodeWindow extends Disposable implements ICodeWindow { load() { //調用electr on 的api 加載一個url 的html 頁面this._win.loadURL(this.getUrl(configuration)); } private getUrl() { // 獲取要打開的url let configUrl = this.doGetUrl(config); return configUrl; } private doGetUrl(config: object): string { // 終於看到html 了！ ！淚流滿面〒▽〒 // 打開VSCode 的工作台，也就是workbench return `${require.toUrl('vs/code/electron-browser/workbench/workbench.html')}?config=${encodeURIComponent(JSON .stringify(config))}`; } }</code></pre>
</div>
<p class="ztext-empty-paragraph"></p>
<h3>代碼編輯器技術</h3>
<p>因為本文關注的重點並不在真正的代碼編輯器技術而是在調研一下大型軟件的工程化，因此本文只會簡要介紹一下代碼編輯相關的的一些核心技術：</p>
<ul>
<li>monaco-editor 文本編輯器，非常精深的領域，不展開聊，可以看一些有意思的細節：</li>
<ul>
<li> <a href="https://link.zhihu.com/?target=https%3A//code.visualstudio.com/blogs/2018/03/23/text-buffer-reimplementation" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Text Buffer性能優化</a></li>
<li><a href="https://link.zhihu.com/?target=https%3A//github.com/microsoft/vscode/wiki/%255BWIP%255D-Code-Editor-Design-Doc" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">MVVM架構</a></li>
</ul>
<li>language server protocol 語言提示， 也是vscode 的一大創舉：</li>
<ul>
<li>不再關注AST 和Parser，轉而關注Document 和Position，從而實現語言無關。</li>
<li>將語言提示變成CS 架構，核心抽象成當點擊了文檔的第幾行第幾列位置需要server 作出什麼響應的一個簡單模型，基於JSON RPC 協議傳輸，每個語言都可以基於協議實現通用後端</li>
</ul>
</ul>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-df15dfb76180d92d6f81ecb619f2f414_r.jpg" data-caption="" data-size="normal" data-rawwidth="883" data-rawheight="366" class="origin_image zh-lightbox-thumb" width="883" data-original="https://pic1.zhimg.com/v2-df15dfb76180d92d6f81ecb619f2f414_b.jpg" title="v2-df15dfb76180d92d6f81ecb619f2f414_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-df15dfb76180d92d6f81ecb619f2f414_r.jpg" data-caption="" data-size="normal" data-rawwidth="883" data-rawheight="366" class="origin_image zh-lightbox-thumb lazy" width="883" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='883'%20height='366'&gt;&lt;/svg&gt;" data-actualsrc="https://pic1.zhimg.com/v2-df15dfb76180d92d6f81ecb619f2f414_b.jpg" title="v2-df15dfb76180d92d6f81ecb619f2f414_r"></figure>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-a48ed65c40ccbc74a3a9a30398684857_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb" width="2880" data-original="https://pic4.zhimg.com/v2-a48ed65c40ccbc74a3a9a30398684857_b.jpg" title="v2-a48ed65c40ccbc74a3a9a30398684857_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-a48ed65c40ccbc74a3a9a30398684857_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb lazy" width="2880" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='2880'%20height='1800'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-a48ed65c40ccbc74a3a9a30398684857_b.jpg" title="v2-a48ed65c40ccbc74a3a9a30398684857_r"></figure>
<ul>
<li><a href="https://link.zhihu.com/?target=https%3A//code.visualstudio.com/api/extension-guides/debugger-extension" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Debug Adaptor Prototal</a> :調試協議</li>
</ul>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-59b7187bb26dd2ff68e1782c03b7e206_r.jpg" data-caption="" data-size="normal" data-rawwidth="696" data-rawheight="243" class="origin_image zh-lightbox-thumb" width="696" data-original="https://pic3.zhimg.com/v2-59b7187bb26dd2ff68e1782c03b7e206_b.jpg" title="v2-59b7187bb26dd2ff68e1782c03b7e206_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-59b7187bb26dd2ff68e1782c03b7e206_r.jpg" data-caption="" data-size="normal" data-rawwidth="696" data-rawheight="243" class="origin_image zh-lightbox-thumb lazy" width="696" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='696'%20height='243'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-59b7187bb26dd2ff68e1782c03b7e206_b.jpg" title="v2-59b7187bb26dd2ff68e1782c03b7e206_r"></figure>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-93ef689eb3e359dd9e19b7224d1e1e6f_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb" width="2880" data-original="https://pic4.zhimg.com/v2-93ef689eb3e359dd9e19b7224d1e1e6f_b.jpg" title="v2-93ef689eb3e359dd9e19b7224d1e1e6f_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-93ef689eb3e359dd9e19b7224d1e1e6f_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb lazy" width="2880" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='2880'%20height='1800'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-93ef689eb3e359dd9e19b7224d1e1e6f_b.jpg" title="v2-93ef689eb3e359dd9e19b7224d1e1e6f_r"></figure>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-b122efe719e56c72e1cea0e65624fd04_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb" width="2880" data-original="https://pic1.zhimg.com/v2-b122efe719e56c72e1cea0e65624fd04_b.jpg" title="v2-b122efe719e56c72e1cea0e65624fd04_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-b122efe719e56c72e1cea0e65624fd04_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb lazy" width="2880" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='2880'%20height='1800'&gt;&lt;/svg&gt;" data-actualsrc="https://pic1.zhimg.com/v2-b122efe719e56c72e1cea0e65624fd04_b.jpg" title="v2-b122efe719e56c72e1cea0e65624fd04_r"></figure>
<div class="highlight">
<pre><code class="language-text">点评： monaco-editor 可以看出专家级人物的领域积累，属于VSCode 的核心竞争力language server protocol 和Debug Adaptor Prototal 的设计就属于高屋建瓴可以看出思想层次，把自己的东西做成标准，做出生态，开放共赢</code></pre>
</div>
<h2>四、VSCode 插件系統</h2>
<h3>理念差異</h3>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-1da3bcd351236f3e6dbf5dea6d0c1696_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb" width="2880" data-original="https://pic3.zhimg.com/v2-1da3bcd351236f3e6dbf5dea6d0c1696_b.jpg" title="v2-1da3bcd351236f3e6dbf5dea6d0c1696_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-1da3bcd351236f3e6dbf5dea6d0c1696_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb lazy" width="2880" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='2880'%20height='1800'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-1da3bcd351236f3e6dbf5dea6d0c1696_b.jpg" title="v2-1da3bcd351236f3e6dbf5dea6d0c1696_r"></figure>
<p>對比幾大IDE：</p>
<ul>
<li>Visual Studio / IntelliJ：不需要插件，all in one （不夠開放）</li>
<li> Eclipse: 一切皆插件（臃腫、慢、不穩定、體驗差）</li>
<li> VSCode：中庸之道</li>
</ul>
<h3>VSCode 插件的強隔離</h3>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-c493a52b89c968d5efbf208d38d2dfe7_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb" width="2880" data-original="https://pic4.zhimg.com/v2-c493a52b89c968d5efbf208d38d2dfe7_b.jpg" title="v2-c493a52b89c968d5efbf208d38d2dfe7_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-c493a52b89c968d5efbf208d38d2dfe7_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb lazy" width="2880" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='2880'%20height='1800'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-c493a52b89c968d5efbf208d38d2dfe7_b.jpg" title="v2-c493a52b89c968d5efbf208d38d2dfe7_r"></figure>
<ul>
<li>獨立進程：VSCode plugin 代碼運行在只屬於自己的獨立Extension Host 宿主進程裡</li>
<li>邏輯與視圖隔離：插件完全無法訪問DOM 以及操作UI，插件只能響應VSCode Core 暴露的擴展點</li>
<li>視圖擴展能力非常弱：VSCode 有非常穩定的交互與視覺設計，提供給插件的UI 上的洞（component slot）非常少且穩定</li>
<li>只能使用限制的組件來擴展：VSCode 對視圖擴展的能力限制非常強，洞裡面的UI 是並不能隨意繪製的，只能使用一些官方提供的內置組件，比如TreeView 之類</li>
</ul>
<blockquote><p>vscode 有哪些擴展能力？ <a href="https://link.zhihu.com/?target=https%3A//code.visualstudio.com/api/extension-capabilities/overview" class=" external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external"><span class="invisible">https://</span> <span class="visible">code.visualstudio.com/a</span> <span class="invisible">pi/extension-capabilities/overview</span></a></p></blockquote>
<div class="highlight">
<pre><code class="language-text">点评：视图扩展的克制带来统一的视觉与交互风格，带来好的用户体验，便于建立稳定的用户心智插件独立进程，与视图隔离，保证整体软件的质量、性能、安全性</code></pre>
</div>
<h3>Workbench 視圖結構</h3>
<blockquote><p><a href="https://link.zhihu.com/?target=https%3A//code.visualstudio.com/docs/getstarted/userinterface" class=" external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external"><span class="invisible">https://</span> <span class="visible">code.visualstudio.com/d</span> <span class="invisible">ocs/getstarted/userinterface</span></a></p></blockquote>
<p class="ztext-empty-paragraph"></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-631c094f0b2e9a106013a3b69c91186b_r.jpg" data-caption="" data-size="normal" data-rawwidth="702" data-rawheight="444" class="origin_image zh-lightbox-thumb" width="702" data-original="https://pic4.zhimg.com/v2-631c094f0b2e9a106013a3b69c91186b_b.jpg" title="v2-631c094f0b2e9a106013a3b69c91186b_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-631c094f0b2e9a106013a3b69c91186b_r.jpg" data-caption="" data-size="normal" data-rawwidth="702" data-rawheight="444" class="origin_image zh-lightbox-thumb lazy" width="702" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='702'%20height='444'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-631c094f0b2e9a106013a3b69c91186b_b.jpg" title="v2-631c094f0b2e9a106013a3b69c91186b_r"></figure>
<ul>
<li>標題欄: Title Bar</li>
<li>活動欄: Activity Bar</li>
<li>側邊欄: Side Bar</li>
<li>面板: Panal</li>
<li>編輯器: Editor</li>
<li>狀態欄: Status Bar</li>
</ul>
<p>在這個視圖結構裡面有哪些可擴展呢？詳見<a href="https://link.zhihu.com/?target=https%3A//code.visualstudio.com/api/extension-capabilities/extending-workbench" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">extending workbench</a> ：</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-b4859559a6a3172374fa40d0378d6f5c_r.jpg" data-caption="" data-size="normal" data-rawwidth="2954" data-rawheight="2058" class="origin_image zh-lightbox-thumb" width="2954" data-original="https://pic1.zhimg.com/v2-b4859559a6a3172374fa40d0378d6f5c_b.jpg" title="v2-b4859559a6a3172374fa40d0378d6f5c_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-b4859559a6a3172374fa40d0378d6f5c_r.jpg" data-caption="" data-size="normal" data-rawwidth="2954" data-rawheight="2058" class="origin_image zh-lightbox-thumb lazy" width="2954" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='2954'%20height='2058'&gt;&lt;/svg&gt;" data-actualsrc="https://pic1.zhimg.com/v2-b4859559a6a3172374fa40d0378d6f5c_b.jpg" title="v2-b4859559a6a3172374fa40d0378d6f5c_r"></figure>
<h3>插件API 注入</h3>
<p>插件開發者調用core 能力時需要引入名為vscode 的npm 模塊</p>
<div class="highlight">
<pre><code class="language-text">import * as vscode from 'vscode';</code></pre>
</div>
<p>而實際上這只是一個vscode.d.ts 類型聲明文件，它聲明了所有插件可用的API 類型。<br />這些API 的具體實現在src/vs/workbench/api/common/extHost.api.impl.ts createApiFactoryAndRegisterActors</p>
<p>那麼具體這些API 在plugin 執行上下文是何時注入的呢？其實是在插件import 語句執行的時候動了手腳。</p>
<div class="highlight">
<pre><code class="language-text">// /src/vs/workbench/api/common/extHostRequireInterceptor.ts class VSCodeNodeModuleFactory implements INodeModuleFactory { public load(_request: string, parent: URI): any { // get extension id from filename and api for extension const ext = this._extensionPaths.findSubstr(parent.fsPath); if (ext) { let apiImpl = this._extApiImpl.get(ExtensionIdentifier.toKey(ext.identifier)); if (!apiImpl) { apiImpl = this._apiFactory(ext, this._extensionRegistry, this._configProvider); this._extApiImpl.set(ExtensionIdentifier.toKey(ext.identifier), apiImpl); } return apiImpl; } // fall back to a default implementation if (!this._defaultApiImpl) { let extensionPathsPretty = ''; this._extensionPaths.forEach((value, index) =&gt; extensionPathsPretty += `t${index} -&gt; ${value.identifier.value}n`); this._logService.warn(`Could not identify extension for 'vscode' require call from ${parent.fsPath}. These are the extension path mappings: n${extensionPathsPretty}`); this._defaultApiImpl = this._apiFactory(nullExtensionDescription, this._extensionRegistry, this._configProvider); } return this._defaultApiImpl; } }</code></pre>
</div>
<p>vscode plugin的require全部被<a href="https://link.zhihu.com/?target=https%3A//github.com/Microsoft/vscode-loader" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Microsoft/vscode-loader</a>劫持了，通過對require的hack將插件API注入到了運行環境。</p>
<h3>插件開發與配置</h3>
<p>腳手架： <a href="https://link.zhihu.com/?target=https%3A//github.com/Microsoft/vscode-generator-code" class=" external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external"><span class="invisible">https://</span> <span class="visible">github.com/Microsoft/vs</span> <span class="invisible">code-generator-code</span></a><br />官方demo: <a href="https://link.zhihu.com/?target=https%3A//github.com/Microsoft/vscode-eslint" class=" external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external"><span class="invisible">https://</span> <span class="visible">github.com/Microsoft/vs</span> <span class="invisible">code-eslint</span></a></p>
<div class="highlight">
<pre><code class="language-bash">npm install -g yo generator-code yo code</code></pre>
</div>
<p>一個插件核心就是一個配置文件：Extension Manifest JSON (package.json 裡面的一個字段)</p>
<blockquote><p><a href="https://link.zhihu.com/?target=https%3A//code.visualstudio.com/api/references/extension-manifest%25EF%25BC%2589" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">https://code.visualstudio.com/api/references/extension-manifest</a></p></blockquote>
<p>一些關鍵配置如下：</p>
<h3>main：主文件入口，比如導出一個activate 方法，可以接受ctx 做一些事情</h3>
<div class="highlight">
<pre><code class="language-bash"><span class="s2">"main"</span> : <span class="s2">"./src/extension.js"</span> , // extension.js const <span class="nv">vscode</span> <span class="o">=</span> require <span class="o">(</span> <span class="s2">"vscode"</span> <span class="o">)</span> <span class="p">;</span> <span class="k">function</span> activate <span class="o">(</span> context <span class="o">)</span> <span class="o">{</span> console.log <span class="o">(</span> <span class="s1">'Congratulations, your extension "helloworld" is now active!'</span> <span class="o">)</span> <span class="p">;</span> <span class="nb">let</span> <span class="nv">disposable</span> <span class="o">=</span> vscode.commands.registerCommand <span class="o">(</span> <span class="s2">"extension.helloWorld"</span> , <span class="k">function</span> <span class="o">()</span> <span class="o">{</span> vscode.window.showInformationMessage <span class="o">(</span> <span class="s2">"Hello World!"</span> <span class="o">)</span> <span class="p">;</span> <span class="o">}</span> <span class="o">)</span> <span class="p">;</span> context.subscriptions.push <span class="o">(</span> disposable <span class="o">)</span> <span class="p">;</span> <span class="o">}</span> exports.activate <span class="o">=</span> activate <span class="p">;</span></code></pre>
</div>
<h3>Activation Events 激活時機</h3>
<ul>
<li>onLanguage：包含該語言類型的文件被打開</li>
<li>onLanguage:json</li>
<li> onCommand：某個命令</li>
<li>onCommand:extension.sayHello</li>
<li> onDebug：開始調試</li>
<li>onDebugInitialConfigurations</li>
<li> onDebugResolve</li>
<li> workspaceContains：有匹配規則的文件被打開</li>
<li>workspaceContains:**/.editorconfig</li>
<li> onFileSystem：打開某個特殊協議的文件</li>
<li>onFileSystem:sftp</li>
<li> onView：某個id 的視圖被顯示</li>
<li>onView:nodeDependencies</li>
<li> onUri：向操作系統註冊的schema</li>
<li> vscode://vscode.git/init</li>
<li> onWebviewPanel：某種viewType 的webview 打開時</li>
<li>onWebviewPanel:catCoding</li>
<li> *：啟動就立即打開</li>
</ul>
<h3>Contribution Points 擴展點</h3>
<ul>
<li>contributes.configuration：本插件有哪些可供用戶配置的選項</li>
<li>contributes.configurationDefaults：覆蓋vscode 默認的一些編輯器配置</li>
<li>contributes.commands：向vscode 的命令系統註冊一些可供用戶調用的命令</li>
<li>contributes.menus：擴展菜單</li>
<li>...</li>
</ul>
<h2>五、感想</h2>
<p>Eric Raymond有一本非常知名的著作<a href="https://link.zhihu.com/?target=https%3A//book.douban.com/subject/25881855/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">《大教堂與集市》</a> ，其中提到過一些有意思的觀點：</p>
<ul>
<li>健壯的結構遠比精巧的設計來得重要。換句話說，結構是第一位的，功能是第二位的。</li>
<li>保持項目的簡單性。設計達到完美的時候，不是無法再增加東西了，而是無法再減少東西了。</li>
</ul>
<p>VSCode 的一些工程上的優秀設計，比如依賴注入、絕對路徑引用、命令系統對於雲鳳蝶來說是可以馬上學以致用的，而contrib 與extension 的擴展系統，則非一日之功，也並不宜盲目下手。</p>
<p>而事實上在嘗試打造每一個開發者都夢想的萬物皆plugin 式的工具軟件之前，有一些通用的問題需要先冷靜下來思考：</p>
<ul>
<li>用戶核心在操作的資源是什麼？</li>
<li>用戶的關鍵路徑是什麼？</li>
<li>這個軟件的整體功能形態，交互與視覺設計已經穩定了嗎？</li>
<li>內核功能區和第三方擴展的功能域之間的界限在哪裡？</li>
<li>哪些環節可能會出現外溢需求需要第三方擴展才能被滿足，不適宜官方動手做嗎？</li>
</ul>
<p>對VSCode 而言：</p>
<ul>
<li>核心操作的資源是文件</li>
<li>關鍵路徑是：打開文件- 編輯文件- 保存文件</li>
<li>整體功能設計，交互與視覺設計非常穩定</li>
<li>內核是文件管理與代碼編輯，多樣性的編程語言生態，CICD 等衍生研發鏈路等可能會出現擴展需求</li>
</ul>
<p>對雲鳳蝶而言：</p>
<ul>
<li>核心操作的資源是頁面：（分為視圖和代碼）</li>
<li>關鍵路徑是：打開頁面- 編輯頁面（拖拽視圖，配置屬性，編寫代碼）- 保存頁面</li>
<li>整體功能設計還在快速迭代中</li>
<li>內核是頁面的製作，多樣性的資產生態，CI CD 等衍生研發鏈路等可能會出現擴展需求</li>
</ul>
<p>圍繞這個思考，雲鳳蝶將持續吸納優秀的思想與架構，持續將編輯器的核心功能鏈路打磨通透，底層架構搭建穩定。</p>
<h2>六、相關資料</h2>
<ul>
<li><a href="https://link.zhihu.com/?target=https%3A//www.youtube.com/watch%3Fv%3DuLrnQtAq5Ec" class=" external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external"><span class="invisible">https://www.</span> <span class="visible">youtube.com/watch?</span> <span class="invisible">v=uLrnQtAq5Ec</span></a></li>
<li><a href="https://link.zhihu.com/?target=https%3A//www.youtube.com/watch%3Fv%3DVs3AGfeuNKU" class=" external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external"><span class="invisible">https://www.</span> <span class="visible">youtube.com/watch?</span> <span class="invisible">v=Vs3AGfeuNKU</span></a></li>
<li><a href="https://link.zhihu.com/?target=https%3A//github.com/JChehe/blog/issues/5" class=" external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external"><span class="invisible">https://</span> <span class="visible">github.com/JChehe/blog/</span> <span class="invisible">issues/5</span></a></li>
<li><a href="https://link.zhihu.com/?target=https%3A//electronjs.org/docs/tutorial/application-architecture" class=" external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external"><span class="invisible">https://</span> <span class="visible">electronjs.org/docs/tut</span> <span class="invisible">orial/application-architecture</span></a></li>
<li><a href="https://zhuanlan.zhihu.com/p/54289476" class="internal" data-wpel-link="external" rel="nofollow external noopener noreferrer"><span class="invisible">https://</span> <span class="visible">zhuanlan.zhihu.com/p/54</span> <span class="invisible">289476</span></a></li>
<li><a href="https://link.zhihu.com/?target=http%3A//phosphorjs.github.io/" class=" external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external"><span class="invisible">http://</span> <span class="visible">phosphorjs.github.io/</span></a></li>
<li><a href="https://link.zhihu.com/?target=https%3A//developer.egret.com/cn/docs/page/778" class=" external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external"><span class="invisible">https://</span> <span class="visible">developer.egret.com/cn/</span> <span class="invisible">docs/page/778</span></a></li>
<li><a href="https://link.zhihu.com/?target=https%3A//developer.chrome.com/extensions/getstarted" class=" external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external"><span class="invisible">https://</span> <span class="visible">developer.chrome.com/ex</span> <span class="invisible">tensions/getstarted</span></a></li>
<li><a href="https://link.zhihu.com/?target=https%3A//developer.alipay.com/article/8708" class=" external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external"><span class="invisible">https://</span> <span class="visible">developer.alipay.com/ar</span> <span class="invisible">ticle/8708</span></a></li>
<li><a href="https://link.zhihu.com/?target=https%3A//zhaomenghuan.js.org/blog/vscode-custom-development-basic-preparation.html" class=" external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external"><span class="invisible">https://</span> <span class="visible">zhaomenghuan.js.org/blo</span> <span class="invisible">g/vscode-custom-development-basic-preparation.html</span></a></li>
</ul>
<hr>
<p><b>未來已來，時不我待！</b><br />雲鳳蝶招聘前端、Java、PD、設計崗位，未來等你共創！<br />如果你感興趣，歡迎聯繫chenyu@antfin.com 或shuai.shao@antfin.com</p>
</div>
</div>
</article>
<p>The post <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com/software-engineering/front-end-dev/14899/topic-96041706/" data-wpel-link="internal">從VSCode 看大型IDE 技術架構</a> appeared first on <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com" data-wpel-link="internal">成長駭客交流第一站 - HyperGrowths™</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>雲鳳蝶可視化搭建的推導與實現</title>
		<link>https://hypergrowths.com/software-engineering/front-end-dev/14789/topic-90746742/</link>
		
		<dc:creator><![CDATA[marketer]]></dc:creator>
		<pubDate>Sat, 30 Jan 2021 18:19:00 +0000</pubDate>
				<category><![CDATA[前端開發]]></category>
		<category><![CDATA[支付寶體驗科技]]></category>
		<guid isPermaLink="false">https://hypergrowths.com/software-engineering/front-end-dev/14789/topic-90746742/</guid>

					<description><![CDATA[<p>前言從古老的桌面軟件領域的WPF、JavaFX，到移動端與時俱進的SwiftUI、JetPack Compose，再到Salesforce、OutSystems、Mendix 等一眾hpaPaaS （High-productivity Application platform as a service），一直…</p>
<p>The post <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com/software-engineering/front-end-dev/14789/topic-90746742/" data-wpel-link="internal">雲鳳蝶可視化搭建的推導與實現</a> appeared first on <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com" data-wpel-link="internal">成長駭客交流第一站 - HyperGrowths™</a>.</p>
]]></description>
										<content:encoded><![CDATA[<article class="Post-Main Post-NormalMain" tabindex="-1">
<header class="Post-Header">
<h1 class="Post-Title">雲鳳蝶可視化搭建的推導與實現</h1>
<div class="Post-Author">
<div class="AuthorInfo" itemprop="author" itemscope="" itemtype="http://schema.org/Person"><meta itemprop="name" content="paranoidjk"><meta itemprop="image" content="https://pic1.zhimg.com/7767136d381ec3e5da22e406ffdec79f_l.jpg?source=172ae18b"><meta itemprop="url" content="https://www.zhihu.com/people/paranoidjk"><meta itemprop="zhihu:followerCount"></div>
</div>
</header>
<div class="Post-RichTextContainer">
<div class="RichText ztext Post-RichText">
<h2>前言</h2>
<p>從古老的桌面軟件領域的WPF、JavaFX，到移動端與時俱進的SwiftUI、JetPack Compose，再到Salesforce、OutSystems、Mendix 等一眾hpaPaaS （High-productivity Application platform as a service），一直以來許多產品都在嘗試通過可視化搭建的手段來降低GUI 應用的研發門檻，提高生產效率。而云鳳蝶則是一個新的挑戰者。</p>
<p>本文將以概覽性的視角來介紹雲鳳蝶在低代碼+可視化搭建這條路上遇到的問題與解決方案，包括：</p>
<ul>
<li>中後台Web 應用搭建有哪些關鍵要素？</li>
<li>可視化編輯器如何對齊Pro Code 下視圖DSL 的表達能力？</li>
<li>交互邏輯與狀態如何進行組織與聚合？</li>
<li>如何基於可視化底盤去探索10 倍效能提升？</li>
</ul>
<h2>一、雲鳳蝶產品介紹</h2>
<p><a class="video-box" href="https://link.zhihu.com/?target=https%3A//www.zhihu.com/video/1175856121427955712" target="_blank" data-video-id="" data-video-playable="true" data-name="云凤蝶产品介绍" data-poster="https://unicom.zhimg.com/pic3.zhimg.com/v2-7eb52e641258598c660e3e099fb3b50a.jpg" data-lens-id="1175856121427955712" rel="noopener nofollow external noreferrer" data-wpel-link="external"><img decoding="async" class="thumbnail" src="" data-original="https://unicom.zhimg.com/pic3.zhimg.com/v2-7eb52e641258598c660e3e099fb3b50a.jpg"><span class="content"><span class="title">雲鳳蝶產品介紹</span><span class="url">https://www.zhihu.com/video/1175856121427955712</span></span></a></p>
<p class="ztext-empty-paragraph"></p>
<h2>二、可視化搭建的關鍵要素</h2>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-a35eff2fcd0bade8943ad86671367258_r.jpg" data-caption="" data-size="normal" data-rawwidth="1500" data-rawheight="640" class="origin_image zh-lightbox-thumb" width="1500" data-original="https://pic1.zhimg.com/v2-a35eff2fcd0bade8943ad86671367258_b.jpg" title="v2-a35eff2fcd0bade8943ad86671367258_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-a35eff2fcd0bade8943ad86671367258_r.jpg" data-caption="" data-size="normal" data-rawwidth="1500" data-rawheight="640" class="origin_image zh-lightbox-thumb lazy" width="1500" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1500'%20height='640'&gt;&lt;/svg&gt;" data-actualsrc="https://pic1.zhimg.com/v2-a35eff2fcd0bade8943ad86671367258_b.jpg" title="v2-a35eff2fcd0bade8943ad86671367258_r"></figure>
<p>如上圖左側所示是一個簡單網頁，一個Tabs 內嵌了一個Form 表單，在普通用戶的視角里看到的世界可能是扁平的，但是在開發者的視角基本都可以看出來右側的一顆<b>組件樹。</b></p>
<p>一個組件化的搭建平台其實本質就是一條<b>組件組裝流水線</b>，其核心目的就是如何多快好省地幫助用戶製作出這顆樹。</p>
<p>那麼讓我們將視角聚焦到“<b>組件</b>”這個東西上，在當前大多數前端框架體系下，組件是一個滿足<code>f: props =&gt; view</code>協議的函數，它的入參一般是一些簡單的抽象好的配置，返回值則是使用某種視圖描述語法（HTML、Virtual DOM）來描述的一塊視圖，而其計算過程可以使用任意框架或語言來實現。</p>
<p>如此看來，組件還牽扯到函數和運算過程，好複雜...</p>
<p>而實際上我們可以先嘗試做一個職責切分，因為現如今在螞蟻前端的Pro Code 研發體系下，Basement 負責研發流程，Gitlab 負責代碼管理， tnpm 負責管理模塊，Bigfish 負責組件開發規範。所有這些都已經非常成熟，我們應該把專業的事情交給專業的人來做，盡量站在這些成熟的體系之上，也就是：</p>
<blockquote><p><i>“讓上帝的歸上帝，凱撒的歸凱撒”</i></p></blockquote>
<p>因此最終雲鳳蝶決定將Pro Code 世界下的組件作為原材料去消費，自身專心去做一條高效且全能的組裝流水線。一條組裝流水線其最小功能閉環至少需要有：</p>
<ul>
<li>組件的導入與二次拼裝能力</li>
<li>組件的入參屬性定制能力</li>
<li>組件的邏輯編排與聯動能力</li>
</ul>
<p>細化來看，每一個其實都是相當複雜的課題：</p>
<ul>
<li><b>組件的導入與二次拼裝能</b>力</li>
<ul>
<li>如何實現中心化的組件註冊與加載體系</li>
<li>如何實現編輯與預覽時實時更新</li>
<li>如何控制組件之間的加載順序</li>
<li>多組件的公共依賴如何去重</li>
<li>如何處理組件的不兼容升級</li>
</ul>
<li><b>組件的入參屬性定制能力</b></li>
<ul>
<li>屬性面板如何表達antd 的所有props 類型</li>
<li>如何支撐對屬性的擴展能力</li>
<ul>
<li>對值的類型的擴展能力</li>
<ul>
<li>JS 基本類型</li>
<li>業務類型：Moment、Regexp、URL、Function、Email、Image...</li>
</ul>
<li>對值的來源的擴展能力</li>
<ul>
<li>靜態值</li>
<li>數據綁定（單向，雙向，一次性）</li>
<li>異步動態數據源（HTTP/TR）</li>
<li>第三方圖片素材庫...</li>
</ul>
</ul>
</ul>
<li><b>組件的邏輯編排與聯動能力</b></li>
<ul>
<li>組件之間組合：如何解決不同屏幕尺寸下的多組件位置關係變化問題</li>
<li>組件之間聯動：如何支持外置共享狀態的管理與消費</li>
</ul>
</ul>
<p>這其中每一個點可能都需要一篇文章的筆墨才能介紹清楚，因此本文只會是一篇目錄性質的綱要介紹，後續我們會陸續發表對更多實現細節的分享文章，敬請期待。</p>
<h2>三、組件導入與製作</h2>
<p>上一小節已經闡釋了雲鳳蝶需要有消費npm 世界的組件能力。如下圖所示，雲鳳蝶既支持從代碼導入也支持拖拽二次拼裝。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-53d3a77e572388354d152adbdc375985_r.jpg" data-caption="" data-size="normal" data-rawwidth="1164" data-rawheight="890" class="origin_image zh-lightbox-thumb" width="1164" data-original="https://pic2.zhimg.com/v2-53d3a77e572388354d152adbdc375985_b.jpg" title="v2-53d3a77e572388354d152adbdc375985_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-53d3a77e572388354d152adbdc375985_r.jpg" data-caption="" data-size="normal" data-rawwidth="1164" data-rawheight="890" class="origin_image zh-lightbox-thumb lazy" width="1164" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1164'%20height='890'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-53d3a77e572388354d152adbdc375985_b.jpg" title="v2-53d3a77e572388354d152adbdc375985_r"></figure>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-24e4f6346a72db48c24d306885049eea_r.jpg" data-caption="" data-size="normal" data-rawwidth="1320" data-rawheight="508" class="origin_image zh-lightbox-thumb" width="1320" data-original="https://pic3.zhimg.com/v2-24e4f6346a72db48c24d306885049eea_b.jpg" title="v2-24e4f6346a72db48c24d306885049eea_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-24e4f6346a72db48c24d306885049eea_r.jpg" data-caption="" data-size="normal" data-rawwidth="1320" data-rawheight="508" class="origin_image zh-lightbox-thumb lazy" width="1320" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1320'%20height='508'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-24e4f6346a72db48c24d306885049eea_b.jpg" title="v2-24e4f6346a72db48c24d306885049eea_r"></figure>
<p>通過上述一套流程，我們可以實現快速導入一個npm 上已存的代碼組件到雲鳳蝶平台上使用，並且基於構建出的依賴Manifest 訊息和SystemJS Loader 可以實現對一些公共依賴的去重，加載順序的控制等等。</p>
<p>更為重要的是，這裡面出現了一份“<b>雲鳳蝶組件定義</b>”，這是一份非常重要的白皮書，它是我們在摸爬滾打接入<a href="https://link.zhihu.com/?target=https%3A//ant.design/index-cn" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">antd</a>所有組件之後，最終總結出來的對一個組件所有編輯時與運行時公共行為的上層建模與抽象，它指導了雲鳳蝶如何去理解一個組件的諸多表現。</p>
<h2><b>四、組件屬性定制與擴展</b></h2>
<h3>對屬性值的定制</h3>
<p>屬性編輯器的意圖是完成對組件的屬性定制，它本質屬於一個複雜的Schema Form 形態的配置器。但是以下圖中截取antd Table組件的部分的props的為例， <a href="https://link.zhihu.com/?target=https%3A//ant.design/components/table-cn/%23header" class=" external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external"><span class="invisible">https://</span> <span class="visible">ant.design/components/t</span> <span class="invisible">able-cn/#header</span></a></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-406e9cca6659f96af45911d4644878c9_r.jpg" data-caption="" data-size="normal" data-rawwidth="1500" data-rawheight="1276" class="origin_image zh-lightbox-thumb" width="1500" data-original="https://pic2.zhimg.com/v2-406e9cca6659f96af45911d4644878c9_b.jpg" title="v2-406e9cca6659f96af45911d4644878c9_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-406e9cca6659f96af45911d4644878c9_r.jpg" data-caption="" data-size="normal" data-rawwidth="1500" data-rawheight="1276" class="origin_image zh-lightbox-thumb lazy" width="1500" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1500'%20height='1276'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-406e9cca6659f96af45911d4644878c9_b.jpg" title="v2-406e9cca6659f96af45911d4644878c9_r"></figure>
<p class="ztext-empty-paragraph"></p>
<p>可以看到：</p>
<ul>
<li>有大量props的值是<b>非JavaScript基本類型</b>的</li>
<li>有大量props的類型是<b>聯合類型</b></li>
<li>有少量props互相之間是<b>邏輯關聯</b>的，或者<b>互斥</b>的</li>
</ul>
<p>雲鳳蝶為此打造了一塊極其強大的屬性配置面板，力求完整的表達能力和良好的用戶體驗兼顧，後續文章會專門介紹，敬請期待。</p>
<h3>對屬性值的擴展</h3>
<p>即使將屬性面板的表單體驗打磨到極致，也只是還原了antd 的能力而已，要想得到比antd 更高的效能提升，還需要具備對原生屬性的擴展能力，因為屬性的多樣性就代表了組件能力的多樣性，比如：</p>
<ul>
<li><b>對值的類型的擴展</b>：除了JS基本類型之外，是否可以自定義任意業務類型？比如：國際化文案，圖片素材庫等。</li>
<li><b>對值的來源的擴展</b>：除了直接在屬性面板裡面輸入靜態值之外，值是否可以來源於變量綁定？來自異步請求？來自數據源？ 。</li>
</ul>
<p>以雲鳳蝶其中一種最重要的對屬性值來源的擴展- <code>binding（数据绑定）</code>為例，它和Vue、Angular、小程序等技術體系下的數據綁定概念一脈相承，交互形式如下：</p>
<p><a class="video-box" href="https://link.zhihu.com/?target=https%3A//www.zhihu.com/video/1175861306061680640" target="_blank" data-video-id="" data-video-playable="true" data-name="云凤蝶 - 数据绑定" data-poster="https://unicom.zhimg.com/pic1.zhimg.com/v2-c7aa2d94df8028c9e9610fa494c397d0.jpg" data-lens-id="1175861306061680640" rel="noopener nofollow external noreferrer" data-wpel-link="external"><img decoding="async" class="thumbnail" src="" data-original="https://unicom.zhimg.com/pic1.zhimg.com/v2-c7aa2d94df8028c9e9610fa494c397d0.jpg"><span class="content"><span class="title">雲鳳蝶-數據綁定</span><span class="url">https://www.zhihu.com/video/1175861306061680640</span></span></a></p>
<p>那麼這種對props 的數據綁定最終是如何存儲與運行的呢？以Table 組件的一個props 範例：</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-b41be041f18f4e293649e07b13ddb421_r.jpg" data-caption="" data-size="normal" data-rawwidth="1332" data-rawheight="1600" class="origin_image zh-lightbox-thumb" width="1332" data-original="https://pic2.zhimg.com/v2-b41be041f18f4e293649e07b13ddb421_b.jpg" title="v2-b41be041f18f4e293649e07b13ddb421_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-b41be041f18f4e293649e07b13ddb421_r.jpg" data-caption="" data-size="normal" data-rawwidth="1332" data-rawheight="1600" class="origin_image zh-lightbox-thumb lazy" width="1332" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1332'%20height='1600'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-b41be041f18f4e293649e07b13ddb421_b.jpg" title="v2-b41be041f18f4e293649e07b13ddb421_r"></figure>
<p>在Pro Code的世界裡，props應該是一顆普通的對象樹，雲鳳蝶通過定義一種<b>{ $$__type, $$__body }</b>的特殊對象結構實現了在一顆對象樹上任意位置去擴展複雜的業務實體類型。</p>
<p>每一種業務類型都是一個在雲鳳蝶系統上註冊過的“實體”，每一個實體都需要實現一個實體Loader，如下圖中的有顏色的節點全部是業務實體：</p>
<p class="ztext-empty-paragraph"></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-6c0cc9990b893f7f42a125deb8e7164d_r.jpg" data-caption="" data-size="normal" data-rawwidth="912" data-rawheight="610" class="origin_image zh-lightbox-thumb" width="912" data-original="https://pic2.zhimg.com/v2-6c0cc9990b893f7f42a125deb8e7164d_b.jpg" title="v2-6c0cc9990b893f7f42a125deb8e7164d_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-6c0cc9990b893f7f42a125deb8e7164d_r.jpg" data-caption="" data-size="normal" data-rawwidth="912" data-rawheight="610" class="origin_image zh-lightbox-thumb lazy" width="912" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='912'%20height='610'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-6c0cc9990b893f7f42a125deb8e7164d_b.jpg" title="v2-6c0cc9990b893f7f42a125deb8e7164d_r"></figure>
<blockquote><p>為什麼數據格式不採用JSON Schema ？因為它寫起來和實現起來都繁瑣，體積臃腫。</p></blockquote>
<p>在運行時真正渲染每一個組件之前，它的props配置數據都會經歷一個<b>“翻譯”</b>過程，雲鳳蝶的Runtime會掃描props對象樹，在任意節點一旦遇到滿足<code>{ $$___type, $$__body }</code>形態的Entity，就會轉而調用對應的Entity Loader 來翻譯該節點，具體操作一般是返回一個真正可交給原始組件運行的plain data 替代該節點，同時也允許Loader 去執行一些副作用，以數據綁定為例，副作用就可能包括監聽數據變化和更新渲染視圖。</p>
<p>一個Entity loader 的偽代碼：</p>
<p class="ztext-empty-paragraph"></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-c9b3c0b75e87564e7550a547fa71a956_r.jpg" data-caption="" data-size="normal" data-rawwidth="954" data-rawheight="716" class="origin_image zh-lightbox-thumb" width="954" data-original="https://pic3.zhimg.com/v2-c9b3c0b75e87564e7550a547fa71a956_b.jpg" title="v2-c9b3c0b75e87564e7550a547fa71a956_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-c9b3c0b75e87564e7550a547fa71a956_r.jpg" data-caption="" data-size="normal" data-rawwidth="954" data-rawheight="716" class="origin_image zh-lightbox-thumb lazy" width="954" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='954'%20height='716'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-c9b3c0b75e87564e7550a547fa71a956_b.jpg" title="v2-c9b3c0b75e87564e7550a547fa71a956_r"></figure>
<h3>對屬性本身的擴展</h3>
<p>除了上一小節提到的擴展antd props的配置形態，雲鳳蝶平台也會向所有組件的屬性面板添加一些<b>通用高級屬性</b>，如：是否渲染、是否隱藏、重複、通用樣式，懸浮提示，固釘，徽標，loading 加載中等等，每一個通用高級屬性都是Web 應用研發中某一類常見功能的抽象與封裝，力求所有能被模式化的Feature 都被沉澱下來成為一條通用路徑。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-151985fe1f8e00283b6205265481ced1_r.jpg" data-caption="" data-size="normal" data-rawwidth="642" data-rawheight="1156" class="origin_image zh-lightbox-thumb" width="642" data-original="https://pic2.zhimg.com/v2-151985fe1f8e00283b6205265481ced1_b.jpg" title="v2-151985fe1f8e00283b6205265481ced1_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-151985fe1f8e00283b6205265481ced1_r.jpg" data-caption="" data-size="normal" data-rawwidth="642" data-rawheight="1156" class="origin_image zh-lightbox-thumb lazy" width="642" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='642'%20height='1156'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-151985fe1f8e00283b6205265481ced1_b.jpg" title="v2-151985fe1f8e00283b6205265481ced1_r"></figure>
<p>而這些高級渲染屬性的實現原理則是利用<a href="https://link.zhihu.com/?target=https%3A//reactjs.org/docs/higher-order-components.html" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">HOC</a> （Higher-Order Components）去包裹原始組件實現這些增強功能，如圖：</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-d9e5c399ca056a65c364abbcc3091fe1_r.jpg" data-caption="" data-size="normal" data-rawwidth="1052" data-rawheight="1166" class="origin_image zh-lightbox-thumb" width="1052" data-original="https://pic2.zhimg.com/v2-d9e5c399ca056a65c364abbcc3091fe1_b.jpg" title="v2-d9e5c399ca056a65c364abbcc3091fe1_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-d9e5c399ca056a65c364abbcc3091fe1_r.jpg" data-caption="" data-size="normal" data-rawwidth="1052" data-rawheight="1166" class="origin_image zh-lightbox-thumb lazy" width="1052" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1052'%20height='1166'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-d9e5c399ca056a65c364abbcc3091fe1_b.jpg" title="v2-d9e5c399ca056a65c364abbcc3091fe1_r"></figure>
<h2>五、組件的可視化組合與編排</h2>
<p>組件的可視化編排會涉及幾個關鍵問題：</p>
<ul>
<li>編輯時拖拽組件的二維坐標如何形成嵌套<b>組件樹</b></li>
<li>當<b>屏幕尺寸變化</b>的時候，組件自身，組件與其他組件之間的位置關係如何變化</li>
</ul>
<p>第一個問題相對簡單，我們<b>以是否被包含來決定父子關係</b>。舉個例子，畫布上有如下[A, B, C, D] 四個元素。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-3145346dc6e831ddfd171a0df3799db6_r.jpg" data-caption="" data-size="normal" data-rawwidth="1068" data-rawheight="612" class="origin_image zh-lightbox-thumb" width="1068" data-original="https://pic3.zhimg.com/v2-3145346dc6e831ddfd171a0df3799db6_b.jpg" title="v2-3145346dc6e831ddfd171a0df3799db6_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-3145346dc6e831ddfd171a0df3799db6_r.jpg" data-caption="" data-size="normal" data-rawwidth="1068" data-rawheight="612" class="origin_image zh-lightbox-thumb lazy" width="1068" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1068'%20height='612'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-3145346dc6e831ddfd171a0df3799db6_b.jpg" title="v2-3145346dc6e831ddfd171a0df3799db6_r"></figure>
<p>我們根據坐標和尺寸數據可以得到一個包含集合，例如：</p>
<ul>
<li>A: [B, C, D] （A 包含了B，C，D）</li>
<li> B: [C, D] （B 包含了C，D）</li>
<li> C: [D] （C 包含了D）</li>
</ul>
<p>然後進行第二輪算法，如果某個被包含的元素，不再被本集合內的其他元素包含，就可以認為它和宿主之間是屬於直接父子關係，得到：</p>
<ul>
<li>A: [B] （A 直接包含B）</li>
<li> B: [C] （B 直接包含C）</li>
<li> C: [D] （C 直接包含D）</li>
</ul>
<p>從而最終得到了<b>A -&gt; B -&gt; C -&gt; D</b>的父子組件樹鏈路。當然真實情況中還要考慮浮層這種獨立圖層，以及非法父子關係等細節，但核心就是依據這個直接被包含的關係算法，我們可以將二維的畫布根據位置訊息建模成一顆組件樹。</p>
<p>解決了樹算法之後，要想解決屏幕尺寸變化的自適應問題我們就必須引入一套<b>佈局系統</b>來解決。</p>
<h3>佈局系統</h3>
<h3>自由佈局</h3>
<p>自由佈局是雲鳳蝶默認的佈局類型，使用體驗就像KeyNote 或者Sketch 等產品一樣自由拖拽，隨心擺放。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-adf803d0a9eafa3baf73063c7d547f5a_r.jpg" data-caption="" data-size="normal" data-rawwidth="1510" data-rawheight="516" data-thumbnail="https://pic3.zhimg.com/v2-adf803d0a9eafa3baf73063c7d547f5a_b.jpg" class="origin_image zh-lightbox-thumb" width="1510" data-original="https://pic3.zhimg.com/v2-adf803d0a9eafa3baf73063c7d547f5a_b.gif" title="v2-adf803d0a9eafa3baf73063c7d547f5a_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-adf803d0a9eafa3baf73063c7d547f5a_r.jpg" data-caption="" data-size="normal" data-rawwidth="1510" data-rawheight="516" data-thumbnail="https://pic3.zhimg.com/v2-adf803d0a9eafa3baf73063c7d547f5a_b.jpg" class="origin_image zh-lightbox-thumb lazy" width="1510" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1510'%20height='516'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-adf803d0a9eafa3baf73063c7d547f5a_b.gif" title="v2-adf803d0a9eafa3baf73063c7d547f5a_r"></figure>
<p class="ztext-empty-paragraph"></p>
<p>自由拖拽可以解決固定屏幕尺寸下的元素擺放問題，但是當屏幕尺寸變化之後如何自適應？雲鳳蝶採用了一種類似<a href="https://link.zhihu.com/?target=https%3A//developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">iOS Auto Layout</a>的系統，但是約束規則會更簡單直觀：</p>
<p class="ztext-empty-paragraph"></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-93f7f81d327675960a8dcbab71a5cd47_r.jpg" data-caption="" data-size="normal" data-rawwidth="606" data-rawheight="854" class="origin_image zh-lightbox-thumb" width="606" data-original="https://pic4.zhimg.com/v2-93f7f81d327675960a8dcbab71a5cd47_b.jpg" title="v2-93f7f81d327675960a8dcbab71a5cd47_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-93f7f81d327675960a8dcbab71a5cd47_r.jpg" data-caption="" data-size="normal" data-rawwidth="606" data-rawheight="854" class="origin_image zh-lightbox-thumb lazy" width="606" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='606'%20height='854'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-93f7f81d327675960a8dcbab71a5cd47_b.jpg" title="v2-93f7f81d327675960a8dcbab71a5cd47_r"></figure>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-4a5d4ac1f2767b5f7c6eb93d7ec118b3_r.jpg" data-caption="" data-size="normal" data-rawwidth="658" data-rawheight="616" class="origin_image zh-lightbox-thumb" width="658" data-original="https://pic4.zhimg.com/v2-4a5d4ac1f2767b5f7c6eb93d7ec118b3_b.jpg" title="v2-4a5d4ac1f2767b5f7c6eb93d7ec118b3_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-4a5d4ac1f2767b5f7c6eb93d7ec118b3_r.jpg" data-caption="" data-size="normal" data-rawwidth="658" data-rawheight="616" class="origin_image zh-lightbox-thumb lazy" width="658" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='658'%20height='616'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-4a5d4ac1f2767b5f7c6eb93d7ec118b3_b.jpg" title="v2-4a5d4ac1f2767b5f7c6eb93d7ec118b3_r"></figure>
<ul>
<li>寬度/高度</li>
<ul>
<li>固定：永遠不變</li>
<li>自適應：隨著容器（父）的變大和變大</li>
<li>適配內容：隨著內容（子）的變大而變大</li>
</ul>
<li>上下左右間距</li>
<ul>
<li>固定：永遠不變</li>
<li>自適應：隨著容器（父）的變大而變大</li>
</ul>
</ul>
<p>根據靜態的坐標訊息再加上佈局系統的約束規則配置，雲鳳蝶運行時就可以將用戶的頁面翻譯成一個自適應的頁面，後續本系列會有專題文章介紹，在此只簡要概述整個算法的核心原理：</p>
<ul>
<li>編輯態用戶操作：</li>
<ul>
<li>自由拖拽：得到x（水平坐標）、 y（垂直坐標）、 w（寬）、 h（高）</li>
<li>按需配置寬、高、間距的佈局約束規則</li>
</ul>
<li>編譯時：</li>
<ul>
<li>基於直接被包含算法，得到組件樹</li>
<li>基於水平垂直軸是否交叉對整個頁面遞歸進行行列分割，將絕對定位的佈局系統轉換為相對佈局</li>
</ul>
</ul>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-faa7d6f8d49498843e23e6c0b9d36fd5_r.jpg" data-caption="" data-size="normal" data-rawwidth="894" data-rawheight="214" class="origin_image zh-lightbox-thumb" width="894" data-original="https://pic2.zhimg.com/v2-faa7d6f8d49498843e23e6c0b9d36fd5_b.jpg" title="v2-faa7d6f8d49498843e23e6c0b9d36fd5_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-faa7d6f8d49498843e23e6c0b9d36fd5_r.jpg" data-caption="" data-size="normal" data-rawwidth="894" data-rawheight="214" class="origin_image zh-lightbox-thumb lazy" width="894" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='894'%20height='214'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-faa7d6f8d49498843e23e6c0b9d36fd5_b.jpg" title="v2-faa7d6f8d49498843e23e6c0b9d36fd5_r"></figure>
<ul>
<ul>
<li>對約束規則進行翻譯</li>
</ul>
<li>運行時</li>
<ul>
<li>一個普通的自適應頁面</li>
</ul>
</ul>
<h3>彈性佈局</h3>
<p>雲鳳蝶同樣支持將佈局類型從自由切換為彈性，彈性佈局更適合流式的頁面編排。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-3a20927fb4295bac998742334ef95ec4_r.jpg" data-caption="" data-size="normal" data-rawwidth="1510" data-rawheight="516" data-thumbnail="https://pic1.zhimg.com/v2-3a20927fb4295bac998742334ef95ec4_b.jpg" class="origin_image zh-lightbox-thumb" width="1510" data-original="https://pic1.zhimg.com/v2-3a20927fb4295bac998742334ef95ec4_b.gif" title="v2-3a20927fb4295bac998742334ef95ec4_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-3a20927fb4295bac998742334ef95ec4_r.jpg" data-caption="" data-size="normal" data-rawwidth="1510" data-rawheight="516" data-thumbnail="https://pic1.zhimg.com/v2-3a20927fb4295bac998742334ef95ec4_b.jpg" class="origin_image zh-lightbox-thumb lazy" width="1510" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1510'%20height='516'&gt;&lt;/svg&gt;" data-actualsrc="https://pic1.zhimg.com/v2-3a20927fb4295bac998742334ef95ec4_b.gif" title="v2-3a20927fb4295bac998742334ef95ec4_r"></figure>
<p class="ztext-empty-paragraph"></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-f7883f4dbfe683aa74dd66185fbcb25a_r.jpg" data-caption="" data-size="normal" data-rawwidth="608" data-rawheight="638" class="origin_image zh-lightbox-thumb" width="608" data-original="https://pic3.zhimg.com/v2-f7883f4dbfe683aa74dd66185fbcb25a_b.jpg" title="v2-f7883f4dbfe683aa74dd66185fbcb25a_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-f7883f4dbfe683aa74dd66185fbcb25a_r.jpg" data-caption="" data-size="normal" data-rawwidth="608" data-rawheight="638" class="origin_image zh-lightbox-thumb lazy" width="608" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='608'%20height='638'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-f7883f4dbfe683aa74dd66185fbcb25a_b.jpg" title="v2-f7883f4dbfe683aa74dd66185fbcb25a_r"></figure>
<h3>畫布體驗</h3>
<p>當然解決了組件樹算法和佈局算法等基建問題之後， 留給可視化搭建平台的還有一個持久的挑戰是，如何打造一塊好用的畫布？因為如果自由拖拽做的不好，反而可能會導致效率低下，畫布這裡面涉及到海量的技術細節與產品設計，如：參考線、對齊、成組、分佈、拖拽、縮放，相對位置等等，本文暫不展開，後續會有專題文章介紹。</p>
<h3>畫布的邏輯表達能力</h3>
<p>雲鳳蝶沒有暴露類似HTML 或者JSX 的視圖DSL 給用戶，只提供了一塊平面的二維可視化畫布，那麼如何來表達視圖的條件，循環等邏輯呢？</p>
<p>提供“多狀態面板組件”表達if/else，switch/case 類能力</p>
<p class="ztext-empty-paragraph"></p>
<figure data-size="normal"><noscript><img decoding="async" src="" data-caption="" data-size="normal" data-rawwidth="376" data-rawheight="270" class="content_image" width="376" data-original="https://pic3.zhimg.com/v2-1557d47d56692b6b4b0aa2ca30281fa6_b.jpg"></noscript><img decoding="async" src="" data-caption="" data-size="normal" data-rawwidth="376" data-rawheight="270" class="content_image lazy" width="376" data-actualsrc="https://pic3.zhimg.com/v2-1557d47d56692b6b4b0aa2ca30281fa6_b.jpg" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='376'%20height='270'&gt;&lt;/svg&gt;"></figure>
<p>提供“重複”的高級屬性來表達forEach 的循環能力，提供“滿足條件才渲染”來表達條件能力</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-4266cb5cc648aff156f1d3e66c071a5c_r.jpg" data-caption="" data-size="normal" data-rawwidth="514" data-rawheight="350" class="origin_image zh-lightbox-thumb" width="514" data-original="https://pic1.zhimg.com/v2-4266cb5cc648aff156f1d3e66c071a5c_b.jpg" title="v2-4266cb5cc648aff156f1d3e66c071a5c_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-4266cb5cc648aff156f1d3e66c071a5c_r.jpg" data-caption="" data-size="normal" data-rawwidth="514" data-rawheight="350" class="origin_image zh-lightbox-thumb lazy" width="514" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='514'%20height='350'&gt;&lt;/svg&gt;" data-actualsrc="https://pic1.zhimg.com/v2-4266cb5cc648aff156f1d3e66c071a5c_b.jpg" title="v2-4266cb5cc648aff156f1d3e66c071a5c_r"></figure>
<h2>六、組件的共享狀態與聯動</h2>
<p>上文我們已經基本了解瞭如何通過一塊畫布生產一顆組件樹，那麼如果組件之間要聯動或者存儲狀態，這些邏輯該如何做呢？</p>
<p>前後端實現共享數據的方式一般都是通過共享內存或者打通通信渠道。前端的Redux，Mobx ，Dva 等架構也都是採取狀態外置的思路，用公共的Model 實例來存儲所有應用狀態，然後不同組件按需的讀寫，輔以一些工程化和最佳實踐的約束。</p>
<p>雲鳳蝶也不外如是，只是我們認為這些框架寫法太繁瑣，概念多，門檻高，雲鳳蝶對外置狀態管理的方案做了極致簡化。</p>
<p>如果使用過React的開發者可能對<i>state</i>和<i>setState</i>這兩個API非常熟悉，React教會我們開發一個組件只需要做三件事情：</p>
<ul>
<li>定義state</li>
<li>使用state 數據來生成試視圖</li>
<li>在必要的時候修改state， 以自動更新視圖</li>
</ul>
<p>很明顯，修改state 之後隨之而來的vdom diff 與更新都屬於自動化流程，你不需要過多關注。</p>
<p>這非常符合現實世界的隱喻，我們下班回到家只會按下控制客廳燈的開關，而不會去細究背後的走線和電路控制信號流程。</p>
<p>可惜React 還是遺留了幾個問題交給用戶自由選擇，社區也有非常多不同的優秀解決方案：</p>
<ul>
<li>多組件如何共享狀態？需要搭配Context、Redux 等方案</li>
<li>setState 修改深層屬性的時候非常痛苦。需要搭配immer、 immutablejs 等方案</li>
</ul>
<p>雲鳳蝶決定沿襲React state 的主體API 設計形態，但是要解決上面兩個問題：</p>
<ul>
<li>store 外置：狀態是永遠standalone 獨立存在的，保證single source of truth</li>
<li> store mutable：no setState，no immutable，請用你最自然舒適的方式修改數據</li>
</ul>
<p>最終雲鳳蝶決定為每個頁面都提供一個類似MMVM 架構下的Controller 角色的View Model 文件，其內容就是導出一個普通的TypeScript Class，而Class 的核心概念正好和狀態管理一一對應，美妙且自然：</p>
<ul>
<li><b>屬性（對應狀態）</b></li>
<li><b>方法（對應修改狀態的行為）</b></li>
</ul>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-ee2d9d0d71074e958425dac785113a72_r.jpg" data-caption="" data-size="normal" data-rawwidth="1320" data-rawheight="936" class="origin_image zh-lightbox-thumb" width="1320" data-original="https://pic3.zhimg.com/v2-ee2d9d0d71074e958425dac785113a72_b.jpg" title="v2-ee2d9d0d71074e958425dac785113a72_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-ee2d9d0d71074e958425dac785113a72_r.jpg" data-caption="" data-size="normal" data-rawwidth="1320" data-rawheight="936" class="origin_image zh-lightbox-thumb lazy" width="1320" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1320'%20height='936'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-ee2d9d0d71074e958425dac785113a72_b.jpg" title="v2-ee2d9d0d71074e958425dac785113a72_r"></figure>
<p>在頁面Controller 中定義好變量和方法之後，用戶可以通過屬性面板的交互操作：</p>
<ul>
<li><b>將組件的props綁定到Controller內的變量</b></li>
<li><b>將組件的event綁定到Controller內的方法</b></li>
</ul>
<p>用自然的Class 語法來聚合state + action，開發者無需再學習Redux 架構下effects，reducer 等概念和編寫大堆模板代碼，而且：</p>
<blockquote><p>voila！可以做響應式：<br />組件屬性所綁定的變量發生變化，組件會精確自動更新</p></blockquote>
<h3>Reactive 理念</h3>
<p>上文提到過，雲鳳蝶的狀態管理目標是自動化，即只需要修改狀態，不需要關注如何更新視圖，那麼如何實現這種效果呢？</p>
<p>核心架構就是<b>Reactive （響應式）和</b><b>Observable （可觀測）。</b>整個雲鳳蝶的Controller Class 都是observable 的，也就是這個class 是被Proxy 化的，雲鳳蝶的Runtime 可以追踪任意屬性的讀寫。而屬性面板的數據綁定（ <i>Button.props.text = $model.buttonText</i> ）的過程實質是在收集依賴，從而可以實現數據變化時檢查依賴列表自動精確更新視圖，達到響應式。</p>
<p>關於Observable和依賴收集理念的優越性，下面這兩張來自<a href="https://link.zhihu.com/?target=https%3A//developer.apple.com/videos/play/wwdc2019/204/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">WWDC 2019 - Session 204：Introducing SwiftUI: Building Your First App</a>的PPT詮釋得相當好：</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-accec17fc8871cf249fc04eacc510b36_r.jpg" data-caption="" data-size="normal" data-rawwidth="1112" data-rawheight="695" class="origin_image zh-lightbox-thumb" width="1112" data-original="https://pic3.zhimg.com/v2-accec17fc8871cf249fc04eacc510b36_b.jpg" title="v2-accec17fc8871cf249fc04eacc510b36_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-accec17fc8871cf249fc04eacc510b36_r.jpg" data-caption="" data-size="normal" data-rawwidth="1112" data-rawheight="695" class="origin_image zh-lightbox-thumb lazy" width="1112" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1112'%20height='695'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-accec17fc8871cf249fc04eacc510b36_b.jpg" title="v2-accec17fc8871cf249fc04eacc510b36_r"></figure>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-f2682d62704ed5d210c5b7e69fea81e9_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb" width="2880" data-original="https://pic2.zhimg.com/v2-f2682d62704ed5d210c5b7e69fea81e9_b.jpg" title="v2-f2682d62704ed5d210c5b7e69fea81e9_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-f2682d62704ed5d210c5b7e69fea81e9_r.jpg" data-caption="" data-size="normal" data-rawwidth="2880" data-rawheight="1800" class="origin_image zh-lightbox-thumb lazy" width="2880" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='2880'%20height='1800'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-f2682d62704ed5d210c5b7e69fea81e9_b.jpg" title="v2-f2682d62704ed5d210c5b7e69fea81e9_r"></figure>
<p>GUI 程序通常使用場景是處理一個長時間段的用戶交互過程，這其中不可避免會涉及到許多用戶輸入訊息，視圖臨時狀態的存儲，此外整個頁面樹上可能有多至數以百計的元素（如一個表單或表格）之間要互相通信和聯動。</p>
<p>如果按照傳統的事件驅動的編程模型，依靠程序員的大腦去掌控所有數據到視圖，數據到數據之間的衍生依賴關係，腦力負擔是非常大的，開發者小心翼翼維護著所有關聯邏輯，而一旦這個依賴複雜度超越了人腦的算力，就會導致關聯關係不正確，也就是Bug 的產生。</p>
<p>而“響應式”就是將這個依賴關係的維護交由框架來處理，開發者只需要“聲明”出依賴關係，而且這個“聲明”是指<b>在描述業務邏輯的過程中來順帶地描述出這種依賴關係，並不需要為此大動干戈</b>，比如：</p>
<ul>
<li><code>State =&gt; View</code>在定義狀態到視圖的過程中，生產視圖消費（getter）了哪些數據，就可以認為是該視圖對該數據建立了依賴（典型場景是雲鳳蝶屬性面板的數據綁定）</li>
</ul>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-011f6fc803b18692bb3d0c0bf329318c_r.jpg" data-caption="" data-size="normal" data-rawwidth="1500" data-rawheight="938" class="origin_image zh-lightbox-thumb" width="1500" data-original="https://pic1.zhimg.com/v2-011f6fc803b18692bb3d0c0bf329318c_b.jpg" title="v2-011f6fc803b18692bb3d0c0bf329318c_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-011f6fc803b18692bb3d0c0bf329318c_r.jpg" data-caption="" data-size="normal" data-rawwidth="1500" data-rawheight="938" class="origin_image zh-lightbox-thumb lazy" width="1500" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1500'%20height='938'&gt;&lt;/svg&gt;" data-actualsrc="https://pic1.zhimg.com/v2-011f6fc803b18692bb3d0c0bf329318c_b.jpg" title="v2-011f6fc803b18692bb3d0c0bf329318c_r"></figure>
<ul>
<li><code>State =&gt; Drived State</code>計算屬性的定義過程中，該屬性的結果依賴了哪些中間數據，就可以認為是該屬性對其他屬性建立了依賴</li>
</ul>
<p><b>在這個理論體系下，State始終是single source of truth，視圖只是數據的一個衍生值（Derived Value）</b> 。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-c22c58927560f3832e0f08e825398780_r.jpg" data-caption="" data-size="normal" data-rawwidth="1500" data-rawheight="938" class="origin_image zh-lightbox-thumb" width="1500" data-original="https://pic1.zhimg.com/v2-c22c58927560f3832e0f08e825398780_b.jpg" title="v2-c22c58927560f3832e0f08e825398780_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-c22c58927560f3832e0f08e825398780_r.jpg" data-caption="" data-size="normal" data-rawwidth="1500" data-rawheight="938" class="origin_image zh-lightbox-thumb lazy" width="1500" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1500'%20height='938'&gt;&lt;/svg&gt;" data-actualsrc="https://pic1.zhimg.com/v2-c22c58927560f3832e0f08e825398780_b.jpg" title="v2-c22c58927560f3832e0f08e825398780_r"></figure>
<p>雲鳳蝶採用響應式的狀態管理方案，從而使應用開發者用“<b>狀態驅動</b>”的思維替代傳統的命令驅動，開發者的腦海中始終在思考此刻控制我的視圖的數據狀態是如何，而背後衍生的視圖如何更新，需不需要create 一個div 然後append 到哪個dom 上去，則不用關注。</p>
<h3>依賴收集的實現</h3>
<p>Observable 和依賴收集已經是非常成熟的技術了，應該這個技術的框架有Vue 或者Mobx 之類，甚至iOS 最新的SwiftUI，Android 的Flutter 也是如此。這部分實現後續文章可能會專門展開來講，感興趣的可以展開閱讀下面兩個開源庫的實現：</p>
<ul>
<li><a href="https://link.zhihu.com/?target=https%3A//github.com/nx-js/observer-util" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">nx-js/observer-util</a></li>
<li> <a href="https://link.zhihu.com/?target=https%3A//github.com/alloc/wana" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">wana</a></li>
</ul>
<p>簡化來看其大致實現原理是：</p>
<ul>
<li>使用Proxy 來追踪對變量的讀與寫</li>
<li>組件渲染過程中發生讀取的的所有變量都會被記錄下來作為依賴</li>
<li>某個變量發生修改的時候，會找到所有依賴自己的組件，觸發組件的重新渲染</li>
</ul>
<p class="ztext-empty-paragraph"></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-129b804100c0980f0301c8bc98086b32_r.jpg" data-caption="" data-size="normal" data-rawwidth="593" data-rawheight="441" class="origin_image zh-lightbox-thumb" width="593" data-original="https://pic3.zhimg.com/v2-129b804100c0980f0301c8bc98086b32_b.jpg" title="v2-129b804100c0980f0301c8bc98086b32_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-129b804100c0980f0301c8bc98086b32_r.jpg" data-caption="" data-size="normal" data-rawwidth="593" data-rawheight="441" class="origin_image zh-lightbox-thumb lazy" width="593" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='593'%20height='441'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-129b804100c0980f0301c8bc98086b32_b.jpg" title="v2-129b804100c0980f0301c8bc98086b32_r"></figure>
<h3>超越手寫代碼的性能</h3>
<p>因為可視化的畫布編輯器天然隔絕了父子組件之間的props 傳遞，那麼雲鳳蝶將一個組件可能會更新的因素全部限制在屬性面板上發生的數據綁定範圍內，因此云鳳蝶可以選擇隔絕掉父子組件的級聯更新，讓整個頁面的更新性能變得極其精確。</p>
<p class="ztext-empty-paragraph"></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-b22f9900308980778990b05a8ae14c18_r.jpg" data-caption="" data-size="normal" data-rawwidth="485" data-rawheight="1002" class="origin_image zh-lightbox-thumb" width="485" data-original="https://pic1.zhimg.com/v2-b22f9900308980778990b05a8ae14c18_b.jpg" title="v2-b22f9900308980778990b05a8ae14c18_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-b22f9900308980778990b05a8ae14c18_r.jpg" data-caption="" data-size="normal" data-rawwidth="485" data-rawheight="1002" class="origin_image zh-lightbox-thumb lazy" width="485" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='485'%20height='1002'&gt;&lt;/svg&gt;" data-actualsrc="https://pic1.zhimg.com/v2-b22f9900308980778990b05a8ae14c18_b.jpg" title="v2-b22f9900308980778990b05a8ae14c18_r"></figure>
<h2>七、與服務端交互</h2>
<p>傳統的ajax 請求代碼編寫細節太多，參數返回值訊息全靠文檔。而云鳳蝶的思路是從源頭出發，採用OpenAPI 的通用規範管理API 訊息，在螞蟻內部可以通過我們提供的工具自動從JAVA 代碼裡導出這份訊息並上傳到雲鳳蝶。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-f454f6da3df0702f5cf3f6ca911121cc_r.jpg" data-caption="" data-size="normal" data-rawwidth="1500" data-rawheight="881" class="origin_image zh-lightbox-thumb" width="1500" data-original="https://pic1.zhimg.com/v2-f454f6da3df0702f5cf3f6ca911121cc_b.jpg" title="v2-f454f6da3df0702f5cf3f6ca911121cc_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-f454f6da3df0702f5cf3f6ca911121cc_r.jpg" data-caption="" data-size="normal" data-rawwidth="1500" data-rawheight="881" class="origin_image zh-lightbox-thumb lazy" width="1500" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1500'%20height='881'&gt;&lt;/svg&gt;" data-actualsrc="https://pic1.zhimg.com/v2-f454f6da3df0702f5cf3f6ca911121cc_b.jpg" title="v2-f454f6da3df0702f5cf3f6ca911121cc_r"></figure>
<p>一旦錄入OpenAPI 的接口訊息之後，開發者在頁面裡就可以一行代碼泛化調用HTTP API 了，而且附帶完整的編輯器類型提示和錯誤發現：</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-67018a914c10b1ff35802fab0d18c658_r.jpg" data-caption="" data-size="normal" data-rawwidth="1442" data-rawheight="580" class="origin_image zh-lightbox-thumb" width="1442" data-original="https://pic1.zhimg.com/v2-67018a914c10b1ff35802fab0d18c658_b.jpg" title="v2-67018a914c10b1ff35802fab0d18c658_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-67018a914c10b1ff35802fab0d18c658_r.jpg" data-caption="" data-size="normal" data-rawwidth="1442" data-rawheight="580" class="origin_image zh-lightbox-thumb lazy" width="1442" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1442'%20height='580'&gt;&lt;/svg&gt;" data-actualsrc="https://pic1.zhimg.com/v2-67018a914c10b1ff35802fab0d18c658_b.jpg" title="v2-67018a914c10b1ff35802fab0d18c658_r"></figure>
<p class="ztext-empty-paragraph"></p>
<p>基於這份訊息雲鳳蝶還可以幫助開發者做自動Mock，接口測試等等更豐富的功能。</p>
<h2>八、結語：10 倍效能提升</h2>
<p>10 倍效能提升代表著我們的美好願景，可視化搭建只是1，雲鳳蝶還將持續挖掘更多的0。</p>
<blockquote><p><a href="https://link.zhihu.com/?target=http%3A//worrydream.com/refs/Brooks-NoSilverBullet.pdf" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">No Silver Bullet – Essence and Accident in Software Engineering</a>這篇文章提到：<br /> there is no single development, in either technology or management technique, which by itself promises even one order-of-magnitude improvement within a decade in producitivity, in reliability, in simplicity.<br />並不存在某種技術或管理手段，可以保證在10 年內給軟件開發的生產力，可靠性，簡單性上帶來量級的提升。</p></blockquote>
<h3>API 驅動</h3>
<p>從CURD API 接口定義智能推導生成表格/表單/列表/詳情等頁面。</p>
<p>從數據格式描述智能推薦生成圖表。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-56791b4805c504fd2b2117037bd5a327_r.jpg" data-caption="" data-size="normal" data-rawwidth="1476" data-rawheight="1042" class="origin_image zh-lightbox-thumb" width="1476" data-original="https://pic4.zhimg.com/v2-56791b4805c504fd2b2117037bd5a327_b.jpg" title="v2-56791b4805c504fd2b2117037bd5a327_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-56791b4805c504fd2b2117037bd5a327_r.jpg" data-caption="" data-size="normal" data-rawwidth="1476" data-rawheight="1042" class="origin_image zh-lightbox-thumb lazy" width="1476" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1476'%20height='1042'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-56791b4805c504fd2b2117037bd5a327_b.jpg" title="v2-56791b4805c504fd2b2117037bd5a327_r"></figure>
<p class="ztext-empty-paragraph"></p>
<p>雲鳳蝶的可視化底盤實則擁有了一整套對Web 應用的描述DSL，不僅僅包含視圖組件樹，還包含數據綁定和交互邏輯，因此讓智能生成應用的難度太太降低，並且生成完的應用還可以被雲鳳蝶編輯器消費進行二次修改和迭代。</p>
<h3>智能還原設計稿</h3>
<ul>
<li>Ant Design 規范特徵明顯，容易訓練</li>
<li>還原成畫布元素後補充缺失交互即可上線</li>
</ul>
<h3>智能佈局</h3>
<ul>
<li>擺出大概位置，一鍵格式化成符合Ant Design 設計規範的佈局</li>
</ul>
<h3>模型驅動</h3>
<ul>
<li>只需製作業務模型，補充字段、邏輯</li>
<li>一鍵完成DB、API 和UI 的全鏈路生成</li>
<li>Low-code ⽅方式書寫後端邏輯，Serverless 部署</li>
<li>應⽤ Host，一鍵發布</li>
</ul>
<h2>相關資料</h2>
<ul>
<li><a href="https://zhuanlan.zhihu.com/p/78425921" class="internal" data-wpel-link="external" rel="nofollow external noopener noreferrer">雲鳳蝶中台研發提效實踐</a></li>
<li><a href="https://zhuanlan.zhihu.com/p/78450750" class="internal" data-wpel-link="external" rel="nofollow external noopener noreferrer">SwiftUI：Better apps. Less code.</a></li>
</ul>
<hr>
<p><b>未來已來，時不我待！</b></p>
<p>雲鳳蝶招聘前端、Java、PD、設計崗位，未來等你共創！</p>
<p>如果你感興趣，歡迎聯繫chenyu@antfin.com 或shuai.shao@antfin.com</p>
</div>
</div>
</article>
<p>The post <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com/software-engineering/front-end-dev/14789/topic-90746742/" data-wpel-link="internal">雲鳳蝶可視化搭建的推導與實現</a> appeared first on <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com" data-wpel-link="internal">成長駭客交流第一站 - HyperGrowths™</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>螞蟻中後台快速研發平台的領域思考</title>
		<link>https://hypergrowths.com/software-engineering/front-end-dev/14775/topic-90238943/</link>
		
		<dc:creator><![CDATA[marketer]]></dc:creator>
		<pubDate>Sat, 30 Jan 2021 18:18:31 +0000</pubDate>
				<category><![CDATA[前端開發]]></category>
		<category><![CDATA[支付寶體驗科技]]></category>
		<guid isPermaLink="false">https://hypergrowths.com/software-engineering/front-end-dev/14775/topic-90238943/</guid>

					<description><![CDATA[<p>概要：本文介紹了什麼是應用快速研發平台，並跟大家分享一些螞蟻的中後台快速研發平台“雲鳳蝶”在探索過程中的思考。 1. hpaPaaS 1.1 hpaPaaS 是什麼？ hpaPaaS 全稱High Productivity Application PaaS，這個詞…</p>
<p>The post <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com/software-engineering/front-end-dev/14775/topic-90238943/" data-wpel-link="internal">螞蟻中後台快速研發平台的領域思考</a> appeared first on <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com" data-wpel-link="internal">成長駭客交流第一站 - HyperGrowths™</a>.</p>
]]></description>
										<content:encoded><![CDATA[<article class="Post-Main Post-NormalMain" tabindex="-1">
<header class="Post-Header">
<h1 class="Post-Title">螞蟻中後台快速研發平台的領域思考</h1>
<div class="Post-Author">
<div class="AuthorInfo" itemprop="author" itemscope="" itemtype="http://schema.org/Person"><meta itemprop="name" content="杨周璇"><meta itemprop="image" content="https://pic4.zhimg.com/d9b1977ec_l.jpg?source=172ae18b"><meta itemprop="url" content="https://www.zhihu.com/people/fool2fish"><meta itemprop="zhihu:followerCount"></div>
</div>
</header>
<div class="Post-RichTextContainer">
<div class="RichText ztext Post-RichText">
<p>概要：本文介紹了什麼是應用快速研發平台，並跟大家分享一些螞蟻的中後台快速研發平台“雲鳳蝶”在探索過程中的思考。</p>
<h2>1. hpaPaaS</h2>
<p><b>1.1 hpaPaaS是什麼？</b></p>
<p> hpaPaaS 全稱High Productivity Application PaaS，這個詞實際上是由造概念老手Gartner 在2018 年初提出來的，除了hpaPaaS，讀者可能還聽說過RAD（Rapid Application Develop）、LowCode/NoCode、LCAP（LowCode Application Platform）等等概念，包括特別接地氣的可視化建站、應用搭建等等多到無法一一列舉，我們先不糾結這些概念之間的差異，本文中，可以認為它們是一碼事。文章標題中提到的雲鳳蝶等均屬於hpaPaaS 類產品，要了解這些產品，我們需要先對hpaPaaS 有一個概要的理解。</p>
<p>簡單點說， <b>hpaPaaS是一個對應用研發進行全生命週期管理的平台，這個平台定義了這樣一種研發模式：在較強的設計、研發規範下，通過可視化拖拽、模型驅動等技術顯著降低研發門檻、提升研發效率、保障基本品質。</b></p>
<p><b>1.2 hpaPaaS發展簡史</b></p>
<p>hpaPaaS 並不是一種新東西，早在1980 年代開始就出現萌芽，而在1999 年創建的salesforce 至今仍是這個行業的領頭羊，高達百億（美金）市值。早期的這些產品希望<b>通過一定的約束（如能力、交互、性能等），以降低開發人員的總體技能要求，換取應用的快速迭代</b>。它們與當時的其他創新技術一同迅猛發展，例如IDE（集成開發環境）、GUI（圖形用戶界面）、CS 架構（客戶端服務端架構）等。特別值得一提的是，它們在當時就已經採用了<b>可視化拖拽、圖形建模、內置框架、組件模板</b>等方案。</p>
<p>在此期間，某些行業標準的可視化模型得到了發展，尤其是針對應用的（如數據的實體關係、對像管理的類圖、用於流程管理的流程模型和狀態機的狀態轉換圖），這些技術開拓了模型驅動的應用研發市場，典型的有BPMS(business process management systems / 業務流程管理系統）等。</p>
<p>以今天的眼光來看，hpaPaaS 要解決的問題以及解決問題的方案跟幾十年前並沒有本質上的區別，這也是為什麼讀者可能會覺得這類產品都很類似，這類產品通常都具有多端支持、創建複雜表單、工作流、應用管理等基礎特性。但是hpaPaaS 在近幾年發展又開始出現新一輪的浪潮（不然Gartner 也不會為它專門造個詞出來了），如果讀者用過不同時代的產品，例如salesforce 和mendix，就會發現兩者之間的體驗差異是非常巨大的。這得益於WEB 設計和開發、雲技術、人工智能的發展和成熟。此前，hpaPaaS 只能做一些簡單、固化的應用，例如行政管理系統，但現在，它逐漸能勝任更複雜的場景，包括2B 的企業級應用，甚至部分2C 的應用。<b>對於研發部門來說，是時候把hpaPaaS作為應用研發的一個常規選項了。而如何選擇一個適合自己的hpaPaaS，則可能需要進行一些更細緻的考察，</b>例如：可視化拖拽到底是怎麼拖拽的，支持ProCode到底是怎麼支持的？</p>
<p>下圖是Gartner 在2019 年發布的hpaPaaS 魔力像限，可以一窺整個行業的情況，細節就不在此贅述了。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-53d6b297ff7681fa2b79d902c6b9fdf9_r.jpg" data-caption="" data-size="normal" data-rawwidth="1494" data-rawheight="862" class="origin_image zh-lightbox-thumb" width="1494" data-original="https://pic2.zhimg.com/v2-53d6b297ff7681fa2b79d902c6b9fdf9_b.jpg" title="v2-53d6b297ff7681fa2b79d902c6b9fdf9_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-53d6b297ff7681fa2b79d902c6b9fdf9_r.jpg" data-caption="" data-size="normal" data-rawwidth="1494" data-rawheight="862" class="origin_image zh-lightbox-thumb lazy" width="1494" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1494'%20height='862'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-53d6b297ff7681fa2b79d902c6b9fdf9_b.jpg" title="v2-53d6b297ff7681fa2b79d902c6b9fdf9_r"></figure>
<p><b>1.3 hpaPaaS適用範圍</b></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-1d14a190c0afeacabd7bea18aeee6fcb_r.jpg" data-caption="" data-size="normal" data-rawwidth="926" data-rawheight="872" class="origin_image zh-lightbox-thumb" width="926" data-original="https://pic4.zhimg.com/v2-1d14a190c0afeacabd7bea18aeee6fcb_b.jpg" title="v2-1d14a190c0afeacabd7bea18aeee6fcb_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-1d14a190c0afeacabd7bea18aeee6fcb_r.jpg" data-caption="" data-size="normal" data-rawwidth="926" data-rawheight="872" class="origin_image zh-lightbox-thumb lazy" width="926" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='926'%20height='872'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-1d14a190c0afeacabd7bea18aeee6fcb_b.jpg" title="v2-1d14a190c0afeacabd7bea18aeee6fcb_r"></figure>
<p>hpaPaaS是否使用主要取決於<b>用戶規模</b>和<b>功能特殊性</b>兩個因素。根據這兩個因素對應用進行分級是使用hpaPaaS 非常關鍵的一步。在未來，大部分應用都全部或部分使用hpaPaaS 開發。</p>
<p><b>適用場景舉例</b></p>
<ul>
<li>常規CRUD 應用，特別是研發資源緊缺或上線時間緊迫的</li>
<li>混合研發應用，如有大量常規頁面和個別特別複雜頁面的應用</li>
<li>工作流程</li>
<li>一次性應用，如年會抽獎、問卷調查等</li>
<li>原型應用，用以驗證想法可行性的</li>
<li>初創應用，研發節奏快，需要根據用戶反應快速調整的</li>
</ul>
<p>此外還有一些hpaPaaS 專注於解決某個領域問題，如多端適配的企業門戶建站，辦公應用等。</p>
<p><b>不適用場景舉例</b></p>
<ul>
<li>有很多特殊的功能需要專業的研發人員通過編碼實現，如WEB IDE</li>
<li>對體驗和性能有極致要求的應用</li>
<li>大規模應用，如淘寶網</li>
</ul>
<p><b>注意事項</b></p>
<ul>
<li>這類產品一般跟廠商深度綁定，會深度整合所在廠商的產品和服務</li>
<li>要對所選的hpaPaaS 能力範圍有清晰的了解，確保能力範圍能滿足你的需求</li>
</ul>
<p><b>1.4為什麼要選擇hpaPaaS</b></p>
<ol>
<li>提升研發、交付速度，在市場競爭中獲得先機</li>
<li>降低研發門檻，解決招聘難的問題</li>
<li>降低企業用人成本</li>
<li>優化企業人才結構，業務研發和技術專家各自有明確的發展線路</li>
<li>保障應用的基本品質</li>
<li>獲得能力增強，自己就能完成或更快更好的完成研發工作</li>
<li>從繁冗的日常研發中解放出來，專注於有挑戰的工作</li>
</ol>
<p><b>1.5如何選擇一個合適的hpaPaaS</b></p>
<p>下表列出了hpaPaaS 主要的基礎功能，可以通過逐項檢查這個表格的條目，以挑選出符合業務需求的產品。</p>
<ol>
<li>產品定位</li>
<ol>
<li>目標用戶</li>
<li>目標場景：通用場景，還是某個特定場景</li>
<li>覆蓋研發鏈路：前端、後端、監控運維</li>
<li>核心優勢</li>
</ol>
<li>前端研發</li>
<ol>
<li>可視化拖拽UI</li>
<li>數據驅動UI：通過接口、模型等生成UI</li>
<li>內置UI 資產：組件、模板</li>
<li>自定義UI 資產</li>
<li>客戶端支持：可創建PC WEB、移動端、小程序應用...</li>
<li>多端適配：一次開發，多客戶端運行</li>
<li>混合研發部分頁面用hpaPaaS 開發，部分頁面用ProCode 研發，混合部署成一個應用</li>
<li>埋點監控</li>
</ol>
<li>後端研發</li>
<ol>
<li>應用託管</li>
<li>用戶和權限：接入不同的用戶登錄方式，提供垂直權限管控</li>
<li>數據連接：HTTP(S)、TR、數據源、各種雲服務...</li>
<li>邏輯編寫</li>
<li>可視化業務建模</li>
<li>流程編排</li>
</ol>
<li>監控運維</li>
<ol>
<li>部署類型：統一部署、私有部署</li>
<li>發布三板斧：可監控、可灰度、可回滾</li>
<li>監控運維</li>
</ol>
<li>其他</li>
<ol>
<li>多人協作</li>
<li>版本控制</li>
<li>國際化</li>
</ol>
</ol>
<h2>2. 雲鳳蝶是什麼</h2>
<p>我們先通過一段視頻來快速了解一下云鳳蝶：</p>
<p><a class="video-box" href="https://link.zhihu.com/?target=https%3A//www.zhihu.com/video/1175084528170901504" target="_blank" data-video-id="" data-video-playable="true" data-name="" data-poster="https://pic4.zhimg.com/v2-f5f2d9f7c419b186a3f352a4666fede7.jpg" data-lens-id="1175084528170901504" rel="noopener nofollow external noreferrer" data-wpel-link="external"><img decoding="async" class="thumbnail" src="" data-original="https://pic4.zhimg.com/v2-f5f2d9f7c419b186a3f352a4666fede7.jpg"><span class="content"><span class="url">https://www.zhihu.com/video/1175084528170901504</span></span></a></p>
<p>正如上面介紹所說，雲鳳蝶是一個hpaPaaS，目標是為中後台應用研發提供簡單、高效、高質量的研發方案。用雲鳳蝶，不僅是前後端，甚至PD、設計師都能直接參與研發工作。</p>
<h2>3. 雲鳳蝶對中後台應用研發的思考</h2>
<p>雲鳳蝶上半年的重心主要在前端能力的建設上，在不斷的嘗試和總結中逐漸明確了四個核心能力。</p>
<p><b>3.1自由拖拽的畫布</b></p>
<p><a class="video-box" href="https://link.zhihu.com/?target=https%3A//www.zhihu.com/video/1175086960807514112" target="_blank" data-video-id="" data-video-playable="true" data-name="" data-poster="https://pic4.zhimg.com/v2-6754cb338559482deea413ec954253c7.jpg" data-lens-id="1175086960807514112" rel="noopener nofollow external noreferrer" data-wpel-link="external"><img decoding="async" class="thumbnail" src="" data-original="https://pic4.zhimg.com/v2-6754cb338559482deea413ec954253c7.jpg"><span class="content"><span class="url">https://www.zhihu.com/video/1175086960807514112</span></span></a></p>
<p>上圖簡單演示了在雲鳳蝶中製作一個帶操作按鈕和搜索按鈕的表格製作過程，我們可以看到過程十分的簡單（而且基本上不可能有更簡單的方式），有那麼點兒像做PPT，當然還需要進行少量的佈局設置，就可以看到頁面能很好的自適應的變化。</p>
<p><b>自由拖拽的優勢非常明顯：使用門檻特別低，幾乎無需學習；另外一個優勢是操作確定性高，你把一個元素放下去之後，這個頁面會變成什麼樣是非常清楚的。</b></p>
<p>但自由拖拽也有讓人吐槽的地方：那就是精確拖拽的效率不高。針對這個問題云鳳蝶做了不少改進，除了上圖中的測距與吸附，還有對齊與分佈</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-ef1ee2c6c3d4ee164c3689dc3e00f83b_r.jpg" data-caption="" data-size="normal" data-rawwidth="481" data-rawheight="187" data-thumbnail="https://pic4.zhimg.com/v2-ef1ee2c6c3d4ee164c3689dc3e00f83b_b.jpg" class="origin_image zh-lightbox-thumb" width="481" data-original="https://pic4.zhimg.com/v2-ef1ee2c6c3d4ee164c3689dc3e00f83b_b.gif" title="v2-ef1ee2c6c3d4ee164c3689dc3e00f83b_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-ef1ee2c6c3d4ee164c3689dc3e00f83b_r.jpg" data-caption="" data-size="normal" data-rawwidth="481" data-rawheight="187" data-thumbnail="https://pic4.zhimg.com/v2-ef1ee2c6c3d4ee164c3689dc3e00f83b_b.jpg" class="origin_image zh-lightbox-thumb lazy" width="481" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='481'%20height='187'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-ef1ee2c6c3d4ee164c3689dc3e00f83b_b.gif" title="v2-ef1ee2c6c3d4ee164c3689dc3e00f83b_r"></figure>
<p>雲鳳蝶還有一個非常有特色的功能是使用了相對定位系統。我們知道在製作頁面的過程中，擺放一個元素，開發者的心裡面其實是有參考物的，比如“在表格的上面放一個右對齊的按鈕”中的表格就是那個參照物，所以使用相對定位就會非常簡單高效。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-9abdbd104cfb7fcc14e1fe83af83a271_r.jpg" data-caption="" data-size="normal" data-rawwidth="666" data-rawheight="356" data-thumbnail="https://pic2.zhimg.com/v2-9abdbd104cfb7fcc14e1fe83af83a271_b.jpg" class="origin_image zh-lightbox-thumb" width="666" data-original="https://pic2.zhimg.com/v2-9abdbd104cfb7fcc14e1fe83af83a271_b.gif" title="v2-9abdbd104cfb7fcc14e1fe83af83a271_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-9abdbd104cfb7fcc14e1fe83af83a271_r.jpg" data-caption="" data-size="normal" data-rawwidth="666" data-rawheight="356" data-thumbnail="https://pic2.zhimg.com/v2-9abdbd104cfb7fcc14e1fe83af83a271_b.jpg" class="origin_image zh-lightbox-thumb lazy" width="666" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='666'%20height='356'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-9abdbd104cfb7fcc14e1fe83af83a271_b.gif" title="v2-9abdbd104cfb7fcc14e1fe83af83a271_r"></figure>
<p>在PC 頁面的做作過程中，佈局中最難的就是處理頁面寬度變化時頁面中的元素如何變化的問題。雲鳳蝶採用了一個非常簡單的佈局模型，如下圖所示，用戶只需要指定一個元素的尺寸和間距是固定的還是自適應的即可，完全無需了解CSS。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-8bb170605197c69c793d7d2b44d7e808_r.jpg" data-caption="" data-size="normal" data-rawwidth="594" data-rawheight="474" class="origin_image zh-lightbox-thumb" width="594" data-original="https://pic1.zhimg.com/v2-8bb170605197c69c793d7d2b44d7e808_b.jpg" title="v2-8bb170605197c69c793d7d2b44d7e808_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-8bb170605197c69c793d7d2b44d7e808_r.jpg" data-caption="" data-size="normal" data-rawwidth="594" data-rawheight="474" class="origin_image zh-lightbox-thumb lazy" width="594" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='594'%20height='474'&gt;&lt;/svg&gt;" data-actualsrc="https://pic1.zhimg.com/v2-8bb170605197c69c793d7d2b44d7e808_b.jpg" title="v2-8bb170605197c69c793d7d2b44d7e808_r"></figure>
<p>而這些都還不夠，其實雲鳳蝶完全可以做到用戶不需要關心佈局這件事情。當給到工程師一張設計稿的時候，設計稿中的組件隨頁面寬度如何變化基本是心中有數的，雲鳳蝶只要把這種開工程師潛意識中的轉換邏輯給找出來，就能做到根據頁面元素的擺放關係自動計算這些設置，想想是不是很酷？</p>
<p><b>3.2開箱即用的精品UI資產</b></p>
<p>雲鳳蝶認為，好的基礎資產應該能滿足應用研發的大部分的需求（大量長尾用戶可能也僅僅會用到這部分），其次是少量的業務資產，而自定義資產只佔非常小的比例。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-1442ee5ec25c5faac3903484bbbde161_r.jpg" data-caption="" data-size="normal" data-rawwidth="880" data-rawheight="584" class="origin_image zh-lightbox-thumb" width="880" data-original="https://pic2.zhimg.com/v2-1442ee5ec25c5faac3903484bbbde161_b.jpg" title="v2-1442ee5ec25c5faac3903484bbbde161_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-1442ee5ec25c5faac3903484bbbde161_r.jpg" data-caption="" data-size="normal" data-rawwidth="880" data-rawheight="584" class="origin_image zh-lightbox-thumb lazy" width="880" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='880'%20height='584'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-1442ee5ec25c5faac3903484bbbde161_b.jpg" title="v2-1442ee5ec25c5faac3903484bbbde161_r"></figure>
<p>開箱即用的基礎資產對應用研發的提效是至關重要的，所以雲鳳蝶全量全能力內置了<a href="https://link.zhihu.com/?target=https%3A//ant.design/index-cn" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Ant Design</a>和<a href="https://link.zhihu.com/?target=http%3A//antv.alipay.com/zh-cn/index.html" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">AntV</a> ，還有金融科技的業務資產庫TechUI。<br />其中<a href="https://link.zhihu.com/?target=https%3A//ant.design/index-cn" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Ant Design</a>是螞蟻的中後台組件庫，擁有全球最高熱度。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-d76745ffa3eaea9f4bbf762fc7b5b349_r.jpg" data-caption="" data-size="normal" data-rawwidth="1120" data-rawheight="72" class="origin_image zh-lightbox-thumb" width="1120" data-original="https://pic2.zhimg.com/v2-d76745ffa3eaea9f4bbf762fc7b5b349_b.png" title="v2-d76745ffa3eaea9f4bbf762fc7b5b349_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-d76745ffa3eaea9f4bbf762fc7b5b349_r.jpg" data-caption="" data-size="normal" data-rawwidth="1120" data-rawheight="72" class="origin_image zh-lightbox-thumb lazy" width="1120" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1120'%20height='72'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-d76745ffa3eaea9f4bbf762fc7b5b349_b.png" title="v2-d76745ffa3eaea9f4bbf762fc7b5b349_r"></figure>
<p>而<a href="https://link.zhihu.com/?target=http%3A//antv.alipay.com/zh-cn/index.html" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">AntV</a>是螞蟻的可視化解決方案，包含常見圖表，關係圖及地圖等等。<br />這兩者都代表了行業頂尖水平。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-41ea4d8e4c5ebd9a49d5aba607795770_r.jpg" data-caption="" data-size="normal" data-rawwidth="1108" data-rawheight="1150" class="origin_image zh-lightbox-thumb" width="1108" data-original="https://pic1.zhimg.com/v2-41ea4d8e4c5ebd9a49d5aba607795770_b.jpg" title="v2-41ea4d8e4c5ebd9a49d5aba607795770_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-41ea4d8e4c5ebd9a49d5aba607795770_r.jpg" data-caption="" data-size="normal" data-rawwidth="1108" data-rawheight="1150" class="origin_image zh-lightbox-thumb lazy" width="1108" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1108'%20height='1150'&gt;&lt;/svg&gt;" data-actualsrc="https://pic1.zhimg.com/v2-41ea4d8e4c5ebd9a49d5aba607795770_b.jpg" title="v2-41ea4d8e4c5ebd9a49d5aba607795770_r"></figure>
<p>自定義資產只佔非常小的比例，但是如果沒有辦法製作自定義資產或者製作成本特別高，會讓用戶放棄使用。同時，在ProCode的世界已經有大量優質的資產（包括<a href="https://link.zhihu.com/?target=https%3A//ant.design/index-cn" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Ant Design</a>和<a href="https://link.zhihu.com/?target=http%3A//antv.alipay.com/zh-cn/index.html" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">AntV</a> ），如果不能以非常低的成本拿來使用那將是非常可惜的事情。所以雲鳳蝶花了很大的精力去做npm 組件一鍵導入，用以構建內置的資產，並以同樣的方式支持用戶沉澱自己的業務資產和自定義資產。</p>
<p><a class="video-box" href="https://link.zhihu.com/?target=https%3A//www.zhihu.com/video/1175448837732425728" target="_blank" data-video-id="" data-video-playable="true" data-name="" data-poster="https://pic4.zhimg.com/v2-5c45b4426154313e858fdaf0c31e8bbf.jpg" data-lens-id="1175448837732425728" rel="noopener nofollow external noreferrer" data-wpel-link="external"><img decoding="async" class="thumbnail" src="" data-original="https://pic4.zhimg.com/v2-5c45b4426154313e858fdaf0c31e8bbf.jpg"><span class="content"><span class="url">https://www.zhihu.com/video/1175448837732425728</span></span></a></p>
<p>UI 資產對研發的提效是毋庸置疑的，但時常令人矛盾的一個點是：資產粒度越小，復用度越高，但用起來越麻煩，資產粒度越大，用起來越簡單，但復用度就非常低。這也是為什麼提供了很多模板，但是用戶使用起來，還是要做大量修改（行業沉澱另當別論）。雲鳳蝶希望能解決這個問題，因此投入了大量精力去做第三個核心能力：<b>數據/接口/模型驅動。</b></p>
<p><b>3.3數據/接口/模型驅動UI</b></p>
<p>雲鳳蝶認為<b>不僅僅是業務模型，所有數據來源都可以驅動UI</b> 。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-ff0a0dc94b0c682f47ae55e3178f9949_r.jpg" data-caption="" data-size="normal" data-rawwidth="840" data-rawheight="774" class="origin_image zh-lightbox-thumb" width="840" data-original="https://pic2.zhimg.com/v2-ff0a0dc94b0c682f47ae55e3178f9949_b.jpg" title="v2-ff0a0dc94b0c682f47ae55e3178f9949_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-ff0a0dc94b0c682f47ae55e3178f9949_r.jpg" data-caption="" data-size="normal" data-rawwidth="840" data-rawheight="774" class="origin_image zh-lightbox-thumb lazy" width="840" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='840'%20height='774'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-ff0a0dc94b0c682f47ae55e3178f9949_b.jpg" title="v2-ff0a0dc94b0c682f47ae55e3178f9949_r"></figure>
<p>而表單生成的過程也十分簡單，僅需3 步：</p>
<ol>
<li>選擇數據/接口/模型</li>
<li>選擇用戶需要填寫的表單項</li>
<li>配置表單項</li>
</ol>
<p>在下圖的最右邊會實時顯示表單的生成結果</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-7501bac147fecc82cd30c427f00a9903_r.jpg" data-caption="" data-size="normal" data-rawwidth="1492" data-rawheight="895" class="origin_image zh-lightbox-thumb" width="1492" data-original="https://pic4.zhimg.com/v2-7501bac147fecc82cd30c427f00a9903_b.jpg" title="v2-7501bac147fecc82cd30c427f00a9903_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-7501bac147fecc82cd30c427f00a9903_r.jpg" data-caption="" data-size="normal" data-rawwidth="1492" data-rawheight="895" class="origin_image zh-lightbox-thumb lazy" width="1492" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1492'%20height='895'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-7501bac147fecc82cd30c427f00a9903_b.jpg" title="v2-7501bac147fecc82cd30c427f00a9903_r"></figure>
<p>這是一個表單生成的動圖</p>
<p><a class="video-box" href="https://link.zhihu.com/?target=https%3A//www.zhihu.com/video/1175090994339655680" target="_blank" data-video-id="" data-video-playable="true" data-name="" data-poster="https://pic3.zhimg.com/v2-e662b4bde07f65388efb291375c5ecde.jpg" data-lens-id="1175090994339655680" rel="noopener nofollow external noreferrer" data-wpel-link="external"><img decoding="async" class="thumbnail" src="" data-original="https://pic3.zhimg.com/v2-e662b4bde07f65388efb291375c5ecde.jpg"><span class="content"><span class="url">https://www.zhihu.com/video/1175090994339655680</span></span></a></p>
<p>根據數據所處的頁面環境、元訊息以及特徵自動生成符合設計標準且美觀的UI，連Loading 這種瑣細但非常體現品質感的細節也一一為用戶處理好。用戶只需要關注業務本身，就能以十倍效率製作出高質量的頁面。</p>
<p>更有趣的是這個能力讓雲鳳蝶對用戶的業務有所理解，就有可能自動進行業務的監控分析，給到業務全面及時的反饋。</p>
<p><b>3.4混合研發</b></p>
<p>對於一些無法一次性遷移的存量應用，或者僅有少量特殊頁面的應用，雲鳳蝶提供了部分使用雲鳳蝶部分使用ProCode 的混合研發能力。像雲鳳蝶自身即是如此，編輯器使用ProCode 研發，其餘頁面使用雲鳳蝶研發。這樣能推進老業務的升級，並能讓開發者為每個頁面選擇合適的研發模式。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-1daec30ebd63ea4df9c462aa8fd67686_r.jpg" data-caption="" data-size="normal" data-rawwidth="1492" data-rawheight="451" class="origin_image zh-lightbox-thumb" width="1492" data-original="https://pic3.zhimg.com/v2-1daec30ebd63ea4df9c462aa8fd67686_b.jpg" title="v2-1daec30ebd63ea4df9c462aa8fd67686_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-1daec30ebd63ea4df9c462aa8fd67686_r.jpg" data-caption="" data-size="normal" data-rawwidth="1492" data-rawheight="451" class="origin_image zh-lightbox-thumb lazy" width="1492" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1492'%20height='451'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-1daec30ebd63ea4df9c462aa8fd67686_b.jpg" title="v2-1daec30ebd63ea4df9c462aa8fd67686_r"></figure>
<p class="ztext-empty-paragraph"></p>
<p><b>最後說一說踩過的坑或一些經驗</b>（其實道理說出來大家都懂，總要自己撞過牆才知道：）</p>
<ol>
<li><b>最最最重要的是要明確產品的定位</b>。即使是在hpaPaaS 這個領域裡，也有非常多的細分場景：是全流程研發還是僅解決部分問題？是面向開發者還是非開發者？要開發的應用是不是有設計師介入？應用的外觀和交互是否遵循統一的標準？等等這些問題，如果沒有明確的答案那是必定會失敗的，因為僅僅是面向開發者或非開發者這一因素帶來的產品差異都非常大。雲鳳蝶的定位是通用中後台應用的研發，但在初期承接了一個門戶類的應用研發，不僅做的非常狼狽，最後業務方還不買單又用procode 重新做了一套。</li>
<li><b>要明確產品的核心競爭力</b>。 hpaPaaS 的基礎能力都非常類似的，明確自己的核心競爭力並做到極致，才能牢牢抓住這部分目標用戶的心。例如雲鳳蝶在產品最初就明確了一個非常重要的產品原則：和procode 的世界要打通。這不僅體現在npm 組件包可以一鍵導入，還體驗在procode 研發的應用可以和雲鳳蝶研發的應用混合部署等特性上。這在很多hpaPaaS 中是沒有也是不必要的，但是雲鳳蝶服務的場景比較複雜，這個產品原則就很好地提振了開發者的信心，知道他想要的東西即使雲鳳蝶中沒有現成的也能很容易從procode 的世界導入使用。</li>
<li><b>要有足夠的耐心</b>。因為hpaPaaS 的最小feature 集比較大，所以這類產品的孵化期一般需要1 到2 年，這跟一般的互聯網產品來說是非常長的，所以如何做好規劃，一步步拿到階段性的成果非常重要，否則不僅團隊的士氣很容易受到打擊，老闆也可能因為看不到希望把項目給咔嚓掉。</li>
<li><b>要有優秀的架構</b>。 hpaPaaS 的代碼量級基本是十萬起步的，如果沒有一個特別優秀的架構，用不了多久就會發現代碼無法維護了，即使是加人也不知道代碼該從何寫起。雲鳳蝶的代碼也一度出現改不動的情況，後來在幾個大項目的推動下對整體的代碼架構都進行了升級，情況才得到了明顯改善。</li>
<li><b>體驗決定成敗</b>。 hpaPaaS 本質上是一個效率工具，它是通過提供優秀的研發體驗來降低研發門檻和提升研發效率。例如可視化拖拽是很好的降低開發門檻的方式，但是如果拖拽的體驗非常差，用戶就會放棄使用；需求超出產品能力的時候，是不是有很低成本的方式來解決等等都是需要仔細打磨的點。一旦研發體驗非常優秀，就能產生非常大的用戶粘性。</li>
</ol>
<h2>4. 中後台應用研發的未來</h2>
<p>隨著hpaPaaS 逐步發展成熟，未來的研發格局將會發生轉變。首先有大量應用全部或部分使用hpaPaaS 研發，同時公司的人才結構將會得到優化，技術專家更專注於技術，產品工程師更專注於業務，兩者都有明確的發展路線。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-88a36bd4f5f577803441e9e88fed3753_r.jpg" data-caption="" data-size="normal" data-rawwidth="1492" data-rawheight="774" class="origin_image zh-lightbox-thumb" width="1492" data-original="https://pic4.zhimg.com/v2-88a36bd4f5f577803441e9e88fed3753_b.jpg" title="v2-88a36bd4f5f577803441e9e88fed3753_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-88a36bd4f5f577803441e9e88fed3753_r.jpg" data-caption="" data-size="normal" data-rawwidth="1492" data-rawheight="774" class="origin_image zh-lightbox-thumb lazy" width="1492" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1492'%20height='774'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-88a36bd4f5f577803441e9e88fed3753_b.jpg" title="v2-88a36bd4f5f577803441e9e88fed3753_r"></figure>
<hr>
<p><b>未來已來，時不我待！</b><br />雲鳳蝶目前在高速發展中，急需各路前端、Java、PD、設計大神加盟，未來等你共創！<br />簡歷請發送給沉魚chenyu@antfin.com</p>
</div>
</div>
</article>
<p>The post <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com/software-engineering/front-end-dev/14775/topic-90238943/" data-wpel-link="internal">螞蟻中後台快速研發平台的領域思考</a> appeared first on <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com" data-wpel-link="internal">成長駭客交流第一站 - HyperGrowths™</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>雲鳳蝶中台研發提效實踐</title>
		<link>https://hypergrowths.com/software-engineering/front-end-dev/14540/topic-78425921/</link>
		
		<dc:creator><![CDATA[marketer]]></dc:creator>
		<pubDate>Sat, 30 Jan 2021 18:09:11 +0000</pubDate>
				<category><![CDATA[前端開發]]></category>
		<category><![CDATA[支付寶體驗科技]]></category>
		<guid isPermaLink="false">https://hypergrowths.com/software-engineering/front-end-dev/14540/topic-78425921/</guid>

					<description><![CDATA[<p>最近我們在螞蟻內部發布了全新雲鳳蝶2.0，把產品的重點由H5 搭建徹底轉向了中台方向。使用雲鳳蝶， 快速製作高品質中台應用。我們目前聚焦於以下三個方面來服務中台業務： 降門檻讓更多人進的來參與中台建設提…</p>
<p>The post <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com/software-engineering/front-end-dev/14540/topic-78425921/" data-wpel-link="internal">雲鳳蝶中台研發提效實踐</a> appeared first on <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com" data-wpel-link="internal">成長駭客交流第一站 - HyperGrowths™</a>.</p>
]]></description>
										<content:encoded><![CDATA[<article class="Post-Main Post-NormalMain" tabindex="-1">
<header class="Post-Header">
<h1 class="Post-Title">雲鳳蝶中台研發提效實踐</h1>
<div class="Post-Author">
<div class="AuthorInfo" itemprop="author" itemscope="" itemtype="http://schema.org/Person"><meta itemprop="name" content="邵帅"><meta itemprop="image" content="https://pic1.zhimg.com/c599c6a82_l.jpg?source=172ae18b"><meta itemprop="url" content="https://www.zhihu.com/people/shao-shuai-97-32"><meta itemprop="zhihu:followerCount"></div>
</div>
</header>
<div class="Post-RichTextContainer">
<div class="RichText ztext Post-RichText">
<p>最近我們在螞蟻內部發布了全新雲鳳蝶2.0，把產品的重點由H5 搭建徹底轉向了中台方向。使用雲鳳蝶，<b>快速製作高品質中台應用</b>。</p>
<p>我們目前聚焦於以下三個方面來服務中台業務：</p>
<ul>
<li><b>降門檻</b>讓更多人進的來參與中台建設</li>
<li><b>提效</b>是否可以做到10倍提效？</li>
<li><b>提升體驗</b>設計規範自動化落地，默認好用</li>
</ul>
<p>本文主要探討雲鳳蝶對於中台提效的理解，從研發模式的角度來看，我們對於十倍提效的達成思路。</p>
<h2>1. 中台應用分層模型</h2>
<p>相信不少同學聽說過<a href="https://zhuanlan.zhihu.com/p/35645859" class="internal" data-wpel-link="external" rel="nofollow external noopener noreferrer">用戶體驗五要素</a>，一個中台產品的從想法到實現落地，也是一個近似的分層模型。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-91da4f10500f80c1def33d3f6964638f_r.jpg" data-size="normal" data-rawwidth="1492" data-rawheight="1083" class="origin_image zh-lightbox-thumb" width="1492" data-original="https://pic4.zhimg.com/v2-91da4f10500f80c1def33d3f6964638f_b.jpg" title="v2-91da4f10500f80c1def33d3f6964638f_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-91da4f10500f80c1def33d3f6964638f_r.jpg" data-size="normal" data-rawwidth="1492" data-rawheight="1083" class="origin_image zh-lightbox-thumb lazy" width="1492" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1492'%20height='1083'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-91da4f10500f80c1def33d3f6964638f_b.jpg" title="v2-91da4f10500f80c1def33d3f6964638f_r"><figcaption>中台應用分層模型</figcaption></figure>
<p>這不僅是一個過程模型，也是實現模型，如今我們寫代碼也是這麼來寫的：</p>
<ul>
<li><b>需求層</b>描述產品目標、功能範圍，以人的視角詮釋原始需求。目前還沒有形式化語言支撐，以PRD 的形式流轉於word 文檔和語雀平台。產品經理工作在這一層。</li>
<li><b>模型層</b>把所有業務概念和操作用形式化系統表述，把需求映射到計算機可理解的格式。這裡是一個比較泛的分層模式，可以簡單理解為充血的廣義模型，涵蓋了多層傳統分層。後端工程師工作在這一層。</li>
<li> <b>API層</b>把所有的業務數據形式化，由於BS架構形成了天然邊界。後端工程師工作在這一層。</li>
<li><b>展現層</b>把所有的內容視覺化，使用交互承載所有的業務操作。產品經理、設計師和前端工程師工作在這一層。</li>
</ul>
<p>在這樣一個中台分層模型中，越靠上的部分細節越豐富，而越靠下的部分越靠近用於原始訴求，越簡潔抽象。</p>
<p>基於這樣一個分層模型，我們來思考，現有的研發模式是否足夠高效。</p>
<h2>2. 層間關係</h2>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-925e5fd228b4ba660773b658c02caf23_r.jpg" data-caption="" data-size="normal" data-rawwidth="1492" data-rawheight="1130" class="origin_image zh-lightbox-thumb" width="1492" data-original="https://pic4.zhimg.com/v2-925e5fd228b4ba660773b658c02caf23_b.jpg" title="v2-925e5fd228b4ba660773b658c02caf23_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-925e5fd228b4ba660773b658c02caf23_r.jpg" data-caption="" data-size="normal" data-rawwidth="1492" data-rawheight="1130" class="origin_image zh-lightbox-thumb lazy" width="1492" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1492'%20height='1130'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-925e5fd228b4ba660773b658c02caf23_b.jpg" title="v2-925e5fd228b4ba660773b658c02caf23_r"></figure>
<h3>2.1 層間具有推導性</h3>
<p>一般來說下層一定程度上可推導出下層，上層一定要遵循下層約束。</p>
<p>例如需求層約束單筆轉賬金額小於1 萬元，那麼模型層一定會遵循這個約束，絕對不會允許大於1 萬元的轉賬發生。模型層在這個基礎上可能會補充額外的約束，例如只能是在賬戶餘額大於轉賬金額的時候、轉賬目標賬戶沒有被封禁的時候才允許交易的發生。經過這一層細節補充後，需求更加具體，約束更加詳細。 API 層和展現層又會遵循這一約束。</p>
<h3>2.1.1 強推導性</h3>
<p>如果是上層可完全由下層推導而出，那麼是一種強推導關係。在這種關係下，平台能力滿足的情況下，可通過No-code 方式快速達成需求。</p>
<h3>2.1.2 弱推導性</h3>
<p>如果上層需要在下層推導結果中增加<b>額外約束和細節補充</b>，那麼是一種弱推導關係。在這種關係下，兼具效率和可定制性的Low-code 方式是更好的選擇。</p>
<p>由於細節由下而上遞增，所以<b>越靠下層推導性越強，越靠上層推導性越弱。</b></p>
<p>在單一強組織架構內通過強制的高約束，可達成強推導性；但在廣闊的企業開發市場，跨約組織或組織內層級結構龐大，完成高約束性治理是無法完成的任務，只能達到弱推導性。</p>
<h3>2.2 層間提效的關鍵在於完成推導性過程</h3>
<p>完成推導性過程是提效的重中之重，因為它會簡化生產關係。如果上層可完全享受到下層的工作成果，而不需要換一種方式重建，將會大大節省時間，提高效率。</p>
<p><b>打通上下游生產資料壁壘</b>是雲鳳蝶提效的主要抓手之一，這樣更容易完成推導性過程。</p>
<p>例如，模型層建立的模型，是否可直接通過推導性幫助建立API，甚至直接生成API（取決於需要補充的額外訊息，也就是是強推導性關係還是弱推導關係）；API 是否可以通過對到行幫助建立展現層界面和交互，甚至直接生成Form 和Table 等業務界面；甚至模型層是否可以直接跨越API 層，直接推導展現層。</p>
<p>如果想完成這種推導性關係，打通層間生產資料壁壘就是必須的，要建立一種穩定可被上層理解並加以利用的數據格式。</p>
<h2>3. 層內關係</h2>
<p>因為需求層的形式化語言探索業界還沒有突破，所以不再討論範圍內。</p>
<p>對於除需求層外每一層的建立過程，如何才是更塊更好的方式？如何搭配生產關係才會達到總體效率的最優？</p>
<h3>3.1 使用Low-code 研發每一層</h3>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-b2ff0e20605f5aaa6d7dd3eacb0da309_r.jpg" data-size="normal" data-rawwidth="1492" data-rawheight="1124" class="origin_image zh-lightbox-thumb" width="1492" data-original="https://pic2.zhimg.com/v2-b2ff0e20605f5aaa6d7dd3eacb0da309_b.jpg" title="v2-b2ff0e20605f5aaa6d7dd3eacb0da309_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-b2ff0e20605f5aaa6d7dd3eacb0da309_r.jpg" data-size="normal" data-rawwidth="1492" data-rawheight="1124" class="origin_image zh-lightbox-thumb lazy" width="1492" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1492'%20height='1124'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-b2ff0e20605f5aaa6d7dd3eacb0da309_b.jpg" title="v2-b2ff0e20605f5aaa6d7dd3eacb0da309_r"><figcaption>層內關係</figcaption></figure>
<h3>3.1.1 可視化研發</h3>
<p>可視化開發不局限於UI 繪製視圖，是指基於GUI 配置化、聲明式的開發方式。</p>
<p><b>好的可視化</b>關鍵是對於常見實現路徑的高層抽象，對眾多處理細節的收斂。只要完成了這種可視化過程，說明完成了細節收斂，用戶每一次操作都力挺萬鈞，以一當十，天然擁有高效率的特點。</p>
<p><b>不好的可視化</b>只是把代碼世界里東西一一映射到可視化世界，不做多對一收斂，這可能會有降門檻的效用，但提效無從談起。</p>
<h3>3.1.2 代碼研發</h3>
<p>代碼開發需要開發者掌握龐大的專業技能體系，但擁有全部的靈活性，功能強大。</p>
<h3>3.1.3 Low-code 兼顧層內建設兩種需求</h3>
<p>由於企業開發市場對於<b>交付效率和可定制性</b>的雙重追求，Low-code平台成為這一市場最合適的開發方式，因為它兼具高效率和靈活性的特點。</p>
<p>所以，Low-code 平台需要解決好可視化開發和代碼開發之間的關係，它是一種部件生產和生產線組裝的關係。</p>
<h3>3.2 層內提效的關鍵在於建立產業鍊式結構</h3>
<h3>3.2.1 富士康如何製造出高精尖產品iPhone</h3>
<p>下圖是iPhone 的供應鏈，紅框內的是富士康。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-759fd834f18ed9479a735513350a7bfc_r.jpg" data-caption="" data-size="normal" data-rawwidth="1492" data-rawheight="1121" class="origin_image zh-lightbox-thumb" width="1492" data-original="https://pic1.zhimg.com/v2-759fd834f18ed9479a735513350a7bfc_b.jpg" title="v2-759fd834f18ed9479a735513350a7bfc_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-759fd834f18ed9479a735513350a7bfc_r.jpg" data-caption="" data-size="normal" data-rawwidth="1492" data-rawheight="1121" class="origin_image zh-lightbox-thumb lazy" width="1492" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1492'%20height='1121'&gt;&lt;/svg&gt;" data-actualsrc="https://pic1.zhimg.com/v2-759fd834f18ed9479a735513350a7bfc_b.jpg" title="v2-759fd834f18ed9479a735513350a7bfc_r"></figure>
<p>產業鏈上游企業集中科技優勢，生產有高精尖屬性的大猩猩玻璃、屏幕模塊、攝像頭模塊等，蘋果公司輸出設計（中台的需求層），富士康就可以做出整體高精尖的產品iPhone 。</p>
<p><b>富士康的核心優勢，是以技能要求不高的方式流水線批量生產高精尖的iPhone。</b></p>
<h3>3.2.2 傳統中台研發（Pro-code）</h3>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-08702f1df0636322e08feb07827bb9ce_r.jpg" data-size="normal" data-rawwidth="1492" data-rawheight="377" class="origin_image zh-lightbox-thumb" width="1492" data-original="https://pic3.zhimg.com/v2-08702f1df0636322e08feb07827bb9ce_b.jpg" title="v2-08702f1df0636322e08feb07827bb9ce_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-08702f1df0636322e08feb07827bb9ce_r.jpg" data-size="normal" data-rawwidth="1492" data-rawheight="377" class="origin_image zh-lightbox-thumb lazy" width="1492" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1492'%20height='377'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-08702f1df0636322e08feb07827bb9ce_b.jpg" title="v2-08702f1df0636322e08feb07827bb9ce_r"><figcaption>傳統中台研發要求每個人掌握所有技能</figcaption></figure>
<p>基於代碼做bottom-up 式研發，成本高昂。以展現層為例，它要求每一個參與者是專家（資深的前端開發經驗），它要求每個人都既會研發高科技的輪胎、齒輪、方向盤，也要掌握整車組裝。在這樣一個研發模式下，人員要求高，生產效率只能對人提出高要求以此提升生產效率，難以有量變的提升。</p>
<h3>3.2.3 Low-code 中台研發</h3>
<p>代碼用於生產零部件，可視化用於組裝。形成上下游分工的產業鍊式結構。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-11cbcaeeebfd703e999ae296ac14ebab_r.jpg" data-size="normal" data-rawwidth="1492" data-rawheight="571" class="origin_image zh-lightbox-thumb" width="1492" data-original="https://pic4.zhimg.com/v2-11cbcaeeebfd703e999ae296ac14ebab_b.jpg" title="v2-11cbcaeeebfd703e999ae296ac14ebab_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-11cbcaeeebfd703e999ae296ac14ebab_r.jpg" data-size="normal" data-rawwidth="1492" data-rawheight="571" class="origin_image zh-lightbox-thumb lazy" width="1492" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1492'%20height='571'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-11cbcaeeebfd703e999ae296ac14ebab_b.jpg" title="v2-11cbcaeeebfd703e999ae296ac14ebab_r"><figcaption> Low-code 中台研發，集中專家力量生產零部件，產品本身可低成本快速組裝</figcaption></figure>
<p>在這樣的分工模式下，專家做高科技研發，會有更多更優質的能力以組件化的方式被開發出來，而中台的建設是以流水線的方式進行組裝。後者人員技能要求低，模式固定，因此生產力也會大大提高。</p>
<p>很容易做出對比，一家工廠生產iPhone 的所有零部件並負責組裝，對比以上產業鏈結構，那種生產力更高？</p>
<p>以展現層為例，我們認為，一個平台即便完成了可視化操作，但還是需要專業的前端技能或深度理解，那麼就是失敗的。因為這是一個要求博士學歷的富士康，注定無法規模化生產。這也是我們特別注意控制產品透出的技術要求復雜度，對用戶提出最小的技能要求範圍。</p>
<h2>4. 雲鳳蝶的提效思路</h2>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-699e0ca255a15f69af65df4bd931ae85_r.jpg" data-caption="" data-size="normal" data-rawwidth="1492" data-rawheight="1104" class="origin_image zh-lightbox-thumb" width="1492" data-original="https://pic2.zhimg.com/v2-699e0ca255a15f69af65df4bd931ae85_b.jpg" title="v2-699e0ca255a15f69af65df4bd931ae85_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-699e0ca255a15f69af65df4bd931ae85_r.jpg" data-caption="" data-size="normal" data-rawwidth="1492" data-rawheight="1104" class="origin_image zh-lightbox-thumb lazy" width="1492" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1492'%20height='1104'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-699e0ca255a15f69af65df4bd931ae85_b.jpg" title="v2-699e0ca255a15f69af65df4bd931ae85_r"></figure>
<p>雲鳳蝶中台應用是Low-code 平台，目前聚焦於展現層流水線的打造，將UI 資產快速組裝出可用站點。</p>
<p><b>做好工具屬性只是滿足提效的基本要求，更重要的是從橫豎兩個方向改善生產關係和打通生產資料壁壘。</b></p>
<h3>4.1 層內建立產業鏈提效</h3>
<p><b>UI資產包</b>專家級前端工程師使用代碼開發組件（UI資產），完全交由pro-code優化專家的生產效率（未來可能轉向CloudIDE），是產業鏈的上游。</p>
<p><b>低代碼組裝</b>使用可視化+低代碼方式組裝UI界面和製作交互，是我們的核心生產線，是產業鏈的下游。</p>
<p><b>自由佈局畫布打破層內生產資料壁壘</b>工作在展現層的PD、設計師和前端工程師工作產物無縫復用。</p>
<h3>4.2 層間完成推導性提效</h3>
<p><b>智能嚮導初探層間推導性關係</b>由API層弱推導展現層，允許用戶在過程中補充額外訊息（交互細節）。初步打破層間生產資料壁壘，目前正在建設中。</p>
<h3>4.3 Next</h3>
<p><b>模型層</b>下半年啟動模型層建設，並在智能嚮導中打通模型-&gt; API -&gt;界面的推導過程，進一步打破層間生產資料壁壘。</p>
<h2>5. 總結</h2>
<p>我們認為：</p>
<ul>
<li>傳統提效思路的努力方向“利其器”沒有錯誤，是所有提效必須完成的第一步。</li>
<li><b>生產力產生量變的更重要武器是改變生產力關係</b>。能夠打穿層級間、打通層級內，消除生產資料壁壘，層級內層級外下游都復用上游產物而不重建，會形成產業鍊式生產關係，從而效率最大化。</li>
</ul>
<p>以上討論僅針對於雲鳳蝶三大目標（降門檻、提效和提升體驗）中的提效，雲鳳蝶在其他目標下的思考會陸續呈現。</p>
</div>
</div>
</article>
<p>The post <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com/software-engineering/front-end-dev/14540/topic-78425921/" data-wpel-link="internal">雲鳳蝶中台研發提效實踐</a> appeared first on <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com" data-wpel-link="internal">成長駭客交流第一站 - HyperGrowths™</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>那些年的體驗技術部</title>
		<link>https://hypergrowths.com/software-engineering/front-end-dev/14443/topic-64214581/</link>
		
		<dc:creator><![CDATA[marketer]]></dc:creator>
		<pubDate>Sat, 30 Jan 2021 18:05:09 +0000</pubDate>
				<category><![CDATA[前端開發]]></category>
		<category><![CDATA[支付寶體驗科技]]></category>
		<guid isPermaLink="false">https://hypergrowths.com/software-engineering/front-end-dev/14443/topic-64214581/</guid>

					<description><![CDATA[<p>2008 年對中國人是複雜的一年，冰災，大地震，奧運會接踵而至。對玉伯來說也一樣，趕在奧運會排查臨時人口之前，玉伯從北京中科院軟件所離開，憑著自己幾年來在程序開發上的經歷和對新興前端行業的看好，來到杭州…</p>
<p>The post <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com/software-engineering/front-end-dev/14443/topic-64214581/" data-wpel-link="internal">那些年的體驗技術部</a> appeared first on <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com" data-wpel-link="internal">成長駭客交流第一站 - HyperGrowths™</a>.</p>
]]></description>
										<content:encoded><![CDATA[<article class="Post-Main Post-NormalMain" tabindex="-1">
<header class="Post-Header">
<h1 class="Post-Title">那些年的體驗技術部</h1>
<div class="Post-Author">
<div class="AuthorInfo" itemprop="author" itemscope="" itemtype="http://schema.org/Person"><meta itemprop="name" content="偏右悄悄地"><meta itemprop="image" content="https://pic1.zhimg.com/80ee75bac_l.jpg?source=172ae18b"><meta itemprop="url" content="https://www.zhihu.com/people/afc163"><meta itemprop="zhihu:followerCount"></div>
</div>
</header>
<div class="Post-RichTextContainer">
<div class="RichText ztext Post-RichText">
<p>2008 年對台灣人是複雜的一年，冰災，大地震，奧運會接踵而至。對<a href="https://link.zhihu.com/?target=https%3A//weibo.com/lifesinger" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">玉伯</a>來說也一樣，趕在奧運會排查臨時人口之前，玉伯從北京中科院軟件所離開，憑著自己幾年來在程序開發上的經歷和對新興前端行業的看好，來到杭州加入了淘寶UED ——彼時台灣最好的前端團隊，同時開始撰寫<a href="https://link.zhihu.com/?target=https%3A//lifesinger.wordpress.com/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">歲月如歌</a>部落格。雖然Google 早在2003 年已經通過Gmail 這個劃時代的產品展示了JavaScript 和Ajax 技術在瀏覽器端的強大能量，前端在當時在國內還是一個十分稚嫩的行業。 windows XP+ IE 統治了國內的互聯網行業的每塊屏幕，也正是那一年Google 推出了v8 和chrome，次年Node.js 發布，即將對前端行業產生巨大的影響。</p>
<p>2008年的雲謙（ <a href="https://link.zhihu.com/?target=http%3A//github.com/sorrycc/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">sorrycc</a> ）拿著不到4000塊錢的工資在一家小公司裡打雜，希望老闆加薪500元未果，離職加入了淘寶UED。同一年的蕭慶也在杭州的某公司裡做Java 程序員兼前端，老闆試探性打開ExtJS 官網對他說，這個不錯但是要錢，能不能用jQuery 改一版免費的出來？一個月後，一個jQuery 版本的ExtJS 雛形出來了。</p>
<p>2009 年因為淘寶店鋪業務的發展，業務上需要一個重型的可視化編輯器，玉伯開始做KISSY Editor。一年後，承玉加入淘寶，並且立志要在5 年內升到P8。玉伯和他、沉魚、喬花一起將Kissy Editor進一步升級成了<a href="https://link.zhihu.com/?target=http%3A//docs.kissyui.com/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Kissy</a> ，成為當時淘寶中前台的標準前端技術棧。</p>
<p>2009 年貫高和臻兒大學畢業，選擇加入當時名不見經傳的支付寶UED 前端開發部。</p>
<p>2010 年的絕雲畢業後，在阿里和一家日本公司的offer 中選擇了出國淘金。 2011 年，臻兒北上南下，在校園中招到了展新和偏右，一起開始參與支付寶前台業務和基礎技術建設。同年蕭慶也加入了淘寶UED，依靠自己先前的經驗，在業務線上搭建出了BUI —— 基於jQuery 的中後台組件庫，在淘係後台場景中大量推廣。</p>
<p>2011 年，玉伯結束了內部創業的湖畔項目，去了淘寶Java 開發團隊。確認了自己不喜歡Java 代碼後，次年從淘寶UED 轉崗到了支付寶UED 前端開發部，負責基礎技術組，偏右和貫高當時都在這個小組。這也是他第一次正式帶團隊，第一次小組週會，玉伯沒有聊技術，而是操著不甚流利的湘普分享了亞馬遜公司的價值觀，所有小組成員面面相覷，一不知道他想表達什麼，二也看不出面前這個<a href="https://zhuanlan.zhihu.com/p/58569326" class="internal" data-wpel-link="external" rel="nofollow external noopener noreferrer">黑黑的湖南漢子</a>和貝佐斯有什麼相似點。</p>
<h3>最後的黃金時代</h3>
<p>外部前端大環境正在銳變的前夜，jQuery 如日中天，Node.js 崛起，ES6 正在醞釀中，前端的標準化和工程化即將到來。前端工程師這個職業依然是一個很不成熟的技術崗位，國內很多公司過分地細分了重構工程師（CSS）和JS 工程師，行業內的大佬們一窩蜂地在使用奇技淫巧悶頭造類似YUI和prototype.js 的輪子，面試中最多的問題是閉包的原理和IE6 hack 技巧，技術環境的割裂造就了前端基礎技術的風潮和大量崗位。和當時國內大多數前端團隊一樣，支付寶也在閉門造自己的前端輪子，大量借鑒了YUI 的組件架構體系，底層使用了Java 生態裡的MVN 進行依賴管理和構建，所有的輪子和釘子都要內部自造，和前端社區越來越遠。</p>
<p>很快支付寶在玉伯的影響下開始嘗試逃脫出這個怪圈，解決辦法是開源。玉伯在一行代碼還沒開始寫之前發了一條微博，我們要用開源的方式打造支付寶下一代前端框架了，這在當時是非常激進的。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-9ad6be6a4a97f75d78870079ffee645e_r.jpg" data-caption="" data-size="normal" data-rawwidth="1160" data-rawheight="316" class="origin_image zh-lightbox-thumb" width="1160" data-original="https://pic3.zhimg.com/v2-9ad6be6a4a97f75d78870079ffee645e_b.jpg" title="v2-9ad6be6a4a97f75d78870079ffee645e_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-9ad6be6a4a97f75d78870079ffee645e_r.jpg" data-caption="" data-size="normal" data-rawwidth="1160" data-rawheight="316" class="origin_image zh-lightbox-thumb lazy" width="1160" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1160'%20height='316'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-9ad6be6a4a97f75d78870079ffee645e_b.jpg" title="v2-9ad6be6a4a97f75d78870079ffee645e_r"></figure>
<blockquote><p>2012 年4 月，玉伯剛剛從淘寶轉崗到支付寶，離開了漸漸進入死胡頭的Kissy，手攥著當紅的Sea.js 準備大干一場。兩年前的支付寶前端團隊也進入了團隊技術的轉型期，舊的前端框架需要升級，笨重的開發方式需要演進，雙方一拍即合，Arale 就此誕生。</p>
<p> —— <i><a href="https://link.zhihu.com/?target=https%3A//github.com/aralejs/aralejs.github.io/issues/358" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">關於Arale的過去、現在和未來</a></i></p></blockquote>
<p><a href="https://link.zhihu.com/?target=https%3A//seajs.github.io/seajs" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Sea.js</a> / <a href="https://link.zhihu.com/?target=http%3A//aralejs.github.io/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Arale</a> / <a href="https://link.zhihu.com/?target=https%3A//yuque.antfin-inc.com/xingmin.zhu/plan/github.com/spmjs/spm" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">spm</a>套件開始在支付寶內部和國內開源界發展起來。開源的工作方式讓貫高偏右們感到非常興奮，雲謙、沉魚和蕭慶也先後從淘寶轉崗到支付寶開始參與新的前端體系的建設。我們去了騰訊深圳本部進行了技術分享，號召騰訊的同學也來使用和共建Sea.js 和Arale 前端社區。現在回頭看來有點天真，雖然是開源技術，當時走的依然是一條前端輪子自研和前端社區自建的道路，最終這條路走沒有成功，Angular 和React 等外部技術體系很快將帶來巨大的衝擊。</p>
<p>前端技術之外，整個支付寶乃至阿里的業務平台也在13 年走到了一個十字路口，前端和業務結合非常緊密，UED 和設計在公司的話語權極高。那兩年的阿里的UED 團隊們的氣氛非常活躍，蜜月一樣的PC 前端時代現在顯得有些光怪陸離，前端和UED 在產品上進行著各種各樣的A/B 測試，更換各種按鈕樣式觀察頁面數據變化，每半年搞一次前端性能優化的戰役，公司內舉辦著各類黑客馬拉鬆比賽，iPhone 和iTouch 送到手軟，996 這個詞那時候還不存在。這是個一行js 代碼的錯誤就可以造成全站交易下跌的時代，也是PC 前端們最後的黃金時代。</p>
<h3>巨變</h3>
<p>2013 年改變了無數人的命運，無線時代的來臨、友商的壓力讓整個阿里坐立不安。 11 月，整個阿里宣布ALL IN 無線，推出來往正面對決友商，誓要火燒南極，淘寶/支付寶等業務也全面無線化。城門失火殃及池魚，60 個人左右的支付寶前端開發部即刻面臨解體，一半以上的人被抽調支持支付寶無線業務，面對巨大的變化，那幾週整個團隊人心渙散，所有人都面對非常具體的抉擇：留下or 離開？當時的前端開發部老大麼麼茶最終去了來往（後來成為了釘釘的創始人之一），玉伯自己也面臨著各種選擇，特意去現場觀察了來往團隊的狀態：『感覺來往可能真的會成功！ 』。</p>
<p>最終，玉伯還是決定和剩下的17 個人一起留在了這個團隊，支持沒有幾個迭代的PC 端業務和進入死胡同的自研前端技術體系。調整完的第一次週會，所有人都很沉默，比起鼓起勇氣做抉擇離開的人，留下的人的心態更多是未知和『擁抱變化』。 ALL IN 無線伴隨的是全集團的瘋狂，全組為配合兄弟團隊主動加班，然而周六來了之後竟然不知道要做什麼，兩週後就作罷了。沒有活干是一方面，更可怕的是對前端自身價值的懷疑，整個阿里前端也陷入了類似的<a href="https://link.zhihu.com/?target=https%3A//github.com/lifesinger/blog/issues/141" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">困局</a>。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-8431222cd5df185d7f02fba81e515165_r.jpg" data-caption="" data-size="normal" data-rawwidth="504" data-rawheight="390" class="origin_image zh-lightbox-thumb" width="504" data-original="https://pic2.zhimg.com/v2-8431222cd5df185d7f02fba81e515165_b.jpg" title="v2-8431222cd5df185d7f02fba81e515165_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-8431222cd5df185d7f02fba81e515165_r.jpg" data-caption="" data-size="normal" data-rawwidth="504" data-rawheight="390" class="origin_image zh-lightbox-thumb lazy" width="504" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='504'%20height='390'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-8431222cd5df185d7f02fba81e515165_b.jpg" title="v2-8431222cd5df185d7f02fba81e515165_r"></figure>
<blockquote><p>在阿里，我們不得不承認一個事實：前端的確有價值，但放在全局來看，前端產生的價值並非核心價值。在阿里，雖然前端的工作已經不可或缺，但對大公司而言，不可或缺的崗位多了去呢，不可或缺不代表有核心價值，我就不說了。</p>
<p> ———— <i><a href="https://link.zhihu.com/?target=https%3A//github.com/lifesinger/blog/issues/141" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">阿里前端的困局與突圍</a></i></p></blockquote>
<p>這個狀態沒有持續很久，本以為是一艘棄船，業務上新的發展方向卻帶來了新生。</p>
<p>無線戰略的同時，大中台也作為公司的重要戰略在那一年被提了出來。剩下的伙伴們沒有閒很久， PC 端的前台業務雖然沒了，前線業務伴隨的中後台的業務量開始大量增長起來。那時候團隊最喜歡用一張冰山圖來做技術和業務宣講：大中後台的業務比例是前台業務的十倍甚至更多，比起前台的兵強馬壯，中後台業務的人力資源、研發效率和產品體驗對我們都是新的巨大的挑戰。戲劇性的是，幾個月前還不知道做什麼的團隊，很快玉伯就在和無數不知道從哪來長出來的中後台業務拉扯人力問題：『我們不是資源！ 』。隨著業務的爆發，團隊人數迅速增長起來，團隊名也從前端開發部改名成體驗技術部，意在體現前端工程師的核心競爭力：<b>用技術解決產品體驗問題</b>。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-3ad51caeb05bb6b2ee45b40e92c32286_r.jpg" data-size="normal" data-rawwidth="866" data-rawheight="862" class="origin_image zh-lightbox-thumb" width="866" data-original="https://pic3.zhimg.com/v2-3ad51caeb05bb6b2ee45b40e92c32286_b.jpg" title="v2-3ad51caeb05bb6b2ee45b40e92c32286_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-3ad51caeb05bb6b2ee45b40e92c32286_r.jpg" data-size="normal" data-rawwidth="866" data-rawheight="862" class="origin_image zh-lightbox-thumb lazy" width="866" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='866'%20height='862'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-3ad51caeb05bb6b2ee45b40e92c32286_b.jpg" title="v2-3ad51caeb05bb6b2ee45b40e92c32286_r"><figcaption>冰山理論，一個前台業務背後是幾十個中後台業務</figcaption></figure>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-88b30ac7503345ba65008808310eb306_r.jpg" data-caption="" data-size="normal" data-rawwidth="1622" data-rawheight="858" class="origin_image zh-lightbox-thumb" width="1622" data-original="https://pic3.zhimg.com/v2-88b30ac7503345ba65008808310eb306_b.jpg" title="v2-88b30ac7503345ba65008808310eb306_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-88b30ac7503345ba65008808310eb306_r.jpg" data-caption="" data-size="normal" data-rawwidth="1622" data-rawheight="858" class="origin_image zh-lightbox-thumb lazy" width="1622" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1622'%20height='858'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-88b30ac7503345ba65008808310eb306_b.jpg" title="v2-88b30ac7503345ba65008808310eb306_r"></figure>
<p>老的一套前端技術體系已經明顯不匹配業務現狀了，亟需換代。這一年設計師<a href="https://link.zhihu.com/?target=https%3A//www.caicai.me/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">子溯</a>加入了體驗技術部，開始和偏右展新們一起做螞蟻金服的第一個技術商業產品『 <a href="https://link.zhihu.com/?target=https%3A//tech.antfin.com/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">螞蟻金融雲</a>』，前端技術棧選的是AngularJS。而2014 年React 技術棧在社區嶄露頭角，承玉們在淘寶維護Kissy 和BUI 等技術體系的時光也到了一個轉折點。於是承玉轉崗來了支付寶，和蕭慶一起開始建設react-component 底層組件生態。</p>
<p><a href="https://link.zhihu.com/?target=https%3A//github.com/lifesinger/blog/issues/184" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">前後端分離的研發模式</a>在社區流行起來，體驗技術部最先實踐的是基於Node.js的應用層方案。</p>
<blockquote><p>在這種研發模式下，前後端的職責很清晰。對前端來說，兩個UI 層各司其職：</p>
<p> 1、Front-end UI layer 處理瀏覽器層的展現邏輯。通過CSS 渲染樣式，通過JavaScript 添加交互功能，HTML 的生成也可以放在這層，具體看應用場景。<br /> 2、Back-end UI layer 處理路由、模板、數據獲取、cookie 等。通過路由，前端終於可以自主把控URL Design，這樣無論是單頁面應用還是多頁面應用，前端都可以自由調控。後端也終於可以擺脫對展現的強關注，轉而可以專心於業務邏輯層的開發。<br />通過Node，Web Server 層也是JavaScript 代碼，這意味著部分代碼可前後復用，需要SEO 的場景可以在服務端同步渲染，由於異步請求太多導致的性能問題也可以通過服務端來緩解。前一種模式的不足，通過這種模式幾乎都能完美解決掉。</p>
<p> —— <i><a href="https://link.zhihu.com/?target=https%3A//github.com/lifesinger/blog/issues/184" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Web研發模式演變</a></i></p></blockquote>
<p><a href="https://link.zhihu.com/?target=https%3A//weibo.com/81715239" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">蘇千</a>、不四等koa社區的活躍成員在2014年先後加盟，和貫高一起開始研發Chair企業級Node.js研發框架，以及後來的<a href="https://link.zhihu.com/?target=https%3A//egg.alipay.com/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Egg.js</a> ，嘗試在大規模高可用的金融業務和前後端分離的研發模式中尋找Node.js 的落地場景。</p>
<p>2012 年，百度商業前端通用技術組的御術（林峰）和幾位團隊成員一起從上百個業務系統中抽取需求，寫出了商業圖表庫ECharts 0.1 版本，2013 年6 月ECharts 1.0 版本發布。幾乎與此同時，因為買不起HighCharts，蕭慶開始把BUI 中的圖表獨立出來，對標做成了內部使用的ACharts。</p>
<p>AngularJS 的嘗試沒有太久，體驗技術部開始決定要統一技術棧，經過激烈的爭吵和決策，押寶React 這條船，嘗試在react-component 基礎上合力建設基於React 的UI 設計系統。 2015年，曾經風光無限破釜沉舟的來往也終於走到了盡頭，團隊像剛成立時那麼迅速地分崩離析了，<a href="https://www.zhihu.com/people/shao-kou-shao/" class="internal" data-wpel-link="external" rel="nofollow external noopener noreferrer">它山</a>沒有跟隨麼麼茶們去做新的釘釘，而是決定來到螞蟻，帶領設計師團隊和承玉偏右一起打造企業級中後台Design System。那時Design System 在國內是一個很新的名詞，只有Apple 和Google 等公司有這樣高大上的概念，而基於中後台的設計語言更是很少有人提。最後玉伯給拍了一個Ant Design 的奇怪名字，偏右很快註冊了一個ant.design 的域名，2015 年第一個對外版本上線的時候，社區很多人都看不懂這是什麼。</p>
<figure data-size="small"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-7932d4afbc49995231761940d7606fda_r.jpg" data-caption="" data-size="small" data-rawwidth="650" data-rawheight="370" class="origin_image zh-lightbox-thumb" width="650" data-original="https://pic3.zhimg.com/v2-7932d4afbc49995231761940d7606fda_b.jpg" title="v2-7932d4afbc49995231761940d7606fda_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-7932d4afbc49995231761940d7606fda_r.jpg" data-caption="" data-size="small" data-rawwidth="650" data-rawheight="370" class="origin_image zh-lightbox-thumb lazy" width="650" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='650'%20height='370'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-7932d4afbc49995231761940d7606fda_b.jpg" title="v2-7932d4afbc49995231761940d7606fda_r"></figure>
<p>React 在內部的推廣經歷了很大的阻力，一方面是對React 技術棧和當時還不成熟的antd 的懷疑，一方面是大量Arale/BUI/jQuery/BootStrap 的技術棧還在業務中不斷使用。為了Ant Design 設計體系能在支付寶業務落地，我們甚至認真討論過jQuery 版本的antd 的可行性，最終團隊通過投入大量基礎技術的工程師去直接參與一線業務，在關鍵時間點把關鍵項目啃下來，一邊落地一邊完善antd。 Ant Design 的中後台設計語言的定位和推出時機是非常合適的，antd 開始在公司外部也開始收穫了大量關注，GitHub 的stars 數直線上升， 17 年3 月突破了一萬star，18 年三月2w star，很快成為國內中後台前端開發的標杆，也讓承玉在2015 年順利升到P8。</p>
<p>Ant Design 的成功讓整個團隊感受到鼓舞，另一個前端大展身手的可視化領域在這個團隊同時生長起來。也在2015年，體驗技術部的蕭慶和好修閱讀了<a href="https://link.zhihu.com/?target=https%3A//www.cs.uic.edu/~wilkinson/TheGrammarOfGraphics/GOG.html" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">The Grammar of Graphics</a>一書後，意識到可視化不只是圖表這麼簡單，開始著手把ACharts升級為G2圖形語法庫，即JavaScript版本的The <b>G</b> rammar of <b>G</b> raphics，並嘗試在螞蟻內推廣落地。 16 年，剛剛回國加入阿里沒多久的絕雲在微博上聯繫到了ECharts 的御術，那時禦術也正面臨著再次創業的失敗，揣著可視化的夢想來到了杭州。他將和蕭慶絕雲沉魚們一起打造<a href="https://link.zhihu.com/?target=https%3A//antv.alipay.com/zh-cn/index.html" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">AntV</a>螞蟻數據可視化解決方案和九色鹿體驗度量產品。</p>
<p>2016 年，展新在螞蟻金融雲的文檔中心業務研發過程中，抽離了一個Markdown 文檔管理應用，起名叫雲雀，想替代公司內部老舊的confluence 系統。展新作為這個項目的唯一的設計師兼PD 兼BD 兼工程師，做了一個很漂亮的Keynote 到體驗技術部各個小組去分享，希望能找到志同道合的同事一起參與。然後子溯作為PD 加入了，玉伯也看到了這個產品的前景，星星之火開始燎原，一個雲雀產品小團隊迅速運轉起來，產品不斷改版迭代試錯。 2017年蘇千不四加入，雲雀迅猛成長為整個阿里經濟體內部最大的文檔平台，次年改名為<a href="https://link.zhihu.com/?target=http%3A//yuque.com/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">語雀</a>正式進行商業化對外服務。</p>
<p>2017 年，禦術北上去愛奇藝挖到了愚道。愚道加入體驗技術部後，本以為內部研發應該已經非常成熟，備受業務和技術折磨後，萌生了開發企業前端研發框架的念頭，和來自成都的水魚一拍即合，一起在酒店里通宵了幾個晚上，開發出了Bigfish 1.0 版本。幾乎同時，雲謙基於雲鳳蝶業務中的實踐做出了類似的<a href="https://link.zhihu.com/?target=http%3A//umijs.org/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">UmiJS</a>並且對外開源，兩者經歷了劇烈的內部競爭後在18年進行了整合，一個你死我活的局出現了雙贏，UmiJS對外開源服務，Bigfish 則基於Umi 重構，成為螞蟻金服內部標準前端應用框架。今天的體驗技術部不再是當年的刀耕火種，我們有了工業化的生產工具進行研發，在前端我們有了Ant Design，有了Bigfish，在服務端我們有了Chair 有了Functions，可視化我們了有了<a href="https://link.zhihu.com/?target=https%3A//antv.alipay.com/zh-cn/g2/3.x/index.html" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">G2</a> / <a href="https://link.zhihu.com/?target=https%3A//antv.alipay.com/zh-cn/g6/3.x/index.html" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">G6</a> / <a href="https://link.zhihu.com/?target=https%3A//antv.alipay.com/zh-cn/f2/3.x/index.html" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">F2</a> / <a href="https://link.zhihu.com/?target=https%3A//antv.alipay.com/zh-cn/l7/1.x/index.html" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">L7</a> ，生產力比起幾年前已是質的飛躍，但是這裡也遠遠沒有成熟到只需要螺絲釘的程度。效率、資源、體驗的平衡是我們的終極命題，也是體驗技術部存在的意義。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-a9fe8eda5409fc671a847befedf4a8aa_r.jpg" data-size="normal" data-rawwidth="1184" data-rawheight="1088" class="origin_image zh-lightbox-thumb" width="1184" data-original="https://pic3.zhimg.com/v2-a9fe8eda5409fc671a847befedf4a8aa_b.jpg" title="v2-a9fe8eda5409fc671a847befedf4a8aa_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-a9fe8eda5409fc671a847befedf4a8aa_r.jpg" data-size="normal" data-rawwidth="1184" data-rawheight="1088" class="origin_image zh-lightbox-thumb lazy" width="1184" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1184'%20height='1088'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-a9fe8eda5409fc671a847befedf4a8aa_b.jpg" title="v2-a9fe8eda5409fc671a847befedf4a8aa_r"><figcaption>化不可能為可能</figcaption></figure>
<h3>砥礪前行</h3>
<p>除了語雀，其他內部技術產品在前端工程化的大背景下也成長起來：Basement 前端應用發布平台，雲鳳蝶可視化搭建平台，九色鹿體驗度量等等，投入了大量人力各自發展。玉伯也在被各個業務部門挑戰，為什麼業務線不能投入足夠的前端資源，所有體驗科技產品都面臨著在螞蟻和阿里內部巨大的自證壓力。語雀在螞蟻內部被問得最多的問題是和金融服務有什麼關係？為了努力向內部業務對齊，語雀的第一個slogan 是『讓知識等於財富』。在大阿里內部，和釘釘在企業協作領域的定位也有重疊，在和強勢的釘釘經歷了無數次業務拉扯之後，非常慘痛的情況還是發生了。 2018 年6 月，包括展新在內的大半個語雀團隊被釘釘合併，語雀HR 在宣布決定的會議上哭了出來，無線all in 的噩夢往事彷彿重現。這對新生的語雀是一次巨大的打擊，準備商業化起飛的翅膀被生生打斷。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-52e3040c3e8e411cc3bfe193c18cf774_r.jpg" data-caption="" data-size="normal" data-rawwidth="1972" data-rawheight="1104" class="origin_image zh-lightbox-thumb" width="1972" data-original="https://pic1.zhimg.com/v2-52e3040c3e8e411cc3bfe193c18cf774_b.jpg" title="v2-52e3040c3e8e411cc3bfe193c18cf774_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-52e3040c3e8e411cc3bfe193c18cf774_r.jpg" data-caption="" data-size="normal" data-rawwidth="1972" data-rawheight="1104" class="origin_image zh-lightbox-thumb lazy" width="1972" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1972'%20height='1104'&gt;&lt;/svg&gt;" data-actualsrc="https://pic1.zhimg.com/v2-52e3040c3e8e411cc3bfe193c18cf774_b.jpg" title="v2-52e3040c3e8e411cc3bfe193c18cf774_r"></figure>
<p>2018 年12 月25 日， Ant Design 彩蛋事件在全網醞釀爆發，一度衝上知乎熱榜第二，用戶的巨大期許轉化成責罵和諷刺崩湧而來，antd 的GitHub 討論區當天基本癱瘓， Ant Design 團隊經歷了噩夢般的一周。事後整個體驗技術部上下都進行了整肅，所有人感受到了身上巨大的責任和敬畏感，玉伯非常生氣並自領3.25 全年績效（無加薪無年終獎股票等獎勵），偏右在內部复盤上許諾antd 會更好，用長期的技術投入一點點彌補損失的信任。</p>
<p>2019 年4 月，禦術在一次部門團建中說『你們有感覺到體驗技術部這兩年不夠好了麼，已經很久沒有社招P8 加入了』。號稱國內最好的前端團隊，今天比以往都更需要新鮮血液的加入。 『到了坡底，就只能向上走了』</p>
<p>2013年玉伯寫過他的<a href="https://link.zhihu.com/?target=https%3A//github.com/lifesinger/blog/issues/115" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">三個夢</a>：技術夢、產品夢、自由夢。語雀、雲鳳蝶、九色鹿、Basement 是這個產品夢，Ant Design、Egg、Umi、AntV 是技術夢，做夢是需要勇氣的，也從來不是一帆風順的。</p>
<blockquote><p>我有三個夢：技術夢、產品夢、自由夢。</p>
<p>之前我一直把前兩個夢割裂開來，2012 年最大的成長是意識到前兩個夢可以合起來，技術即產品，產品即技術。 12 年下半年很清楚明確基礎技術最重要的是產品化。只有用做產品的心態去做技術，才有可能把技術做好做長久。</p>
<p>產品夢不僅僅是技術夢，但技術夢可以融合進產品。做產品不一定要出去創業，在公司依舊可以做到。公司本身也是一個產品，對業務的了解、深入、改進等等，都很有挑戰，非常值得去做。產品夢重要的不是所做的事情，而是做事的產品心態。</p>
<p>至於自由夢，於我而言，一是財富自由，二是精神自由。愚公（周愛民）說過挺有意思的一句話：財富自由不要只看收入，最主要取決於支出。目前愚公就已實現了財富自由，因為愚公老家那地方，日常開銷真是小，呵呵。真正難得是精神自由...</p>
<p> —— <i><a href="https://link.zhihu.com/?target=https%3A//github.com/lifesinger/blog/issues/115" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">畢業十年與我的三個夢</a></i></p></blockquote>
<p class="ztext-empty-paragraph"></p>
<p>2019 年阿里內已經有幾十個名字是『體驗技術部』的前端團隊。</p>
<p>2019 年的展新在釘釘繼續追逐自己的文檔夢。</p>
<p>2019 年的蘇千子溯在和語雀一起蟄伏，在剛剛過去的四月份發布了企業空間功能，語雀的商業化再次上路。</p>
<p>2019 年的雲謙已經是兩個男孩的父親，剛下線了老邁的spm，發佈著umi 的一個個新版本。</p>
<p>2019 年Ant Design 的stars 數已經突破了5 萬，偏右和勺子正在籌劃antd 4.0，努力把西湖區第一做成太平洋第一。</p>
<p>2019年的沉魚開始從九色鹿轉向雲鳳蝶，探索<a href="https://link.zhihu.com/?target=https%3A//www.forbes.com/sites/jasonbloomberg/2018/07/30/low-codeno-code-hpapaas-heres-what-everybody-is-missing/%2376d237883ac0" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">hpaPaaS</a>智能建站的可能性。</p>
<p>2019 年的貫高們正在用Node.js 搭建下一代Serverless for Frontend 架構，做阿里經濟體小程序云開發的標配。</p>
<p>2019 年的蕭慶和絕雲把AntV 做成了阿里數據可視化的核心技術，還在探索用可視化技術給業務帶來價值。</p>
<p>2019 年的臻兒正在嘗試把螞蟻前端研發搬到雲上，讓下一代研發模式早點到來。</p>
<p>2019 年的御術開始帶領體驗技術部下的平台前端技術部，重走玉伯那年的路。</p>
<p>2019 年的玉伯很久不寫部落格了，他的產品夢和技術夢都在路上，自由夢實現了一半。而另一半也遙遙無期，也近在咫尺。</p>
<hr>
<p>這是一篇部門招聘貼，我想藉這個機會從自己的視角小結一下體驗技術部這幾年的經歷，也希望能找到和我們意氣相投的未來同事。我們還在路途中，有前進也有折回，各位無論工程師、設計師、產品還是運營，也無論阿里內外，如若有夢，歡迎一起同行。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-8dd3f108d5cdab404b9deeb84c8c3925_r.jpg" data-size="normal" data-rawwidth="1492" data-rawheight="839" class="origin_image zh-lightbox-thumb" width="1492" data-original="https://pic2.zhimg.com/v2-8dd3f108d5cdab404b9deeb84c8c3925_b.jpg" title="v2-8dd3f108d5cdab404b9deeb84c8c3925_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-8dd3f108d5cdab404b9deeb84c8c3925_r.jpg" data-size="normal" data-rawwidth="1492" data-rawheight="839" class="origin_image zh-lightbox-thumb lazy" width="1492" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1492'%20height='839'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-8dd3f108d5cdab404b9deeb84c8c3925_b.jpg" title="v2-8dd3f108d5cdab404b9deeb84c8c3925_r"><figcaption>螞蟻金服體驗技術部全家福2019.04.15</figcaption></figure>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-5ac9727e74213e73576236c327dba5ef_r.jpg" data-caption="" data-size="normal" data-rawwidth="1518" data-rawheight="658" class="origin_image zh-lightbox-thumb" width="1518" data-original="https://pic4.zhimg.com/v2-5ac9727e74213e73576236c327dba5ef_b.jpg" title="v2-5ac9727e74213e73576236c327dba5ef_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-5ac9727e74213e73576236c327dba5ef_r.jpg" data-caption="" data-size="normal" data-rawwidth="1518" data-rawheight="658" class="origin_image zh-lightbox-thumb lazy" width="1518" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1518'%20height='658'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-5ac9727e74213e73576236c327dba5ef_b.jpg" title="v2-5ac9727e74213e73576236c327dba5ef_r"></figure>
<p class="ztext-empty-paragraph"></p>
<ul>
<li>簡歷投遞郵箱：afx-platform-talent <a href="https://link.zhihu.com/?target=https%3A//yuque.antfin-inc.com/list.alibaba-inc.com" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">@list.alibaba-inc.com</a></li>
<li>阿里轉崗聯繫：玉伯</li>
<li>崗位：</li>
<ul>
<li> <a href="https://link.zhihu.com/?target=https%3A//www.yuque.com/afx/platform/asg4i0/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">前端/可視化工程師</a></li>
<li><a href="https://link.zhihu.com/?target=https%3A//job.alibaba.com/zhaopin/position_detail.htm%3Ftrace%3Dqrcode_share%26positionCode%3DGP501104" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">視覺設計師</a></li>
<li><a href="https://link.zhihu.com/?target=https%3A//job.alibaba.com/zhaopin/position_detail.htm%3Ftrace%3Dqrcode_share%26positionCode%3DGP071014" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">交互設計師</a></li>
<li><a href="https://link.zhihu.com/?target=https%3A//job.alibaba.com/zhaopin/position_detail.htm%3Ftrace%3Dqrcode_share%26positionCode%3DGP501093" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">產品經理</a></li>
<li><a href="https://link.zhihu.com/?target=https%3A//job.alibaba.com/zhaopin/position_detail.htm%3Ftrace%3Dqrcode_share%26positionCode%3DGP062474" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">產品運營</a></li>
</ul>
<li>體驗技術部-平台前端技術部詳細介紹： <a href="https://link.zhihu.com/?target=https%3A//www.yuque.com/afx/platform/lsouyk" class=" external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external"><span class="invisible">https://www.</span> <span class="visible">yuque.com/afx/platform/</span> <span class="invisible">lsouyk</span></a></li>
</ul>
<hr>
<blockquote><p>文中時間可能有出入，人名均為阿里花名。</p></blockquote>
<p>參考鏈接：</p>
<ul>
<li><a href="https://link.zhihu.com/?target=https%3A//github.com/lifesinger/blog/issues/115" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">畢業十年與我的三個夢</a></li>
<li><a href="https://link.zhihu.com/?target=https%3A//github.com/lifesinger/blog/issues/184" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Web研發模式演變</a></li>
<li><a href="https://link.zhihu.com/?target=https%3A//github.com/lifesinger/blog/issues/132" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">關於前端的那些事</a></li>
<li><a href="https://link.zhihu.com/?target=https%3A//github.com/lifesinger/blog/issues/141" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">阿里前端的困局與突圍</a></li>
<li><a href="https://link.zhihu.com/?target=https%3A//weibo.com/1748374882/ygSM72QJv" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Arale發布預告-玉伯也叫黑俠微博</a></li>
<li><a href="https://link.zhihu.com/?target=https%3A//github.com/aralejs/aralejs.github.io/issues/358" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">關於Arale的過去、現在和未來</a></li>
<li><a href="https://link.zhihu.com/?target=https%3A//echarts.baidu.com/echarts2/doc/about.html" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">關於我們- ECharts</a></li>
<li> <a href="https://link.zhihu.com/?target=https%3A//www.yuque.com/yuque/help/about" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">語雀是什麼？</a></li>
<li> <a href="https://link.zhihu.com/?target=http%3A//iamsujie.com/simple_life/impossible-triangle/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">沒戲，做不到，不存在的“不可能三角”</a></li>
<li> <a href="https://link.zhihu.com/?target=https%3A//xtech.antfin.com/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">螞蟻體驗科技</a></li>
</ul>
</div>
</div>
</article>
<p>The post <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com/software-engineering/front-end-dev/14443/topic-64214581/" data-wpel-link="internal">那些年的體驗技術部</a> appeared first on <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com" data-wpel-link="internal">成長駭客交流第一站 - HyperGrowths™</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>第二屆SEE Conf 2019 精彩回顧（附PPT 及視頻）</title>
		<link>https://hypergrowths.com/software-engineering/front-end-dev/14307/topic-54459056/</link>
		
		<dc:creator><![CDATA[marketer]]></dc:creator>
		<pubDate>Sat, 30 Jan 2021 17:57:51 +0000</pubDate>
				<category><![CDATA[前端開發]]></category>
		<category><![CDATA[支付寶體驗科技]]></category>
		<guid isPermaLink="false">https://hypergrowths.com/software-engineering/front-end-dev/14307/topic-54459056/</guid>

					<description><![CDATA[<p>2019年1月5日，第二屆螞蟻金服體驗科技大會SEE Conf 2019 於杭州螞蟻Z 空間成功舉辦，數位講師、嘉賓為大家帶來了一場體驗科技的分享盛宴，近500 位參會者到場參與此次體驗科技盛宴，近2 萬人在線收看直播。無…</p>
<p>The post <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com/software-engineering/front-end-dev/14307/topic-54459056/" data-wpel-link="internal">第二屆SEE Conf 2019 精彩回顧（附PPT 及視頻）</a> appeared first on <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com" data-wpel-link="internal">成長駭客交流第一站 - HyperGrowths™</a>.</p>
]]></description>
										<content:encoded><![CDATA[<article class="Post-Main Post-NormalMain" tabindex="-1">
<header class="Post-Header">
<h1 class="Post-Title">第二屆SEE Conf 2019 精彩回顧（附PPT 及視頻） </h1>
<div class="Post-Author">
<div class="AuthorInfo" itemprop="author" itemscope="" itemtype="http://schema.org/Person"><meta itemprop="name" content="vagusX"><meta itemprop="image" content="https://pic4.zhimg.com/cec097b0928764539c704c26be683afa_l.jpg?source=172ae18b"><meta itemprop="url" content="https://www.zhihu.com/people/vagusx"><meta itemprop="zhihu:followerCount"></div>
</div>
</header>
<div class="Post-RichTextContainer">
<div class="RichText ztext Post-RichText">
<p>2019年1月5日，第二屆螞蟻金服體驗科技大會SEE Conf 2019 於杭州螞蟻Z 空間成功舉辦，數位講師、嘉賓為大家帶來了一場體驗科技的分享盛宴，近500 位參會者到場參與此次體驗科技盛宴，近2 萬人在線收看直播。無論是Ant Design 的情感化設計，還是數據可視化之Story Telling，以及workshop 中的Ant Design 資產一起造和Ant Designers 圓桌沙龍，相信都讓大家印象深刻。</p>
<p>開場由螞蟻金服體驗技術部的負責人玉伯為大會致開幕詞，他從體驗技術的升級、普惠和創新等多個維度，闡述螞蟻金服體驗技術部的初心及願景。 <a href="https://link.zhihu.com/?target=https%3A//v.youku.com/v_show/id_XNDAwMjk1NjM2OA%3D%3D.html%3Fspm%3Da2h1n.8251843.playList.5~5~A%26f%3D52028043%26o%3D1" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">點擊查看演講視頻</a></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-012e0acfd8006b0f4cc6918c69655b9d_r.jpg" data-caption="" data-size="normal" data-rawwidth="1616" data-rawheight="1080" class="origin_image zh-lightbox-thumb" width="1616" data-original="https://pic2.zhimg.com/v2-012e0acfd8006b0f4cc6918c69655b9d_b.jpg" title="v2-012e0acfd8006b0f4cc6918c69655b9d_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-012e0acfd8006b0f4cc6918c69655b9d_r.jpg" data-caption="" data-size="normal" data-rawwidth="1616" data-rawheight="1080" class="origin_image zh-lightbox-thumb lazy" width="1616" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1616'%20height='1080'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-012e0acfd8006b0f4cc6918c69655b9d_b.jpg" title="v2-012e0acfd8006b0f4cc6918c69655b9d_r"></figure>
<p>同濟大學設計創意學院院長婁永琪帶來首個分享《<b>交互設計與人類未來</b>》，分享中婁院長呼呼和倡導一種新的設計—— “可持續社會交互設計”，以更好地應對人地危機的挑戰，它將充分運用交互設計和體驗設計的思想、方法和工具來設計和管理一個可持續的人類世界。 <a href="https://link.zhihu.com/?target=https%3A//v.youku.com/v_show/id_XNDAwMjk2MDIxMg%3D%3D.html%3Fspm%3Da2h1n.8251843.playList.5%212~5~A%26f%3D52028043%26o%3D1" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">點擊查看演講視頻</a></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-aef685155c15b7462df7221b500549f4_r.jpg" data-caption="" data-size="normal" data-rawwidth="1616" data-rawheight="1080" class="origin_image zh-lightbox-thumb" width="1616" data-original="https://pic1.zhimg.com/v2-aef685155c15b7462df7221b500549f4_b.jpg" title="v2-aef685155c15b7462df7221b500549f4_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-aef685155c15b7462df7221b500549f4_r.jpg" data-caption="" data-size="normal" data-rawwidth="1616" data-rawheight="1080" class="origin_image zh-lightbox-thumb lazy" width="1616" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1616'%20height='1080'&gt;&lt;/svg&gt;" data-actualsrc="https://pic1.zhimg.com/v2-aef685155c15b7462df7221b500549f4_b.jpg" title="v2-aef685155c15b7462df7221b500549f4_r"></figure>
<p>第二位登場的是周姮和梓義帶來關於《 <b>Ant Design情感化設計</b>》的分享，他們深度剖析螞蟻金服在產品體驗設計中，如何結合人類情感的實踐經驗，助力產品的體驗升級和業務增長。 <a href="https://link.zhihu.com/?target=http%3A//v.youku.com/v_show/id_XNDAwMjk4MjUyOA%3D%3D.html%3Fspm%3Da2h1n.8251843.playList.5%213~5~A%26f%3D52028043%26o%3D1" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">點擊查看演講視頻</a></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-b0b7dbbc8c20e3902f100f2a9559c461_r.jpg" data-caption="" data-size="normal" data-rawwidth="4096" data-rawheight="2730" class="origin_image zh-lightbox-thumb" width="4096" data-original="https://pic2.zhimg.com/v2-b0b7dbbc8c20e3902f100f2a9559c461_b.jpg" title="v2-b0b7dbbc8c20e3902f100f2a9559c461_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-b0b7dbbc8c20e3902f100f2a9559c461_r.jpg" data-caption="" data-size="normal" data-rawwidth="4096" data-rawheight="2730" class="origin_image zh-lightbox-thumb lazy" width="4096" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='4096'%20height='2730'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-b0b7dbbc8c20e3902f100f2a9559c461_b.jpg" title="v2-b0b7dbbc8c20e3902f100f2a9559c461_r"></figure>
<p class="ztext-empty-paragraph"></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-137607d294efd7120ec195a2f0980d7d_r.jpg" data-caption="" data-size="normal" data-rawwidth="1616" data-rawheight="1080" class="origin_image zh-lightbox-thumb" width="1616" data-original="https://pic2.zhimg.com/v2-137607d294efd7120ec195a2f0980d7d_b.jpg" title="v2-137607d294efd7120ec195a2f0980d7d_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-137607d294efd7120ec195a2f0980d7d_r.jpg" data-caption="" data-size="normal" data-rawwidth="1616" data-rawheight="1080" class="origin_image zh-lightbox-thumb lazy" width="1616" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1616'%20height='1080'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-137607d294efd7120ec195a2f0980d7d_b.jpg" title="v2-137607d294efd7120ec195a2f0980d7d_r"></figure>
<p>上午第三場是螞蟻金服體驗技術部的數據可視化負責人林峰，他展示了業界首次探究體驗分的計算模型，提供以⽤戶為中心的UBA + APM 閉環下的體驗洞察，讓產品體驗可度量、可優化、可監控，演講視頻可見<a href="https://link.zhihu.com/?target=http%3A//v.youku.com/v_show/id_XNDAwMzI4MzI0OA%3D%3D.html%3Fspm%3Da2h1n.8251843.playList.5%214~5~A%26f%3D52028043%26o%3D1" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">《科技與人文結合的體驗度量》</a> 。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-278f2340d6e381881a6c3a6ff1c2bd2b_r.jpg" data-caption="" data-size="normal" data-rawwidth="4096" data-rawheight="2730" class="origin_image zh-lightbox-thumb" width="4096" data-original="https://pic4.zhimg.com/v2-278f2340d6e381881a6c3a6ff1c2bd2b_b.jpg" title="v2-278f2340d6e381881a6c3a6ff1c2bd2b_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-278f2340d6e381881a6c3a6ff1c2bd2b_r.jpg" data-caption="" data-size="normal" data-rawwidth="4096" data-rawheight="2730" class="origin_image zh-lightbox-thumb lazy" width="4096" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='4096'%20height='2730'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-278f2340d6e381881a6c3a6ff1c2bd2b_b.jpg" title="v2-278f2340d6e381881a6c3a6ff1c2bd2b_r"></figure>
<p>除了會場內的分享，場外互動區的精彩也吸引了大量參會者，這裡集中展示了螞蟻金服近幾年沈淀的體驗科技類產品，包含大家熟知的Ant Design、AntV、雲鳳蝶、小錢袋等等。參會的小伙伴們與展台工作人員展開了密切交流。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-9047820d42d2ff6f50e0a056987bc3a7_r.jpg" data-caption="" data-size="normal" data-rawwidth="1616" data-rawheight="1080" class="origin_image zh-lightbox-thumb" width="1616" data-original="https://pic4.zhimg.com/v2-9047820d42d2ff6f50e0a056987bc3a7_b.jpg" title="v2-9047820d42d2ff6f50e0a056987bc3a7_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-9047820d42d2ff6f50e0a056987bc3a7_r.jpg" data-caption="" data-size="normal" data-rawwidth="1616" data-rawheight="1080" class="origin_image zh-lightbox-thumb lazy" width="1616" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1616'%20height='1080'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-9047820d42d2ff6f50e0a056987bc3a7_b.jpg" title="v2-9047820d42d2ff6f50e0a056987bc3a7_r"></figure>
<p class="ztext-empty-paragraph"></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-ea564902780a3796d394f394d3193fd8_r.jpg" data-caption="" data-size="normal" data-rawwidth="4096" data-rawheight="2730" class="origin_image zh-lightbox-thumb" width="4096" data-original="https://pic1.zhimg.com/v2-ea564902780a3796d394f394d3193fd8_b.jpg" title="v2-ea564902780a3796d394f394d3193fd8_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-ea564902780a3796d394f394d3193fd8_r.jpg" data-caption="" data-size="normal" data-rawwidth="4096" data-rawheight="2730" class="origin_image zh-lightbox-thumb lazy" width="4096" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='4096'%20height='2730'&gt;&lt;/svg&gt;" data-actualsrc="https://pic1.zhimg.com/v2-ea564902780a3796d394f394d3193fd8_b.jpg" title="v2-ea564902780a3796d394f394d3193fd8_r"></figure>
<p>下午場首先是來自浙江大學計算機科學與技術學院王銳教授帶來《<b>實時繪製的過去、現在與將來</b>》，介紹了實時繪製技術的原理及驅動其發展的硬件與軟件技術的發展歷程，在總結實時繪製技術的現狀後，還對實時繪製技術的未來演進做出了展望。 <a href="https://link.zhihu.com/?target=http%3A//v.youku.com/v_show/id_XNDAwMzM3MjYyOA%3D%3D.html%3Fspm%3Da2h1n.8251843.playList.5%215~5~A%26f%3D52028043%26o%3D1" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">點擊查看演講視頻</a></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-18caa470194193c0f722294567d5ada6_r.jpg" data-caption="" data-size="normal" data-rawwidth="1616" data-rawheight="1080" class="origin_image zh-lightbox-thumb" width="1616" data-original="https://pic3.zhimg.com/v2-18caa470194193c0f722294567d5ada6_b.jpg" title="v2-18caa470194193c0f722294567d5ada6_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-18caa470194193c0f722294567d5ada6_r.jpg" data-caption="" data-size="normal" data-rawwidth="1616" data-rawheight="1080" class="origin_image zh-lightbox-thumb lazy" width="1616" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1616'%20height='1080'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-18caa470194193c0f722294567d5ada6_b.jpg" title="v2-18caa470194193c0f722294567d5ada6_r"></figure>
<p>自荷馬的時代以來，講故事就是一項悠久而傳統的技能。故事與數據可視化的結合會產生更大的想像空間，米法在《<b>數據可視化之Story Telling</b> 》的演講中，通過對泰坦尼克號和颱風迴旋曲兩段數據集的可視化講述，讓數據變得更加直觀易懂，進而提煉出可視化story telling 的流程和方法。 <a href="https://link.zhihu.com/?target=http%3A//v.youku.com/v_show/id_XNDAwMzk0MTg2NA%3D%3D.html%3Fspm%3Da2h1n.8251843.playList.5%216~5~A%26f%3D52028043%26o%3D1" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">點擊查看演講視頻</a></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-21438ad52e25cd4112375f317ac4920d_r.jpg" data-caption="" data-size="normal" data-rawwidth="1616" data-rawheight="1080" class="origin_image zh-lightbox-thumb" width="1616" data-original="https://pic2.zhimg.com/v2-21438ad52e25cd4112375f317ac4920d_b.jpg" title="v2-21438ad52e25cd4112375f317ac4920d_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-21438ad52e25cd4112375f317ac4920d_r.jpg" data-caption="" data-size="normal" data-rawwidth="1616" data-rawheight="1080" class="origin_image zh-lightbox-thumb lazy" width="1616" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1616'%20height='1080'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-21438ad52e25cd4112375f317ac4920d_b.jpg" title="v2-21438ad52e25cd4112375f317ac4920d_r"></figure>
<p>雲謙講述了螞蟻金服自2015年應用React開始的自研前端框架之路，從Roof到Redux到DvaJS，再到UmiJS，期間有很多收穫，也踩了很多坑，他的演講《<b>螞蟻金服前端框架探索之路</b>》為大家分享了這中間的心路歷程。 <a href="https://link.zhihu.com/?target=http%3A//v.youku.com/v_show/id_XNDAwNDA0ODUxNg%3D%3D.html%3Fspm%3Da2h1n.8251843.playList.5%217~5~A%26f%3D52028043%26o%3D1" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">點擊查看演講視頻</a></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-11d16670dc6ecb2d49e1bc1de8f215df_r.jpg" data-caption="" data-size="normal" data-rawwidth="4032" data-rawheight="3024" class="origin_image zh-lightbox-thumb" width="4032" data-original="https://pic4.zhimg.com/v2-11d16670dc6ecb2d49e1bc1de8f215df_b.jpg" title="v2-11d16670dc6ecb2d49e1bc1de8f215df_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-11d16670dc6ecb2d49e1bc1de8f215df_r.jpg" data-caption="" data-size="normal" data-rawwidth="4032" data-rawheight="3024" class="origin_image zh-lightbox-thumb lazy" width="4032" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='4032'%20height='3024'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-11d16670dc6ecb2d49e1bc1de8f215df_b.jpg" title="v2-11d16670dc6ecb2d49e1bc1de8f215df_r"></figure>
<p>螞蟻莊園的悠鶴，分享了他們是如何去精心打磨螞蟻莊園這款國民級“養雞” 應用，通過一些列的技術手段和優化，將螞蟻莊園的用戶體驗極大地提升，並且依然在極致體驗的提昇路上，演講視頻請查看<a href="https://link.zhihu.com/?target=http%3A//v.youku.com/v_show/id_XNDAwNDE3NjMwOA%3D%3D.html%3Fspm%3Da2h1n.8251843.playList.5%218~5~A%26f%3D52028043%26o%3D1" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">《螞蟻莊園背後的技術與思考》</a> 。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-57be9c1747dfcb5fabbb45c75c8b2d6d_r.jpg" data-caption="" data-size="normal" data-rawwidth="4032" data-rawheight="3024" class="origin_image zh-lightbox-thumb" width="4032" data-original="https://pic2.zhimg.com/v2-57be9c1747dfcb5fabbb45c75c8b2d6d_b.jpg" title="v2-57be9c1747dfcb5fabbb45c75c8b2d6d_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-57be9c1747dfcb5fabbb45c75c8b2d6d_r.jpg" data-caption="" data-size="normal" data-rawwidth="4032" data-rawheight="3024" class="origin_image zh-lightbox-thumb lazy" width="4032" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='4032'%20height='3024'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-57be9c1747dfcb5fabbb45c75c8b2d6d_b.jpg" title="v2-57be9c1747dfcb5fabbb45c75c8b2d6d_r"></figure>
<p>今年我們的設計分會場同樣熱火朝天，海納和竹爾帶來Ant Design 資產一起造workshop，通過工作坊的方式，還原界面資產的提煉過程，在場演練定義美觀、系統的風格化指南的技巧。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-240833cf0df9e4e98df33ecfcc964973_r.jpg" data-caption="" data-size="normal" data-rawwidth="1656" data-rawheight="1242" class="origin_image zh-lightbox-thumb" width="1656" data-original="https://pic4.zhimg.com/v2-240833cf0df9e4e98df33ecfcc964973_b.jpg" title="v2-240833cf0df9e4e98df33ecfcc964973_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-240833cf0df9e4e98df33ecfcc964973_r.jpg" data-caption="" data-size="normal" data-rawwidth="1656" data-rawheight="1242" class="origin_image zh-lightbox-thumb lazy" width="1656" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1656'%20height='1242'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-240833cf0df9e4e98df33ecfcc964973_b.jpg" title="v2-240833cf0df9e4e98df33ecfcc964973_r"></figure>
<p class="ztext-empty-paragraph"></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-9efa8bb02a4189b860f0c33096b342d5_r.jpg" data-caption="" data-size="normal" data-rawwidth="1280" data-rawheight="960" class="origin_image zh-lightbox-thumb" width="1280" data-original="https://pic2.zhimg.com/v2-9efa8bb02a4189b860f0c33096b342d5_b.jpg" title="v2-9efa8bb02a4189b860f0c33096b342d5_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-9efa8bb02a4189b860f0c33096b342d5_r.jpg" data-caption="" data-size="normal" data-rawwidth="1280" data-rawheight="960" class="origin_image zh-lightbox-thumb lazy" width="1280" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1280'%20height='960'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-9efa8bb02a4189b860f0c33096b342d5_b.jpg" title="v2-9efa8bb02a4189b860f0c33096b342d5_r"></figure>
<p>它山、林外等帶來圓桌沙龍：Ant Designers 面對面，為大家答疑解惑、熱烈交流，與大家一同探討Ant Design 的最新動向與去向何方。</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-c01417460bd395ba5667f4b3cd96d24b_r.jpg" data-caption="" data-size="normal" data-rawwidth="1616" data-rawheight="1080" class="origin_image zh-lightbox-thumb" width="1616" data-original="https://pic4.zhimg.com/v2-c01417460bd395ba5667f4b3cd96d24b_b.jpg" title="v2-c01417460bd395ba5667f4b3cd96d24b_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-c01417460bd395ba5667f4b3cd96d24b_r.jpg" data-caption="" data-size="normal" data-rawwidth="1616" data-rawheight="1080" class="origin_image zh-lightbox-thumb lazy" width="1616" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1616'%20height='1080'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-c01417460bd395ba5667f4b3cd96d24b_b.jpg" title="v2-c01417460bd395ba5667f4b3cd96d24b_r"></figure>
<p class="ztext-empty-paragraph"></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-73344ab8bd30f0744d81aa8cf49a88d1_r.jpg" data-caption="" data-size="normal" data-rawwidth="3359" data-rawheight="2135" class="origin_image zh-lightbox-thumb" width="3359" data-original="https://pic2.zhimg.com/v2-73344ab8bd30f0744d81aa8cf49a88d1_b.jpg" title="v2-73344ab8bd30f0744d81aa8cf49a88d1_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-73344ab8bd30f0744d81aa8cf49a88d1_r.jpg" data-caption="" data-size="normal" data-rawwidth="3359" data-rawheight="2135" class="origin_image zh-lightbox-thumb lazy" width="3359" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='3359'%20height='2135'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-73344ab8bd30f0744d81aa8cf49a88d1_b.jpg" title="v2-73344ab8bd30f0744d81aa8cf49a88d1_r"></figure>
<p>大會參會者集體合影</p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-da5cc018e28a91519d3df28c761ffda9_r.jpg" data-caption="" data-size="normal" data-rawwidth="4096" data-rawheight="2730" class="origin_image zh-lightbox-thumb" width="4096" data-original="https://pic2.zhimg.com/v2-da5cc018e28a91519d3df28c761ffda9_b.jpg" title="v2-da5cc018e28a91519d3df28c761ffda9_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-da5cc018e28a91519d3df28c761ffda9_r.jpg" data-caption="" data-size="normal" data-rawwidth="4096" data-rawheight="2730" class="origin_image zh-lightbox-thumb lazy" width="4096" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='4096'%20height='2730'&gt;&lt;/svg&gt;" data-actualsrc="https://pic2.zhimg.com/v2-da5cc018e28a91519d3df28c761ffda9_b.jpg" title="v2-da5cc018e28a91519d3df28c761ffda9_r"></figure>
<p>以上就是本次大會議的全部內容，讓我們一起期待下一屆SEE Conf！</p>
<p>歡迎大家回答本次大會相關的知乎問題：</p>
<p class="ztext-empty-paragraph"></p>
<p class="ztext-empty-paragraph"></p>
<p>最後，演講相關的PPT 已上傳至SEE Conf 語雀在線知識庫，歡迎大家下載。</p>
<p><a href="https://link.zhihu.com/?target=https%3A//www.yuque.com/seeconf/content/kbnzac" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">點此前往語雀下載</a></p>
<p class="ztext-empty-paragraph"></p>
<p>關注我們：<a href="https://zhuanlan.zhihu.com/xtech" class="internal" data-wpel-link="external" rel="nofollow external noopener noreferrer">螞蟻金服體驗科技知乎專欄</a>| <a href="https://link.zhihu.com/?target=https%3A//weibo.com/u/6420205486" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">螞蟻金服體驗科技官微</a>| <a href="https://link.zhihu.com/?target=https%3A//xcloud.alipay.com/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">螞蟻金服體驗科技官網</a></p>
</div>
</div>
</article>
<p>The post <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com/software-engineering/front-end-dev/14307/topic-54459056/" data-wpel-link="internal">第二屆SEE Conf 2019 精彩回顧（附PPT 及視頻）</a> appeared first on <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com" data-wpel-link="internal">成長駭客交流第一站 - HyperGrowths™</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>第二屆螞蟻金服體驗科技大會</title>
		<link>https://hypergrowths.com/software-engineering/front-end-dev/14239/topic-51468853/</link>
		
		<dc:creator><![CDATA[marketer]]></dc:creator>
		<pubDate>Sat, 30 Jan 2021 17:54:45 +0000</pubDate>
				<category><![CDATA[前端開發]]></category>
		<category><![CDATA[支付寶體驗科技]]></category>
		<guid isPermaLink="false">https://hypergrowths.com/software-engineering/front-end-dev/14239/topic-51468853/</guid>

					<description><![CDATA[<p>SEE = Seeking Experience &#38; Engineering，意為探索用戶體驗與工程實踐，由螞蟻金服集團舉辦，包括專業分享、產品展台、Workshop 等內容。我們希望通過SEE Conf，能與業界同行一起分享交流體驗科技的當前進展…</p>
<p>The post <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com/software-engineering/front-end-dev/14239/topic-51468853/" data-wpel-link="internal">第二屆螞蟻金服體驗科技大會</a> appeared first on <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com" data-wpel-link="internal">成長駭客交流第一站 - HyperGrowths™</a>.</p>
]]></description>
										<content:encoded><![CDATA[<article class="Post-Main Post-NormalMain" tabindex="-1">
<header class="Post-Header">
<h1 class="Post-Title">第二屆螞蟻金服體驗科技大會</h1>
<div class="Post-Author">
<div class="AuthorInfo" itemprop="author" itemscope="" itemtype="http://schema.org/Person"><meta itemprop="name" content="vagusX"><meta itemprop="image" content="https://pic1.zhimg.com/cec097b0928764539c704c26be683afa_l.jpg?source=172ae18b"><meta itemprop="url" content="https://www.zhihu.com/people/vagusx"><meta itemprop="zhihu:followerCount"></div>
</div>
</header>
<div class="Post-RichTextContainer">
<div class="RichText ztext Post-RichText">
<p>SEE = Seeking Experience &amp; Engineering，意為探索用戶體驗與工程實踐，由螞蟻金服集團舉辦，包括專業分享、產品展台、Workshop 等內容。我們希望通過SEE Conf，能與業界同行一起分享交流體驗科技的當前進展，一起探討切磋體驗科技的未來發展，共同努力促進體驗設計與技術的開放，讓生態繁榮共贏。</p>
<p>繼首屆SEE Conf 成功舉辦後，第二屆SEE Conf 將於2019.01.05（週六）在浙江杭州的螞蟻Z 空間舉辦。</p>
<p>這次我們邀請來同濟大學婁永琪院長和浙江大學王銳教授帶我們走入學術前沿，還有大量螞蟻金服體驗科技相關的主題分享，期待你來參與。</p>
<p><a href="https://link.zhihu.com/?target=https%3A//seeconf.antfin.com/%3Ffrom%3Dzhihu" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">立即報名</a></p>
<h2>會議日程</h2>
<h2>主會場</h2>
<ul>
<li>9:00 - 9:15：開幕致辭</li>
<li>9:15 - 10:15：交互設計與人類未來</li>
<li>10:05 - 11:00：Ant Design 情感化設計</li>
<li>11:15 - 12:00：科技與人文結合的體驗度量</li>
<li>12:00 - 14:00：午餐時間</li>
<li>14:00 - 14:45：實時繪製的過去、現在與將來</li>
<li>15:00 - 15:45：數據可視化之Story Telling</li>
<li> 15:45 - 16:15：活動/ 茶歇</li>
<li>16:15 - 17:00：螞蟻金服前端框架探索之路</li>
<li>17:15 - 18:00：螞蟻莊園背後的技術與思考</li>
</ul>
<h2>分會場</h2>
<ul>
<li>14:00 - 15:45：Workshop：Ant Design 資產一起造</li>
<li>15:45 - 16:15：活動/ 茶歇</li>
<li>16:15 - 18:00：圓桌沙龍：Ant Designers 面對面</li>
</ul>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-bfdf59efe4872732a5ae8269311c438e_r.jpg" data-caption="" data-size="normal" data-rawwidth="1440" data-rawheight="578" class="origin_image zh-lightbox-thumb" width="1440" data-original="https://pic3.zhimg.com/v2-bfdf59efe4872732a5ae8269311c438e_b.jpg" title="v2-bfdf59efe4872732a5ae8269311c438e_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-bfdf59efe4872732a5ae8269311c438e_r.jpg" data-caption="" data-size="normal" data-rawwidth="1440" data-rawheight="578" class="origin_image zh-lightbox-thumb lazy" width="1440" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1440'%20height='578'&gt;&lt;/svg&gt;" data-actualsrc="https://pic3.zhimg.com/v2-bfdf59efe4872732a5ae8269311c438e_b.jpg" title="v2-bfdf59efe4872732a5ae8269311c438e_r"></figure>
<h2>大會看點</h2>
<p>過去40 年台灣從物質極度匱乏時代迅速發展為物質過剩的時代，經濟快速發展的同時，一方面帶來了巨大的經濟成就，另一方面也帶來了大量可持續發展的問題。那麼體驗和設計，是否是開啟未來人類可持續發展的金鑰匙呢？本次我們非常榮幸邀請到同濟大學設計與創意學院<a href="https://link.zhihu.com/?target=https%3A//baike.baidu.com/item/%25E5%25A8%2584%25E6%25B0%25B8%25E7%2590%25AA" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">婁永琪</a>院長，為大家帶來<b>交互設計與人類未來</b>的相關探索。</p>
<p>技術是人類快速改造世界的手段，學術研究是技術發展的基石和前沿。在計算機上呈現一個高真實感的虛擬世界，是人們長久以來的一個夢想，而實時繪製技術則是其中的<b>核心技術</b>。本屆大會我們榮幸的邀請到浙江大學計算機科學與技術學院<a href="https://link.zhihu.com/?target=http%3A//www.cad.zju.edu.cn/home/rwang/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">王銳</a>教授，為我們揭開實時繪製技術的神秘面紗。</p>
<p><b>沒有度量，就沒有優化。</b>提升體驗是大家共同的使命和目標，但長久以來，如何評估體驗是困擾體驗技術人的最大難題之一。本次螞蟻金服數據可視化部負責人<b>禦術</b>將為大家帶來螞蟻金服體驗技術部在這個方向上的探索。</p>
<p>螞蟻<b>企業級前端框架</b><a href="https://link.zhihu.com/?target=https%3A//github.com/umijs" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">UmiJS</a>正式上線9個月，在Github收穫了3,000個star，作為目前在螞蟻內最流行的前端框架。從Redux到<a href="https://link.zhihu.com/?target=https%3A//github.com/dvajs" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">DvaJS</a>再到UmiJS ，它背後的思考是什麼？坑是什麼？收穫是什麼？</p>
<p>多年前知名媒體人柴靜，一場《穹頂之下》發布會，引爆了台灣社會對於霧霾的熱烈討論。會後很多媒體人會探究為何那次調查發布會有如此的感染力？各大媒體都紛紛總結出用<b>大量的數據可視化的形式說故事</b>，這讓論點不但有理，而且有據。本次，我們邀請了螞蟻金服數據可視化專家（前新華社技術總監）<b>米法</b>為大家帶來，數據可視化之story telling的相關分享。</p>
<p>螞蟻莊園作為支付寶UV 千萬級別的超級應用，開發者在開發過程中，精心打磨產品，追求極致體驗。那麼，它背後的技術是什麼呢？產品的心智是什麼？這隻小雞又是怎麼一步一步，從雛鳥長成雄鷹的呢？</p>
<p><a href="https://link.zhihu.com/?target=https%3A//ant.design/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Ant Design</a>是螞蟻金服的明星產品，過去1年Github的star數翻番到達36,000+，在本屆大會原班人馬帶我們近距離立體式觀察它，看如何通過Ant Design的情感化設計完善企業級產品。值得一提的是，本次大會除了主會場的報告外，我們還另外開闢分會場讓大家有機會<b>零距離</b>跟Ant Design設計師一起對它展開探討。</p>
<h2>如何報名</h2>
<p>訪問<a href="https://link.zhihu.com/?target=https%3A//seeconf.antfin.com/%3Ffrom%3Dzhihu" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">SEE Conf ·螞蟻金服體驗科技大會</a>，點擊「立即報名」按鈕</p>
</div>
</div>
</article>
<p>The post <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com/software-engineering/front-end-dev/14239/topic-51468853/" data-wpel-link="internal">第二屆螞蟻金服體驗科技大會</a> appeared first on <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com" data-wpel-link="internal">成長駭客交流第一站 - HyperGrowths™</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Redux-Saga 漫談</title>
		<link>https://hypergrowths.com/software-engineering/front-end-dev/13839/topic-35437092/</link>
		
		<dc:creator><![CDATA[marketer]]></dc:creator>
		<pubDate>Sat, 30 Jan 2021 17:35:26 +0000</pubDate>
				<category><![CDATA[前端開發]]></category>
		<category><![CDATA[支付寶體驗科技]]></category>
		<guid isPermaLink="false">https://hypergrowths.com/software-engineering/front-end-dev/13839/topic-35437092/</guid>

					<description><![CDATA[<p>原文有更好的閱讀體驗：《Redux-Saga 漫談》。新知識很多，且學且珍惜。在選擇要係統地學習一個新的框架/庫之前，首先至少得學會先去思考以下兩點： 它是什麼？它解決了什麼問題？然後，才會帶著更多的好奇…</p>
<p>The post <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com/software-engineering/front-end-dev/13839/topic-35437092/" data-wpel-link="internal">Redux-Saga 漫談</a> appeared first on <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com" data-wpel-link="internal">成長駭客交流第一站 - HyperGrowths™</a>.</p>
]]></description>
										<content:encoded><![CDATA[<article class="Post-Main Post-NormalMain" tabindex="-1">
<header class="Post-Header">
<h1 class="Post-Title">Redux-Saga 漫談</h1>
<div class="Post-Author">
<div class="AuthorInfo" itemprop="author" itemscope="" itemtype="http://schema.org/Person"><meta itemprop="name" content="Lovesueee"><meta itemprop="image" content="https://pic1.zhimg.com/v2-400bb9d4c9b5ed49448f3a927d1c2338_l.jpg?source=172ae18b"><meta itemprop="url" content="https://www.zhihu.com/people/lovesueee"><meta itemprop="zhihu:followerCount"></div>
</div>
</header>
<div class="Post-RichTextContainer">
<div class="RichText ztext Post-RichText">
<p>原文有更好的閱讀體驗<a href="https://link.zhihu.com/?target=https%3A//yuque.com/lovesueee/blog/redux-saga" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">：《Redux-Saga漫談</a>》。</p>
<p class="ztext-empty-paragraph"></p>
<blockquote><p>新知識很多，且學且珍惜。</p></blockquote>
<p class="ztext-empty-paragraph"></p>
<p>在選擇要係統地學習一個新的<b>框架/庫</b>之前，首先至少得學會先去思考以下兩點：</p>
<p class="ztext-empty-paragraph"></p>
<ul>
<li>它是什麼？</li>
<li>它解決了什麼問題？</li>
</ul>
<p class="ztext-empty-paragraph"></p>
<p>然後，才會帶著更多的好奇心去了解：它的由來、它名字的含義、它引申的一些概念，以及它具體的使用方式...</p>
<p class="ztext-empty-paragraph"></p>
<p><i>本文嘗試通過<b>自我學習/自我思考</b>的方式，談談對redux-saga的學習和理解。</i></p>
<p class="ztext-empty-paragraph"></p>
<h2>學前指引</h2>
<p class="ztext-empty-paragraph"></p>
<p><a href="https://link.zhihu.com/?target=https%3A//github.com/redux-saga/redux-saga" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">『Redux-Saga』</a>是一個<b>庫（Library）</b> ，更細緻一點地說，大部分情況下，它是以<a href="https://link.zhihu.com/?target=https%3A//redux.js.org/advanced/middleware" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Redux中間件</a>的形式而存在，主要是為了更優雅地<b>管理</b>Redux應用程序中的<b>副作用（Side Effects ）。</b></p>
<p class="ztext-empty-paragraph"></p>
<p><i>那麼，什麼是Side Effects?</i></p>
<p class="ztext-empty-paragraph"></p>
<h2><b>Side Effects</b></h2>
<p class="ztext-empty-paragraph"></p>
<p>來看看<a href="https://link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Side_effect_%28computer_science%29" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Wikipedia</a>的專業解釋（敲黑板，劃重點）：</p>
<p class="ztext-empty-paragraph"></p>
<blockquote><p>Side effects are the most common way that a program interacts with the outside world (people, filesystems, other computers on networks).</p></blockquote>
<p class="ztext-empty-paragraph"></p>
<p>映射在Javascript程序中，Side Effects主要指的就是：<b>異步網絡請求</b>、<b>本地讀取localStorage/Cookie</b>等外界操作：</p>
<p class="ztext-empty-paragraph"></p>
<blockquote><p>Asynchronous things like <b>data fetching</b> and impure things like <b>accessing the browser cache</b></p></blockquote>
<p class="ztext-empty-paragraph"></p>
<p>雖然中文上翻譯成“副作用”，但並不意味著不好，這完全取決於特定的<a href="https://link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Programming_paradigm" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Programming Paradigm</a> （編程範式），比如說：</p>
<p class="ztext-empty-paragraph"></p>
<blockquote><p><a href="https://link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Imperative_programming" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Imperative programming</a> is known for its frequent utilization of side effects.</p></blockquote>
<p class="ztext-empty-paragraph"></p>
<p>所以，在Web應用，側重點在於Side Effects的<b>優雅管理（manage）</b> ，而不是<b>消除（eliminate）</b> 。</p>
<p class="ztext-empty-paragraph"></p>
<p><i>說到這裡，很多人就會有疑問：相比於</i><a href="https://link.zhihu.com/?target=https%3A//github.com/gaearon/redux-thunk" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">redux-thunk</a><i>或者</i><a href="https://link.zhihu.com/?target=https%3A//github.com/redux-utilities/redux-promise" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">redux-promise</a> <i>，同樣在處理Side Effects（比如：異步請求）的問題上，redux-saga會有什麼優勢？</i></p>
<p class="ztext-empty-paragraph"></p>
<h2>Saga vs Thunk</h2>
<p class="ztext-empty-paragraph"></p>
<blockquote><p>這裡是指<b>redux-saga</b> vs <b>redux-thunk</b> 。</p></blockquote>
<p class="ztext-empty-paragraph"></p>
<p>首先，從簡單的字面意義就能看出：<b>背後的思想來源不同</b>—— <a href="https://link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Thunk" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Thunk</a> vs <a href="https://link.zhihu.com/?target=http%3A//microservices.io/patterns/data/saga.html" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Saga Pattern</a> 。</p>
<p class="ztext-empty-paragraph"></p>
<p>這裡就不展開講述了，感興趣的同學，推薦認真閱讀以下兩篇文章：</p>
<p class="ztext-empty-paragraph"></p>
<ul>
<li><a href="https://link.zhihu.com/?target=https%3A//frontendmasters.com/courses/rethinking-async-js/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">《Thunk | Rethinking Asynchronous Javascript》</a></li>
<li> <a href="https://link.zhihu.com/?target=https%3A//blog.couchbase.com/saga-pattern-implement-business-transactions-using-microservices-part-2/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">《Saga Pattern | How to implement business transactions using Microservices》</a></li>
</ul>
<p class="ztext-empty-paragraph"></p>
<p>其次，再從程序的角度來看：<b>使用方式上的不同</b>。</p>
<p class="ztext-empty-paragraph"></p>
<p><i><b>Note：</b>以下範例會省去部分Redux代碼，如果你對Redux相關知識還不太了解，那麼</i><a href="https://link.zhihu.com/?target=http%3A//www.cnblogs.com/lovesueee/p/5199686.html" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">《Redux卍解》</a><i>了解一下。</i></p>
<p class="ztext-empty-paragraph"></p>
<h2>redux-thunk</h2>
<p class="ztext-empty-paragraph"></p>
<p>一般情況下，actions都是符合<a href="https://link.zhihu.com/?target=https%3A//github.com/redux-utilities/flux-standard-action" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">FSA</a>標準的（即：a plain javascript object），像下面這樣：</p>
<p class="ztext-empty-paragraph"></p>
<div class="highlight">
<pre><code class="language-text">{ type: 'ADD_TODO', payload: { text: 'Do something.' } };</code></pre>
</div>
<p class="ztext-empty-paragraph"></p>
<p>它代表的含義是：每次執行<code>dispatch(action)</code>會通知reducer<u>將action.payload（數據）以action.type的方式（操作）</u><b>同步更新</b>到本地store 。</p>
<p class="ztext-empty-paragraph"></p>
<p>而一個豐富多變的Web應用，payload數據往往來自於遠端服務器，為了能將<b>異步獲取數據</b>這部分代碼跟UI解耦，redux-thunk選擇以middleware的形式來增強redux store的dispatch方法（即：支持了<code>dispatch(function)</code> ），從而在擁有了<u>異步獲取數據能力</u>的同時，又可以進一步將<u>數據獲取相關的業務邏輯</u>從View層分離出去。</p>
<p class="ztext-empty-paragraph"></p>
<p>來看看以下代碼：</p>
<p class="ztext-empty-paragraph"></p>
<div class="highlight">
<pre><code class="language-text">// action.js // --------- // actionCreator(eg fetchData) 返回function // function 中包含了业务数据请求代码逻辑// 以回调的方式，分别处理请求成功和请求失败的情况export function fetchData(someValue) { return (dispatch, getState) =&gt; { myAjaxLib.post("/someEndpoint", { data: someValue }) .then(response =&gt; dispatch({ type: "REQUEST_SUCCEEDED", payload: response }) .catch(error =&gt; dispatch({ type: "REQUEST_FAILED", error: error }); }; } // component.js // ------------ // View 层dispatch(fn) 触发异步请求// 这里省略部分代码this.props.dispatch(fetchData({ hello: 'saga' }));</code></pre>
</div>
<p class="ztext-empty-paragraph"></p>
<p><i>如果同樣的功能，用redux-saga如何實現呢？它的優勢在哪裡？</i></p>
<p class="ztext-empty-paragraph"></p>
<h2>redux-saga</h2>
<p class="ztext-empty-paragraph"></p>
<p>先來看下代碼，大致感受下（後面會細講）：</p>
<div class="highlight">
<pre><code class="language-text">// saga.js // ------- // worker saga // 它是一个generator function // fn 中同样包含了业务数据请求代码逻辑// 但是代码的执行逻辑：看似同步(synchronous-looking) function* fetchData(action) { const { payload: { someValue } } = action; try { const result = yield call(myAjaxLib.post, "/someEndpoint", { data: someValue }); yield put({ type: "REQUEST_SUCCEEDED", payload: response }); } catch (error) { yield put({ type: "REQUEST_FAILED", error: error }); } } // watcher saga // 监听每一次dispatch(action) // 如果action.type === 'REQUEST'，那么执行fetchData export function* watchFetchData() { yield takeEvery('REQUEST', fetchData); } // component.js // ------- // View 层dispatch(action) 触发异步请求// 这里的action 依然可以是一个plain object this.props.dispatch({ type: 'REQUEST', payload: { someValue: { hello: 'saga' } } });</code></pre>
</div>
<p class="ztext-empty-paragraph"></p>
<p>將從上面的代碼，與之前的進行對比，可以歸納以下幾點：</p>
<ul>
<li><u>數據獲取相關的業務邏輯</u>被轉移到單獨saga.js中，不再是摻雜在action.js或component.js中。</li>
<li> dispatch 的參數依然是一個純粹的action (FSA)，而不是充滿“黑魔法” thunk function。</li>
<li>每一個saga都是一個generator function，代碼採用<b>同步書寫</b>的方式來處理<b>異步邏輯</b>（No <a href="https://link.zhihu.com/?target=http%3A//callbackhell.com/" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">Callback Hell</a> ），代碼變得更易讀（沒錯，這很co~ ）。</li>
<li>同樣是受益於generator function 的saga 實現，代碼異常/請求失敗都可以直接通過try/catch 語法直接捕獲處理。</li>
</ul>
<p class="ztext-empty-paragraph"></p>
<p class="ztext-empty-paragraph"></p>
<h2>深入學習</h2>
<p class="ztext-empty-paragraph"></p>
<blockquote><p>最簡單完整的一個單向數據流，從hello saga 說起。</p></blockquote>
<p class="ztext-empty-paragraph"></p>
<p><b>先來看看，如何將store和saga關聯起來？</b></p>
<p class="ztext-empty-paragraph"></p>
<div class="highlight">
<pre><code class="language-text">import { createStore, applyMiddleware } from 'redux'; import createSagaMiddleware from 'redux-saga'; import rootSaga from './sagas'; import rootReducer from './reducers'; // 创建saga middleware const sagaMiddleware = createSagaMiddleware(); // 注入saga middleware const enhancer = applyMiddleware(sagaMiddleware); // 创建store const store = createStore(rootReducer, /* preloadedState, */ enhancer); // 启动saga sagaMiddleWare.run(rootSaga);</code></pre>
</div>
<p class="ztext-empty-paragraph"></p>
<p>代碼分析：</p>
<p class="ztext-empty-paragraph"></p>
<ul>
<li>8L：通過工廠函數<code>createSagaMiddleware</code>創建sagaMiddleware（當然創建時，你也可以傳遞一些可選的<a href="https://link.zhihu.com/?target=https%3A//redux-saga.js.org/docs/api/%23createsagamiddlewareoptions" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">配置參數</a>）。</li>
<li> 10L~13L：注入sagaMiddleware，並創建store實例，意味著：之後每次執行<code>store.dispatch(action)</code> ，數據流都會經過sagaMiddleware這一道工序，進行必要的“加工處理”（比如：發送一個異步請求） 。</li>
<li> 16L：啟動saga，也就是執行rootSaga，通常是程序的一些初始化操作（比如：初始化數據、註冊action 監聽）。</li>
</ul>
<p class="ztext-empty-paragraph"></p>
<p>整合以上分析：程序啟動時， <code>run(rootSaga)</code>會開啟sagaMiddleware對某些action進行監聽，當後續程序中有觸發<code>dispatch(action)</code> （比如：用戶點擊）的時候，由於數據流會經過sagaMiddleware，所以sagaMiddleware能夠判斷當前action 是否有被監聽？如果有，就會進行相應的操作（比如：發送一個異步請求）；如果沒有，則什麼都不做。</p>
<p class="ztext-empty-paragraph"></p>
<p><b>所以來看看，初始化程序時，rootSaga具體可以做些什麼？</b></p>
<p class="ztext-empty-paragraph"></p>
<div class="highlight">
<pre><code class="language-text">// sagas/index.js import { fork, takeEvery, put } from 'redux-saga/effects'; import { push } from 'react-router-redux'; import ajax from '../utils/ajax'; export default function* rootSaga() { // 初始化程序（欢迎语:-D） console.log('hello saga'); // 首次判断用户是否登录yield fork(function* fetchLogin() { try { // 异步请求用户訊息const user = yield call(ajax.get, '/userLogin'); if (user) { // 将用户訊息存入本地store yield put({ type: 'UPDATE_USER', payload: user }) } else { // 路由跳转到403 页面yield put(push('/403')); } } catch (e) { // 请求异常yield put(push('/500')); } }); // watcher saga 监听dispatch 传过来的action // 如果action.type === 'FETCH_POSTS' 那么请求帖子列表数据yield takeEvery('FETCH_POSTS', function* fetchPosts() { // 从store 中获取用户訊息const user = yield select(state =&gt; state.user); if (user) { // TODO: 获取当前用户发的帖子} }); }</code></pre>
</div>
<p class="ztext-empty-paragraph"></p>
<p>如同前面所說，rootSaga 裡面的代碼會在程序啟動時，會依次被執行：</p>
<ul>
<li>8L：控制台同步打印出'hello saga' 歡迎語。</li>
<li> 11L~21L：發起一個異步非阻塞數據請求（Non-Blocking），初始化用戶訊息，也做了一些異常情況的容錯處理。</li>
<li> 31L~38L： <code>takeEvery</code>方法會註冊一個watcher saga，對<code>{ type: 'FETCH_POSTS' }</code>的action實施監聽，後續會執行與之匹配的worker saga（比如：fetchPosts）。</li>
</ul>
<p class="ztext-empty-paragraph"></p>
<p><i><b>PS：</b>通常情況下，在無需進行<b>saga按需加載</b>的情況下，rootSaga裡會集中<b>引入並註冊</b>程序中所有用到的</i><i>watcher saga（就像combine rootReducer那樣）。</i></p>
<p class="ztext-empty-paragraph"></p>
<p class="ztext-empty-paragraph"></p>
<p><b>最後再看看，程序啟動後，一個完整的單向數據流是如何形成的？</b></p>
<p class="ztext-empty-paragraph"></p>
<div class="highlight">
<pre><code class="language-text">import React from 'react'; import { connect } from 'react-redux'; // 关联store 中state.posts 字段(即：帖子列表数据) @connect(({ posts }) =&gt; ({ posts })) class App extends React.PureComponent { componentDidMount() { // dispatch(action) 触发数据请求this.props.dispatch({ type: 'FETCH_POSTS' }); } render() { const { posts = [] } = this.props; return ( &lt;ul&gt; { posts.map((post, index) =&gt; (&lt;li key={index}&gt;{ post.title }&lt;/li&gt;)) } &lt;/ul&gt; ); } } export default App;</code></pre>
</div>
<p class="ztext-empty-paragraph"></p>
<p>當組件<code>&lt;App /&gt;</code>被執行掛載後，通過<code>dispatch({ type: 'FETCH_POSTS' })</code>通知sagaMiddleware尋找到匹配的watcher saga後，執行對應的woker saga，從而發起數據異步請求......最終<code>&lt;App/&gt;</code>會在得到最新posts數據後，執行re-render更新UI。</p>
<hr>
<p>至此，以上三個部分代碼實現了基於redux-saga的一次<b>完整單向數據流，</b>如果用一張圖來表現的話，應該是這樣：</p>
<p class="ztext-empty-paragraph"></p>
<figure data-size="normal"><noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-9697122f53bb1c92a9c455c1b0e5d22f_r.jpg" data-caption="" data-size="normal" data-rawwidth="1076" data-rawheight="353" class="origin_image zh-lightbox-thumb" width="1076" data-original="https://pic4.zhimg.com/v2-9697122f53bb1c92a9c455c1b0e5d22f_b.jpg" title="v2-9697122f53bb1c92a9c455c1b0e5d22f_r"></noscript><img decoding="async" src="https://hypergrowths.com/wp-content/uploads/v2-9697122f53bb1c92a9c455c1b0e5d22f_r.jpg" data-caption="" data-size="normal" data-rawwidth="1076" data-rawheight="353" class="origin_image zh-lightbox-thumb lazy" width="1076" data-original="data:image/svg+xml;utf8,&lt;svg%20xmlns='http://www.w3.org/2000/svg'%20width='1076'%20height='353'&gt;&lt;/svg&gt;" data-actualsrc="https://pic4.zhimg.com/v2-9697122f53bb1c92a9c455c1b0e5d22f_b.jpg" title="v2-9697122f53bb1c92a9c455c1b0e5d22f_r"></figure>
<p class="ztext-empty-paragraph"></p>
<p><i>文章看到這裡，對於一個redux-saga新手而言，可能會留有這樣的疑惑：上述代碼中put/call/fork/takeEvery這些方法是乾什麼用的？這就是接下來要詳細討論的saga effects。</i></p>
<p class="ztext-empty-paragraph"></p>
<p class="ztext-empty-paragraph"></p>
<h2>Effects</h2>
<p class="ztext-empty-paragraph"></p>
<p>前面說到，saga是一個<a href="https://link.zhihu.com/?target=https%3A//developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function%2A" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">generator function</a> ，這就意味著它的執行原理必然是下面這樣：</p>
<p class="ztext-empty-paragraph"></p>
<div class="highlight">
<pre><code class="language-text">function isPromise(value) { return value &amp;&amp; typeof value.then === 'function'; } const iterator = saga(/* ...args */); // 方法一： // 一步一步，手动执行let result; result = iterator.next(); result = iterator.next(result.value); result = iterator.next(result.value); // ... // done!! // 方法二： // 函数封装，自主执行function next(args) { const result = iterator.next(args); if (result.done) { // 执行结束console.log(result.value); } else { // 根据yielded 的值，决定什么时候继续执行（resume） if (isPromise(result.value)) { result.value.then(next); } else { next(result.value) } } } next();</code></pre>
</div>
<p class="ztext-empty-paragraph"></p>
<p>也就是說，generator function在未執行完前（即：result.done === false），它的控制權始終掌握在<b>執行者（caller）</b>手中，即：</p>
<p class="ztext-empty-paragraph"></p>
<ul>
<li>caller決定什麼時候<b>恢復（resume</b> ）執行。</li>
<li> caller決定每次<b>yield expression</b>的返回值。</li>
</ul>
<p class="ztext-empty-paragraph"></p>
<p>而caller本身要實現上面上述功能需要依賴原生API ： <code>iterator.next(value)</code> ，value就是yield expression的返回值。</p>
<p class="ztext-empty-paragraph"></p>
<p>舉個例子：</p>
<p class="ztext-empty-paragraph"></p>
<div class="highlight">
<pre><code class="language-text">function* gen() { const value = yield Promise.reslove('hello saga'); console.log('value: ', value); // value?? }</code></pre>
</div>
<p class="ztext-empty-paragraph"></p>
<p>單純的看gen 函數，沒人知道value 的值會是多少？</p>
<p class="ztext-empty-paragraph"></p>
<p>這完全取決於gen 的執行者（caller），如果使用上面的next 方法來執行它，value 的值就是'hello saga'，因為next 方法對expression 為promise 時，做了特殊處理（這不就是縮小版的co 麼~ wow~⊙o⊙）。</p>
<p class="ztext-empty-paragraph"></p>
<p>換句話說， <b>expression可以是任何值，關鍵是caller如何來解釋expression，並返回合理的值！</b></p>
<p class="ztext-empty-paragraph"></p>
<p>以此結論，推理來看：</p>
<p class="ztext-empty-paragraph"></p>
<ul>
<li>大家熟知的<a href="https://link.zhihu.com/?target=https%3A//github.com/tj/co" class=" wrap external" target="_blank" rel="noreferrer noopener nofollow external" data-wpel-link="external">co</a>可以認為是一個caller，它解釋的expression是：promise/thunk/generator function/iterator等。</li>
<li>這裡的sagaMiddleware 也算是一個caller，它主要解釋的expression 就是effect（當然還可以是promise/iterator） 。</li>
</ul>
<p class="ztext-empty-paragraph"></p>
<p>講了這麼多，那麼effect 到底是什麼呢？先來看看官方解釋：</p>
<p class="ztext-empty-paragraph"></p>
<blockquote><p>An effect is a plain JavaScript Object containing some instructions to be executed by the saga middleware.</p></blockquote>
<p class="ztext-empty-paragraph"></p>
<p>意思是說：effect 本質上是一個普通對象，包含著一些指令訊息，這些指令最終會被saga middleware 解釋並執行。</p>
<p class="ztext-empty-paragraph"></p>
<p>用一段代碼來解釋上述這句話：</p>
<p class="ztext-empty-paragraph"></p>
<div class="highlight">
<pre><code class="language-text">function* fetchData() { // 1. 创建effect const effect = call(ajax.get, '/userLogin'); console.log('effect: ', effect); // effect: // { // CALL: { // context: null, // args: ['/userLogin'], // fn: ajax.get, // } // } // 2. 执行effect，即：调用ajax.get('/userLogin') const value = yield effect; console.log('value: ', value); }</code></pre>
</div>
<p class="ztext-empty-paragraph"></p>
<p>可以明顯的看出：</p>
<p class="ztext-empty-paragraph"></p>
<ul>
<li><b>call</b>方法用來創建effect對象<b>，</b>被稱作是<b>effect factory</b> 。</li>
<li> <b>yield</b>語法將effect對像傳給sagaMiddleware，被解釋執行，並返回值。</li>
</ul>
<p class="ztext-empty-paragraph"></p>
<p>這裡的<b>call effect</b>表示執行<code>ajax.get('user/Login')</code> ，又因為它的返回值是promise，為了等待異步結果返回，fetchData函數會暫時處於<b>阻塞</b>狀態。</p>
<p class="ztext-empty-paragraph"></p>
<p>除了上述所說的call effect 之外，redux-saga 還提供了很多其他effect 類型，它們都是由對應的effect factory 生成，在saga 中應用於不同的場景，比較常用的是：</p>
<p class="ztext-empty-paragraph"></p>
<ul>
<li>put：相當於在saga 中調用store.dispatch(action)。</li>
<li> take：阻塞當前saga，直到接收到指定的action，代碼才會繼續往下執行，有種Event.once() 事件監聽的感覺。</li>
<li> fork: 類似於call effect，區別在於它不會阻塞當前saga，如同後台運行一般，它的返回值是一個task 對象。</li>
<li> cancel：針對fork 方法返回的task ，可以進行取消關閉。</li>
<li> ...等等</li>
</ul>
<p class="ztext-empty-paragraph"></p>
<p><i>其中，比較難以理解的就屬：如何區分call和fork？什麼是阻塞/非阻塞？這是接下來要講的。</i></p>
<p class="ztext-empty-paragraph"></p>
<h2>Call vs Fork</h2>
<p class="ztext-empty-paragraph"></p>
<p>前面已經提到，saga 中call 和fork 都是用來執行指定函數fn，區別在於：</p>
<p class="ztext-empty-paragraph"></p>
<ul>
<li>call effect 會阻塞當前saga 的執行，直到被調用函數fn 返回結果，才會執行下一步代碼。</li>
<li> fork effect 則不會阻塞當前saga，會立即返回一個task 對象。</li>
</ul>
<p class="ztext-empty-paragraph"></p>
<p>舉個例子，假設fn 函數返回一個promise：</p>
<p class="ztext-empty-paragraph"></p>
<div class="highlight">
<pre><code class="language-text">// 模拟数据异步获取function fn() { return new Promise((resolve, reject) =&gt; { setTimeout(() =&gt; { resolve('hello saga'); }, 2000); }); } function* fetchData() { // 等待2 秒后，打印欢迎语（阻塞） const greeting = yield call(fn); console.log('greeting: ', greeting); // 立即打印task 对象（非阻塞） const task = yield fork(fn); console.log('task: ', task); }</code></pre>
</div>
<p class="ztext-empty-paragraph"></p>
<p>顯然，fork 的異步非阻塞特性更適合於在後台運行一些不影響主流程的代碼（比如：後台打點/開啟監聽），這往往是加快頁面渲染的一種方式，有點類似於Egg 的runInBackground，倘若在這種情況下，你依然要獲取返回結果，可以這樣做：</p>
<p class="ztext-empty-paragraph"></p>
<div class="highlight">
<pre><code class="language-text">const task = yield fork(fn); // 0.16.0 api task.done().then((greeting) =&gt; { console.log('greeting: ', greeting); }); // 1.0.0-beta.0 api task.toPromise().then((greeting) =&gt; { console.log('greeting: ', greeting); });</code></pre>
</div>
<p class="ztext-empty-paragraph"></p>
<p><i><b>PS：</b>這裡的函數fn是一個<b>normal function</b> ，其實它還可以是一個<b>generator function</b> （被稱作是<b>Child Saga</b> ）。</i></p>
<p class="ztext-empty-paragraph"></p>
<p class="ztext-empty-paragraph"></p>
<p><i>最後的最後，再簡單聊聊saga中的錯誤處理方式？</i></p>
<p class="ztext-empty-paragraph"></p>
<h2>Error Handling</h2>
<p class="ztext-empty-paragraph"></p>
<blockquote><p>在saga 中，無論是請求失敗，還是代碼異常，均可以通過try catch 來捕獲。</p></blockquote>
<p class="ztext-empty-paragraph"></p>
<p>倘若訪問一個接口出現代碼異常，可能是網絡請求問題，也可能是後端數據格式問題，但不管怎樣，給予日誌上報或友好的錯誤提示是不可缺少的，這也往往體現了代碼的健壯性，一般會這麼做：</p>
<p class="ztext-empty-paragraph"></p>
<div class="highlight">
<pre><code class="language-text">function* saga() { try { const data = yield call(fetch, '/someEndpoint'); return data; } catch(e) { // 日志上报logger.error('request error: ', e); // 错误提示antd.message.error('请求失败'); } }</code></pre>
</div>
<p class="ztext-empty-paragraph"></p>
<p>這是最正確的處理方式，但這裡更想討論的是：<i><u>如果忘記寫try catch進行異常捕獲，結果會怎麼樣？</u></i></p>
<p class="ztext-empty-paragraph"></p>
<p>就好比下面這樣：</p>
<p class="ztext-empty-paragraph"></p>
<div class="highlight">
<pre><code class="language-text">function* saga1 () { /* ... */ } function* saga2 () { throw new Error('模拟异常'); } function* saga3 () { /* ... */ } function* rootSaga() { yield fork(saga1); yield fork(saga2); yield fork(saga3); } // 启动saga sagaMiddleware.run(rootSaga);</code></pre>
</div>
<p class="ztext-empty-paragraph"></p>
<p>假設saga2 出現代碼異常了，且沒有進行異常捕獲，這樣的異常會導致整個Web App 崩潰麼？答案是：肯定的！</p>
<p class="ztext-empty-paragraph"></p>
<p>來具體解釋下：</p>
<p class="ztext-empty-paragraph"></p>
<p>redux-saga中執行<code>sagaMiddleware.run(rootsaga)</code>或<code>fork(saga)</code>時，均會返回一個task對象（上文中說到），嵌套的task之間會存在<b>父子關係，</b>就比如上述代碼：</p>
<p class="ztext-empty-paragraph"></p>
<ul>
<li>rootSaga 生成了rootTask。</li>
<li> saga1，saga2 和saga3，在rootSaga 內部執行，生成的task，均被認為是rootTask 的childTask。</li>
</ul>
<p class="ztext-empty-paragraph"></p>
<p>現在某一個childTask 異常了（比如這裡的： saga2），那麼它的parentTask（如：rootTask）收到通知先會執行自身的cancel 操作，再通知其他childTask（如：saga1，saga3） 同樣執行cancel 操作。 （這其實正是Saga Pattern 的思想）</p>
<p class="ztext-empty-paragraph"></p>
<p>但這就意味著，用戶可能會因為一個按鈕點擊引發的異常，而導致整個Web 應用的功能均無法使用！ ！</p>
<p class="ztext-empty-paragraph"></p>
<p>那麼，面對這樣的問題，如何優化呢？隔離childTask 是首先想到的一種方案。</p>
<p class="ztext-empty-paragraph"></p>
<div class="highlight">
<pre><code class="language-text">export default function* root() { yield spawn(saga1); yield spawn(saga2); yield spawn(saga3); }</code></pre>
</div>
<p class="ztext-empty-paragraph"></p>
<p>使用spawn替換fork，它們的區別在於spawn返回<b>isolate task</b> ，不存在<b>父子關係</b>，也就是說，即使saga2掛了，rootSaga也不受影響，saga1和saga3自然更不會受影響，依然可以正常工作。</p>
<p class="ztext-empty-paragraph"></p>
<p>但這樣的方案並不是讓人最滿意的！如果因為某一次網絡原因，導致saga2 掛了，在不刷新頁面的情況下，用戶連重試的機會都不給，顯然是不合理的，那麼如果可以做到saga 自動重啟呢？社區裡已經有一個比較好的方案了：</p>
<div class="highlight">
<pre><code class="language-text">function* rootSaga () { const sagas = [ saga1, saga2, saga3 ]; yield sagas.map(saga =&gt; spawn(function* () { while (true) { try { yield call(saga); } catch (e) { console.log(e); } } }) ); }</code></pre>
</div>
<p>上述代碼通過在最上層為每一個childSaga添加異常捕獲，並通過<code>while(true) {}</code>循環自動創建新的childTask取代異常childTask，以保證功能依然可用（這就類似於Egg中某一個woker進程掛了，自動重啟一個新的woker 進程一樣）。</p>
<p class="ztext-empty-paragraph"></p>
<p>OK，差不多就先講這些吧...<b>完！</b></p>
</div>
</div>
</article>
<p>The post <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com/software-engineering/front-end-dev/13839/topic-35437092/" data-wpel-link="internal">Redux-Saga 漫談</a> appeared first on <a rel="nofollow noopener noreferrer" href="https://hypergrowths.com" data-wpel-link="internal">成長駭客交流第一站 - HyperGrowths™</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
