2015-個人前端之路:數據流驅動的界面

本文從屬於筆者的Web 前端入門與最佳實踐,2016年度版本在:2016-個人前端之路:工具化與工程化javascript

撰寫本文的時候筆者閱讀了如下文章,不可避免的會借鑑或者引用其中的一些觀點與文字,如有冒犯,請隨時告知。文列以下:html

若是你想進行WebAPP的學習,建議先看下個人編程之路:知識管理與知識體系相關內容
順便推廣下筆者總結的泛前端知識點綱要總結:Coder Essential之客戶端知識索引(iOS/Android/Web) Coder Essential之編程語言學習知識點綱要Coder Essential之編程語言語法特性概論github

幾年前初入大學,才識編程的時候,崇尚的是一路向下,那個時候喜歡搞Windows、Linux底層相關的東西,以爲那些作網頁的太Low了。直到後來偶然的機會接觸到HTML、JavaScript、CSS,很長一段時間以爲這種這麼不嚴謹的,毫無工程美學的搭配不過是詩餘罷了。後來,深刻了,才發現,可以有幸在這片星辰大海里遊蕩,能夠以幾乎領先於其餘方向的技術變革速度來感覺這個時代的脈動,是多麼幸運的一件事。這是一個最壞的時代,由於一不當心就發現本身Out了;這也是一個最好的時代,咱們永遠在前行。繁華漸欲,萬馬齊鳴!

借用蘇寧前端結構師的總結,任何一個編程生態都會經歷三個階段,第一個是原始時期,因爲須要在語言與基礎的API上進行擴充,這個階段會催生大量的Tools。第二個階段,隨着作的東西的複雜化,須要更多的組織,會引入大量的設計模式啊,架構模式的概念,這個階段會催生大量的Frameworks。第三個階段,隨着需求的進一步複雜與團隊的擴充,就進入了工程化的階段,各種分層MVC,MVP,MVVM之類,可視化開發,自動化測試,團隊協同系統。這個階段會出現大量的小而美的Library。固然,筆者以Tools-Frameworks-Library只是想說明我我的感受的變化。

筆者從jQuery時代一路走來,經歷了以BootStrap爲表明的基於jQuery的插件式框架與CSS框架的興起,到後面以Angular 1爲表明的MVVM框架,以及到如今以React爲表明的組件式框架的興起。從最初的認爲前端就是切頁面,加上一些交互特效,到後面造成一個完整的webapp,整體的變革上,筆者覺得有如下幾點:

  • 移動優先與響應式開發

  • 前端組件化與工程化的變革

  • 從直接操做Dom節點轉向以狀態/數據流爲中心

筆者在本文中的敘事方式是按照本身的認知過程,夾雜了大量我的主觀的感覺,看看就好,不必定要當真,畢竟我菜。梳理來講,有如下幾條線:

  • 交互角度的從PC端爲中心到Mobile First

  • 架構角度的從以DOM爲中心到MVVM/MVP到以數據/狀態爲驅動。

  • 工程角度的從隨意化到模塊化到組件化。

  • 工具角度的從人工到Grunt/Gulp到Webpack/Browserify。

在正文以前,重要的事情說三遍,我是菜鳥!我是菜鳥!我是菜鳥!歷來都沒有最好的技術,而只有合適的技術與懂它的人。我感謝這些偉大的類庫/框架,感恩它們的Contributor,給我呈現了一個何其廣闊的世界。雖然2015的前端領域有點野蠻生長,可是也體現了前端一直是開源領域的扛鼎之處,但願有一天我也能爲它的繁榮作出本身的貢獻。

基石與催化劑

瀏覽器的躍進

如今H5已經成爲了一個符號,基本上全部具備絢麗界面或者交互的Web界面,不管是PC仍是Mobile端,都被稱爲基於H5。筆者一直認爲,H5技術的發展以及帶來的一系列前端的變革,都離不開現代瀏覽器的發展與以IE爲典型表明的老的瀏覽器的消逝。目前瀏覽器的市場分佈能夠由以下兩個圖:

  • 瀏覽器分佈圖
    瀏覽器分佈率

  • 國際瀏覽器分佈圖
    國際瀏覽器分佈率

這裏順嘴說下,若是想要明確某個屬性是否可使用能夠參考Can I Use。話說雖然微信內置的某X5內核瀏覽器連Flexbox都不支持,不過它幫咱們屏蔽了大量手機的底層差別,筆者仍是很是感恩的。固然了,在有了Webpack以後,用Flexbox不是問題,能夠查看這嘎達

ECMAScript

