2017值得一瞥的JavaScript相關技術趨勢
2017值得一瞥的JavaScript相關技術趨勢從屬于筆者的Web 前端入門與工程實踐,推薦閱讀2016-我的前端之路:工具化與工程化獲得更多關于2016年前端總結。本文主要內容翻譯自,筆者對于每個條目進行了些許完善。
本文中提及的這些趨勢可能離大部分開發者還很遠,或者說離真正的大規模工程化應用還很遠,不過不妨礙我們提前兩三年了解下。本文僅代表原作者個人看法,不喜留言輕噴,譯者也很好奇大家對這個列表的看法。
跨年前兩天,Dan Abramov在Twitter上提了一個問題:
JS社區毫不猶豫的拋出了它們對于新技術的預期與期待,本文內容也是總結自Twitter的回復,按照流行度降序排列。有一個尚未確定的小點是既然函數式編程已不再是少數派,是否要把它踢出紅毯呢?
WebAssembly
去年筆者就表示過了對于WebAssembly的期待,WebAssembly就是面向Web平臺的底層代碼。其初衷是希望能夠使所有語言都能夠編譯運行到Web平臺,這一點對于很多函數式編程、響應式編程的粉絲充滿吸引力。特別是隨著這幾年JavaScript社區的突飛猛進,很多開發者并不能跟得上這門語言衍化的速度,因此他們也非常希望能夠直接用自己習慣的語言而不是要去重頭學一門從入門到直接放棄的語言。不過JavaScript目前還處于明顯的上升勢頭,暫時還沒人唱衰它。并且WebAssembly仍處于襁褓中,才進入到預覽階段,離真正的發布還有很長的距離。總結而言,筆者建議我們都應該對WebAssembly保持一定的關注,畢竟它會對未來的JavaScript造成極大的影響。如果你對于WebAssembly有興趣,那么推薦閱讀Eric Elliott的相關博客。
Elm
筆者個人不太意愿使用Elm,不過其特性還是很有借鑒價值
2016年不少的開發者參與到Elm的開發中,Elm不僅僅是JavaScript的擴展庫,而是一門可以編譯到JavaScript的編程語言,對于很多熱衷于函數式編程的開發者是個不錯的選擇。參考Elm 入門介紹,Elm提供了如下特性:
- 并不會存在運行時錯誤,沒有null,沒有undefined is not a funtion。
- 非常友好的錯誤提示信息能夠輔助你開發。
- 比較嚴格的代碼規范與項目架構,保證了你的應用在快速迭代中依然保持著***實踐。
- 自動為所有的Elm包添加語義版本描述。
總而言之,Elm為我們提供了優秀的工具來保證編寫干凈、簡單與碎片化的代碼,并且因為Elm是可以編譯到JavaScript,因此很多JavaScript開發者都可以保持下關注或者嘗試下。
babili(babel-minify)
Babili最早于2016年8月份發布,它是基于Babel工具鏈上的支持原生ES6語法的壓縮工具。Henry Zhu在這篇文章中稱述了為什么我們需要另一個壓縮工具,關鍵點如下:
目前大部分壓縮工具只能
夠處理ES5代碼,因此在壓縮之前需要先進性編譯,而Babili能夠支持直接輸入ES2015+。隨著瀏覽器性能的提升,越來越多的瀏覽器支持直接運行ES2015的代碼,因此我們不需要再進行轉換編譯。另外Babili也可以作為Babel preset引入到現有的Babel配置中,也可以作為直接使用的命令行工具。
這里舉個簡單的例子,我們編寫了如下的ES6類:
- class Mangler {
- constructor(program) {
- this.program = program;
- }
- }
- // need this since otherwise Mangler isn't used
- new Mangler();
之前,利用傳統的Babel進行編譯與壓縮,會得到如下代碼:
- // ES2015 code -> Babel -> Uglify/Babili -> Minified ES5 Code
- var a=function a(b){_classCallCheck(this,a),this.program=b};a();
而Babili的效果如下:
- // ES2015 code -> Babili -> Minified ES2015 Code
- class a{constructor(b){this.program=b}}new a;
OCaml
OCaml本身和JS沒啥關系,不過列表接下來的兩項都是基于OCaml,因此還是要先介紹下。如果你關注了近兩年來的函數式編程崛起之路,你或許聽過Haskell。而得益于OCaml能夠編譯到就S,其以后來居上的姿態凌駕于Haskell。Facebook的不少開發者都是OCaml的粉絲,他們的Hack、Flow以及Infer都是基于OCaml構建的。
BuckleScript
BuckleScript是基于OCaml實現的服務端框架,由著名的Bloomberg團隊創造而來。Duane Johnson對他們的解釋如下:
BuckleScript或者bsc,是個基于OCaml編譯器的相對較新的JavaScript服務端框架。換言之,你可以使用優秀的函數式、自帶類型的OCaml語言,同時也能繼續背靠基于npm包管理器的Web生態系統。
我們來簡要的看下BuckleScript代碼風格,譬如用BuckleScript實現簡單的服務端:
- let port = 3000
- let hostname = "127.0.0.1"
- let create_server http =
- let server = http##createServer begin fun [@bs] req resp ->
- resp##statusCode #= 200;
- resp##setHeader "Content-Type" "text/plain";
- resp##_end "Hello world\n"
- end
- in
- server##listen port hostname begin fun [@bs] () ->
- Js.log ("Server running at http://"^ hostname ^ ":" ^ Pervasives.string_of_int port ^ "/")
- end
- let () = create_server Http_types.http
編譯輸出為:
- 'use strict';
- var Pervasives = require("bs-platform/lib/js/pervasives");
- var Http = require("http");
- var hostname = "127.0.0.1";
- function create_server(http) {
- var server = http.createServer(function (_, resp) {
- resp.statusCode = 200;
- resp.setHeader("Content-Type", "text/plain");
- return resp.end("Hello world\n");
- });
- return server.listen(3000, hostname, function () {
- console.log("Server running at http://" + (hostname + (":" + (Pervasives.string_of_int(3000) + "/"))));
- return /* () */0;
- });
- }
- create_server(Http);
OCaml***的特性就是其函數式語言特性,我們再看下其對于不可變類型的支持,我們使用OCaml stdlib實現的不可變類型如下:
- module IntMap = Map.Make(struct
- type t = int
- let compare (x : int) y = compare x y
- end)
- let test () =
- let m = ref IntMap.empty in
- let count = 1000000 in
- for i = 0 to count do
- m := IntMap.add i i !m
- done;
- for i = 0 to count do
- ignore (IntMap.find i !m)
- done
- let () = test()
而如果要用Facebook Immutable實現的代碼為:
- 'use strict';
- var Immutable = require('immutable');
- var Map = Immutable.Map;
- var m = new Map();
- function test() {
- var count = 1000000;
- for(var i = 0; i < count; ++i) {
- m = m.set(i, i);
- }
- for(var j = 0; j < count; ++j) {
- m.get(j);
- }
- }
- test();
性能評測下,二者的執行時間對比為:
- BuckleScript: 1186ms
- JavaScript: 3415ms
編譯后的體積為:
- BuckleScript (production): 899 Bytes
- JavaScript: 55.3K Bytes
ReasonML
ReasonML與React師出同門,是基于OCamel設計的語法友好、編輯器支持程度高,并且有強大的編譯工具支持的語言。建議閱讀Sean Grove對ReasonML的介紹。本文簡單介紹幾個JavaScript與Reason的語法對比:
Purescript
另一個強類型、高性能的能夠編譯到JavaScript的編程語言,其定位與Elm類似,主要特性為:
- 沒有運行時錯誤
- 嚴格的,類似于JavaScript的計算
- 支持JavaScript 對象語法
- 提供相較于Hashkell更強大方便的類型系統
- 更方便地JavaScript庫集成
Webpack-blocks
Dan Abramov說過,Webpack的定位就是在相對底層,因此將配置以編程塊的方式實現會更加完備。
- const { createConfig, defineConstants, env, entryPoint, setOutput, sourceMaps } = require('@webpack-blocks/webpack2')
- const babel = require('@webpack-blocks/babel6')
- const devServer = require('@webpack-blocks/dev-server2')
- const postcss = require('@webpack-blocks/postcss')
- const autoprefixer = require('autoprefixer')
- module.exports = createConfig([
- entryPoint('./src/main.js'),
- setOutput('./build/bundle.js'),
- babel(),
- postcss([
- autoprefixer({ browsers: ['last 2 versions'] })
- ]),
- defineConstants({
- 'process.env.NODE_ENV': process.env.NODE_ENV
- }),
- env('development', [
- devServer(),
- devServer.proxy({
- '/api': { target: 'http://localhost:3000' }
- }),
- sourceMaps()
- ])
- ]);
GraphQL
GraphQL是個不錯的REST替代查詢語言,特別是對于那些擁有大量數據的公司。這個案例分析很好地闡述了從REST到GraphQL的轉變之路。我能夠想象2017年GraphQL會繼續處于上升勢頭,不過要談到真的大規模實施,還要到2018年吧。
React Storybook
相信大家對于React Storybook并不陌生了,你能夠獨立于應用而交互式的開發你的組件,就如下圖所示:
[jQuery 3.0]()
爺爺輩的jQuery仍然處于不斷的迭代更新中,可能很多開發者忽略了2016年6月份發布的jQuery 3.0版本,可以參考這里獲取更多信息。
Pixi.js
如果你打算在瀏覽器中實現精彩的2D效果,特別是對于使用WebGL的游戲開發者,Pixi.js是個值得一看的庫,可以參考這里獲取更多的Demo。
Preact與[inferno]()
非常優秀的React的替代庫。
Rust
Rust可以編譯到JavaScript啦(通過emscripten)。
Custom Elements
Custom Elements(包括Shadow DOM)一直不被主流的開發者接受,不過看似2017這一點將會發生些許變化。變化的關鍵因素在于瀏覽器支持比例的改善。個人還是蠻期待Custom Elements的,可以關注SmashingMag或者Google’s關于Custom Elements的解釋。
WebRTC
很難相信WebRTC已經五歲了,Facebook、Slack、Snapchat以及WhatsApp都在他們的服務中集成了WebRTC。可以預見WebRTC會在2017年被更多的公司采用,蒸蒸日上。
Next.js
Next.js是個基于React、Webpack與Babel構建的,支持服務端渲染的小框架,其來源于ZEIT團隊,在React社區獲得了不小的關注度。