微信小程序的require机制浅析

(注: 本文中所列微信小程序工具代码,并不是为微信小程序原始代码,而是学习概括的示意代码)json

在学习开发微信小程序中, 分析总结了最近版本微信小程序模块化的函数 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函数出场了。app

二, 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模块化机制也是颇有价值的.

相关文章
相关标签/搜索