2015年是JavaScript誕生的20週年。同時又是ES6標準落地的一年。ES6是迄今爲止 ECMAScript標準最大的變革(若是不算上胎死腹中的ES4的話),帶來了一系列令開發者興奮的新特性。從目前es的進化速度來看,es後面應該會變成一個個的feature發佈而不是像之前那樣大版本號的方式,因此如今官方也在推薦 ES+年份這種叫法而不是 ES+版本。在ES2015中,筆者以爲比較欣賞的特性以下,其餘完整的特性介紹能夠參考這篇文章ES6 Overview in 350 Bullet Points

  • Module & Module Loader:ES2015中加入的原生模塊機制支持可謂是意義最重大的feature了,且不說目前市面上五花八門的module/loader庫,各類不一樣實現機制互不兼容也就罷了(其實這也是很是大的問題),關鍵是那些模塊定義/裝載語法都醜到爆炸,可是這也是無奈之舉,在沒有語言級別的支持下,js只能作到這一步,正所謂巧婦難爲無米之炊。ES2016中的Module機制借鑑自 CommonJS,同時又提供了更優雅的關鍵字及語法(雖然也存在一些問題)。

  • Class:準確來講class關鍵字只是一個js裏構造函數的語法糖而已,跟直接function寫法無本質區別。只不過有了Class的原生支持後,js的面向對象機制有了更多的可能性,好比衍生的extends關鍵字(雖然也只是語法糖)。

  • Promise & Reflect API:Promise的誕生其實已經有幾十年了,它被歸入ES規範最大意義在於,它將市面上各類異步實現庫的最佳實踐都標準化了。至於Reflect API,它讓js歷史上第一次具有了元編程能力,這一特性足以讓開發者們腦洞大開。

除此以外,ES2016的相關草案也已經肯定了一大部分其餘new features。這裏提兩個我比較感興趣的new feature:

  • async/await:協程。ES2016中 async/await 實際是對Generator&Promise的上層封裝,幾乎同步的寫法寫異步比Promise更優雅更簡單,很是值得期待。

  • decorator:裝飾器,其實等同於Java裏面的註解。註解機制對於大型應用的開發的做用想必不用我過多贅述了。用過的同窗都說好。

更讓人興奮的是,JavaScript慢慢再也不侷限於前端開發中,NodeJs的提出讓人們感覺到了利用JavaScript進行全棧開發的能力,今後大大提升了開發的效率(至少不用多學習一門語言)。JavaScript在物聯網中的應用也曾經引發一些追捧與風潮,不過今年物聯網社區更加冷靜地看待着這個問題,可是並不影響各大廠商對於JavaScript的支持,能夠參閱javascript-beyond-the-web-in-2015這篇文章。筆者仍是很看好JavaScript在其餘領域繼續大放異彩,畢竟ECMAScript 6,7已是如此的優秀。

WebAssembly

WebAssembly 選擇了跟ES2015在同一天發佈,其項目領頭人是大名鼎鼎的js之父Brendan Eich。WebAssembly旨在解決js做爲解釋性語言的先天性能缺陷,試圖經過在瀏覽器底層加入編譯機制從而提升js性能。WebAssembly所作的正是爲Web打造一套專用的字節碼,這項標準在將來應用場景多是這樣的:

  1. 開發應用,但使用任何一門可被編譯爲WebAssembly的語言編寫源代碼。

  2. 用編譯器將源代碼轉換爲WebAssembly字節碼,也可按需轉換爲彙編代碼。

  3. 在瀏覽器中加載字節碼並運行。

須要注意的是,WebAssembly不會替代JavaScript。愈來愈多的語言和平臺想在Web上大展手腳,這會迫使JavaScript和瀏覽器廠商不得不加快步伐來補充缺失的功能,其中某些功能經過複雜的JavaScript語義來實現並不合適,因此WebAssembly能夠做爲JavaScript的補集加入到Web陣營中來。WebAssembly最一開始的設計初衷就是做爲不依賴於JavaScript的編譯目標而存在,進而得到了主流瀏覽器廠商的普遍支持。很期待有一天WebAssembly可以發展起來,到那個時候,咱們用JavaScript編寫的應用也會像如今用匯編語言寫出的大型程序的感受咯~

漸隱的jQuery與服務端渲染

HTML:附庸之徒

前端用於數據展現

在筆者最先接觸前端的時候,那個時候還不知道前端這個概念,只是知道HTML文件能夠在瀏覽器中顯示。彼時連GET/POST/AJAX這些概念都不甚明瞭,還記得那個時候看到一本厚厚的AJAX實戰手冊不明覺厲。筆者閱讀過Roy Thomas Fielding博士的Architectural Styles andthe Design of Network-based Software Architectures這篇論文,也就是RESTful架構風格的源處。在這篇文章裏,筆者反而感受最有感觸的是從BS到CS架構的躍遷。一開始我以爲網頁是典型的BS的,咋說呢,就是網頁是數據、模板與樣式的混合,即以經典的APS.NET、PHP與JSP爲例,是由服務端的模板提供一系列的標籤完成從業務邏輯代碼到頁面的流動。因此,前端只是用來展現數據。

