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 进行加载。

           最后运行的结果是:

     

  • 相关阅读:
    js截取字符串区分汉字字母代码
    List 去处自定义重复对象方法
    63. Unique Paths II
    62. Unique Paths
    388. Longest Absolute File Path
    41. First Missing Positive
    140. Word Break II
    139. Word Break
    239. Sliding Window Maximum
    5. Longest Palindromic Substring
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/6687727.html
Copyright © 2011-2022 走看看