2017 年值得一瞥的 JavaScript 相關技術趨勢

王下邀月熊發表於2017-01-02

跨年前兩天,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的粉絲,他們的HackFlow以及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的語法對比:

元型別| JavaScript | Reason |

333.14153.1415″Hello World!”"Hello world!”‘Hello world!’Strings must use “Characters are strings’a'truetrue[1,2,3][1,2,3]null()const x = y;let x = y;let x = y;reference cellsvar x = y;No equivalent (thankfully)[x, ...lst] (linear time)[x, ...lst] (constant time)[...lst, x] (linear time)Not supported{…obj, x: y}{…obj, x: y}

表示式| JavaScript | Reason |

login ? “hi” : “bye”login ? “hi” : “bye”let res = undefined;switch (thing) { case first: res = “first”; break; case second: res = “second”; break;};`let res = switch thing {first => “first”second => “second”}; `

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社群獲得了不小的關注度。

相關文章