zoukankan      html  css  js  c++  java
  • JS模块加载器加载原理是怎么样的?

    路人一:

    原理一:id即路径 原则。
    通常我们的入口是这样的: require( [ 'a', 'b' ], callback ) 。这里的 'a'、'b' 都是 ModuleId。通过 id 和路径的对应原则,加载器才能知道需要加载的 js 的路径。在这个例子里,就是 baseUrl + 'a.js' 和 baseUrl + 'b.js'。

    但 id 和 path 的对应关系并不是永远那么简单,比如在 AMD 规范里就可以通过配置 Paths 来给特定的 id 指配 path。

    原理二:createElement('script') & appendChild
    知道路径之后,就需要去请求。一般是通过 createElement('script') & appendChild 去请求。这个大家都知道,不多说。有时候有的加载器也会通过 AJAX 去请求脚本内容。

    一般来说,需要给 <script> 设置一个属性用来标识模块 id, 作用后面会提到。

    原理三:document.currentScript
    a.js 里可能是 define( id, factory ) 或者是 define( factory ),后者被称为匿名模块。那么当 define(factory) 被执行的时候,我们怎么知道当前被定义的是哪个模块呢,具体地说,这个匿名模块的实际模块 id 是什么? 答案是通过 document.currentScript 获取当前执行的<script>,然后通过上面给 script 设置的属性来得到模块 id。

    需要注意的是,低级浏览器是不支持 currentScript 的,这里需要进行浏览器兼容。在高级浏览器里面,还可以通过 script.onload 来处理这个事情。

    原理四:依赖分析
    在继续讲之前,需要先简单介绍下模块的生命周期。模块在被 Define 之后并不是马上可以用了,在你执行它的 factory 方法来生产出最终的 export 之前,你需要保证它的依赖是可用的。那么首先就要先把依赖分析出来。

    简单来说,就是通过 toString 这个方法得到 factory 的内容,然后用正则去匹配其中的 require( 'moduleId' )。当然也可以不用正则。

    这就是为什么 require( var ); 这种带变量的语句是不被推荐的,因为它会影响依赖分析。如果一定要用变量,可以用 require( [ var ] ) 这种异步加载的方式。

    原理五:递归加载
    在分析出模块的依赖之后,我们需要递归去加载依赖模块。
    上面的代码只是表达一个意思,实际上 load 方法很可能是异步的,所以递归的返回要特殊处理下。

    实现一个可用的加载器并没有那么简单,比如你要处理循环依赖,还有各种各样的牵一发动全身的细节。但要说原理,大概就是这么几条。个人觉得,比起照着规范实现一个加载器,更加吸引人的是 AMD 或者 CommonJS 这些规范的完善和背后的设计思路。

    路人二:

    Require、Seajs模块器加载的原理是怎么样的?
    1. 定义一套依赖规则, 如AMD CMD CommonJS Modules规范,规范即规则
    2. 加载入口文件及其依赖,原理即按依赖关系递归执行 document.createElement('script') 
    3. 维护模块从初始到销毁的生命周期

    模块加载都有什么方式?
    1. 手动模式 - 人肉管理
    2. 自动模式- 模块加载器管理
    3. 混合模式 - 1,2结合

    不同方式各有什么利弊?
    1. 首先千万别拿着锤子看啥都是钉子,依场景使用
    2. 基于约定的模块依赖管理相比人肉是更好实践,但谨记1
    3. 使用了模块管理器后,必然会引入复杂度,这是复杂度的转移,如何驾驭这些也是成为优秀工程师的修炼之路
    4. 使用模块加载器后最头疼的是构建发布问题,使用seajs的童鞋应该深有体会吧

    just do myself
  • 相关阅读:
    Win10系列:C#应用控件进阶9
    Win10系列:C#应用控件进阶6
    Win10系列:C#应用控件进阶7
    Win10系列:C#应用控件进阶5
    Win10系列:C#应用控件进阶4
    max_element()函数和min_element()函数
    typename的一些用法和注意问题
    std中list作为常量传参时一个迭代器错误
    C++ STL 中list是双向循环链表中循环可以实现什么功能?
    C++中list的erase()函数问题
  • 原文地址:https://www.cnblogs.com/rookieCat/p/4612348.html
Copyright © 2011-2022 走看看