如果你以前有编程经验,但是一名前端 JavaScript 开发的初学者,那么一系列的术语和工具容易引起混淆。我们不会纠缠于细节的讨论,而是会纵览当前的“JavaScript 生态圈”。这应该足够你找准方向,开启前端开发之旅。
关键术语显示为粗体。如果你想跳到可以工作的样板代码库,那么我已经将我的一些建议整理成了一个GitHub 库。
客户端JavaScript 是如何工作的,为什么要使用它?
关键术语:DOM(文档对象模型)、JavaScript、async、AJAX
为了编写高效的前端代码,你需要对如何综合运用HTML、CSS 和JavaScript 创建Web 页面有一个基本的了解。
当客户端(通常是浏览器)访问HTML 页面时,它会下载它,解析它,然后使用它构造 DOM(文档对象模型)。JavaScript 可以同 DOM 交互及修改 DOM,交互式站点就是这样创建的。这里有一个DOM 的基本介绍。
JavaScript 是如何包含到页面中的?那是另一个复杂的问题,但它是以script 标签开始的。
JavaScript 的执行会阻塞 DOM 构造。这就是说,执行 JavaScript 的时间过长会让人觉得页面没响应。为了避免这种情况,客户端 JavaScript 经常都是大量使用异步。(你可能听说过AJAX,它就代表asynchronous JavaScript and XML。)
如果你正在构建一个交互式站点,那么你会需要使用 JavaScript,你可能会使用这种或另一种方式处理异步。
框架是什么?我需要使用 trendy.js 吗?
关键术语:React、Angular、Ember、Backbone、jQuery、Underscore、Lodash
“框架”这个词有许多意思。JavaScript 框架的目标通常是减少构建交互式 Web 页面过程中无谓的工作。从根本上说,框架就是脚手架,设计用来解决一个特定种类的问题。
许多当前流行的框架都是设计用来解决这样的问题的,“如何创建一个支持复杂用户交互的单页 Web 应用,并在前端管理所有的业务逻辑?”单页应用或者SPA是不需要刷新页面的 Web 应用,产品的大部分都是作为一个单独的“页面”而存在——回想下 Facebook 首页或者 Gmail 收件箱。
那么该用哪个框架呢?React? Angular? 还是 Ember? 甚至说你需要框架吗?选择麻痹症的信号!
所有这些项目都试图帮你编写更好的 Web 应用程序。对于选择哪个框架,没有正确的答案,如果有,你就应该使用。
如果你是刚刚开始使用 JavaScript,那么不使用框架可能会更好一些,尝试使用 jQuery 构建一个站点,其他的少用或不用。那很快就会变得让人厌烦,但你能做到,这会让你了解到一些重要的、有关 JavaScript 工作原理的东西。你还可以使用jQuery 践行好的软件工程准则。
如果你正在开发一个相当复杂的站点,那么你会发现框架很有用。当前, Angular 、 React 和 Ember 都是流行且明智的选择。 Backbone 是一个相对较小的老式框架;它也适合于许多项目。我为本文整理的初学者工具包使用了React,但实际上,没有错误的选择。 TodoMVC 使用不同的框架实现了同一个清单应用程序,检出它,自己比较一下各种框架。
JavaScript 还缺少许多其他语言内置的标准库函数,像字符串填充或数组重排。为此,我们通常会使用像 jQuery 、 Underscore 和 Lodash 这样的库来弥补这种不足。按照惯例,这些库在导入后要分别使用 $、_ 和 _ 引用,因此,如果你看到一个 JavaScript 文件中有许多美元符号,几乎可以肯定这是调用了 jQuery。
如果你要开始一个新项目,我建议使用 React 或者 Angular 以及 Lodash。
我应该编写 JavaScript,还是其他的什么?JavaScript 的种类有哪些?
关键术语:ES5、ES6、ES2015、CoffeeScript、TypeScript、ClojureScript、Babel、“转译(transpiling)”、“编译(compiling)”、MDN 参考
“JavaScript”实际上并不是一门单独的语言。每个浏览器供应商都实现了自己的 JavaScript 引擎,由于浏览器和版本之间的差别,JavaScript 饱受碎片化之苦。 CanIUse.com 记录了部分不一致的情况;你也可以查看 Mozilla 开发者社群里的文档。
ES6又称 ES2015/Harmony/ECMAScript6/ECMAScript 2015,是 JavaScript 规范的最新版本。它引入了新的语法和功能。胖箭头、ES6 类、本地模块和模板字符串都是这个 JavaScript 版本的一部分。 Treehouse 提供了一份不错的 ES6 入门教程。
虽然 JavaScript 处于一个碎片化的环境,但能够使用新的语言特性也不错。因此,像Babel这样的工具会把你闪亮的标准 JavaScript 代码转换成一个同旧平台兼容的版本。这个过程称为转译。这同编译没有太大的区别。使用像 Babel 这样的工具,你不必太过担心特定的浏览器是否支持你使用的 JavaScript 特性。
转译工具不只是将 ES6 JavaScript 转换成 ES5。还有一些工具可以对 JavaScript 的变体,如ClojureScript、TypeScript和CoffeeScript,做同样的事情。 ClojureScript 是 Clojure 的一个版本,可以编译成 JavaScript。 TypeScript 本质上是 JavaScript,但有一个类型系统。 CoffeeScript 同 JavaScript 非常像,但有更闪亮的语法;由 CoffeeScript 创建的许多语法糖都已经被 ES6 采用,这在很大程度上显得 CoffeeScript 不那么有用了。所有这些都会编译成普通的 JavaScript。
那么你应该使用什么呢?如果你是前端开发的初学者,那么你也许应该编写 ES6 风格的 JavaScript。大部分 ES6 特性都得到了各浏览器供应商的广泛支持。如果你需要支持相对较老的平台,那么像 Babel 这样的工具可以替你将 ES6 编译成兼容 ES5 的 JavaScript。现在先不要考虑闪亮的 compile-to-JavaScript 选项,如 ClojureScript,不过,一旦你有了更多的前端开发经验,那么它们当然值得研究。
如何使用其他人的代码?
关键术语:AMD、commonJS 模块、ES6 模块、npm、Github
在 JavaScript 中,代码共享和模块的历史有一点复杂。我强烈建议你阅读 Preethi Kasireddy 的文章“ JavaScript 模块入门指南”来了解更多信息。
对于我们而言,术语模块和库基本上是等价的:它们代表大量的自包含代码,我们可以在自己的项目中使用及重用。JavaScript 模块一般通过 node 包管理器 npm 发布。你可以在 npm 或 GitHub 上搜索 JavaScript 模块。
模块定义(有时称为模块语法)有几种存在竞争关系的方式,主要包括CommonJS、AMD和ES6 原生模块。CommonJS 采用一种同步的、面向服务器的方法。相反,AMD(异步模块定义)允许你使用异步、非阻塞的方式定义和加载模块。CommonJS 和 AMD 都是在 JavaScript 没有原生支持任何模块或依赖概念的情况下创建的。
ES6 增加了原生 JavaScript 模块支持,它既支持 CommonJS 的声明式语法,又支持 AMD 的异步加载,还有其他一些特性。终于,模块成为现行语言的一部分。
在工作中,你很可能会遇到所有这三种类型的模块。对于新项目,你该应该使用 ES6 原生模块。构建工具,如 webpack(下面会介绍),会帮助你在现有项目中使用各种类型的模块。
我需要 Node.js 吗?
关键术语:Node.js、npm、nvm
Node.js是一款编写服务器端 JavaScript 的工具。等一下,难道我们谈论的不只是前端 JavaScript 吗?
由于 JavaScript 模块通常在打包后通过 node 包管理器 npm 分享,所以你需要安装 Node.js,即使你不会把它用于服务器端开发。在 OS X 或基于 Linux 的系统上,最好的方式是通过 Node 版本管理器nvm,这简化了不同 Node.js 版本的管理。Windows 用户应该看下 nvm-windows 。
我该用什么构建工具?
关键术语:grunt、gulp、bower、browserify、webpack、“热重载(hot reloading)”、sourcemap
一个 script 标签接一个 script 标签地请求将每个 JavaScript 依赖作为页面的一部分会很慢。因此,大多数站点都使用所谓的 JavaScript bundles。捆绑过程会获取所有依赖,并把它们“捆绑”在一起,生成一个单独的文件,包含到页面中。根据需要,有些开发人员还会使用一个“最小化(minifying)”步骤,将所有不必要的字符从 JavaScript 代码中去除,而又不改变代码的功能。这可以减少客户端需要下载的数据量。
有些工具还支持诸如热重载及sourcemaps这样的特性,前者会在你保存一个文件时自动在浏览器中更新你的项目,后者提供了一个从捆绑好的 JavaScript 到其原始形式的映射,简化了调试工作。
本质上讲,我刚刚描述的是一个构建过程。不管是否大多数 JavaScript 开发人员都这样描述,你都是将代码编译成一个生产就绪的格式。“前端 devops”或者管理构建、部署工具及依赖项的过程成为一项日益复杂的工作。
Grunt、gulp、broccoli、brunch、browserify和webpack都是 JavaScript 构建工具。比较它们非常困难,因为它们每一个都致力于解决不同的问题。它们中有许多使用了不同的抽象概念来讨论相同的问题,我们实在是还没有一个共用的术语库。
根据我的经验,开发人员往往对这些工具的配置文件不甚了解,因此就在项目之间粘来粘去。下面是我为初学者库整理的 webpack 配置文件,供参考:
var webpack = require('webpack'); module.exports = { entry: [ "./app.js" ], output: { path: __dirname + '/static', filename: "bundle.js" }, module: { loaders: [ { test: /\.js?$/, loader: 'babel-loader', query: { presets: ['es2015', 'react'] }, exclude: /node_modules/ } ] }, plugins: [ ] };
如上,该 webpack 配置文件指示 webpack 完成以下工作:
- 启动 app.js 作为入口点;
- 处理以.js 结尾的所有文件;
- 使用 babel-loader 对它们进行转换,尤其是处理 ES6 转译(所以 es2015 query)和 JSX(所以 react query);
- 将所有 JavaScript 文件捆绑成一个文件 static/bundle.js。
对于新项目,我推荐webpack。它有很强的适应性,而且能够很好地处理具有复杂依赖图的大型项目。
我如何测试代码?
关键术语:Mocha、Jasmine、Chai、Tape、Karma、Selenium、phantomjs
同许多其他类型的编程一样,前端 JavaScript 可以从测试中获益。大多数 JavaScript 开发人员都表示,他们至少会编写部分测试。
JavaScript 缺少一种内置的框架用于运行测试,因此,开发人员需要依赖外部库。不同的测试工具致力于问题的不同方面,这点同 JavaScript 构建系统非常像。
Mocha和Jasmine是两个流行的库,有时候称为测试框架,可以帮助你编写测试。他们的 API 十分类似;你描述应该出现的行为,然后使用断言测试它。
describe('helloWorld()', function() { it('should greet me by name', function() { // 在这里添加断言 }); });
Mocha 实际上没有内置断言库,因此,大多数开发人员都会将它同Chai结合使用。它们的断言语法类似:
// Jasmine expect(helloWorld("Bonnie")).toEqual("Hello, Bonnie"); // Chai expect(helloWorld("Bonnie")).to.equal("Hello, Bonnie");
为了运行测试,Mocha 提供了一个命令行工具,而 Jasmine 没有。许多开发人员使用Karma,这是一个测试执行器,既可以运行 Jasmine 风格的测试,也可以运行 Mocha 风格的测试。
那很适合单元测试;对于基于 JavaScript 的集成测试,我们需要更多工具。在前端领域,集成测试通常涉及使用一个浏览器实际地渲染和加载页面,模拟用户交互,并检查结果。
Selenium是一个 Web 驱动程序,通常可以用于这些测试。你需要为 Selenium 配备一个浏览器驱动程序,以便它能够启动浏览器。PhantomJS是一个所谓的无头浏览器——它运行时没有图形用户界面——通常用于测试中。由于它们不需要 GUI,所以无头浏览器对自动化测试而言非常有用。你可能会发现Sinon有用;它提供了一个模拟服务器,可以用于模拟 AJAX 请求的响应。
你还可以设置 JavaScript 测试同持续集成(CI)系统一起运行,如Jenkins或Travis。
JavaScript 测试工具有大量堪称完美的选择。对于新项目,我常常选择 Karma 和 Jasmine,并使用 PhantomJS 作为测试浏览器,但 Mocha + Chai 也是一个不错的选择。
那么我如何入手呢?
我整理了一个 GitHub 库,里面包含一个基本的前端开发配置: https://github.com/bonniee/react-starter 。
它使用:
- React;
- Babel 转译;
- Webpack 构建;
- ES6 语法(针对 React 类和模块导出);
- Karma + Jasmine + PhantomJS 测试;
让我们稍微详细地讨论下。React 是我们使用的框架,它让我们可以更轻松地创建交互式站点。(你描述 UI,React 会为你渲染并处理 DOM 操作。)我们将编写符合 ES6 规范的 JavaScript 代码。Webpack 会使用 Babel 将 ES6 JavaScript 代码转译成兼容 ES5 的 JavaScript 代码。Webpack 还会管理依赖和模块导入。最后,我们使用 Karma 和 PhantomJS 运行测试,并使用 Jasmine 库编写这些测试。
首先,确保你有一个可用的 npm 版本。然后,安装这个 GitHub 库的依赖,并开始使用:
npm install webpack
然后,使用它进行开发,运行:
webpack --watch
这会指示 webpack 监视项目,并在 JavaScript 文件变化时重新编译它。想要查看应用程序,就需要启动一个本地服务器。在 OS X 或 Linux 上,使用 Python 很容易做到:
python -m SimpleHTTPServer
……你已经准备好开始了! 编辑 app.js 或 Hello.js 增加更多的 React 组件,并使用 npm test 来运行测试。
当然,有一个可以工作的初始代码库只是成功的一半。前端 JavaScript 开发领域很复杂,有大量的工具、术语以及新概念需要学习,同时也有大量的问题需要解决。上述任意一个主题都很容易写满一个博客。希望这篇文章能让你对 JavaScript 生态圈有一些了解,能在你学习更多有关前端开发的知识时提供一些指导。
欢迎加入社区!
注意:徽标许可
- React : React-docs 许可协议及知识共享归属许可协议
- Babel: MIT 许可协议
- Webpack: MIT 许可协议
- Karma: MIT 许可协议
- Jasmine: MIT 许可协议
- PhantomJS: BSD 许可协议
关于作者
Bonnie Eisenman是 Twitter 的一名软件工程师,同时也是骇客空间 NYC Resistor 的成员之一,之前曾在 Codecademy、Fog Creek Software 和 Google 工作过。她是 *Learning React Native* 一书的作者,那是一本关于使用 JavaScript 构建原生 iOS 和 Android 应用程序的书,由 O’Reilly Media 出版。她曾在若干会议上做过演讲,主题涵盖从 ReactJS 到音乐编程和 Arduinos 的内容。在业余时间,她喜欢学习语言,摆弄硬件项目以及激光切割巧克力。她的 Twitter 账号为 @brindelle。
查看英文原文: State of the JavaScript Landscape: A Map for Newcomers
评论