2017值得一瞥的JavaScript相关技术趋势

reding7e4f 7年前
   <p><a href="/misc/goto?guid=4959732850100319796" rel="nofollow,noindex">2017值得一瞥的JavaScript相关技术趋势</a> 从属于笔者的 <a href="/misc/goto?guid=4959732850200495319" rel="nofollow,noindex">Web 前端入门与工程实践</a> ,推荐阅读 <a href="/misc/goto?guid=4959732850316022269" rel="nofollow,noindex">2016-我的前端之路:工具化与工程化</a> 获得更多关于2016年前端总结。本文主要内容翻译自,笔者对于每个条目进行了些许完善。本文中提及的这些趋势可能离大部分开发者还很远,或者说离真正的大规模工程化应用还很远,不过不妨碍我们提前两三年了解下。本文仅代表原作者个人看法,不喜留言轻喷,译者也很好奇大家对这个列表的看法。</p>    <p><img src="https://simg.open-open.com/show/324364fac0ebdfe7b758535716c10ef0.jpg"></p>    <p>跨年前两天, <a href="/misc/goto?guid=4959729725720706193" rel="nofollow,noindex">Dan Abramov</a> 在推ter上提了一个问题:</p>    <p><img src="https://simg.open-open.com/show/c602eca3d6c1e911c776771cf9b08dcb.png"></p>    <p>JS社区毫不犹豫的抛出了它们对于新技术的预期与期待,本文内容也是总结自推ter的回复,按照流行度降序排列。有一个尚未确定的小点是既然函数式编程已不再是少数派,是否要把它踢出红毯呢?</p>    <h2>WebAssembly</h2>    <p><img src="https://simg.open-open.com/show/ac6d0c55df10eaaf1bb811bf00742ad5.jpg"></p>    <p>去年笔者就表示过了对于WebAssembly的期待,WebAssembly就是面向Web平台的底层代码。其初衷是希望能够使所有语言都能够编译运行到Web平台,这一点对于很多函数式编程、响应式编程的粉丝充满吸引力。特别是随着这几年JavaScript社区的突飞猛进,很多开发者并不能跟得上这门语言衍化的速度,因此他们也非常希望能够直接用自己习惯的语言而不是要去重头学一门从入门到直接放弃的语言。不过JavaScript目前还处于明显的上升势头,暂时还没人唱衰它。并且WebAssembly仍处于襁褓中,才进入到预览阶段,离真正的发布还有很长的距离。总结而言,笔者建议我们都应该对WebAssembly保持一定的关注,毕竟它会对未来的JavaScript造成极大的影响。如果你对于WebAssembly有兴趣,那么推荐阅读 <a href="/misc/goto?guid=4959732850449301842" rel="nofollow,noindex">Eric Elliott的相关博客</a> 。</p>    <h2>Elm</h2>    <p>笔者个人不太意愿使用Elm,不过其特性还是很有借鉴价值</p>    <p>2016年不少的开发者参与到 <a href="/misc/goto?guid=4959732850558200254" rel="nofollow,noindex">Elm的开发中</a> ,Elm不仅仅是JavaScript的扩展库,而是一门可以编译到JavaScript的编程语言,对于很多热衷于函数式编程的开发者是个不错的选择。参考 <a href="/misc/goto?guid=4959732850657345483" rel="nofollow,noindex">Elm 入门介绍</a> ,Elm提供了如下特性:</p>    <ul>     <li> <p>并不会存在运行时错误,没有 null ,没有 undefined is not a funtion 。</p> </li>     <li> <p>非常友好的错误提示信息能够辅助你开发。</p> </li>     <li> <p>比较严格的代码规范与项目架构,保证了你的应用在快速迭代中依然保持着最佳实践。</p> </li>     <li> <p>自动为所有的Elm包添加语义版本描述。</p> </li>    </ul>    <p>总而言之,Elm为我们提供了优秀的工具来保证编写干净、简单与碎片化的代码,并且因为Elm是可以编译到JavaScript,因此很多JavaScript开发者都可以保持下关注或者尝试下。</p>    <h2>babili(babel-minify)</h2>    <p><a href="/misc/goto?guid=4959732647186057903" rel="nofollow,noindex">Babili</a> 最早于2016年8月份发布,它是基于Babel工具链上的支持原生ES6语法的压缩工具。Henry Zhu在 <a href="/misc/goto?guid=4959732850787505518" rel="nofollow,noindex">这篇文章</a> 中称述了为什么我们需要另一个压缩工具,关键点如下:</p>    <p>目前大部分压缩工具只能够处理ES5代码,因此在压缩之前需要先进性编译,而Babili能够支持直接输入ES2015+。随着浏览器性能的提升,越来越多的浏览器支持直接运行ES2015的代码,因此我们不需要再进行转换编译。另外Babili也可以作为 <a href="/misc/goto?guid=4959648207016529317" rel="nofollow,noindex">Babel preset</a> 引入到现有的Babel配置中,也可以作为直接使用的命令行工具。</p>    <p>这里举个简单的例子,我们编写了如下的ES6类:</p>    <pre>  <code class="language-javascript">class Mangler {    constructor(program) {      this.program = program;    }  }  // need this since otherwise Mangler isn't used  new Mangler();</code></pre>    <p>之前,利用传统的Babel进行编译与压缩,会得到如下代码:</p>    <pre>  <code class="language-javascript">// ES2015 code -> Babel -> Uglify/Babili -> Minified ES5 Code  var a=function a(b){_classCallCheck(this,a),this.program=b};a();</code></pre>    <p>而Babili的效果如下:</p>    <pre>  <code class="language-javascript">// ES2015 code -> Babili -> Minified ES2015 Code  class a{constructor(b){this.program=b}}new a;</code></pre>    <h2>OCaml</h2>    <p>OCaml本身和JS没啥关系,不过列表接下来的两项都是基于OCaml,因此还是要先介绍下。如果你关注了近两年来的函数式编程崛起之路,你或许听过Haskell。而得益于OCaml能够编译到就S,其以后来居上的姿态凌驾于Haskell。非死book的不少开发者都是OCaml的粉丝,他们的 <a href="/misc/goto?guid=4958832157693614541" rel="nofollow,noindex">Hack</a> 、 <a href="/misc/goto?guid=4959714402765517148" rel="nofollow,noindex">Flow</a> 以及 <a href="/misc/goto?guid=4958876983572348251" rel="nofollow,noindex">Infer</a> 都是基于OCaml构建的。</p>    <h2>BuckleScript</h2>    <p><a href="/misc/goto?guid=4959732851044772671" rel="nofollow,noindex">BuckleScript</a> 是基于OCaml实现的服务端框架,由著名的Bloomberg团队创造而来。 <a href="/misc/goto?guid=4959732851146814762" rel="nofollow,noindex">Duane Johnson</a> 对他们的解释如下:</p>    <p>BuckleScript或者bsc,是个基于OCaml编译器的相对较新的JavaScript服务端框架。换言之,你可以使用优秀的函数式、自带类型的OCaml语言,同时也能继续背靠基于 npm 包管理器的Web生态系统。</p>    <p>我们来简要的看下BuckleScript代码风格,譬如用BuckleScript实现简单的服务端:</p>    <pre>  <code class="language-javascript">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</code></pre>    <p>编译输出为:</p>    <pre>  <code class="language-javascript">'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);</code></pre>    <p>OCaml最大的特性就是其函数式语言特性,我们再看下其对于不可变类型的支持,我们使用OCaml stdlib实现的不可变类型如下:</p>    <pre>  <code class="language-javascript">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()</code></pre>    <p>而如果要用非死book Immutable实现的代码为:</p>    <pre>  <code class="language-javascript">'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();</code></pre>    <p>性能评测下,二者的执行时间对比为:</p>    <ul>     <li> <p>BuckleScript: 1186ms</p> </li>     <li> <p>JavaScript: 3415ms</p> </li>    </ul>    <p>编译后的体积为:</p>    <ul>     <li> <p>BuckleScript (production): 899 Bytes</p> </li>     <li> <p>JavaScript: 55.3K Bytes</p> </li>    </ul>    <h2>ReasonML</h2>    <p>ReasonML与React师出同门,是基于OCamel设计的语法友好、编辑器支持程度高,并且有强大的编译工具支持的语言。建议阅读 <a href="/misc/goto?guid=4959732851242981279" rel="nofollow,noindex">Sean Grove</a> 对ReasonML的介绍。本文简单介绍几个JavaScript与Reason的语法对比:</p>    <ul>     <li> <p>元类型</p> <p>| JavaScript | Reason |</p> </li>    </ul>    <table>     <tbody>      <tr>       <td>3</td>       <td>3</td>      </tr>      <tr>       <td>3.1415</td>       <td>3.1415</td>      </tr>      <tr>       <td>"Hello world!"</td>       <td>"Hello world!"</td>      </tr>      <tr>       <td>'Hello world!'</td>       <td>Strings must use “</td>      </tr>      <tr>       <td>Characters are strings</td>       <td>'a'</td>      </tr>      <tr>       <td>true</td>       <td>true</td>      </tr>      <tr>       <td>[1,2,3]</td>       <td>[1,2,3]</td>      </tr>      <tr>       <td>null</td>       <td>()</td>      </tr>      <tr>       <td>const x = y;</td>       <td>let x = y;</td>      </tr>      <tr>       <td>let x = y;</td>       <td>reference cells</td>      </tr>      <tr>       <td>var x = y;</td>       <td>No equivalent (thankfully)</td>      </tr>      <tr>       <td>[x, ...lst] (linear time)</td>       <td>[x, ...lst] (constant time)</td>      </tr>      <tr>       <td>[...lst, x] (linear time)</td>       <td>Not supported</td>      </tr>      <tr>       <td>{...obj, x: y}</td>       <td>{...obj, x: y}</td>      </tr>     </tbody>    </table>    <ul>     <li> <p>表达式</p> <p>| JavaScript | Reason |</p> </li>    </ul>    <table>     <tbody>      <tr>       <td>login ? "hi" : "bye"</td>       <td>login ? "hi" : "bye"</td>      </tr>      <tr>       <td>let res = undefined;switch (thing) { case first: res = "first"; break; case second: res = "second"; break;};</td>       <td>`let res = switch thing {</td>       <td>first => "first"</td>       <td>second => "second"}; `</td>      </tr>     </tbody>    </table>    <h2>Purescript</h2>    <p>另一个强类型、高性能的能够编译到JavaScript的编程语言,其定位与Elm类似,主要特性为:</p>    <ul>     <li> <p>没有运行时错误</p> </li>     <li> <p>严格的,类似于JavaScript的计算</p> </li>     <li> <p>支持JavaScript 对象语法</p> </li>     <li> <p>提供相较于Hashkell更强大方便的类型系统</p> </li>     <li> <p>更方便地JavaScript库集成</p> </li>    </ul>    <h2><a href="/misc/goto?guid=4959732851324341307" rel="nofollow,noindex">Webpack-blocks</a></h2>    <p>Dan Abramov说过,Webpack的定位就是在相对底层,因此将配置以编程块的方式实现会更加完备。</p>    <pre>  <code class="language-javascript">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()    ])  ])</code></pre>    <h2><a href="/misc/goto?guid=4959732851417387989" rel="nofollow,noindex">GraphQL</a></h2>    <p>GraphQL是个不错的REST替代查询语言,特别是对于那些拥有大量数据的公司。这个 <a href="/misc/goto?guid=4959732851508633176" rel="nofollow,noindex">案例分析</a> 很好地阐述了从REST到GraphQL的转变之路。我能够想象2017年GraphQL会继续处于上升势头,不过要谈到真的大规模实施,还要到2018年吧。</p>    <h2><a href="/misc/goto?guid=4959007488383776686" rel="nofollow,noindex">React Storybook</a></h2>    <p>相信大家对于React Storybook并不陌生了,你能够独立于应用而交互式的开发你的组件,就如下图所示:</p>    <p><img src="https://simg.open-open.com/show/b122378cd72f3254e556853319c620bf.gif"></p>    <h2>[jQuery 3.0]()</h2>    <p>爷爷辈的jQuery仍然处于不断的迭代更新中,可能很多开发者忽略了2016年6月份发布的jQuery 3.0版本,可以参考 <a href="/misc/goto?guid=4959732851639435115" rel="nofollow,noindex">这里获取更多信息</a> 。</p>    <h2><a href="/misc/goto?guid=4958832993945597568" rel="nofollow,noindex">Pixi.js</a></h2>    <p>如果你打算在浏览器中实现精彩的2D效果,特别是对于使用WebGL的游戏开发者,Pixi.js是个值得一看的库,可以参考 <a href="/misc/goto?guid=4959732851760437629" rel="nofollow,noindex">这里</a> 获取更多的Demo。</p>    <h2><a href="/misc/goto?guid=4958999005994964561" rel="nofollow,noindex">Preact</a> 与[inferno]()</h2>    <p>非常优秀的React的替代库。</p>    <h2>Rust</h2>    <p>Rust可以编译到JavaScript啦(通过 <a href="/misc/goto?guid=4958197069372055328" rel="nofollow,noindex">emscripten</a> )。</p>    <h2>Custom Elements</h2>    <p>Custom Elements(包括Shadow DOM)一直不被主流的开发者接受,不过看似2017这一点将会发生些许变化。变化的关键因素在于 <a href="/misc/goto?guid=4959732851915110577" rel="nofollow,noindex">浏览器支持比例的改善</a> 。个人还是蛮期待Custom Elements的,可以关注 <a href="/misc/goto?guid=4959732852000581446" rel="nofollow,noindex">SmashingMag</a> 或者 <a href="/misc/goto?guid=4959732852077994853" rel="nofollow,noindex">Google’s</a> 关于Custom Elements的解释。</p>    <h2>WebRTC</h2>    <p>很难相信WebRTC已经五岁了,非死book、Slack、Snapchat以及WhatsApp都在他们的服务中集成了WebRTC。可以预见WebRTC会在2017年被更多的公司采用,蒸蒸日上。</p>    <h2><a href="/misc/goto?guid=4959724300407068588" rel="nofollow,noindex">Next.js</a></h2>    <p>Next.js是个基于React、Webpack与Babel构建的,支持服务端渲染的小框架,其来源于ZEIT团队,在React社区获得了不小的关注度。</p>    <p> </p>    <p>来自:https://segmentfault.com/a/1190000007983437</p>    <p> </p>