打包方案、模块化编程

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/Reagan_/article/details/86558297
首先,为什么需要打包方案呢?

随着前端页面的不断发展,我们的页面承载着越来越多的样式、功能,我们开始尝试往页面里插入各种库和插件,不再局限于简单的静态页面,相应的,在网速的限制下,单位时间内网页的响应和加载速度都极其不尽如人意,js文件的压力越来越大。为了解决这些问题,打包方案应运而生了。(需要明确的是,还有一些其他的作用:代码混淆了不容易被盗用…)

打包方案。

1. js 文件压缩合并工具+脚本执行
当时有JSMin、YUI Compressor、Closure Compiler、UglifyJS 等 js 文件压缩合并工具,单有压缩工具就像只有切好的菜没有锅去煮,于是想要压缩工具起作用,就又得写脚本来执行它,windows 上写 bat 脚本,mac / linux 上写 bash 脚本,要合并的文件和要压缩的文件分好类,发布的时候运行一下脚本,生成压缩后的文件。

有了合并压缩技术,我们的项目越做越大,但是慢慢的,就发现了一些问题:

  • 在合作中,为了其他人也可以调用我们的库和插件,一般就在 window 下申明一个全局的函数或对象来保存。如果引用多个库,名字需要时刻警醒不可以重复。
  • 本地的库和插件如果还依赖其他的库和插件,就需要告知使用人,需要先引哪些依赖库,那些依赖库也有自己的依赖库的话,就要先引依赖库的依赖库,以此类推。

针对这样的:将一个完整逻辑,拆成不同的模块,根据模块来写代码的开发方式,我们引入了一个概念—模块化编程

而对于细节上的操作,不同的人有不同的写法,这样在开发上就会造成不便,于是我们引入了一个概念—js的模块化规范。

1.CommonJS 模块化规范
大概的语法是: 如果 a.js 依赖 b.js 和 c.js, 那么就在 a.js 的头部,引入这些依赖文件:

var b = require('./b')
var c = require('./c')

就如同通常情况下的引入文件一样,引入了就可以正常使用了。

但是也有一个问题,因为 require() 的返回是同步的, 意味着有多个依赖的话需要一个一个依次下载,下载完成后才会继续js脚本的执行,所以CommonJS 规范会堵塞 js 脚本的执行,在浏览器内并不适用。

于是有了下一个规范— Asynchronous Module Definition (AMD) 规范(2011 年)。

2.AMD 模块化规范
为了解决同步阻塞的问题,AMD使用了异步回调的语法来并行下载多个依赖项,比如作为入口的 a.js 可以这样写:

require(['./b', './c'], function(b, c) {
  var n = b.square(2)
  console.log(c)
})

相应的导出语法也是异步回调方式,比如 c.js 依赖 d.js, 就写成这样:

define(['./d'], function(d) {
  return d.PI
})

可以看到,定义一个模块是使用 define() 函数。
define()有返回值, require()没有返回值。
define() 必须要在回调函数中返回一个值作为导出的东西,require() 不需要导出东西,因此也没有返回值,无法作为依赖项被其他文件导入,一般用于入口文件,比如页面中这样加载 a.js:

<script src="js/require.js" data-main="js/a"></script>

以上是 AMD 规范的基本用法,因为已经被淘汰了,就不多说了。

有了模块化编程,我们用于打包的脚本也可以更规范地投入使用了,上面说到针对不同的设备,我们需要写不同的脚本:windows 上写 bat 脚本,mac / linux 上写 bash 脚本,如果有跨平台需求的话,解决方法有二:
其一,windows 上装个可以执行 bash 脚本的命令行工具,比如 msys(目前最新的是 msys2)。
其二,使用 php 或 python 等其他语言的脚本来编写。
对于非全栈型的前端程序员来说,写 bash / php / python 还是很生涩的,因此我们需要一个简单的打包工具,可以利用各种编译工具,编译 / 压缩 js、css、html、图片等资源。
然后 Grunt 产生了(2012 年),配置文件格式是 js。
一年多后另一个打包工具 gulp 诞生了,扩展性更强,采用流式处理效率更高(流处理是一种允许用户在接收到的数据后的短时间内快速查询连续数据流和检测条件的技术。检测时间从几毫秒到几分钟不等。)。

有了模块化编程和有效的打包方式,我们的网页可以更加轻松地承载更多,此时,我们要引入一个新的概念:SPA(Single-page application) — 单页面的程序化,意思是:只有一张web页面,通过用户与页面间的交互,(用js)驱动页面动态更新的应用程序。

当时我们还通过AMD 模块化编程来实现SPA,具体过程是这样的:

SPA 应用有一个总的入口页面,我们通常把它命名为 index.html、app.html、main.html,这个 html 的 一般是空的,或者只有总的布局,布局会把 header、nav、footer 的内容填上,但 main 区域是个空的容器,因为这个作为入口的 html 最主要的工作是加载启动 SPA 的 js 文件。然后由 js 驱动,根据当前浏览器地址进行路由分发,加载对应的 AMD 模块,然后该 AMD 模块执行,渲染对应的 html 到页面指定的容器内(比如 main.html)。
在点击链接等交互时,页面不会跳转,而是由 js 路由加载对应的 AMD 模块,然后该 AMD 模块渲染对应的 html 到容器内。

虽然通过AMD 模块化编程可以更方便地实现SPA,但它也存在着一些问题,比如说:
AMD 规范定义和引用模块的语法太麻烦、不支持动态加载 css等问题。

为了更好的解决这些问题,webpack就应运而生了。

猜你喜欢

转载自blog.csdn.net/Reagan_/article/details/86558297