Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

在mod.js基础上, 实现本地 localStorage 缓存 #35

Closed
wyntau opened this issue Apr 19, 2016 · 0 comments
Closed

在mod.js基础上, 实现本地 localStorage 缓存 #35

wyntau opened this issue Apr 19, 2016 · 0 comments

Comments

@wyntau
Copy link
Contributor

wyntau commented Apr 19, 2016

使用 mod.js, 配合 fis-postpackager-loader 生成 resourcemap, 然后在 mod.js 基础上, 实现将代码缓存在本地 localStorage, 当有新的发布时, 会将本地缓存的内容进行覆盖.

  1. mod.js初始化时, 会将本地过期的模块删除
  2. 调用 require.resourceMap 时, 会将本地没过期, 但是在resourceMap中不存在的模块删除
  3. define时, 会将模块缓存至本地

如果不想使用缓存, 可以在构建时, 使用 fis-plugin-uglifyjs的 global_defs, 设置 __MOD_CAHCE, 将缓存部分代码去除

diff --git a/mod.js b/mod.js
index d5adf29..d52b4fb 100644
--- a/mod.js
+++ b/mod.js
@@ -25,6 +25,128 @@ var define;
     var resMap = {};
     var pkgMap = {};

+    if(typeof __MOD_CACHE !== 'undefined' && __MOD_CACHE){
+        var cacheMap = {};
+        var cacheTime = 1000 * 60 * 60 * 24 * 10;
+        var supportCacheModule = !!(typeof(JSON) != "undefined" && window.localStorage);
+        var getModuleKey = function(id){
+            return '_m_' + id;
+        };
+        var getModuleUrl = function(id){
+            //
+            // resource map query
+            //
+            var res = resMap[id] || resMap[id + '.js'] || {};
+            var pkg = res.pkg;
+            var url;
+
+            if (pkg) {
+                url = pkgMap[pkg].url || pkgMap[pkg].uri;
+            }else {
+                url = res.url || res.uri || id;
+            }
+            return url;
+        };
+        var hasCacheModule = function(id){
+            if(cacheMap[id] && cacheMap[id].url == getModuleUrl(id)){
+                return true;
+            }else{
+                return false;
+            }
+        };
+        var hasValueModule = function(id){
+            return resMap[id] || resMap[id + '.js'] || false;
+        };
+        var useCacheModules = function(queues){
+            if(!supportCacheModule){
+                return queues;
+            }
+
+            var needLoad = [];
+            var docFrag = document.createDocumentFragment();
+
+            for(var i = 0; i < queues.length; i++){
+                var queue = queues[i];
+                var id = queue.id;
+                if(!hasCacheModule(id)){
+                    needLoad.push(queue);
+                    deleteCacheModule(id);
+                    continue;
+                }
+                var scriptNode = document.createElement('script');
+                scriptNode.setAttribute('type', 'text/javascript');
+                scriptNode.setAttribute('data-module', id);
+                try{
+                    scriptNode.appendChild(document.createTextNode("define('" + id + "', " + cacheMap[id].factory + ");"));
+                }catch(e){
+                    scriptNode.text = "define('" + id + "', " + cacheMap[id].factory + ");";
+                }
+                docFrag.appendChild(scriptNode);
+            }
+
+            head.appendChild(docFrag);
+
+            return needLoad;
+        };
+        var _writeCacheModule = function(key, module){
+            window.localStorage.removeItem(key);
+            window.localStorage.setItem(key, JSON.stringify(module));
+        };
+        var writeCacheModule = function(id, module){
+            if(!supportCacheModule){
+                return false;
+            }
+            var key = getModuleKey(id);
+            module.expires = (+new Date()) + cacheTime;
+            try{
+                _writeCacheModule(key, module);
+            }catch(e){}
+        };
+        var _deleteCacheModule = function(key){
+            window.localStorage.removeItem(key);
+        }
+        var deleteCacheModule = function(id){
+            if(!supportCacheModule){
+                return false;
+            }
+            var key = getModuleKey(id);
+            try{
+                _deleteCacheModule(key);
+            }catch(e){}
+        };
+        var cleanCacheModules = function(){
+            for(var id in cacheMap){
+                if(hasValueModule(id)){
+                    continue;
+                }
+                deleteCacheModule(id);
+            }
+        };
+        (function loadCacheModules(){
+            if(!supportCacheModule){
+                return false;
+            }
+            for(var key in window.localStorage){
+                if(!/^_m_/.test(key)){
+                    continue;
+                }
+                var module = JSON.parse(window.localStorage.getItem(key));
+                var id = key.substr(3);
+
+                // cache expire
+                if(module.expires < (+new Date())){
+                    window.localStorage.removeItem(key);
+                    continue;
+                }
+
+                cacheMap[id] = module;
+
+                // update cacheTime, and write back to localStorage
+                writeCacheModule(id, module);
+            }
+        })();
+    }
+
     var createScripts = function(queues, onerror){

         var docFrag = document.createDocumentFragment();
@@ -103,6 +225,13 @@ var define;
             });
         }

+        if(typeof __MOD_CACHE !== 'undefined' && __MOD_CACHE){
+            queues = useCacheModules(queues);
+            if(!queues || !queues.length){
+                return;
+            }
+        }
+
         createScripts(queues, onerror);
     };

@@ -117,6 +246,19 @@ var define;
             }
             delete loadingMap[id];
         }
+
+        if(typeof __MOD_CACHE !== 'undefined' && __MOD_CACHE){
+            // 缓存已经有了, 不需要再次覆盖写入
+            if(hasCacheModule(id)){
+                return;
+            }
+
+            // 写入缓存
+            writeCacheModule(id, {
+                url: getModuleUrl(id),
+                factory: factory.toString()
+            });
+        }
     };

     require = function (id) {
@@ -234,6 +376,10 @@ var define;
                 pkgMap[k] = col[k];
             }
         }
+
+        if(typeof __MOD_CACHE !== 'undefined' && __MOD_CACHE){
+            cleanCacheModules();
+        }
     };

     require.loadJs = function (url) {
@wyntau wyntau closed this as completed Oct 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant