zoukankan      html  css  js  c++  java
  • 前端模块化概述

    一、为什么需要模块化

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

     

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

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

           1、如何定义模块以确保模块的作用域独立,避免命名冲突?

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

           3、模块化的代码如何部署,以降低HTTP请求数?

           4、如何实现按需加载?

           5、如何在解决上述问题之后,保证性能且不影响debug?

     

    三、原始的解决方案有何局限?

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

       局限性:

       1、全局空间污染

       2、需手动管理依赖,不具备可扩展性

       3、无法实现按需加载

     

    四、新的解决方案

    1、CommonJS

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

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

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

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

     

    2、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');

     

    3、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:依赖就近,延迟加载

     

    4、UMD

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

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

          

    5、打包工具:Browserify&Webpack

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

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

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

      减少 HTTP 请求和按需加载其实是相互矛盾的,都打包成一个文件了,自然不需要考虑模块加载的问题。但是把所有文件都打包成一个文件,又显得有些冗余。所以 webpack 也支持 code spliting,把文件打成多个包。

     

    6、终结者:ES6 Module

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

     

    五、模块打包的技术实现

    图片来源: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 进行加载。

           最后运行的结果是:

     

  • 相关阅读:
    ThreadSafety with the AutoResetEvent, ManualResetEvent Class(Synchronization of .net)
    使用Python SMTP发送邮件
    flask项目中设置logo
    如何解决Bootstrap中分页不能居中的问题
    pip install mysql_python报错解决办法
    git上拉项目
    AttributeError: 'str' object has no attribute 'decode'
    pycharm设置SDK
    为git创建远程仓库
    开发过程中git的使用
  • 原文地址:https://www.cnblogs.com/kidney/p/6673189.html
Copyright © 2011-2022 走看看