前端模块化概述

1、为何须要模块化jquery

   代码量骤增 => 分治管理的刚性需求webpack

 

2、模块化方案需解决什么问题?web

       模块化要实现两个东西:模块加载与模块封装。面临的具体问题包括:数组

       一、如何定义模块以确保模块的做用域独立,避免命名冲突?浏览器

       二、如何管理模块间的依赖关系,避免重复加载与循环引用?网络

       三、模块化的代码如何部署,以下降HTTP请求数?异步

       四、如何实现按需加载?模块化

       五、如何在解决上述问题以后,保证性能且不影响debug?函数

 

3、原始的解决方案有何局限?工具

   命名空间 + 当即执行函数 + script标签

   局限性:

   一、全局空间污染

   二、需手动管理依赖,不具有可扩展性

   三、没法实现按需加载

 

4、新的解决方案

一、CommonJS

       CommonJS 起源于一个服务端项目 SeverJS,该项目意在经过模块化的开发模式, 解决 JS 做用域的问题。后来发展成了一个致力于构建 JS 生态圈的组织。

       CommonJS 提供了一套模块加载的规范,其核心语法是经过 module.exports 暴露接口,经过 require() 加载资源。

   CommonJS 规范采用同步加载,适用于服务端,但并不适用于浏览器环境(网络延迟、异步特性),所以在浏览器端出现了各种模块加载器,以解决模块加载的问题。

   各种模块加载器提出了各自的模块封装的规范。其中 Sea.js 提出/实现的封装规范,就是 CMD 规范;RequireJS 提出/实现的封装规范,就是 AMD 规范。

 

二、Sea.js

  模块封装:

   define (function (require, exports, module) {

    var a = require('./a')  // 模块加载

    a.doSomething();

    // ……

    var b = require('./b')  // 依赖能够就近书写

    b.doSomething();

    // 经过 exports 对外提供接口

    exports.doSomething = ...

    // 或者经过 module.exports 提供整个接口

    module.exports = ...

   })

   模块加载:

   var $ = require('jquery');

 

三、RequireJS

       模块封装:

   define (['./a', './b'], function(a, b) {

    a.doSomething();

    // 此处略去 100 行

    b.doSomething();

    return function () { } //返回模块的值,能够是函数,也能够是对象

  })

  模块加载:

  require (['./a', './b'], function (a, b) {

        // do sth

  })  

      区别

      RequireJS:依赖前置,提早加载

      Sea.js:依赖就近,延迟加载

 

四、UMD

       一种兼容 CommonJS 和 AMD 的语法糖。事实上 RequireJS 和 Sea.js 就是相互支持的。

图片来源:https://www.leanpanda.com/blog/2015/06/28/amd-requirejs-commonjs-browserify/

      

五、打包工具:Browserify&Webpack

       在模块化的开发方式下,模块加载器(Module loader)解决了模块的加载与依赖的自动管理,可是并无解决 HTTP 请求数的问题。如何将分散的文件合并成一个或几个文件以减小 HTTP 请求,这就是打包工具(Module bundler)的做用。

       打包工具的核心能力是对 js 代码进行合并,扩展能力是对 js 代码进行优化、编译和压缩。webpack 的特点是扩展得比较狠,经过各种插件,能够打包任意类型的文件。

       打包工具的真正价值在哪里呢?仅仅是合并文件从而减小 HTTP 请求数吗?固然不止,打包工具的真正价值是在工程开发中,完成从开发状态到发布状态的自动化构建

  减小 HTTP 请求和按需加载实际上是相互矛盾的,都打包成一个文件了,天然不须要考虑模块加载的问题。可是把全部文件都打包成一个文件,又显得有些冗余。因此 webpack 也支持 code spliting,把文件打成多个包。

 

六、终结者:ES6 Module

      原生模块标准获得浏览器全面支持之时,就是全部模块封装方案灭亡之日。但打包工具(自动化构建工具)仍会继续存在。

 

5、模块打包的技术实现

图片来源:https://www.leanpanda.com/blog/2015/06/28/amd-requirejs-commonjs-browserify/

  以上是 browserify 的实现,webpack 的实现也差很少,这里详细说明一下。

  首先,webpack 会将每一个 js 文件编译成一个函数:

   webpack 会将文件路径映射为一个数字 id,入口文件默认 id 为 0,在入口文件中遇到的第一个加载的模块,id 为 1……,总之按照加载的顺序依次赋予一个 id。

    webpack 函数用于整个模块的加载,全部模块函数会按照 id 的顺序组成一个数组,传给 webpack 进行加载。

       最后运行的结果是:

相关文章
相关标签/搜索