NW.js无法正确清除缓存

时间:2016-03-18 20:00:07

标签: javascript module nw.js

环境

问题

从父窗口打开新窗口。 Webchimera 模块已加载但由于其窗口对象指向父窗口而崩溃。那是因为NW.js caches its modules

PARENT

<div id="chimera_container"></div>

...
var gui; // global variable for parent object
var wjs; // global variable for parent object
....
gui = require('nw.gui');
wjs = wjs = require('wcjs-player');
....
video_emit = gui.Window.open('video_emit.html',{
    "window" : {
        "focus": true,
        "toolbar": true,
        "frame": true,
        "width" : 640,
        "height" : 640
    },
    "dependencies": {
        "require-new": "^1.1.0",
        "wcjs-player": "^0.5.6"
    },  
});

video_emit窗口

<div id="vid"></div>

....
var wjs; // global variable for new window object
wjs = require('wcjs-player');  
video_container = new wjs("#vid"); <---- CRASHES **** !!!

node_modules \ wcjs-player \ index.js第82行我添加了

console.log(window.document);

PARENT CONSOLE OUTPUT

#document
...
<div id="chimera_container"></div>

video_emit CONSOLE OUTPUT

#document
...
<div id="chimera_container"></div>  

已尝试解决方案

手动清除缓存

video_emit窗口上要求'wcjs-player'模块之前,调用 clearRequiredModules 函数。

var clearRequiredModules = function(){
    // clear wcjs-player from require cache to force new load
    var clearModules = [
        "wcjs-player",
        "jquery" // https://github.com/jaruba/wcjs-player/issues/38
    ];
    for (var i in clearModules) {
        for (var module in global.require.cache) {
            if ( global.require.cache.hasOwnProperty(module) 
                 && module.indexOf(clearModules[i]) > -1
                )
                delete global.require.cache[module];
        }
    }
};

不工作。同样的问题,好像我根本没有清除。仍然指向父窗口对象。

使用require-new模块

此代码没有科学,我加载模块并在 video_emit窗口中使用它。

var req_new = require('require-new');
wjs = req_new('wcjs-player');

仍在崩溃。

我知道将** new-instance:true **添加到父级的gui.Window.open会解决这个问题,但我需要父窗口和新窗口通过全局变量进行通信只有当它们在同一个渲染上时才可用。

------------------------ 解决方案 --------------- --------------------------

自行清除缓存不起作用,为了使其有效,必须从窗口完成以下操作。

video_emit = gui.Window.open('video_emit.html',{
    ...
});
video_emit .on('document-start', function() {
    video_emit .reload(3);
});

在子窗口中:

clearRequiredModules(); //Same code as protrayed above
wjs = require('wcjs-player');  
video_container = new wjs("#vid");

问题

注意,执行此操作会呈现全局变量(用于在窗口之间共享信息的变量,无用。所以它与在父窗口中执行此操作相同(而不是清除子窗口中的缓存):

video_emit = gui.Window.open('video_emit.html',{
        "window" : {
            "focus": true,
            "toolbar": true,
            "frame": true,
            "width" : 640,
            "height" : 640
        },
        "new-instance" : true // <---- That right there
    });

此问题的可能解决方案是使用 localStorage 来在窗口之间进行通信。

2 个答案:

答案 0 :(得分:1)

wcjs-player严重依赖于能够访问window.documentNW.js v0.12.3有一个错误,将父{q} window个对象泄漏到子窗口。

我已经看到这会产生许多问题,包括将所有错误和日志推送到主窗口,并且它总是会破坏所有依赖window的模块。

修复此问题的方法是在创建子窗口后对其进行node.js级重新加载。

Proof of Concept

Discussion

使用示例:

var new_win = require('nw.gui').Window.open('index.html');
new_win.on('document-start', function() {
    new_win.reload(3);
});

备注:

  • 还应该提到这是NW.js特定问题,Electron新窗口没有此问题。

  • 由于这是一个高级页面重新加载,global对象也将被清除,将信息传递到这个新窗口的替代解决方案是使用localStorage(持久),或者更复杂的需求websockets。

答案 1 :(得分:0)

试着&#34;触摸&#34;您服务器上的所有js文件。 &#34;清除缓存&#34;并不像它应该那么容易。我没有清除浏览器上的缓存,而是意识到&#34;触摸&#34;缓存的服务器文件实际上会更改缓存在服务器上的源文件的日期和时间(在Edge,Chrome和Firefox上测试),大多数浏览器会自动下载服务器上最新的最新版本(代码,图形,任何多媒体)太)。我建议你只需要在服务器上复制最新的脚本,然后做一些触摸操作&#34;在程序运行之前的解决方案,因此它会将所有问题文件的日期更改为最新的日期和时间,然后将新的副本下载到您的浏览器:

 <?php
    touch('/www/sample/file1.js');
    touch('/www/sample/file2.js');
    touch('/www/sample/file2.js');
 ?>  

然后......你的其他程序......

我花了一些时间来解决这个问题(因为许多浏览器对不同的命令采取不同的行动,但他们都检查文件的时间并与浏览器中下载的副本进行比较,如果不同的日期和时间,将进行刷新) ,如果你不能按照正确的方式行事,总会有另一个可用的更好的解决方案。最好的问候和快乐的露营。顺便说一下touch();或者替代品在许多编程语言中工作,包括在javascript bash sh php中,你可以在html中包含或调用它们。