微信小顺序的require机制浅析

(注: 本文中所列微信小顺序东西代码,并不是为微信小顺序原始代码,而是进修归结的表示代码)

在进修开辟微信小顺序中, 剖析总结了近来版本微信小顺序模块化的函数 require的加载与初始化模块机制,
归结说来,小顺序JS模块加载可分为两大步骤:
一,JS模块加载
二,JS模块初始化
详细以下:

一, JS模块加载:一次性加载悉数JS, 但并不一定马上实行.

先提一提微信小顺序架构: 类浏览器 -> HTTP当地效劳 -> 云端效劳

微信小顺序运转的架构,基本上是浏览器 -> HTTP当地效劳 -> 云端效劳, HTTP当地效劳用来读取当地文件或许代办云端的文件资本。
读取项目中JS文件, 是由HTTP当地效劳取当地存储的剧本文件.

好像比较简朴,一个HTML 援用一切JS文件

既然采用了这类架构,那微信小顺序就相似浏览器那样,借助一个HTML页面来援用加载一切的JS文件。(注:这同NODE.JS的体式格局区分)
在小顺序开辟开具的HTTP效劳部份代码,能够看到这个效劳干了这件事变:
微信小顺序包目次下面一切.js文件, 会按<script src=”../xxx.js”> 体式格局插进去天生一个HTML文件,然后相似浏览器体式格局加载.

让HTTP当地效劳合营,对JS文件作的包装手段

但是事变并未完毕,这类体式格局一加载,一切js文件都邑马上实行,乱糟糟天生一团,怎么能够..那require函数又拿来干什么呢?
本来这儿,HTTP效劳在返回.JS文件内容的,给剧本内容包装上了一层: define函数

代办效劳部份代码:
(projectManager.js)
function getScripts(projInfo, callback) {
  ...
    fs.readFile(fname, 'utf8', function(err, scripts) {
        ....    
        scripts = 'define("' + moduleName + '", function(require, module, exports, ' + noBrowserStr +
        '){ ' + scripts + '\n});',
        needRequire && (scripts += 'require("' + moduleName + '")'), //page页面js文件,会添加上require本身,加载后马上初始化。
        .....
        callback(null, scripts) //scripts串内容作为HTTP GET的返回

define函数异常简朴,大抵以下:

......
    var 
    ......
    moduleList = {}; 
    define = function(moduleName, factory) {  //define是全局函数,每一个JS文件都默许会挪用. 
        moduleList[moduleName] = { status: status1, factory: factory }
    };

从上面代码看出,,如许一来,每加载一个JS文件,只是将其文件名与剧本内容串加入了内存中的一个变量保留,并未实行。 注重,这就与一般的HTML 剧本援用加载马上实行完整差别了.

接下来,就轮到微信小顺序的require函数进场了。

二, JS模块初始化:按需递归式require初始化

先看看微信小顺序require函数的定义:

....
    require = function(moduleName) {       
        ....
        var module = moduleList[moduleName]; //define函数挪用时为moduleList赋的值
        .....
        if (module.status === status1) {  
            //假如未初始化,则初始化
            var factory = module.factory,  //这个factory就是这个JS文件的剧本.
            obj = { exports: {} }, u = void 0;
            factory && (u = factory(o(moduleName), obj, obj.exports)), module.exports = obj.exports || u, module.status = status2
        }
        return module.exports
    }

从上面能够看出, require函数只是经由过程模块名,从内存中猎取剧本内容实行,并置标志以保证只实行一次.

再精简一下:

require --挪用-> factory --->模块中能够再require另一个模块...

如许就是一个典范的递归构造。

三,补充一下:页面js 实在也是被require函数加载

所谓页面JS,,就是在app.json中注册的page的js, 它们并没有被别的JS require体式格局援用,
那末它们在什么时候初始化?
回到之前当地代办效劳器的代码,注意下面一点:

代办效劳部份代码:
(projectManager.js)
function getScripts(projInfo, callback) {
  ...
    fs.readFile(fname, 'utf8', function(err, scripts) {
        ....    
        //page页面js文件,needRequire值为TRUE,会添加上require本身
        needRequire && (scripts += 'require("' + moduleName + '")'), 
        .....

本来它们照样运用require函数初始化,而且是加载后马上实行。

现在一般微信小顺序代码构造不会太庞杂,但随着产物的生长,需求的增添, 代码构造能够愈来愈庞杂,愈来愈注重模块化.
同时,如何将旧有JS模块在微信小顺序中重用,这也是个主要话题。 所以深切明白微信小顺序的JS模块化机制也是很有代价的.

    原文作者:半个哈欠
    原文地址: https://segmentfault.com/a/1190000007586766
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