JS模块化 -- CMD

逻辑织雪使
• 阅读 716

CMD usage

    // sea.js
    define('a', function(require, exports, module){
        console.log('a load');
        exports.run = function (){ console.log('a run') }
    })

    define('b', function(require, exports, module){
        console.log('b load');
        exports.run = function (){ console.log('b run') }
    })

    define('main', function(require, exports, module){
        console.log('main run');
        var a = require('a');
        a.run();
        var b = require('b');
        b.run();
    })

    seajs.use('main');

    // main run
    // a load
    // a run
    // b load
    // b run

seajs简单实现

const modules = {};
const exports = {};

const sj = {}

// 获取地址
// dep -> a -> a.js -> http:xxx/xx/xx/a.js
const __getUrl = (dep) => {
    const p = location.pathname;
    return p.slice(0, p.lastIndexOf('/')) + '/' + dep + 'js';
}

// normal script
const __load = (url) => {
    return new Promise((resolve, reject) => {
        const header = document.getElementsByTagName("header")[0];
        const script = document.createElement('script');
        script.async = true;
        script.src = url;
        script.type = 'text/javascript';
        script.onload = resolve;
        script.onerror = reject;
        header.appendChild(script);
    }) 
}

const __getDepsFromFn = (fn) => {
    let matches = [];
    // require('a')
    // (?:require\() -> require( (?:) 非捕获性分组
    // (?:['"]) -> require(' 
    // ([^'"]+) -> a  避免回溯 -> 回溯 状态机
    let reg = /(?:require\()(?:['"])([^'"]+)/g
    let r = null;
    while((r = reg.exec(fn.toString())) !== null){
        reg.lastIndex;
        matches.push(r[1])
    }
    return matches;
}

// 依赖呢?
// 提取依赖:1. 正则表达式 2. 状态机
const define = (id, factory) => {
    const url = __getUrl(id);
    const deps = __getDepsFromFn(factory);
    if(!modules[id]){
        modules[id] = {url, id, factory, deps};
    }
}

const __exports = (id) => exports[id] || (exports[id] = {});
const __module = this;
// 这里才是加载模块地方
// 这个写法是promise的  所以在 var a = require('a') 时 需要加 async/await 方式
const __require = (id) => {
    return __load(__getUrl(id)).then(() => {
        // 加载之后
        const {factory, deps} = modules[id];
        if(!deps || deps.length == 0){
            factory(__require, __exports(id), __module);
            return __exports(id);
        }
    })
}

sj.use = (mods, callback) => {
    mods = Array.isArray(mods) ? mods : [mods];
    return new Promise((resolve, reject) => {
        Promise.all(mods.map(mod =>{
            return __load(__getUrl(mod)).then(() => {
                // 加载之后
                const {factory} = modules[mod];
                factory(__require, __exports(mod), __module);
                return __exports(mod);
            })
        })).then(resolve, reject);
    }).then(instance => callback && callback(...instance));
}
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
待兔 待兔
11个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
小嫌 小嫌
3年前
js中箭头函数在对象内部的继承
function函数functionPerson()this.name'Jack',this.age25,this.sayNamefunction()console.log(this.name)functioninner()console.log(this.n
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
JS 对象数组Array 根据对象object key的值排序sort,很风骚哦
有个js对象数组varary\{id:1,name:"b"},{id:2,name:"b"}\需求是根据name或者id的值来排序,这里有个风骚的函数函数定义:function keysrt(key,desc) {  return function(a,b){    return desc ? ~~(ak
Wesley13 Wesley13
3年前
Java 多态
类型的检测——向上转型向下转型向上转型:父类对象的引用指向子类对象,向下转型:向上转型的基础上再次指向子类的对象1.向上转型!(https://oscimg.oschina.net/oscnet/dd0d05d39a724e781b799ff5e35b921775d.jpg)!(https://oscimg.oschina.net/o
Easter79 Easter79
3年前
SpringBoot学习:整合shiro自动登录功能(rememberMe记住我功能)
首先在shiro配置类中注入rememberMe管理器!复制代码(https://oscimg.oschina.net/oscnet/675f5689159acfa2c39c91f4df40a00ce0f.gif)/cookie对象;rememberMeCookie()方法是设置Cookie的生成模
Stella981 Stella981
3年前
QeePHP中的访问控制配置
(1)\_code/myapp.php文件中: /      访问被拒绝时的错误处理函数     /    protected function _on_access_denied()    {        $message  "";        require(_MYAP
Stella981 Stella981
3年前
Eclipse 中的Maven常见报错及解决方法
1.不小心将项目中的MavenDependencies删除报错!(https://oscimg.oschina.net/oscnet/fd35e500e2580bca2afb81f35233b87a6ee.png)项目报错:!(https://oscimg.oschina.net/oscnet/8623bd4293fea39ca83a6
跨端轻量JavaScript引擎的实现与探索
一、JavaScript1.JavaScript语言JavaScript是ECMAScript的实现,由ECMA39(欧洲计算机制造商协会39号技术委员会)负责制定ECMAScript标准。ECMAScript发展史:|时间|版本|说明||||||1997
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(