简单记录下自己对前端模块化的一些浅薄理解,不对之处欢迎指正
在介绍前端模打包工具之前,我们先简单说一下浏览器、v8和nodejs,因为我们现在用到的大部分前端模打包工具,都是需要nodejs环境运行的,同时他们都能通过npm进行下载
1. 浏览器:
浏览器组成可分两部分:Shell+内核。浏览器内核又可以分成两部分:渲染引擎(layout engineer或者Rendering Engine)和JS引擎。
渲染引擎,负责对网页语法的解释(如HTML、JavaScript)并渲染网页。我们平时说的“浏览器内核”就是指“浏览器所采用的渲染引擎”。
渲染引擎决定了浏览器如何显示网页的内容以及页面的格式信息。不同的浏览器内核对网页编写语法的解释也有不同,因此同一网页在不同的内核的浏览器里的渲染(显示)效果也可能不同,所以过去需要测试人员人肉测试页面在不同浏览器中的效果。
最开始渲染引擎和JS引擎并没有区分的很明确,后来JS引擎越来越独立,内核就倾向于只指渲染引擎。JS引擎负责对JavaScript进行解释、编译和执行,以使网页达到一些动态的效果。
2. V8引擎:
Chrome的JS引擎,使用C/C++编写的一款非常优秀的开源JS引擎
3. node.js
Nodejs对V8引擎进行了封装,使V8可以运行在非浏览器环境,这使得我们的JavaScript代码可以在非浏览器环境运行
4. npm
NPM是随同NodeJS一起安装的包管理工具,简单来讲,是一个代码共享仓库
npm包下都有package.json配置文件,注明了包的版本号,依赖,作者等信息,下载包时,会一起下载package.json中注明依赖的包
npm install 包名 //安装最新版本的包到当前文件夹
npm i 包名 //npm install 包名简写
npm i包名@版本号 //安装制定版本
npm i 包名 –-save //--save两个减号,安装包到当前文件夹,并将包名及版本号添加到package.json的dependencies
npm i 包名 –-save-dev //并将包名及版本号添加到package.json的devDependencies,下载包时,不会下载devDependencies中的包
npm i 包名 –D //npm i 包名 –save-dev缩写
npm i 包名 –g //全局安装包
5. javascript模块化
简单来讲,有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块。这样做有一个前提,那就是大家必须以同样的方式编写模块,否则你有你的写法,我有我的写法,岂不是乱了套!
正是有了统一的规范,我们才能方便的在npm上下载别人的代码/包/类库,并在我们自己的工程中引用
CommonJS
CommonJS(nodejs, webpack等实现了该规范)
node.js的模块系统,就是参照CommonJS规范实现的。,webpack 也是以CommonJS的形式来书写。在CommonJS中,有一个全局性方法require
,用于加载模块。假定有一个数学模块math.js,就可以像下面这样加载。
var math = require('math');
然后,就可以调用模块提供的方法:
math.add(2,3); // 5
AMD
AMD(Asynchronous Module Definition)(RequireJS实现了该规范)
基于commonJS规范的nodeJS出来以后,服务端的模块概念已经形成,很自然地,大家就想要客户端模块。而且最好两者能够兼容,一个模块不用修改,在服务器和浏览器都可以运行。但是,由于一个重大的局限,使得CommonJS规范不适用于浏览器环境。还是上面的代码,如果在浏览器中运行,会有一个很大的问题,因为require 是同步的,所以如果加载时间很长,整个应用就会停在那里等。因此,浏览器端的模块,不能采用"同步加载"(synchronous),只能采用"异步加载"(asynchronous)。这就是AMD规范诞生的背景。
AMD也采用require()语句加载模块,但是不同于CommonJS,它要求两个参数:require([module], callback);
第一个参数[module],是一个数组,里面的成员就是要加载的模块;第二个参数callback,则是加载成功之后的回调函数。如果将前面的代码改写成AMD形式,就是下面这样:
require(['math'], function (math) {
math.add(2, 3);
});
es6
通过import、export实现模块的输入输出。其中import命令用于输入其他模块提供的功能,export命令用于规定模块的对外接口。(个人观点,虽然import和export在浏览器端实现有着巨大的技术难点,但是标准就是标准,早晚会被浏览器端实现或有更优的标准,早晚一统天下,干掉commonjs、cmd、amd)
然而像import和export这两个命令现在在任何浏览器中都是不支持的, 同时babel也无法将其转换为浏览器支持的ES5, 原因在于babel只是个翻译,假设a.js 里 import 了 b.js, 对a.js进行转码,只是翻译了a.js,并不会把b.js的内容给读取合并进来, 如果想在最终的某一个js里,包含 a.js,b.js 的代码,那就需要用到打包工具,例如webpack。
6. 打包工具
目前常用的前端打包工具有很多,grunt、Gulp、webpack、rollup等,这些工具可以单独使用,也可以互相配合使用
这些打包工具可以帮助前端工程师们完成预处理语言编译、es6代码转es5、代码压缩混淆等工作
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。