自从 HTML5__ 变得流行以来,整个 Web__ 平台取得了长足的进步,人们也开始将 JavaScript__ 视为一门能够创建复杂应用的语言。许多新的 API__ 纷纷浮现,而关于浏览器如何应用这些技术的文章也大量涌现。
这一系列文章的视角更进一步,它们将关注于如何在实践中应用这些强大的技术,这并不是指创建多么酷炫的示例和原型,而是在第一线进行实际应用。在这个(后)HTML5__ 系列文章中,我们不需要响亮的口号,而是基于行业专家的实际经验,获得实践性的见解。我们也将讨论那些更进一步的技术(例如AngularJS _),并对 web__ 标准和 web__ 开发的未来进行定义。_
发布在 InfoQ__ 上的这篇文章是“下个时代的HTML5 和JavaScript __”系列文章其中的一篇。你可以订阅本系列文章,通过RSS__ 获取文章更新的通知。
作为一门脚本语言,JavaScript 最初创建的目的是用于增强web 页面的表现能力,而现如今JavaScript 几乎已经用在所有你能想到的地方了。随着整个业界的技术能力不断提高,JavaScript 如今已经可以在服务端运行,同时也能够被编译为原生手机应用的代码。当今的JavaScript 开发者都是整个丰富生态圈中的一份子,他们可以在几百种IDE、工具和框架中进行随意选择。由于各种选择和资源的数量实在太多,某些开发者也会感到不知从哪里开始学习。我很乐于讨论并概述一下现代JavaScript 开发者所面临的处境,首先我将简要的介绍一下JavaScript 的历史,随后会涵盖目前最流行的一些框架、工具和IDE。
快速回顾历史
让我们开始一次快速的旅行。时间回到1995 年,当时Netscape Navigator 和Internet Explorer 1.0 是浏览器方面仅有的选择。网站上充斥着各种烦人的闪烁文字以及太多的GIF 图片。要通过拨号网络加载一个包含了大量丰富内容的页面,最多需要等待整整两分钟时间。随后出现了一种web 语言,它允许这些古老的网站执行客户端的代码。这一年正是JavaScript 所诞生的年份。
创建于20 年之前的这些网站对于JavaScript 的使用并不多,当然也没有充分发掘这门语言的潜力。偶尔会通过弹出对话框告诉你某些信息,或是在某个方框中通过滚动文字的方式显示新闻,或是用cookie 保存你的用户名,以便当你经过几个月后再来访问这个网站时能够直接显示出你的名字。职场中当然也不存在任何以JavaScript 作为主要开发语言的工作职位,当时能够在工作中真正编写一些JavaScript 以及是非常幸运了。总之,当时的网站对于JavaScript 的应用就是在DOM 中玩一些小花招。
如今,你基本上已经可以在所有地方看到JavaScript 的身影了。从Bootstrap 到ReactJS、Angular、通用的jQuery,甚至是运行在服务端的Node.js,JavaScript 已经成为了最重要、最流行的web 语言之一。
框架
自从问世以来,JavaScript 的改动的最大方面之一就是对于它的应用方式。调用那些尴尬的document.GetElementById 方法和创建繁重的XmlHttpRequest 对象的日子已经一去不复返了。取而代之的方式,是通过各种帮助性的类库对这些基本功能进行抽象,让JavaScript 更易于为开发者使用。这也正是如今JavaScript 随处可见的主要原因之一。
jQuery
jQuery 是由 John Resig 在 2006 年推出的,它提供了一套丰富的工具集,对各种隐晦的、神秘的 JavaScript 命令与方法进行了抽象与简化。展示这一工具最简单的方式莫过于代码示例了。
使用纯粹的 JavaScript 创建一个 AJAX 请求:
function loadXMLDoc() { var xmlhttp; if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp = new XMLHttpRequest(); } else { // code for IE6, IE5 xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 ) { if(xmlhttp.status == 200){ alert("success"); } else if(xmlhttp.status == 400) { alert("error 400") } else { alert("something broke") } } } xmlhttp.open("GET", "test.html", true); xmlhttp.send(); }
来源: Stack Overflow
而使用 jQuery 创建 AJAX 请求:
$.ajax({ url: "test.html", statusCode: { 200: function() { alert("success"); }, 400: function() { alert("error 400"); } }, error: function() { alert("something broke"); } });
jQuery 使得复杂的 JavaScript 函数变得方便使用,DOM 操作更是小菜一碟。从结果上说,jQuery 成为了最早的一批被广泛使用的 JavaScript 框架,其中对 JavaScript 进行抽象的思想则成为了其它各种框架构建的基础。
AngularJS
AngularJS 通常也被称为“Augular”,于 2009 年登台亮相。它是由 Google 创建的一种框架,目标是为了简化单一页面应用(SPA)的创建。类似于 jQuery,它的目标同样是将复杂的操作抽象成为具有高度重用性的方法。它为 JavaScript 提供了一种模型 - 视图 - 控制器(MVC)的架构。
ReactJS
ReactJS 通常也被称为“React”,是一个刚刚在这场游戏中登场的新手。它由 Facebook 创建,并在 2013 年首次发布。Facebook 认为 React 在处理 SPA 问题上可以成为 Angular 的替代品,因此如果你认为 Angular 和 React 这两种框架是竞争对手,那你的理解就对了。不过,与 Angular 相比,React 最大的不同之处在于,它是一个更高效、具有更高性能、速度更快的类库。下图展示了使用 React、Angular、Knockout(另一种类库,在本文中不做讨论),以及纯粹的 JavaScript 在 DOM 中渲染包含 1000 个内容的列表,各自所需的时间:
如果你的应用非常看重性能,那么 React 就是正确的选择。
JavaScript 开发环境
对于高效的开发来说,IDE 的使用是非常重要的。IDE 的全名是集成开发环境,是一种为开发者提供了一系列工具的应用程序。这种工具中最重要的一部分通常来说是一个富文本编辑器,通常会为使用者提供语法高亮、自动完成和键盘快捷键,以加速各种烦人的手动操作。
Sublime Text
Sublime Text 实际上并不是一种 IDE,而是一个轻量级的、速度飞快的用于编程的文本编辑器,提供了语法高亮功能和直观的键盘快捷键。它本身是跨平台的,因此对于那些想在 PC 环境中使用 Mac(或者反之)的开发者来说是理想的选择。Sublime Text 的每个部分几乎都是可以进行自定义的,它还提供了多种插件,为它加入了类似于 IDE 的功能,例如和 Git 的集成,以及代码整理。对于 JavaScript 的爱好者和新手开发者来说,它是一个很好的选择。当本文发布时,每个 Sublime Text 授权的价格为 70 美金。
来源: Sublime Text
WebStorm
WebStorm 是由 JetBrains 团队开发的一种智能 IDE,主要专注于 HTML、CSS 和 JavaScript 的开发。它只收取象征性的授权费用(在本文发布时为 49 美金),在有经验的 JavaScript 专家之间,它得到了广泛的认可,并已经被视为事实上的标准,这一点不无道理,因为它内置的代码完成功能和审查工具可以说是独一无二的。WebStorm 中也提供了一个丰富的 JavaScript 调试器,并且与各种流行的单元测试框架进行了集成,例如 Karma 测试执行器和 JSDriver,甚至还包括支持 Node.js 的 Mocha。
WebStorm 最优秀的特性之一莫过于它的实时编辑(Live Edit)功能了。只要在 Chrome 和 WebStorm 中同时安装某个插件,开发者就可以在变更代码的同时,直接在浏览器中看到结果。开发者还可以对实时编辑进行配置,让浏览器窗口中的变更高亮显示,这极大地提升了调试与编码的生产力。
总的来说,如果 JavaScript 是你的全职工作,那么 WebStorm 这个 IDE 可以成为一个很好的选择。
来源: JetBrains
Brackets
Brackets 是一种开源的免费 IDE,专注于可视化工具。Brackets 提供了一种类似于 WebStorm 的实时编辑特性,让你可以在浏览器窗口中直接看到代码改变的结果。它还支持并行式的编辑,让你一边进行编码工作,同时直接看到代码的结果,而无需在不同的应用程序间进行切换,或是使用弹出窗口。Brackets 中最有趣的一个特性叫做抽取(Extract),它能够对 Photoshop 的 PSD 文件进行分析,以获取其中的字体、颜色和大小等信息。由于这一特性的存在,Brackets 非常适合于那些同时进行设计工作的 JavaScript 开发者。
(单击图片以放大)
来源: Brackets
Atom
Atom 是由 GitHub 推出的一款开源的免费富文本编辑器,非常易于上手使用,在安装后可以直接运行,而无需进行任何配置文件的改动,就能够“良好地运行了”。Atom 最有趣的一点是可以对它的每一方面都进行自定义(GitHub 将其称为“可以随便折腾”),它是在一个 web 核心的基础上所创建的,因此用户就可以通过编写标准的 HTML、CSS 和 JavaScript,对它的外观进行自定义。想要为 Atom 换个不同的背景和文本字体?改一下 CSS 就行。或者你也可以选择下载并应用各种为 Atom 所创建的主题。这种灵活性让 Atom 能够按照你所希望的方式进行展现。对于 JavaScript 新手开发者和热衷于自定义的用户来说,Atom 是一个优秀的工具。
(单击图片以放大)
来源: Atom
构建与自动化工具
现代的 JavaScript 项目正倾向于变得越来越复杂,变化的部分也在不断增多。这并不是说这门语言或是对应的工具不够高效,而是由于当前所创建的 web 应用程序的丰富性、酷炫的体验和复杂性所导致的直接后果。在大型的项目中工作时,你必须经常做许多重复性的工作,无论是在你打算签入代码、或是将代码构建到生产环境中。这些工作可能会包括合并、压缩、对 LESS 或 SASS CSS 文件的编译,甚至是运行测试。手动完成这些工作不仅令人沮丧,效率也很低下。更好的办法是通过某种支持这些任务的构建工具,对这些工作进行自动化。
合并(Bundling)与压缩(Minification)
你所编写的大多数 JavaScript 和 CSS 都会在多个 web 页面中共享。因此,你很可能会将这些内容放到单独的.js 和.css 文件中,然后在 web 页面中引用这些文件。这种方式的结果是,用户的浏览器为了完全显示你的 web 引用,需要分别发送一个 HTTP 请求,以获取这些文件(或者至少需要验证一下这些文件是否已经改变了)。
HTTP 请求的代价是很高的。除了请求本身的大小之外,你还将因为网络延迟、HTTP 头和 Cookie 等内容买单。合并与压缩工具的设计目的就是减少、乃至完全消除这些请求所带来的影响。
合并
要改善 web 代码的性能,开发者所能做的最简单的一件事就是将代码进行合并。在合并流程中,多个 JavaScript 或 CSS 文件将被并入一个单一的 JavaScript 或 CSS 文件中。感觉上就像是将多张个别的全景图像的照片连接在一起,以完成一张继续的单一照片。通过将 JavaScript 文件与 CSS 文件进行合并,我们就能够消除很大一部分 HTTP 请求的开销。
压缩
JavaScript 开发者还有一种可以改善性能的方式,就是将刚刚合并的代码进行压缩。压缩过程能够将 JavaScript 和 CSS 代码以尽可能最小的形式进行压缩,同时保证功能不变。对于 JavaScript 来说,这就意味着将变量重命名为无意义的单字符形式,并且去除所有空白和格式符。而对于 CSS 来说,由于页面风格依赖于变量的名称,因此通常来说只会去除格式符与空白。压缩能够极大的改进网络性能,因为它减少了每个 HTTP 响应的字节数。
未经压缩的 AJAX JavaScript 代码,与上面所展示的代码相同:
$.ajax({ url: "test.html", statusCode: { 200: function() { alert("success"); }, 400: function() { alert("error 400"); } }, error: function() { alert("something broke"); } });
同样的代码经过压缩之后的形式:
$.ajax({url:"test.html",statusCode:{200:function() {alert("success");}, 400:function(){alert("error 400");}},error:function(){alert("something broke");}});
请注意,我将压缩后的输出结果分为两行的目的,只是为了在文章中阅读起来更方便,而实际上经过压缩后的输出通常来说只有一行。
合并与压缩的时机
通常来说,合并与压缩步骤只会在生产环境上执行,这样做的原因是为了让你在本地或是开发环境中可以对包含了格式符和行号的原始代码进行调试。而调试上面所显示的那种压缩代码会非常困难,因为所有的代码都挤在一行中。而且压缩后的代码会变得完全不可读,在你尝试调试时会发现这种代码完全无用,并让你感到非常受挫。
源代码映射文件
有些时候,代码中的某些 bug 只有在生产环境才能重现。这样一来,当你要调试某些问题时,经过压缩的代码就成为了一个问题。幸运的是,JavaScript 支持源代码映射文件,它能够在压缩后的代码和原始代码之间进行“映射”。这些代码映射文件是在压缩阶段由下文所说的某些构造工具所生成的。随后你的 JavaScript 调试器就能够使用这些映射文件,为你提供清晰可读的代码进行调试了。你应当尽可能将映射文件与实际代码一起发布,这样就能够在某些功能出错时进行代码的调试了。
代码整理
代码整理工具会根据预定义的格式化规则检查你代码中的常见错误和问题,这些工具所报告的错误通常都类似于以下这些:使用了 tab 缩进而不是空格、在行末遗漏了分号、或是在没有使用 if、for 或 while 语句的情况下使用了大括号。大多数 IDE 中都提供了代码整理工具,而其它一些 IDE 也允许用户自行安装代码整理插件。
最流行的两种 JavaScript 整理工具是 JSHint 和 JSLint,JSLint 是由 Doug Crockford 开发的整理框架,而 JSHint 则是由社区人员从 JSLint 中分支出来的。他们仅在各自的代码格式化标准上有着一些区别。我的建议是两者都尝试一下,然后选择一个最适合你的代码风格的工具。
自动化任务:Grunt
与它的名称不同,Grunt(本意为打呼噜)绝不是一个粗糙的工具,而是一个健壮的命令行构造工具,能够运行用户所定义的各种任务。通过设置一个简单的配置文件,你就可以让 Grunt 进行各种工作,例如编译 LESS 或 SASS 文件、构建并压缩某个特定文件夹中的所有 JavaScript 和 CSS 文件、甚至是运行某种代码整理工具或是测试框架。你也可以通过配置,将 Grunt 作为一种 Git 钩子运行,当你往源代码控制库里进行签入时,自动地压缩与合并你的代码。
Grunt 支持各种命名的目标,因为你可以在不同的环境中指定不同的命令,比方说你可以将“dev”和“prod”指定为目标。这一点对于某些场景来说非常有用,例如在生产环境中将代码进行合并与压缩,而在开发环境中忽略这一步骤,以便于调试的需要。
Grunt 中一个很有用的特性叫做“grunt watch”,它能够对一个目录中的文件,或一个文件集合中的变更进行监控。这一特性可以整合入 WebStorm 和 Sublime Text 这样的 IDE 中使用。通过使用监控特性,你可以根据文件变更的情况触发事件。对于 LESS 或 SASS 的编译就是这一特性的实用作法,你可以设置 grunt 以监控你的 LESS 或 SASS 文件,当文件产生变更时立即进行编译,编译后生成的文件就可以直接在开发环境中进行使用了。你也可以让 grunt 监控在你修改了每个文件之后都自动地运行某种代码整理工具。通过 grunt 监控进行实时任务执行,是一种加速你的生产力的极好的方式。
自动化任务:Gulp
Grunt 和 Gulp 都是用于解决构建自动化问题的工具,可以说两者是直接的竞争者。他们之间主要的差别在于,Grunt 更专注于配置,而 Gulp 更专注于代码。你在 Grunt 文件中通过声明式的 JSON 对构建任务进行配置,而在 Gulp 文件中通过编写 JavaScript 函数以实现相同的功能。
下面的这个 Grunt 配置文件会在 SASS 文件产生变更时,编译生成 CSS 文件:
grunt.initConfig({ sass: { dist: { files: [{ cwd: "app/styles", src: "**/*.scss", dest: "../.tmp/styles", expand: true, ext: ".css" }] } }, autoprefixer: { options: ["last 1 version"], dist: { files: [{ expand: true, cwd: ".tmp/styles", src: "{,*/}*.css", dest: "dist/styles" }] } }, watch: { styles: { files: ["app/styles/{,*/}*.scss"], tasks: ["sass:dist", "autoprefixer:dist"] } } }); grunt.registerTask("default", ["styles", "watch"]);
来源: Grunt vs Gulp - Beyond the Numbers
下面的这个 Gulp 配置文件同样会在 SASS 文件产生变更时,编译生成 CSS 文件:
gulp.task("sass", function () { gulp.src("app/styles/**/*.scss") .pipe(sass()) .pipe(autoprefixer("last 1 version")) .pipe(gulp.dest("dist/styles")); }); gulp.task("default", function() { gulp.run("sass"); gulp.watch("app/styles/**/*.scss", function() { gulp.run("sass"); }); });
来源: Grunt vs Gulp - Beyond the Numbers
我建议你可以随意选择自己所喜欢的那一种。这两种工具一般来说都是通过 Node.js 的包管理器 npm 下载的。
总结
JavaScript 自从互联网的早期诞生以来,已经经历了巨大的改进。如今,它已成为了交互式 web 应用程序中一个突出的重要组成部分。
开发者们从 1995 年起到如今也经历了巨大的变化,如今的开发者们更乐于使用丰富而健壮的框架、工具和 IDE,以提高工作的效率和生产力。
创建你的第一个现代 JavaScript 应用程序或者比你自己想象中还要简单!只要选择好一个 IDE(我向初学者推荐 Atom ),然后安装 npm 和 grunt 。如果你之后在哪里卡住了, Stack Overflow 是非常好的资源。只要稍稍花一点时间学习基础知识,你就很快能够上手开发并最终发布你的第一个现代 JavaScript 应用了。
资源
框架:
IDE:
代码整理工具:
构建与自动化工具
实用资源
关于作者
David Haney是 Stack Exchange 核心团队的工程师经理, StackOverflow 和 ServerFault 这些问答网站都是基于 Stack Exchange 创建的。他的日常工作包括帮助开发者解决问题,以及改善流程。他之前曾是 Fanatics 的电子商务平台的首席开发者,基于这个平台搭建的网站数量超过 1 万,其中包括 NFL 的官方在线商店 NFLShop,以及 NBA 的官方商店 NBAStore.com 。
David 也是 Dache 的作者,这是一个开源的分布式缓存框架。他在业务时间主要用于喝啤酒,以及参与社区用户小组和各种编程活动,而且经常是边说边喝。
自从 HTML5__ 变得流行以来,整个 Web__ 平台取得了长足的进步,人们也开始将 JavaScript__ 视为一门能够创建复杂应用的语言。许多新的 API__ 纷纷浮现,而关于浏览器如何应用这些技术的文章也大量涌现。
这一系列文章的视角更进一步,它们将关注于如何在实践中应用这些强大的技术,这并不是指创建多么酷炫的示例和原型,而是在第一线进行实际应用。在这个(后)HTML5__ 系列文章中,我们不需要响亮的口号,而是基于行业专家的实际经验,获得实践性的见解。我们也将讨论那些更进一步的技术(例如AngularJS _),并对 web__ 标准和 web__ 开发的未来进行定义。_
发布在 InfoQ__ 上的这篇文章是“下个时代的HTML5__ 和JavaScript”系列文章其中的一篇。你可以订阅本系列文章,通过RSS__ 获取文章更新的通知。
活动推荐:
2023年9月3-5日,「QCon全球软件开发大会·北京站」 将在北京•富力万丽酒店举办。此次大会以「启航·AIGC软件工程变革」为主题,策划了大前端融合提效、大模型应用落地、面向 AI 的存储、AIGC 浪潮下的研发效能提升、LLMOps、异构算力、微服务架构治理、业务安全技术、构建未来软件的编程语言、FinOps 等近30个精彩专题。咨询购票可联系票务经理 18514549229(微信同手机号)。
评论