美文网首页
require简单实现

require简单实现

作者: ITtian | 来源:发表于2017-10-18 10:44 被阅读12次
requ(path){
        // 找到路径,引进代码字符串
        // let code = load(path)
        let code = 'function add(a, b) {return a+b}; module.exports = add'
        code = `(function(module){${code}})(context)`

        // 此处context就是内部的module
        let context = {}
        const run = new Function('context',code)
        run(context)

        return context.exports
    }

在浏览器环境,所有的 Js 模块都需要远程读取,尴尬的是,受限于浏览器提供的能力,并不能通过 ajax 以文件流的形式将远程的 js 文件直接读取为字符串代码。前提条件无法达成,上述运行策略便行不通,只能另辟蹊径

这就是为什么有了 CommonJs 规范了,为什么还会出现 AMD/CMD 规范的原因

那么浏览器上是怎么做的呢?在浏览器中通过 Js 控制动态的载入一个远程的 Js 模块文件,需要动态的插入一个 <script> 节点:

// 摘抄自 require.js 的一段代码
var node = config.xhtml ?
                document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
                document.createElement('script');
node.type = config.scriptType || 'text/javascript';
node.charset = 'utf-8';
node.async = true;
node.setAttribute('data-requirecontext', context.contextName);
node.setAttribute('data-requiremodule', moduleName);
node.addEventListener('load', context.onScriptLoad, false);
node.addEventListener('error', context.onScriptError, false);

要知道,设置了 <script> 标签的 src 之后,代码一旦下载完成,就会立即执行,根本由不得你再封装成闭包,所以文件模块需要在定义之初就要做文章,这就是我们说熟知的 AMD/CMD 规范中的 define,开篇的 add.js 需要重新改写一下

// add.js 文件
define ('add',function () {
    function add (a, b) {
      return a + b;
    }
    return add;
})

而对于 define 的实现,最重要的就是将 callback 的执行结果注册到 context 的一个模块数组中:

context.modules = {}
    function define(name, callback) {
        context.modules[name] = callback && callback()
    }

AMD 和 CMD 的差异主要是,前者需要在定义之初声明所有的依赖,后者可以在任意时机动态引入模块。CMD 更接近于 CommonJS

两种规范都需要从远程网络中载入模块,不同之处在于,前者是预加载,后者是延迟加载

参考自Js 中的模块化是如何达成的

相关文章

网友评论

      本文标题:require简单实现

      本文链接:https://www.haomeiwen.com/subject/idusuxtx.html