那個時候筆者更菜,對於CSS、JS都不甚明瞭,一切的數據渲染都是放在服務端完成的。筆者第一次學HTML的時候,驚呆了,臥槽,這能算上一門語言嘛?太簡單了吧。。。原來作個網頁這麼簡單啊,而後生活就華麗麗打了臉。那個時候,根本不會以script或者link的方式將資源載入,而是所有寫在一個文件裏,好吧,那時候連jQuery都不會用。記得那個時候Ajax都是本身手寫的,長長的毫無美感的大量重複冗餘的代碼真是日了狗。

爲何說HTML只是附庸之徒呢,那個時候咱們沒有把Browser的地位與其餘的Client並列,換言之,在經典的Spring MVC框架裏,以下所示,用戶全部的邏輯操做的核心咱們都會放置到Java代碼中,根本不會想到用JavaScript進行控制。另外一個方面,由於沒有AJAX的概念,致使了每次都是表單提交-後臺判斷-從新渲染這種方式。這樣致使了每個渲染出來的網頁都是無狀態的,換言之,網頁是依賴於後端邏輯反應不一樣有不一樣的呈現,自身沒有一個完整的狀態管理。

Service MVC
圖片來源於《前端篇:前端演進史》

AJAX與客戶端開發

筆者最先的區分CS與BS架構,抽象來講,會認爲CS是客戶端與服務器之間的雙向通訊,而BS是客戶端與服務端之間的單向通訊。換言之,網頁端自己也變成了有狀態。從初始打開這個網頁到最終關閉,網頁自己也有了一套本身的狀態,而擁有這種變化的狀態的基礎就是AJAX,即從單向通訊變成了雙向通訊。圖示以下:

Micro Services

漸隱的jQuery

jQuery做爲了影響一代前端開發者的框架,是Tools的典型表明,它留下了璀璨的痕跡與沒法磨滅的腳印。筆者在這裏以jQuery做爲一個符號,來表明以Dom節點的操做爲核心的一代的前端開發風格。那個年代裏,要插入數據或者更改數據,都是直接操做Dom節點,或者手工的構造Dom節點。譬如從服務端得到一個用戶列表以後,會經過構造<i>節點的方式將數據插入到Dom樹中。

可是不得不認可,在將來至關長的一段時間內,jQuery並不會直接退出歷史的舞臺,筆者我的認爲一個重要的緣由就是如今仍然存在着很大比重的各式各樣的基於jQuery的插件或者應用,對於崇尚拿來主義的咱們,不可避免的會繼續使用着它。

You-Dont-Need-jQuery

jQuery引領了一個輝煌的時代,可是隨着技術的演進它也慢慢在不少項目中隱去。jQuery這個框架自己很是的優秀而且在不斷的完善中,可是它自己的定位,做爲早期的跨瀏覽器的工具類屏蔽層在今天這個瀏覽器API逐步統一而且完善的今天,逐漸不是那麼關鍵。所以,筆者認爲jQuery會逐漸隱去的緣由可能爲:

  • 現代瀏覽器的發展與逐步統一的原生API

因爲瀏覽器的歷史緣由,曾經的前端開發爲了兼容不一樣瀏覽器怪癖,須要增長不少成本。jQuery 因爲提供了很是易用的 API,屏蔽了瀏覽器差別,極大地提升了開發效率。這也致使不少前端只懂 jQuery。其實這幾年瀏覽器更新很快,也借鑑了不少 jQuery 的 API,如 querySelectorquerySelectorAll 和 jQuery 選擇器一樣好用,並且性能更優。

  • 前端由以DOM爲中心到以數據/狀態爲中心

jQuery 表明着傳統的以 DOM 爲中心的開發模式,但如今複雜頁面開發流行的是以 React 爲表明的以數據/狀態爲中心的開發模式。應用複雜後,直接操做 DOM 意味着手動維護狀態,當狀態複雜後,變得不可控。React 以狀態爲中心,自動幫咱們渲染出 DOM,同時經過高效的 DOM Diff 算法,也能保證性能。

  • 不支持同構渲染與跨平臺渲染

React Native中不支持jQuery。同構就是先後端運行同一份代碼,後端也能夠渲染出頁面,這對 SEO 要求高的場景很是合適。因爲 React 等流行框架自然支持,已經具備可行性。當咱們在嘗試把現有應用改爲同構時,由於代碼要運行在服務器端,但服務器端沒有 DOM,因此引用 jQuery 就會報錯。這也是要移除 jQuery 的迫切緣由。同時不但要移除 jQuery,在不少場合也要避免直接操做 DOM。

  • 性能缺陷

jQuery的性能已經不止一次被詬病了,在移動端興起的初期,就出現了Zepto這樣的輕量級框架,Angular 1也內置了jqlite這樣的小工具。前端開發通常不須要考慮性能問題,但你想在性能上追求極致的話,必定要知道 jQuery 性能不好。原生 API 選擇器相比 jQuery 豐富不少,如 document.getElementsByClassName 性能是 $(classSelector) 的 50 多倍!

