• webpack(一)模块化


    模块化演变过程

    • 阶段一:基于文件的划分模块方式
      概念:将每个功能和相关数据状态分别放在单独的文件里
      约定每一个文件就是一个单独的模块,使用每个模块,直接调用这个模块的成员
      缺点:所有的成员都可以在模块外被访问和修改(所有的模块都是直接在全局工作,没有【私有空间】)
      模块多了之后会产生【命名冲突】
      无法管理各个模块之间的【依赖关系】
    • 阶段二:命名空间模式
      概念:每个模块只暴露一个全局对象,所有模块成员都挂载到这个对象上,通过将每个模块包裹成一个全局对象的方式实现,类似于为每个模块添加【命名空间】的感觉。
    var  name = 'module-a'
    function method1 () {
        cosnole.log(name + '#method1')
    }
    function method2 () {
        cosnole.log(name + '#method2')
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    优点:减少了命名冲突
    缺点:所有的成员都可以在模块外被访问和修改(所有的模块都是直接在全局工作,没有【私有空间】)
    无法管理各个模块之间的【依赖关系

    var moduleA = {
        name: 'module-a',
        method1: function () {
          console.log(this.name + '#method1')
        },  
        method2: function () {
          console.log(this.name + '#method2')
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 阶段三:IIFE
      使用IIFE(立即执行表达式)为模块提供四有空间,对于需要向外暴露的成员,挂载到全局对象上的方式实现
      优点:模块有了私有空间
      缺点:无法管理各个模块之间的依赖关系。
      有了私有成员,私有成员只能在模块成员内通过闭包的形式访问
    // (function(){})() : 自加载执行该方法
    (function () {
        var  name = 'module-a'
        function method1 () {
            cosnole.log(name + '#method1')
        }
        function method2 () {
            cosnole.log(name + '#method2')
        }
        // 将需要向外暴露的成员,挂载到全局对象上
        window.moduleA = {
            method1: method1,
            method2: method2    
        }   
    })()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 阶段四
      概念:使用(IIFE)参数作为依赖声明使用
      做法:在第三阶段的基础上,利用立即执行函数的参数传递模块依赖项
      优点: 使得模块之间的关系变得更加明显
    (function ($) {
        var  name = 'module-a'
        function method1 () {
            cosnole.log(name + '#method1')
            $('body').animate({ margin: '200px'})
        }
        function method2 () {
            cosnole.log(name + '#method2')
        }
        // 将需要向外暴露的成员,挂载到全局对象上
        window.moduleA = {
            method1: method1,
            method2: method2    
        }   
    })(jQuery)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    模块化规范总结

    在这里插入图片描述

    • CommonJs
      是运行在node.js环境下的模块化规范,node的机制是在启动时,加载模块,执行时直接使用模块
      一个文件就是一个模块,每个模块都有单独的作用域
      通过module.export导出,通过require函数导入

    该模块规范不适合浏览器的原因:
    浏览器在加载页面是,如果需要同步加载所有模块,必然导致性能低下,所以早期的浏览器没有使用CommonJS规范

    • AMD
      主要用于浏览器端,通过define定义,通过require导入,异步加载模块
    • CMD
      主要用于浏览器端,通用模范定义规范,通过define定义,通过require导入,同步加载模块
    • ESModule
      浏览器和服务器通用,用import和export关键字来导入和导出,AMD和commonjs是运行时确定这些东西,es6的模块化设计思想是尽量的静态化,使得编译时就确定模块的依赖关系,以及输入输出变量。

    ES Module

    基本特性

    <script type="module">
       console.log(this) // 因为是module类型 所以是undefined
       var foo = 100
       console.log(foo)  // 100
    </script>
    <script type="module">
       console.log(foo) // 报错 foo没有定义,因为每个 ES Module 都是运行在单独的私有作用域中
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    自动采用严格模式,不能直接采用this
    每个ESM模块都是单独的私有作用域
    ESM是通过CORS去请求外部JS模块的
    ESMscript标签会延迟执行脚本

    导入导出

    导入的是模块成员的地址,并且是只读

    // 默认导出
    var name = 'foo module'
    export default name
    // 默认导入
    import fooName from './module'
    
    // 多个导入导出  {}是固定语法,并不是数据解构
    export const name = 'hello'
    export const age= 18
    export default const sex = 0
    
    import sex,{name,age} from './module'
    
    // 与commonjs的区别:先将模块整体导入为一个对象,再从对象中解构出需要的成员
    export obj = {name, age}
    const { name, age } = require('./module.js')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    使用方式

    1.使用import导入模块路径必须是完整路径,路径的./不能省略,路径可以是绝对路径和url
    2.只加载模块,不提取成员

    import {} from './module.js' 
    import './module.js'
    
    • 1
    • 2

    3.用*导出模块所有成员,并将其放入一个对象中,从对象中提取需要的成员

    import * as mod from './module.js'
    
    • 1

    4.动态加载模块:使用import()动态加载一个模块,返回一个promise对象,等异步加载完成之后会自动加载then指定的回调函数,获取参数

    import('./module.js').then(function (module) { 
       console.log(module) 
    })
    
    • 1
    • 2
    • 3

    5.导入时直接导出

    export { default as Button } from './button.js'
    export { Avatar } from './avatar.js'
    
    • 1
    • 2

    Interview Q

    说说对模块化的理解

    编程中的模块化,是遵守固定的规则是将程序代码拆分成独立模块的编程方式,有两个基本的特征:外部特征和内部特征
        外部特征是指模块跟外部环境联系的接口(其余模块的引用)和模块的功能。内部特征是指模块内部的环境具有的特点
        提高了代码的可复用性和易维护性,实现按需加载(路由),通过定义模块之间的依赖和导入导出模式,使得代码组织和管理更加的灵活和高效
    
        js中存在多种模块化语法和规范:
        commonjs:用于服务端,通过module.exports导出,通过require导入,同步加载,相当于浅拷贝了一份模块的内容
        AMD:用于浏览器端,通过define定义,通过require导入,异步加载模块
        CMD:主要用于浏览器端,通用模范定义规范,通过define定义,通过require导入,同步加载模块
        ES6:浏览器和服务器通用,用import和export关键字来导入和导出,AMD和commonjs是运行时确定这些东西,es6的模块化设计思想是尽量的静态化,使得编译时就确定模块的依赖关系,以及输入输出变量。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    commonjs与es6模块化有什么区别

    1、CommonJS模块是运行时加载,而ES6模块是编译时输出接口;
        2、CommonJS模块的require()是同步加载模块,而ES6模块的import命令是异步加载;
        3、CommonJS是对模块的浅拷贝,ES6是对模块的引入
    
    • 1
    • 2
    • 3
  • 相关阅读:
    Yearning-SQL审核平台
    068:mapboxGL绘制多边形,过滤获取选中的点的集合信息
    部署大数据平台详细教程以及遇到的问题解答(ubuntu18.04下安装ambari2.7.3+HDP3.1.0)
    一种tcp传输json包时出现包不完整、粘包的解决方案
    【OpenGL ES】渲染管线
    使用 Keras 和 TensorFlow Lite 的设备端大型语言模型
    php初级教程十 过滤器
    FFmpeg 解码 H.264 视频出现花屏和马赛克的解决办法
    三艾云 Kubernetes 集群最佳实践
    CTP行情推送规则是怎样执行文件的?
  • 原文地址:https://blog.csdn.net/cwjxyp/article/details/132558013