部署
大约 7 分钟
构建流程
代码不应该不做任何处理就直接交给浏览器,原因:
- 知识产权问题:如果把满是注释的代码放到网上,其他人就很容易了解你在做什么,重用它,并可能发现安全漏洞。
- 文件大小:你写的代码可读性很好,容易维护,但性能不好。浏览器不会因为代码中多余的空格、缩进、冗余的函数和变量名而受益。
- 代码组织:位保证可维护性而组织的代码不一定适合直接交付给浏览器。为此,需要为js文件建立构建流程。
- 文件结构
构建流程首先定义在源代码控制中存储文件的逻辑结构。最好不要在一个文件中包含所有js代码。相反,要遵循面向对象编程语言的典型模式,把对象和自定义类型保存到自己独立的文件中。这样可以让每个文件只包含最小量的代码,让后期修改更方便,也不易引入错误。注意
把代码分散到多个文件是从可维护性而不是部署角度出发的,对于部署,应该把所有源文件合并为一个或多个汇总文件。Web应用程序使用的js文件越少越好,因为HTTP请求对某些Web应用程序而言是主要的性能瓶颈。而且,使用
<script>
标签包含js是阻塞性操作,这导致代码下载和执行期间停止所有其它下载任务。因此。要尽量以符合逻辑的方式把js代码组织到部署文件中。 - 任务管理器
如果要把大量文件组合成一个应用程序,很可能需要任务运行器自动完成一些任务。任务运行器可以完成代码检查、打包、转译、启动本地服务器、部署,以及其它可以脚本化的任务。很多时候,任务运行器要通过命令行界面来执行操作。Grunt和Gulp是两个主流的任务运行器。它们非常稳健。其任务和指令都是通过配置文件,以纯js形式指定的。使用Grunt和Gulp的好处是它们分别有各自的插件生态,因此可以直接使用npm包。 - Tree Shaking
Tree shaking是非常常见且极为有效的减少冗余代码的策略。使用静态模块声明风格,有利于构建工具可以确定代码各部分之间的依赖关系。更重要的是,Tree Shaking还能确定代码中的哪些内容是完全不需要的。实现了摇树优化策略的构建工具能够分析出选择性导入的代码,其余模块文件中的代码可以在最终打包得到的文件中完全省略。 - 模块打包器 以模块形式编写代码,并不意味着必须以模块形式交付代码。通常,由大量模块组成的js代码在构建时需要打包到一起,然后只交付一个或少数几个js文件。
模块打包器的工作是识别应用程序中涉及的js依赖关系,将它们组合成一个大文件,完成对模块的串行组织和拼接,然后生成最终提供给浏览器的输出文件。
能够实现模块打包的工具有:webpack、rollup、browserify只是其中几个,可以将基于模块的代码转换为普遍兼容的网页脚本。
验证
有一些工具可以帮我们发现js代码中潜在的问题,最流行的是 Douglas Crockford 的 JSLint 和 ESLint。
这些代码检查工具可以发现js代码中的语法错误和常见的编码错误,下面是它们会报告的一些问题:
- 使用eval();
- 使用未声明的变量;
- 遗漏了分号;
- 不适当地换行;
- 不正确地使用逗号;
- 遗漏了包含语句的括号;
- 遗漏了 switch 分支中的 break;
- 重复声明变量
- 使用了 with;
- 错误地使用等号(应该是两个或三个等号);
- 执行不到的代码 在开发过程中添加代码检查工具有助于避免出错。推荐开发者在构建流程中也加入代码检查环节,以便在潜在问题成为错误之间识别它们。
压缩
谈到js文件压缩,实际上主要是两件事:代码大小和传输负载。代码大小指的是浏览器需要解析的字节数,而传输负载是服务器实际发送给浏览器的字节数。在web开发的早期阶段,这两个数值几乎相等,服务器发送给浏览器的是未经修改的源文件。而今天,这两个数值不可能相等,实际上也不应该相等。
- 代码压缩
注释、额外的空格、长变量或函数名都能提升开发者的可读性,但对浏览器而言这些都是多余的字节。压缩工具可以通过如下操作减少代码大小:- 删除空格(包括换行)
- 删除注释
- 缩短变量名、函数名和其它标识符。 所有js文件都应该在部署到线上环境前进行压缩。在构建流程中加入这个环节压缩js很容易的。 :::wanrning 注意 在 Web 开发的上下文中,“压缩”(compression)经常意味着“最小化”(minification)。虽然这两个术语可以互换使用,但实际上它们的含义并不相同。最小化是指把文件大小减少到比原始大小还要小,但结果文件包含的仍是语法正确的代码。通常,最小化只适合 JavaScript 等解释型语言,编译为二进制的语言自然会被编译器最小化。压缩与最小化的区别在于前者得到的文件不再包含语法正确的代码。压缩后的文件必须通过解压缩才能恢复为代码可读的格式。压缩通常能得到比最小化更小的文件,压缩算法不用考虑保留语法结构,因此自由度更高。 :::
- js编译
类似最小化,js代码编译通常指的是把源代码转换为一种逻辑相同但字节更少的形式。与最小化的不同之处在于,编译后代码的结构可能不同,但仍然具备与原始代码相同的行为。编译器通过输入全部 JavaScript 代码可以对程序流执行稳健的分析。 编译可能会执行如下操作:- 删除未使用的代码
- 将某些代码转换为更简洁的语法
- 全局函数调用、常量和变量行内化。
- js转译
通过js转译,可以在开发时使用最新的语法特性而不用担心浏览器的兼容性问题。转译可以将现代的代码转换成更早的ECMAScript版本,通常是ES3或ES5,具体取决于你的需求。这样可以确保代码能够跨浏览器兼容 - HTTP压缩 传输负载是从服务器发送给浏览器的实际字节数。这个字节数不一定与代码大小相同,因为服务器和浏览器都具有压缩能力。所有当前主流的浏览器(IE/Edge、Firefox、Safari、Chrome和Opera)都支持客户端解压缩收到的资源。服务器则可以根据浏览器通过请求头部标明自己支持的格式,选择一种用来压缩js文件。在传输压缩后的文件时,服务器响应的头部会有字段标明使用了哪种压缩格式。浏览器看到则会个头部字段后,就会根据这个压缩格式进行解压缩。结果是通过网络传输的字节数明显小于原始代码大小。