[jQuery VS Native AP](https://camo.githubusercontent.com/b1f3d997150c7103b566d6afc76b839f6ae15236/687474703a2f2f7365676d656e746661756c742e636f6d2f696d672f625672676b57)

說這麼多,只是想在之後技術選型的時候,能有一個通盤考慮,畢竟,這是曾經的Best Love。

蛋疼的模塊化與SPA

若是當時的移動網絡速度能夠更快的話,我想不少SPA框架就不存在了

隨着踩得坑愈來愈多與相似於Backbone、AngularJs這樣的更加純粹全面的客戶端框架的興起,Single Page Application流行了起來。至此,在網頁開發領域也就徹底變成了CS這種理念。至此以後,咱們會考慮在前端進行更多的用戶交互與狀態管理,而不是一股腦的所有交給後臺完成。特別是頁面的切換與不一樣數據的呈現再也不是須要用戶進行頁面的跳轉,從而在弱網狀況下使用戶得到更好的體驗與更少的流量浪費。與此同時,前端就變得更加的複雜化,咱們也迫切的須要更加完善的代碼分割與管理方案,因而,筆者開始嘗試接觸模塊化的東西。筆者自RequireJs、SeaJs興起以來一直關注,可是從未在實際項目中投入使用。額,第一次用這兩個框架的時候,發現貌似須要對現有的代碼或者喜歡的jQuery Plugins進行封裝,當時我這種懶人就有點心理陰影了。不過SeaJs做爲早期國人開發的有必定影響力的前端輔助工具,筆者仍是很是敬佩的。

前端掃盲-之打造一個自動化的前端項目

模塊化的進步與不足

在筆者知道模塊化這個概念以前,文件夾是這麼分的:

mulu_right

看上去很是的工整,可是稍微有個多人協做的項目,或者稍微多用一點jQuery的插件,看着那十來二十個不知道里面究竟是啥的JS文件,筆者是崩潰的。筆者最先打算使用模塊化的動力來源於避免做用域污染,那個時候常常發現的問題是一不當心引進來的兩個第三方文件就打架了,你還不知道怎麼去修改。

模塊通常指可以獨立拆分且通用的代碼單元,在ES6正式出來規範以前,咱們會選擇使用RequireJs或者SeaJs來進行有點像依賴注入的東西:

require([
    'Tmpl!../tmpl/list.html','lib/qqapi','module/position','module/refresh','module/page','module/net'
], function(listTmpl, QQapi, Position, Refresh, Page, NET){

大概是這樣子的,可是筆者就是以爲好煩啊,而且它整個頁面的邏輯仍是面向過程編碼的。換言之,我若是頁面上稍微換了個佈局或者有那麼三四個有交集的頁面,那就日了狗了,根本談不上覆用。

Backbone.js:MVC方式的SPA

Backbone是筆者較早期接觸到的,以數據爲驅動的一種框架。Backbone誕生於2010年,和響應式設計出如今同一個年代裏,但他們彷佛在同一個時代裏火了起來。若是CSS3早點流行開來,彷佛就沒有Backbone啥事了。不過移動網絡仍是限制了響應式的流行,只是在今天這些都有所變化。換言之,就是將數據的處理與頁面的渲染分離了出來。算是在以jQuery那種以DOM操做爲核心的基礎上完成了一次變革。一樣的筆者用過的框架還有easy-ui,不過它是一個封裝的更加徹底的框架。開發時,不須要考慮怎麼去寫大量的HTML/CSS代碼,只須要在他的組件內填充不一樣的邏輯與配置便可。很方便,也很不方便,記得筆者想稍稍修改下他的表格的功能都蛋疼了好一陣子。

Backbone相對而言會更開放一點,在筆者大量使用Angular的時候也有同窗提議使用Backbone + avaon這種更輕量級的方案。咱們用Ajax向後臺請求API,而後Mustache Render出來,這裏已經會開始將Web端視做一個完整的Client而不只僅是個附庸的存在。一個典型的Backbone組件的代碼以下:

//《前端篇:前端演進史》
define([
    'zepto',
    'underscore',
    'mustache',
    'js/ProductsView',
    'json!/configure.json',
    'text!/templates/blog_details.html',
    'js/renderBlog'
],function($, _, Mustache, ProductsView, configure, blogDetailsTemplate, GetBlog){

    var BlogDetailsView = Backbone.View.extend ({
        el: $("#content"),

        initialize: function () {
            this.params = '#content';
        },

        getBlog: function(slug) {
            var getblog = new GetBlog(this.params, configure['blogPostUrl'] + slug, blogDetailsTemplate);
            getblog.renderBlog();
        }
    });

    return BlogDetailsView;
});

能夠看見,在Backbone中已經將DOM元素與數據渲染以及邏輯剝離了開來,這樣就有助於進行團隊內的分工與協做,以及大量的代碼複用。那個時候常常會將Backbone與Angular進行對比,兩者各有優劣。Backbone在顯示模板、建立數據綁定和鏈接組件方面給使用者更多的選擇。與之相反,Angular爲這些問題提供了規定的方案,不過在建立模型與控制器方面的限制就比較少一些。筆者當時是由於想要用一套Framework來解決問題,因此仍是投入了Angular的懷抱。

AngularJs 1.0:MVVM 方式的 SPA

AngularJs是第一個我真正喜歡的Framework,不只僅是由於它提出的MVVM的概念,還有由於它自帶的DI以及模塊化的組織方式。或許正是由於使用了AngularJs 1.0,筆者纔沒有深刻使用RequireJs、SeaJs這些吧。AngularJs 1.0的優秀與槽點就不細說了,在那個時代他成功讓筆者有了一點完整的前端項目的概念,而不是多個分離的互相之間跳轉的HTML文件。最近,AngularJs 2.0終於出了Beta版本,筆者也一直保持關注。不過我的感受唱衰的聲音仍是會大於褒揚之聲,從筆者我的感受而言,一個大而全的框架可能不如多個小而美的框架更加的靈活,關於這個對比能夠參考下文的Web Components VS Reactive Components這一章節。此外,對於AngularJs 中一直詬病的性能問題,Facebook提出的Virtual DOM的算法毫無疑問爲前端的性能優化指明瞭一條新的道路,筆者這裏推薦一個Performance Benchmarks,其中詳細對比了多個DOM操做的庫。筆者在這裏只貼一張圖,別的能夠去原文查看:

Major GC collection times

整體而言,Vue偏輕量,適合移動端,ng適應pc端,avalon適合兼容老瀏覽器的項目。雖然Vue.js如今也有組件化的實現,包括相似於Flux的Vuex這樣的Single State Tree的框架,可是筆者仍是比較傾向於把它當作一個MVVM模型來對待。

組件化的將來與Mobile-First

最初隨着React的風靡,組件化的概念深刻人心。筆者一直堅信組件化是很是值得去作的事情,它在工程上會大大提高項目的可維護性及拓展性,同時會帶來一些代碼可複用的附加效果。但這裏要強調的一點是,組件化的指導策略必定是分治而不是複用,分治的目的是爲了使得組件之間解耦跟正交,從而提升可維護性及多人協同開發效率。若是以複用爲指導原則那麼組件最後必定會發展到一個配置繁雜代碼臃腫的狀態。組件化最著名的標準無疑是W3C制定的Web Components標準,它主要包含如下幾個方面:

  • <template>模板能力

  • ShadowDom 封裝組件獨立的內部結構

  • 自定義原生標籤

  • imports解決組件間的依賴

不過這個標準自己還沒發揚光大就被Angular、React這樣的框架完爆了,不過他仍是指明瞭咱們組件化的幾個準則:

  • 資源高內聚:有點像Vue提到的理念,Single File Component。組件資源內部高內聚,組件資源由自身加載控制

  • 做用域獨立:內部結構密封,不與全局或其餘組件產生影響 

  • 自定義標籤:能夠像使用HTML的預設標籤同樣方便地使用組件

  • 可相互組合:組件正在強大的地方,組件間組裝整合

  • 接口規範化:組件接口有統一規範,或者是生命週期的管理

Web Components VS Reactive Components

對於Web組件化的典型表明,應該是React與Angular 2。Angular 2基本上徹底革了Angular 1的命,Angular開發團隊最先於2014年3月提出路線圖,直到2015年末才進入alpha階段。筆者自Angular 2開發之始就一直保持關注,見證了其規範或者接口的更迭。不能否認Angular 2在性能以及設計理念上都會比Angular 1先進不少,可是隨着2014年中到2015年初以React爲表明的組件式UI框架以及Flux/Redux爲表明的響應式數據流驅動興起,可能Angular 2並不會達到Angular 1的高度。筆者也在斷斷續續地更新一些Angular 2的指導與學習文檔,不過確實,除了從零開始的大型項目,Angular 2仍是太笨重了。

Will Angular 2 be a success? You bet!(注意,評論更精彩)

實際上,在咱們選擇一個庫或者所謂的框架時,爲咱們的組件選擇一個合適的抽象可能會比以爲哪一個框架更好更有意義。目前Web的組件化開發分爲兩個大的趨勢,一個是以Angular 二、Polymer爲表明的Web Components,另外一個是以React、Vue、Riot爲表明的Reactive Components。目前Web Components方面由於各個庫之間沒法就如何定義它們達成一致,致使了相似於Angular 二、Aurelia這樣的框架用它們本身的核心來定義Web Components。只有Polymer 100%實踐了Web Components的規範。Web Components有點相似於Google,而React更像Facebook。

另外,當咱們選擇一個框架時,還須要考慮清楚咱們是須要一個包含了全部的功能的執拗己見的框架,就像Angular二、Ember 2這樣的,仍是一系列小的專精的框架的組合,就像React、Flux以及React Router這樣的。固然,咱們在選擇一個框架時還必須考慮進它潛在的變化的代價與難度,以及與其餘的技術集成的難度,還有就是他有沒有一個完善的生態系統。

就像筆者在本身的[AARF]()說起的,不管先後端,在這樣同樣敏捷式開發與快速迭代地背景下,咱們須要更多獨立的分離的能夠方便組合的相似於插件同樣的模塊。

響應式解決方案

隨着WAP的出現與移動智能終端的飛速普及,開發者們不得不面臨一個問題,大量的流量來自於手機端而再也不是PC端,傳統的PC端佈局的網頁,在手機上顯示的根本不友好,什麼鬼!最先的時候人們考慮的是面向PC端與WAP設計不一樣的頁面,不過這樣就毫無疑問將原來的工做量乘以二,而且產品管理與發佈上也會存在着必定的問題,特別是在那個組件化與工程化理念尚未流行的時代裏。因而,人們開始設計一套可以針對不一樣的屏幕響應式地自反饋的佈局方案,也就是這裏提到的響應式設計。

響應式設計不得不提到的一個缺點是:他只是將本來在模板層作的事,放到了樣式(CSS)層來完成。複雜度同力同樣不會消失,也不會憑空產生,它老是從一個物體轉移到另外一個物體或一種形式轉爲另外一種形式。

筆者最先接觸到的響應式設計來自於BootStrap,它的Media Query功能給當時的筆者很大的驚喜的感受。特別是CSS3中Flexbox的提出,更是能方便地踐行響應式設計的原則。不過,就以淘寶首頁爲例,若是用響應式方式完成一套代碼在PC端與手機端不一樣的徹底適應的展現效果,我以爲還不如直接寫兩套呢。不能否認響應式設計在例如菜單啊,瀑布流佈局啊這些功能組件上起到了很是巧妙的做用,可是爲了單純的追尋響應式佈局而把整個CSS的邏輯判斷搞得那麼複雜,那我是拒絕的。特別是如今組件化這麼流行的今天,我寧肯在根控件中自由的組織各個組件,也好過不斷地自適應判斷。

筆者不是很是提倡響應式解決方案來解決從PC端到移動端的遷移,筆者我的以爲PC端和移動端就是額,不是同一種畫風的東西。話說筆者接觸過很多徹底用代碼控制的響應式佈局,譬如融雲的Demo,它能夠根據你顯示器屏幕控制元素的顯隱和事件。不能否認設計很精巧,可是在沒有組件的那個時候,這種代碼複雜度和性價比,在下服了。筆者在本身的實踐中,對於純移動端的響應式開發,譬如微信中的H5,仍是比較喜歡使用pageResponse這種方式或者它的一些改進版本。

移動優先

響應式解決方案,表明着隨着不一樣的分辨率下智能的響應式佈局。而移動優先的概念,筆者認爲則是在界面設計之初即考慮到適應移動端的佈局。固然,還有一個方面就是要照顧到移動端的瀏覽器的語法支持度、它的流量以及各類各樣的Polyfill。

Hybrid:WebView VS Cross Compilation

筆者很懶,最先的時候只是有一點Android開發經驗,那個時候Hybrid技術剛剛興起,每天看DZone上N多的炫耀本身的Hybrid開發多快、性能多好的文章,立馬激發起了個人懶癌。寫一波就能跨平臺運行,多爽啊!Hybrid技術分爲兩個大的分支,一個以Cordova爲表明的基於系統的WebView與本地調用。另外一種早期以Titanium、Tamarin,現在以React Native這樣爲表明的Cross Compilation,即跨平臺編譯技術。

在咱們須要學習C語言的時候,GCC就有了這樣的跨平臺編譯。

在咱們開發桌面應用的時候,QT就有了這樣的跨平臺能力。

在咱們構建Web應用的時候,Java就有了這樣的跨平臺能力。

在咱們須要開發跨平臺應用的時候,Cordova就有了這樣的跨平臺能力。

因而乎,在筆者第一次正式創業時,我斬釘截鐵的跟投資人說,用Hybrid開發,用Cordova,沒錯的。記得那時候筆者還不懂iOS開發,因此在第一次正式作App的時候選擇了Ionic 1.0。其實最先是打算用jQuery Mobile,不過寫了第一個小的tab的Demo而後在本身的千元機上運行的時候,打開應用居然花了20多秒,當時投資人看到的時候臉是綠的,心是涼的。估計是那時候還不會用jQuery Mobile吧(雖然如今也不會),但確實不是一個可行方案。後來筆者轉到了Ionic 1.0,確實一開始感受不錯,速度還闊以。可是當時筆者還小,犯了一個很大的認知錯誤,就是打算徹底摒棄掉Native所有用Web技術開發,因而,一個簡單地文件上傳分分鐘就教我作了人。最後產品作出來了,可是壓根用不了。插一句,一開始爲了在Android老版本設備上解決WebView的兼容性問題,打算用Crosswalk。筆者第一次用Crosswalk編譯完成以後,嚇尿了。速度上確實快了一點,可是包體上實在增長的太大了,臣妾作不到啊!至此以後,筆者熄滅了徹底依賴於Cordova進行APP開發的理念。

結果時間軸又錯了,人們老是超前一個時期作錯了一個在將來是正確的決定。大概是那個時候機器性能還不是足夠的好吧。

Cordova或者Webview這種方向是沒錯的,如今也大量的存在於筆者的APP中,可是對於中大型APP而言,若是直接架構在Cordova之上,筆者仍是不推薦的。Build Once,Run Everywhere,貌似作不到了,或者說差強人意。那就考慮Learn Once,Write Everywhere。React Native又引領了一波時代潮流。

Cross Compilation的典型表明是NativeScript與React Native。筆者天然是更喜歡React Native的,畢竟背靠整個React生態圈,對於原生組件的支持度也是很好的。React框架自己雖好,可是仍是有許多能夠與之媲美的優秀的框架的,可是React依靠Virtual DOM以及組件化等概念,依賴Facebook工程師強大的工程與架構能力,已經打造了一個完整的生態。特別是0.14版本以後的react與react-dom的分割,愈發的能夠看出React的雄心壯志。將表現層與具體的界面分離開來,經過Canvas、Native、Server乃至將來的Desktop這樣不一樣的渲染引擎,保證了代碼的高度重用性,特別是邏輯代碼的重用性。

工程化與Builder

前端工程化

大部分時候咱們談論到工程化這個概念的時候,每每指的是工具化。可是任何一個通向工程化的道路上都不可避免的會走過一段工具化的道路。筆者最先的接觸Java的時候用的是Eclipse,那個時候不懂什麼構建工具,不懂發佈與部署,每次要用類庫都要把jar包拷貝到Libs目錄下。以致於多人協做的時候常常出現依賴相互衝突的問題。後來學會了用Maven、Gradle、Jenkins這些構建和CI工具,慢慢的才造成了一套完整的工做流程。前端工程化的道路,目標就是但願能用工程化的方法規範構建和維護有效、實用和高質量的軟件。

筆者我的感受的工程化的要素,會有如下幾個方面:

  • 統一的開發規範(語法/流程/工程結構)與編譯工具。實際上考慮到瀏覽器的差別性,自己咱們在編寫前端代碼時,就等於在跨了N個「平臺」。在早期沒有編譯工具的時候,咱們須要依賴本身去判斷瀏覽器版本(固然也能夠用jQuery這樣人家封裝好的),而後根據不一樣的版本寫大量的重複代碼。最簡單的例子,就是CSS的屬性,須要加不一樣的譬如-o--moz-這樣的前綴。而這樣開發時的判斷無疑是浪費時間而且存在了大量的冗餘代碼。開發規範也是這樣一個概念,JavaScript自己做爲腳本語言,語法的嚴謹性一直比較欠缺,而各個公司都有本身的規範,就像當年要實現個類都有好幾種寫法,着實蛋疼。

  • 模塊化/組件化開發。在一個真正的工程中,咱們每每須要進行協做開發,以前每每是按照頁面來劃分,可是會形成大量的重複代碼,而且維護起來會很是麻煩。這裏的模塊化/組件化開發的要素與上面的第一點都是屬於開發需求。

  • 統一的組件發佈與倉庫。筆者在使用Maven先後會有很大的一個對比感,沒有一個統一的中央倉庫與版本管理工具,簡直就是一場災難。這樣也沒法促進開發者之間的溝通與交流,會形成大量的重複造輪子的現象。

  • 性能優化與項目部署。前端的錯誤追蹤與調試在早期一直是個蛋疼的問題,筆者基本上每次都要大量的交互才能重現錯誤場景。另外一方面,前端會存在着大量的圖片或者其餘資源,這些的發佈啊命名啊也是個很蛋疼的問題。當咱們在構建一個webapp的完整的流程時,咱們須要一套自動化的代碼質量檢測方案來提升系統的可靠性,須要一套自動化以及高度適應的項目發佈/部署方案來提升系統的伸縮性和靈活性。最後,咱們須要減小冗餘的接口、冗餘的資源請求、提升緩存命中率,最終達到近乎極致的性能體驗。

Webpack

Webpack跟browserify本質上都是module bundler,差別點在於Webpack提供更強大的loader機制讓其更變得更加靈活。固然,Webpack的流行天然仍是離不開背後的react 跟facebook。可是從如今HTTP/2標準的應用及實施進展來看,Webpack/browserify這種基於bundle的打包工具也面臨着被歷史車輪碾過的危機,相對的基於module loader的jspm反而更具前景。Browserify 可讓你使用相似於 node 的 require() 的方式來組織瀏覽器端的 Javascript 代碼,經過預編譯讓前端 Javascript 能夠直接使用 Node NPM 安裝的一些庫。相較於Webpack,Browserify具備更悠久的歷史,記得當年仍是看這篇文章纔開始慢慢認識到Webpack,那時候Webpack仍是一個至關年輕的框架啊。

Webpack是前端開發真正意義上成爲了工程級別,而再也不是隨意,能夠看看這篇文章。筆者第一次看Webpack的時候,沒看懂。當時用Gulp用的正順手,不須要本身往HTML文件裏引入大量的Script文件,還能自動幫你給CSS加先後綴,自動地幫你壓縮,多好啊。不過Grunt和Gulp如今存在的問題就是須要本身去組裝大量的插件,良莠不齊的插件質量致使了大量時間的浪費。而且Gulp/Grunt還並不能稱爲一個完整的編譯工具,只是一個輔助工具。

Webpack還有很令筆者欣慰的一點,它支持Lazy Load Component,而且這種懶加載技術是與框架無關的。這樣就避免了筆者在編碼時還須要考慮固定的組件或者代碼分割,畢竟在一個快速迭代的項目中仍是很難在一開始就規劃好所有的組件分割。這一點對於筆者這種被SPA JS加載以及原來的不管是基於Angular的懶加載仍是React Router的懶加載折磨的人是一個大大的福音。同時,Webpack還支持配合了React Hot Loader的代碼熱插拔,能夠大大地提升代碼的開發效率。畢竟等着Browserify編譯好也是很蛋疼的。

在筆者的我的的感觸中,Webpack是促成了前端真正工程化的不可缺乏的一環。記得以前看過美團的前端技術分享,它提出了前端分佈式編譯系統。大型系統的分佈式編譯很常見,可是在前端,這典型的腳本與解釋執行的領域,出現了大型分佈式編譯系統,仍是很讓人震驚的。筆者是個懶惰的人,懶人總但願能夠用一套方法去解決所有的問題,因此慢慢的筆者徹底切入到了Webpack。或許將來某天也會離開Webpack,就像離開jQuery同樣,可是會永遠記得陪我走過的這些歲月。

響應式數據流驅動的頁面

現代這樣一個雲計算與大數據的時代,Data Driven的概念早已深刻人心。隨着WEB應用變得愈來愈複雜,再加上node先後端分離愈來愈流行,那麼對數據流動的控制就顯得愈加重要。筆者在開篇就說起過,前端變革的一個核心路線就是從以DOM Manipulation爲核心到以State爲核心,這樣也就能將邏輯控制、渲染與交互給分離開來。用一個函數來表示,如今的渲染就是:$UI=f(state)$。在React中$f$能夠看作是那個render函數,能夠將state渲染成Virtual DOM,Virtual DOM再被React渲染成真正的DOM。在控制器中,咱們不須要關心DOM是如何變動的,只須要在咱們的業務邏輯中完成狀態轉變,React會自動將這個變動顯示在UI中。其實在Angular中也是這樣,只不過Angular中採起的數據雙向綁定與髒檢測的技術,而React中採用的是JSX這樣來完成一種從狀態到頁面的綁定。

這樣一種以響應式數據流驅動的頁面,毫無疑問會將編程工做,特別是複雜的交互與邏輯處理變得更加明晰,也方面了產品迭代與變動,也就是敏捷式開發的理念。採用這樣的響應式數據流驅動的方式,還有一個很大的好處就是方便錯誤追蹤與調試。SPA State is hard to reproduce!而在Redux這樣的框架中,存在着相似於Global State Object這樣的能夠將頁面所有還原,來重現Bug的東西。當測試人員/用戶遇到問題的時候,主動將當時的State發送給開發人員,開發人員就闊以直接根據State來還原現場咯。Immutable的魅力正在於此,靈活的可追蹤性。

Redux是在flux的基礎上產生的,在此基礎上它引入了函數式編程、單一數據源、不可變數據、中間件等概念,基本思想是保證數據的單向流動,同時便於控制、使用、測試。Redux不依賴於任意框架(庫),只要subscribe相應框架(庫)的內部方法,就可使用該應用框架保證數據流動的一致性。Redux在必定程度上能夠說是今年React生態甚至整個前端生態中影響最大的一個框架,它給整個前端技術棧引入了不少新成員,儘管這些概念可能在其餘領域已經有了普遍的應用。筆者仍是比較推崇響應式開發的,實際工做中用的比較多的仍是FPR的一些實現,譬如RxJava啊這些。Redux標榜的是Immutable的State Tree,而Vue採用的是Mutable的State Tree。

筆者在不長的代碼之路上從Windows Developer 到 Pentester,到 Android Developer,到 Server-Side Developer,最後選擇了Front-end 做爲本身的歸宿。不過Server-Side Architecture 和 Data Science也是個人最愛,哈哈哈哈哈哈,怎麼有一種坐擁後宮的趕腳~

但願能永遠在這條路上,心懷激情,熱淚盈眶。

相關文章
相關標籤/搜索