在撰写本文时没有创建任何JavaScript框架。
以下内容受 Circle CI 的文章“这是未来”启发。您可以在此处阅读原文。本文仅代表个人观点,与任何 JavaScript 框架一样,不应太当真。
嘿,我接手了这个新的网络项目,但说实话,我已经好几年没有编写太多网络代码了,而且我听说情况发生了一些变化。你是这里最新的网络开发人员,对吧?
-实际的术语是前端工程师,但没错,我就是那个人。我在 2016 年从事网络工作。可视化、音乐播放器、会踢足球的飞行无人机,应有尽有。我刚从 JsConf 和 ReactConf 回来,所以我知道创建网络应用的最新技术。
太棒了。我需要创建一个显示用户最新活动的页面,所以我只需要从 REST 端点获取数据并将其显示在某种可过滤的表中,并在服务器发生任何变化时更新它。我在想也许可以使用 jQuery 来获取和显示数据?
-天哪,现在没人用 jQuery 了。你应该试着学习 React,现在已经是 2016 年了。
哦,好的。什么是 React?
-这是 Facebook 的一些人制作的超酷的库,它确实为您的应用程序带来了控制和性能,允许您非常轻松地处理任何视图更改。
听起来不错。我可以使用 React 显示来自服务器的数据吗?
-是的,但首先您需要在您的网页中添加 React 和 React DOM 作为库。
等等,为什么有两个库?
-所以一个是实际的库,第二个用于操作 DOM,现在您可以在 JSX 中描述它。
JSX?什么是 JSX?
-JSX 只是 JavaScript 语法扩展,与 XML 非常相似。它是描述 DOM 的另一种方式,可以将其视为更好的 HTML。
HTML 有什么问题?
-现在是 2016 年了。没有人再直接编写 HTML 代码了。
是的。无论如何,如果我添加这两个库,那么我就可以使用 React 了?
-不完全是。你需要添加 Babel,然后才能使用 React。
另一个库?Babel 是什么?
-哦,Babel 是一个转译器,它允许你使用特定版本的 JavaScript,同时你还可以使用任何版本的 JavaScript 进行编码。你不必包含 Babel 即可使用 ReactJS,但除非你这样做,否则你只能使用 ES5,让我们面对现实吧,现在是 2016 年了,你应该像其他酷孩子一样使用 ES2016+ 进行编码。
ES5?ES2016+?我搞糊涂了。ES5 和 ES2016+ 是什么?
-ES5 代表 ECMAScript 5。这是大多数人关注的版本,因为现在大多数浏览器都已实现了它。
ECMAScript?
-是的,你知道,JavaScript 的脚本标准是在 1995 年首次发布后于 1999 年制定的,当时 JavaScript 名为 Livescript,只能在 Netscape Navigator 中运行。当时情况非常混乱,但幸运的是,现在一切都很清晰,我们有大约 7 个版本的实现。
7 个版本。真的。ES5 和 ES2016+ 呢?
-分别是第五版和第七版。
等一下,第六个发生了什么?
-你的意思是 ES6?是的,我的意思是,每个版本都是前一个版本的超集,因此如果你使用 ES2016+,那么你将使用以前版本的所有功能。
对。那么为什么要使用 ES2016+ 而不是 ES6 呢?
-嗯,您可以使用 ES6,但要使用 async 和 await 等酷炫功能,您需要使用 ES2016+。否则,您只能使用 ES6 生成器和协程来阻止异步调用,以实现正确的控制流。
我不知道你刚才说了什么,这些名字都让人困惑。你看,我只是从服务器加载一堆数据,我以前可以从 CDN 中包含 jQuery,然后通过 AJAX 调用获取数据,为什么我不能这样做呢?
-现在已经 2016 年了,没人再使用 jQuery 了,它的代码乱七八糟。大家都知道这一点。
是的。所以我的替代方案是加载三个库来获取数据并显示 HTML 表。
-好吧,你包含这三个库,但将它们与模块管理器捆绑在一起以仅加载一个文件。
我明白了。那么模块管理器是什么?
-定义取决于环境,但在网络中,我们通常指支持 AMD 或 CommonJS 模块的任何东西。
对。AMD 和 CommonJS 是……?
-定义。有多种方式可以描述多个 JavaScript 库和类应如何交互。您知道,导出和要求吗?您可以编写多个定义 AMD 或 CommonJS API 的 JavaScript 文件,然后可以使用 Browserify 之类的工具将它们捆绑在一起。
好的,我觉得这很有道理。什么是 Browserify?
-这是一个工具,可让您将 CommonJS 描述的依赖项捆绑到可在浏览器中运行的文件中。创建它的原因是大多数人将这些依赖项发布在 npm 注册表中。
npm 注册表?
-这是一个非常大的公共存储库,聪明的人将代码和依赖项作为模块放在里面。
像 CDN 一样?
-不是。它更像是一个集中式数据库,任何人都可以发布和下载库,因此您可以在本地使用它们进行开发,然后根据需要将它们上传到 CDN。
哦,就像鲍尔!
-是的,但是现在已经是 2016 年了,没有人再使用 Bower 了。
哦,我明白了...那么我需要从 npm 下载库吗?
是的。例如,如果你想使用 React,你可以下载 React 模块并将其导入到你的代码中。你可以对几乎所有流行的 JavaScript 库执行此操作。
哦,像 Angular!
-Angular 太 2015 年了。但没错。Angular 会存在,与 VueJS 或 RxJS 以及其他很酷的 2016 年库一起。想了解这些吗?
还是继续用 React 吧,我现在已经学了太多东西了。所以,如果我需要使用 React,我会从这个 npm 中获取它,然后使用这个 Browserify 东西吗?
-是的。
仅仅抓住一堆依赖关系并将它们绑定在一起似乎过于复杂了。
-是的,这就是为什么你要使用 Grunt、Gulp 或 Broccoli 等任务管理器来自动运行 Browserify。你甚至可以使用 Mimosa。
咕噜声?咕噜声?西兰花?含羞草?我们现在到底在说什么?
-任务管理器。但它们不再那么酷了。我们在 2015 年左右使用过它们,然后我们使用 Makefile,但现在我们用 Webpack 包装一切。
Makefiles?我以为它主要用于 C 或 C++ 项目。
-是的,但显然在网络上我们喜欢把事情弄复杂,然后再回到基础。我们每年都会这样做,等着瞧吧,我们将在一两年内实现网络上的组装。
唉。你提到了 Webpack 之类的东西?
-它是浏览器的另一个模块管理器,同时也是一种任务运行器。它就像 Browserify 的升级版。
哦,好的。为什么这样更好呢?
-好吧,也许不是更好,它只是对如何绑定依赖项有更多意见。Webpack 允许您使用不同的模块管理器,而不仅仅是 CommonJS 模块管理器,例如原生 ES6 支持模块。
我对整个 CommonJS/ES6 事情感到非常困惑。
-每个人都是这样的,但是有了 SystemJS 你不必再关心了。
天啊,又一个名词 js。好吧,这个 SystemJS 是什么?
-嗯,与 Browserify 和 Webpack 1.x 不同,SystemJS 是一个动态模块加载器,它允许您将多个模块绑定在多个文件中,而不是将它们捆绑在一个大文件中。
等等,但是我以为我们想在一个大文件中构建我们的库并加载它!
是的,但是因为 HTTP/2 现在即将推出,所以多个 HTTP 请求实际上更好。
等等,那么我们不能只添加 React 的三个原始库吗?
-不是。我的意思是,你可以将它们作为外部脚本从 CDN 添加,但你仍然需要包含 Babel。
唉。这很糟糕,对吧?
-是的,您将包含整个 babel-core,这对于生产来说效率不高。在生产中,您需要执行一系列预任务来准备您的项目,这使得召唤撒旦的仪式看起来像煮鸡蛋的食谱。您需要最小化资产,丑化它们,在折叠上方内联 css,延迟脚本,以及-
我明白了,我明白了。那么,如果您不直接将库包含在 CDN 中,您会怎么做?
-我将使用 Webpack + SystemJS + Babel 组合将其从 Typescript 转译。
Typescript?我以为我们在用 JavaScript 编码!
-Typescript 就是 JavaScript,或者更确切地说,是 JavaScript 的超集,更具体地说是 ES6 版本的 JavaScript。你知道我们之前讨论过的第六个版本吗?
我以为 ES2016+ 已经是 ES6 的超集了!为什么我们现在需要这个叫 Typescript 的东西?
-哦,因为它允许我们使用 JavaScript 作为类型语言,并减少运行时错误。现在是 2016 年,您应该在 JavaScript 代码中添加一些类型。
而 Typescript 显然做到了这一点。
-Flow 也是如此,尽管它只检查类型,而 Typescript 是 JavaScript 的超集,需要进行编译。
唉…Flow 呢?
-这是 Facebook 的一些人制作的静态类型检查器。他们用 OCaml 编写了代码,因为函数式编程很棒。
OCaml?函数式编程?
-这就是现在的酷年轻人使用的东西,你知道吗,2016 年?函数式编程?高阶函数?柯里化?纯函数?
我不知道你刚才说了什么。
-一开始没人知道。你看,你只需要知道函数式编程比 OOP 更好,这就是我们在 2016 年应该使用的。
等一下,我在大学时学过 OOP,我认为那很好?
-Java 在被 Oracle 收购之前也是如此。我的意思是,OOP 在以前很好,现在仍然有用,但现在每个人都意识到修改状态相当于踢婴儿,所以现在每个人都在转向不可变对象和函数式编程。Haskell 的人已经调用它很多年了,-Elm 的人就更不用说了-但幸运的是,在网络上,现在我们有了像 Ramda 这样的库,允许我们在纯 JavaScript 中使用函数式编程。
你只是为了这个目的而说出名字吗?Ramnda 到底是什么?
-不。Ramda。就像 Lambda。你知道,那是 David Chambers 的图书馆吗?
大卫是谁?
-David Chambers。很酷的家伙。玩 Coup 游戏很厉害。Ramda 的贡献者之一。如果你认真学习函数式编程,你还应该看看 Erik Meijer。
那么 Erik Meijer 是......?
- 也是函数式编程的人。太棒了。他有很多演讲,他穿着这件颜色怪异的衬衫,抨击敏捷。你还应该看看 Tj、Jash Kenas、Sindre Sorhus、Paul Irish、Addy Osmani 的一些作品-
好的。我就到此为止。这些都很好,但我认为这些对于获取数据并显示数据来说太复杂和不必要了。我很确定我不需要认识这些人或学习所有这些东西来创建包含动态数据的表。让我们回到 React。如何使用 React 从服务器获取数据?
-嗯,实际上你并不是用 React 获取数据,你只是用 React 显示数据。
哦,该死。那么你用什么来获取数据呢?
-您使用 Fetch 从服务器获取数据。
抱歉,您使用 Fetch 来获取数据吗?给这些东西命名的人需要一本词典。
-我知道对吧?Fetch 是针对服务器执行 XMLHttpRequests 的本机实现的名称。
哦,所以是 AJAX。
-AJAX 只是 XMLHttpRequests 的使用。但可以肯定的是。Fetch 允许您基于承诺执行 AJAX,然后您可以解析它以避免回调地狱。
回调地狱?
-是的。每次你对服务器执行异步请求时,你都需要等待它的响应,这就迫使你在函数中添加一个函数,这就是所谓的地狱回调金字塔。
哦,好的。这个承诺能解决这个问题吗?
-确实如此。通过承诺来操纵回调,您可以编写更易于理解的代码,模拟和测试它们,以及一次执行并发请求并等到所有请求都加载完毕。
那么可以用 Fetch 来实现吗?
-是的,但前提是您的用户使用常用浏览器,否则您需要包含 Fetch polyfill 或使用 Request、Bluebird 或 Axios。
老天爷啊,我到底需要知道多少个图书馆?有多少个?
-这是 JavaScript。肯定有成千上万个库都做同样的事情。我们了解库,事实上,我们拥有最好的库。我们的库非常庞大,有时我们会在里面放上 Guy Fieri 的照片。
你刚才说的是 Guy Fieri 吗?让我们把这件事搞定。这些 Bluebird、Request、Axios 库是做什么的?
-它们是执行返回承诺的 XMLHttpRequests 的库。
jQuery 的 AJAX 方法不是也开始返回承诺了吗?
-2016 年我们不再使用“J”字。只需使用 Fetch,并在不在浏览器中时对其进行 polyfill,或者改用 Bluebird、Request 或 Axios。然后在异步函数中使用 await 管理承诺,然后你就有了正确的控制流。
这是您第三次提到 await 但我不知道它是什么。
-Await 允许您阻止异步调用,让您更好地控制何时获取数据并总体上提高代码的可读性。这很棒,您只需确保在 Babel 中添加 stage-3 预设,或使用 syntax-async-functions 和 transform-async-to-generator 插件。
这太疯狂了。
-不,疯狂的是,你需要预编译 Typescript 代码,然后使用 Babel 进行转译才能使用 await。
什么?它不包含在 Typescript 中吗?
- 它将会在下一个版本中实现,但是从 1.7 版开始它只针对 ES6,所以如果你想在浏览器中使用 await,首先你需要编译针对 ES6 的 Typescript 代码,然后使用 Babel 将其升级到针对 ES5。
此刻我不知道该说什么。
-看,这很简单。用 Typescript 编写所有内容。所有使用 Fetch 的模块都会将其编译为 ES6,使用 Babel 在 stage-3 预设上对其进行转译,然后使用 SystemJS 加载它们。如果您没有 Fetch,请对其进行 polyfill,或者使用 Bluebird、Request 或 Axios,并使用 await 处理所有承诺。
我们对“简单”的定义截然不同。那么,通过这个仪式,我终于获取了数据,现在我可以用 React 显示它了,对吗?
- 您的应用程序能处理任何状态变化吗?
呃,我不这么认为。我只需要显示数据。
-哦,谢天谢地。否则我就得给你解释 Flux 以及 Flummox、Alt、Fluxible 等实现。不过说实话你应该使用 Redux。
我将只是快速浏览一下这些名称。同样,我只需要显示数据。
-哦,如果你只是显示数据,你一开始就不需要 React。使用模板引擎就足够了。
你在跟我开玩笑吗?你觉得这好笑吗?这就是你对待亲人的方式吗?
-我只是在解释您可以使用什么。
停!停!就停!
-我的意思是,即使只是使用模板引擎,如果我是你,我仍然会使用 Typescript + SystemJS + Babel 组合。
我需要在页面上显示数据,而不是执行 Sub Zero 的原始 MK 致命操作。只需告诉我要使用什么模板引擎,我就可以开始操作了。
-有很多,你熟悉哪一个?
呃,记不起名字了。那是很久以前的事了。
-j模板?jQote?纯粹?
呃,没听懂。又一个?
-透明度?JSRender?MarkupJS?KnockoutJS?这个有双向绑定。
还有一个?
-PlatesJS?jQuery-tmpl?Handlebars?有些人仍在使用它。
也许吧。还有类似最后这个的吗?
-胡子,下划线?说实话我觉得现在 lodash 也有一个了,不过那些都是 2014 年的了。
呃。。也许它比较新。
-Jade?DustJS?
不。
-DotJS?EJS?
不。
-Nunjucks?ECT?
不。
-Mah,反正没人喜欢 Coffeescript 语法。Jade?
不,你已经说了 Jade。
-我指的是 Pug。我指的是 Jade。我是说,Jade 现在是 Pug。
唉。不,记不清了。你会用哪一个?
-可能只是 ES6 原生模板字符串。
让我猜一下。这需要 ES6。
-正确的。
这取决于我使用的浏览器是否需要 Babel。
-正确的。
如果我想包含它但不添加整个核心库,我需要从 npm 将其作为模块加载。
-正确的。
它需要 Browserify 或 Wepback,或者最有可能是其他称为 SystemJS 的东西。
-正确的。
除非是 Webpack,否则理想情况下应该由任务运行器来管理。
-正确的。
但是,因为我应该使用函数式编程和类型语言,所以我首先需要预编译 Typescript 或添加这个 Flow 东西。
-正确的。
如果我想使用 await,则将其发送给 Babel。
-正确的。
所以我可以使用 Fetch、承诺、控制流和所有这些魔法。
-如果不支持,不要忘记填充 Fetch,否则 Safari 仍然无法处理它。
你知道吗?我想我们到此为止了。实际上,我想我已经完成了。我完成了 Web 开发,完成了 JavaScript 开发。
-没关系,几年后我们都将使用 Elm 或 WebAssembly 编写代码。
我要回到后端。我无法处理这么多的变更、版本、编译器和转译器。如果 JavaScript 社区认为任何人都能跟上这些,那它就是疯了。
-我明白你的意思。那么你应该尝试一下 Python 社区。
为什么?
-听说过 Python 3 吗?
更新:感谢您指出错别字和错误,我将根据提示更新文章。讨论请见HackerNews和Reddit 。