
作者介紹:Andrew Montalenti是Parse.ly的CTO, 一個長期的Python愛好者,以及初創公司和其他項目的創始人。
原文鏈接:https://amontalenti.com/2019/08/10/javascript-the-modern-parts
在過去的幾個月里,我通過Node 8,Webpack 4和Babel 7提供的本地工具學到了很多關於現代JavaScript和CSS開發的知識。作為其中的一部分,我正在進行第二次“重新認識JavaScript”。 我在1998年首次學習JS。然后在2008年重新開始,在“The Good Parts”年代,Firebug,jQuery,IE6兼容性,以及最終成熟的Node生態系統時代。 在那個時代,我在網上編寫了一個最廣泛部署的一個JavaScript前端系統。

現在我正在ECMAScript(ES6 / ES2017)時代重新學習它,預編譯,第三方庫和模塊化的正式支持,以及PWA,代碼分割和WebWorkers/ServiceWorkers等移動網絡性能。 令人驚喜的是,通過ECMAScript標准和Babel,JS已經發展成為一種非常好的編程語言,所有事情都被考慮在內。
為了鞏固所有這些東西,我使用webpack/babel為一個簡單的Python/Flask Web應用程序構建所有靜態資產,最終部署成一個數百頁的靜態站點。
一個周末,我將所有內容從Flask-Assets移植到webpack,並使用ES2017功能,以及探索Sass CSS預處理器和一些D3.js示例。讓我們從頭開始!
1998年的JavaScript
我在1998年首次學習JavaScript。很難相信這是20年以前了。這篇文章將描述自那以來的二十年 - 涵蓋了1998年,2008年和2018年的JavaScript。本文的重點將放在“現代”JavaScript上,根據我在2018/2019的理解,特別是非JavaScript程序員應該知道語言及其相關的工具和運行時是如何發展的。
如果你是那種思考的程序員,“我用Python/Java/Ruby/C編寫代碼,因此我沒有使用JavaScript,也不需要了解它”,你錯了,我會描述原因。順便說一句,你在1998年是對的,你可以在2008年沒有它,而你在2018年就錯了。
此外,如果你是一個程序員,他認為“JavaScript是一個變化很快的技術,我寧願避免,因為它缺乏基本的基礎設施,我們認為在'真正'的編程語言中這些是理所當然的”,那么你也錯了。我將能夠向你展示在2018年“不認真對待JavaScript”就像2008年代程序員不認真對待Python或Ruby一樣嚴重無知。
JavaScript不僅是一種語言,而且已經並將繼續在幾個重要領域接管世界。要成為一名認真的程序員,您必須了解JavaScript的現代和好的部分以及其他一些服務器端語言,如Python,Ruby,Go,Elixir,Clojure,Java等。但是,盡管您可以為使用不同的一種后端語言,但您無法避免使用JavaScript:它在各種Web部署方案中都很普遍。而且,開發人員工具已經完全滿足您的期望。
瀏覽器大戰中的JavaScript
瀏覽器是一個苛刻的環境,以發展為目標; 不僅互聯網采用率低,而且互聯網連接不僅緩慢,而且瀏覽器大戰 - 主要是在網景和微軟之間 - 引發了很多混亂。
Netscape Navigator 4於1997年發布,Internet Explorer 5於1998年發布。網絡仍在嘗試理解HTML和CSS; 畢竟,CSS1僅在一年前發布。
在這種環境下,當時最權威的網絡開發書籍是“JavaScript:The Definitive Guide”,超過500頁。 請注意,在1998年,使用最廣泛的編程語言是C,C ++和Java,以及Microsoft Visual Basic for Windows。因此,關於“編程是什么”的主題主要圍繞着這些語言。
從這個意義上講,JavaScript非常不同。它沒有編譯器,沒有調試器(至少不是很好的調試器), 沒有辦法“運行JavaScript程序”,除了在瀏覽器中編寫腳本,並查看它們是否運行。 JavaScript的開發工具仍然是原始的或不存在的。JS當然沒有太多的開源社區; 要弄清楚如何做事,你通常會在其他人的網站上“查看源碼”。 此外,Web開發人員編程社區中的大部分討論都是JavaScript中兼容性和安全性的噩夢。
不僅可以跨瀏覽器實現不同的實現,還可以通過多種方式直接依賴JavaScript來破壞Web應用程序的安全性。那個時代的常見安全漏洞是使用JavaScript驗證表單,但仍允許將無效(和不安全)值傳遞給服務器。或者,要對系統進行密碼保護,但檢查JavaScript代碼本身可能會破壞對該系統的訪問。結合缺乏適當的開發環境,“真正的網絡程序員”使用JavaScript只不過是最后的手段 - 一種將一些客戶端代碼和邏輯注入到服務器端的服務器端的方式。我記得當時JavaScript最常見的用例之一只是在懸停時更改圖像,作為風格效果,或在復雜的多選項卡表單上實現基本的懸停菜單。目前,這些任務可以通過純CSS實現,但是,當時,JavaScript DOM操作是您唯一的選擇。
2008年的JavaScript
快進10年來到2008年,Douglas Crockford發布了“JavaScript:The Good Parts”這本書。 通過使用語言子集方法,Crockford指出,JavaScript不僅不是一種糟糕的語言,它實際上是一種優秀的語言,設計精良,具有某些關鍵功能,使其與競爭對手相比更加突出。
大約在這個時候,一些JavaScript庫變得流行,特別是jQuery,Prototype,YUI和Dojo。 這些庫試圖為JavaScript提供它缺少的東西:跨瀏覽器兼容性和編程模型,用於對瀏覽器內的頁面進行動態操作,特別是對於新出現的JavaScript編程模型-AJAX。 這是富互聯網應用程序,“動態”Web應用程序,單頁應用程序等趨勢的開始。
JavaScript工具集的飛躍
JavaScript的開發工具也取得了一些重要的飛躍。 2006年,Firefox團隊發布了Firebug,這是Firefox的JavaScript和DOM調試器,后來Firefox成為世界上最受歡迎的Web瀏覽器之一,也是開源的。兩年后,谷歌將首次發布谷歌Chrome,它捆綁了一些開發人員工具。大約在Chrome發布的同時,谷歌還發布了V8,這是嵌入Chrome內部的JavaScript引擎。這標志着世界第一次看到JavaScript語言的完整,高性能的開源實現,並沒有完全與瀏覽器綁定。 Firefox的JS引擎SpiderMonkey是其源代碼樹的一部分,但不一定是在Firefox瀏覽器的上下文之外進行模塊化和使用。
我記得除了Crockford確定JavaScript的優點之外的工作,除了新的(和更好的)開發人員工具之外,Mozilla網站上的一篇特定文章幫助我重新欣賞了這種語言,並拋棄了我1998年的概念。那篇文章被稱為“A Reintroduction to JavaScript”。它展示了JavaScript實際上是一種真正的編程語言。它的標准庫有點不足,因此你必須依賴框架(比如jQuery)來為你提供一些工具,以及除此之外的微型庫。
讀完那篇文章一年后,我寫了一篇關於JavaScript的文章,它被稱為“Real, Functional Programs with JavaScript”。 它描述了JavaScript是一種非常令人驚訝的功能語言,它不是Java 8或Python 2.7。 而且只需要專注於理解功能核心,就可以編寫出非常好的程序。 我最近將這篇文章轉換成了一組教學幻燈片,名稱為“Lambda JavaScript”,我現在用它來向新設計師/開發人員講授第一原理語言。
好吧,讓我們回到歷史。Chrome發布僅一年后,在2009年,我們看到了NodeJS的第一個版本,它采用V8 JavaScript引擎並將其嵌入到服務器端環境中,可用於在REPL上試驗JavaScript,以便編寫 腳本,甚至可以依賴高性能事件循環特性來實現HTTP服務器。
人們開始嘗試用JavaScript編寫的命令行工具,以及用JavaScript編寫的Web框架。正是在這一點上,JavaScript社區的發展速度加快了。 2010年,npm(節點包管理器)發布了,它及其軟件包注冊表迅速發展,代表了完整的JavaScript開源社區興起。在接下來的幾年里,Mozilla,谷歌,蘋果和微軟的瀏覽器廠商參與了“JavaScript引擎戰爭”,每個人都將SpiderMonkey,V8,Nitro和Chakra發展到了一個新的高度。
同時,NodeJS和V8成為從命令行在開發人員的機器上運行的“標准”JS引擎。雖然開發人員仍然不得不兼容舊的“ECMAScript 3”瀏覽器(例如IE6),因此必須編寫受限制的JavaScript代碼,但Mozilla,Google和Apple的“年輕”(自動更新)瀏覽器對ECMAScript 5和后續ES版本的支持,移動網絡瀏覽成為主流,從而使Chrome和Safari在市場份額中占據主導地位,特別是在智能手機上。
我記得在2012年,我在當地的一個技術會議上做了題為“用JavaScript編寫真正的程序!?”的演講。 “!?”標點符號是故意的。那是我在一個充滿開發人員的房間里記得的一個時代的變化:也就是說,“用JavaScript編寫真正的程序......實際上可能!?”將這些幻燈片作為歷史遺跡進行審查是很有趣的。我在講座的前半部分讓觀眾相信JavaScript的功能核心實際上非常好。然后我花了下半部分說服NodeJS可能......它可能......創建一個開發人員工具生態系統和JavaScript的標准庫。 Comet vs Ajax之類的東西也有一些有趣的“繞行”幻燈片,這個辯論實際上並不多(但提醒科技的流行趨勢很好)。
幾年前,在Web 2.0,雲端和移動設備的所有噪音中,我們終於來到了移動時代,2015年移動流量超過了桌面流量,我們也看到了幾個桌面操作系統遷移到了大多數常青樹模型,例如Windows 10,Mac OS X和ChromeOS。因此,早在2015年 - 但肯定到2018年 - JavaScript成為部署最廣泛且性能最高的編程語言,幾乎在世界上所有台式機和移動計算機上都具有“內置支持”。
換句話說,如果您希望您的代碼在2015年左右“一次編寫,隨處運行”,您最好的選擇是JavaScript。那么,今天更是如此。廣泛分發代碼的可靠選擇仍然是JavaScript。正如克羅克福德在2008年預測的那樣:“幸運比聰明更好。”
2018-2019年的JavaScript
在2018-2019,關於JavaScript社區的一些事情發生了變化。開發工具不再是初出茅廬的,而是成熟的。所有Safari,Firefox和Chrome瀏覽器都有內置的開發工具(Firebug項目大多已被棄用)。還有一些方法可以使用移動開發工具調試移動Web瀏覽器。 NodeJS和npm是成熟的項目,是整個JavaScript社區的共享基礎架構。
更重要的是,JavaScript作為一種語言已經得到發展。它不再僅僅是我們在1998年所知道的核心語言,也不再是我們在2008年所知道的“The Good Parts”,而是JavaScript的“現代部分”包括幾個新的語言特征,名稱為“ES6”(ECMAScript v6)或“ES2017”(ECMAScript 2017版)等等。
HTML中的一些概念已經發展,例如HTML5視頻和音頻元素。隨着CSS2和CSS3規范的批准和廣泛采用,CSS也在不斷發展。JSON幾乎完全取代了XML作為交換格式,當然是基於JavaScript的。
V8引擎也獲得了大量以性能為導向的開發。它現在是一種JIT編譯語言,具有快速啟動時間和CPU綁定塊的快速近原生性能。現代Web性能技術幾乎完全基於快速的JavaScript引擎,並能夠編寫Web應用程序加載方法的不同元素的腳本。
語言本身已經適應了類似於Python,Ruby,C和Java社區中可能找到的“編譯器”和“命令行”工具。代替JavaScript“編譯器”,我們有節點,JavaScript單元測試框架,如Mocha / Jest,以及用於語法檢查的eslint和babel。
代替“調試器”,我們在我們最喜歡的瀏覽器中內置了devtools,例如Chrome或Firefox。這包括豐富的調試器,REPL /控制台和可視化檢查工具。與節點環境或瀏覽器進程的腳本化遠程連接(通過Puppeteer等新工具)進一步閉環了開發流程。
因此,在2018/2019中使用JavaScript是采用一種已經達到2008年成熟度的系統,您將在Python,Ruby和Java等編程生態系統中看到這種系統。但是,在很多方面,JavaScript已經超越了這些社區。例如,Python 3的參考實現CPython在動態語言方面肯定是快速的,JavaScript的參考實現V8通過JIT和熱點優化技術進行優化,這些技術只能在更成熟的編程社區中找到,例如Java(它在Sun時代的應用/高級編譯器技術中獲得了數百萬美元的商業支持。這意味着未經修改的熱點JavaScript代碼可以由Node運行時和Chrome等瀏覽器自動優化為本機代碼。
雖然Java和C用戶可能仍然爭論開源項目應該在何處發布他們的版本,但是這個問題在JavaScript社區中得到了解決:它是npm,其操作類似於Python社區中的PyPI和pip。
一些重要的開發人員工具問題最近才解決。 例如,因為現代JavaScript(例如使用ES2017功能編寫的代碼)需要以舊瀏覽器為目標,所以需要使用“轉換”工具將ES2017代碼編譯為適合舊版瀏覽器的ES3或ES5 JavaScript代碼。 因為“舊JavaScript”是圖靈完整的函數式編程語言,我們知道我們幾乎可以將任何新的“語法糖”翻譯成舊語言,實際上,新語言特性的設計者正在謹慎地僅引入語法可以安全進行編譯。
然而,這意味着要進行JavaScript開發“現代方式”,同時采用其新功能,您只需使用本地轉換器工具。 目前社區的標准被稱為babel,它很可能在未來很好地保持社區標准。
困擾2008年JavaScript的另一個問題是構建工具和模塊化。在2008-2012時代,像make這樣的特殊工具被用於將JavaScript模塊連接在一起,並且通常使用基於Java的工具(如Google的Closure Compiler或UglifyJS)將JavaScript項目組裝到可以包含在頁面中的模塊中。 2012年,Grunt工具作為JavaScript構建工具發布,在NodeJS上編寫,可從命令行運行,並可使用JavaScript“Gruntfile”進行配置。在此期間發布了大量類似於此的構建工具,造成了大量的代碼流失和混亂。
值得慶幸的是,今天,像React這樣的單頁應用程序框架在很大程度上解決了這個問題,其中包括webpack的優勢和對npm run-script的依賴。今天,webpack社區已經提出了一種理智的JavaScript模塊化方法,它依賴於現代JS對模塊的支持,然后主要通過webpack CLI工具提供的開發時工具允許本地開發和生產構建。這可以通過簡單的npm run-script命令編寫腳本並連接在一起。而且由於webpack本身可以通過npm安裝,這使得整個開發堆棧保持自包含的方式與Clojure中的lein或Python中的python / pip不同。
是的,它經歷了20年時間,但現在JavaScript已經成為Python后端和CLI工具項目的可行選擇。 而且,對於網絡前端,它是您唯一的選擇。 所以,如果你是一個完全關心代碼分發給用戶的程序員,那么就該關心JavaScript吧!
有興趣同學可以關注微信公眾號奶爸碼農,不定期分享關於投資、理財、IT的信息:
