前端工具演变

21次阅读

共计 3802 个字符,预计需要花费 10 分钟才能阅读完成。

假如你烘焙过蛋糕(哪怕没有亲自做过,但是也应该听说过),除了基本的面粉,鸡蛋等原材料外,或许你还需要一个电动蛋白打发器,一个烤箱。这是现代的做法,那么在打发器和烤箱发明之前,人们怎么烤蛋糕呢?没有打发器,只能手动打发,这样的弊端是不仅花费时间长,而且你的手可能也要废掉。没有烤箱,用炭烤,这样就会出现温度不好掌握,或许还得有人一直盯着的问题。
我一直爱把软件开发想成做菜,原材料就是编程语言,菜单是算法逻辑,而做菜的这些工具也是我们在软件开发中使用的各种工具。做菜的工具有历史演变的过程,我们软件开发的工具也是如此。
只是有些工具,现在被大家广泛使用,而有些却只能在一些老文章里面见证他们曾经的辉煌。今天就从前端工具演变来聊聊前端的历史发展。
摸鱼警告:本篇没有干货,纯粹闲聊。
1:没有任何工具的纯手工时代最开始的前端开发,只需要掌握 HTML + CSS + JavaScript 就好,我们要在一个页面上使用 js,除了通过 <script>…</script> 标签外,还可以把 js 代码放到一个 js 文件,通过在 HTML 文件引用这个 js 文件的方式:
<!– index.html –>
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title></title>
<script src=”index.js”></script>
</head>
<body>
</body>
</html>
但是,当我们的业务需求变复杂,项目变大,我们通常会把逻辑相关的代码都放同一个 js 文件里面,这样慢慢就形成了模块的概念,例如你在做一个超市收银系统,项目里有一个(或者几个)js 文件是跟价格计算相关,有些 js 文件是跟时间格式化相关。现在你正在开发收银小票功能模块,毋庸置疑,这个模块肯定需要用到前面的价格计算和时间格式化模块。这里,就产生了模块访问模块的需求。
很多语言都天然地支持在 A 文件里面引用 B 文件的功能,但是 javaScript 一开始却不是这样。因为 javaScript 一开始是被设计来只在浏览器(准确地说是用户的浏览器)上运行的语言。处于安全性的考虑,它不被赋予访问文件的权利和功能。
在这个阶段我们要做到在 A 文件使用 B 文件提供的功能,只能在 HTML 文件里面引用相关的 js 文件,通过在全局暴露相关变量,然后这样就能使用到了。
2:包管理(package management)工具在上面第一点我们提到了模块。在一个稍大的项目中,一般会用到很多前端社区已经成熟的模块和框架。比如,专门用来处理时间格式问题的 moment.js,以前可能会用到 jQuery 等。我们要在项目里面使用他们,得先找到他们在网络上的地址,把相应的文件下载下来,放到我们自己的项目某个目录,然后再在 HTML 文件里面引用相应的文件路径。
上面的做法很显然是存在效率和不方便的问题,在这种情况下前端的 package management 工具应运而生。我们先来了解一下包管理工具为我们做了什么事:1:帮我们从网络上下载依赖 2:管理依赖的版本 3:有的还具备 task runner 功能(npm)这里就要提到几个包管理工具:

bower
npm
yarn

bower 和 npm 都是包管理工具,但是又有不同。现在大家听得最多,用的的可能是 npm,yarn,bower 已经差不多死掉了。
npm vs bower
npm(node package manager) 本是 nodejs 用来管理 node 依赖的,但是后来也被用于前端的依赖管理。bower 是只被用于管理前端的组件,例如 html,css,js 的工具,只用在前端。
在依赖结构上二者也不相同。bower 是扁平的依赖树,需要用户管理依赖的依赖。而 npm 采用的是嵌套的依赖树,不需要用户关心依赖的依赖。
bower
bower init // 创建 bower.json
bower install jquery –save // 安装 jquery 依赖

安装成功之后会,bower 会在当前目录下创建一个名叫 bower_components/ 的文件夹。所以通过 bower 安装的依赖都会放到这个目录下。例如上面的 jquery 安装成功之后,我们能在 bower_components/ 目录下得到 jquery 相关文件,然后我们就可以在 HTML 文件里面引用了:
<script src=”bower_components/jquery/dist/jquery.min.js”></script>

npm 也是类似的:
npm init // 创建 package.json 文件
npm install jquery –save // 安装 jquery 依赖

安装成功之后会,npm 会在当前目录下创建一个名叫 node_modules/ 的文件夹。所以通过 npm 安装的依赖都会放到这个目录下。例如上面的 jquery 安装成功之后,我们能在 node_modules/ 目录下得到 jquery 相关文件,然后我们就可以在 HTML 文件里面引用了:
<script src=”node_modules/jquery/dist/jquery.min.js”></script>

3:Module bundler 工具在上面的第二点里面,我们使用了包管理工具,已经不再需要我们自己手动去网上找依赖,下载到项目库里,但是想要使用,依然需要在 HTML 文件里面一一引用。我们要怎样才能像别的语言一样在一个 js 文件里面引用另外一个 js 文件(模块)呢?
当然自从 ES6(ES2015) 开始,JavaScript 已经有这个功能了,我们可以通过 import 来引入,export 来导出。但是在这之前,我们只能依赖 Module bundler 工具来做到这一点。
当时比较出名和流行的一下 2 大解决方案:

CommonJs – node.js, Browserify.js
AMD(Asynchronous Module Definition)- Require.js

至今仍然有很多人没有弄明白 CommonJS 和 AMD 都是一个协议标准,而不是一个具体的库。CommonJs 的核心就是 module(模块),定义了 JavaScript 代码怎样引用和导出代码。实现了 CommonJs 的最出名的就是 node.js 和 Browserify.js,而对应的实现了 AMD 的比较是 Require.js
大家都知道 node.js 是运行在服务端的 JavaScript,不属于我们本篇的范畴,这里不讲。接下来我们来看看
Browserify.js
如果你打开 Browserify 的官网,可以看到这样一句话:
Browserify lets you require(‘modules’) in the browser by bundling upall of your dependencies.
Browserify 提供 require() 方法在一个 js 文件里面引入另外一个 js 文件或者一个 js 文件 export 的变量。最终 Browserify 会根据依赖关系,把所有的 js 代码都整合到一个 js 文件里,也就是我们常说的 bundle 文件。之后就只需要在 HTML 文件里面引用这一个 js bundle 文件就行了。
接下来看看具体怎么使用:
step1: 全局安装 browserify
npm install browserify -g // 全局安卓 browserify

step2: 在 module/ 目录下创建一个 module.js,有如下示例代码:
function getSum(a, b) {
return a + b;
}

module.exports = getSum;
step3: 创建 main.js 文件,在这里面使用 module/module.js
var getSum = require(‘./module/module’);
var sum = getSum(10, 10);
console.log(’10 + 10 = ‘, sum);

step4: 利用 browserify 创建 bundle 文件:
browserify main.js -o build/bundle.js -d
上面的命令就是:browserify 以 main.js 为源文件,生成 bundle 文件 bundle.js,创建文件夹 build/,并把 bundle.js 放到 build/ 路径下。-o(-output) 表示后面跟上输出文件路径,- d 表示生成 source map.
step5: 在 HTMl 文件里面引入上一步的 bundle.js
<!doctype html>
<html>
<head>
<meta charset=”UTF-8″>
<script src=”build/bundle.js”></script>
</head>
<body></body>
</html>
step6: 验证结果
10 + 10 = 20 // 控制台得到我们正确地结果

4:task runner 工具前端的 task 可能会有:检查代码格式,预编译,跑测试,压缩代码,起 server 等。Task Runner 就是按照用户自定义的任务流自动地完成一系列的 task。
一般 task runner 工具本身并不具体具体执行某项任务的功能,而是每一个任务都有相应的插件来完成。例如曾经流行过的 grunt 和 gulp。
但是现在的前端项目也不会再用到 grunt 和 gulp 了。现如今,因为项目上一般会用到 npm 来做依赖管理,而 npm 自己的 script 就可以用来 run task, 这样也不用额外再多下一个额外的工具了。

正文完
 0