Quantcast
Channel: Tópicos
Viewing all articles
Browse latest Browse all 14700

Node Webkit com Require JS

$
0
0
Para quem não conhece, o Node Webkit é uma aplicação baseada no Chromium que permite executar aplicações Web de forma a que aparentem ser nativas. No fundo é um container para aplicações Web que podem executar num sistema operativo fora do browser.

Uma das coisas interessantes deste container é fornecer um contexto Node.js partilhado com o contexto do Javascript, e o container já existe compilado para Mac OS X, Windows e Linux, e pode ser utilizado facilmente para distribuir aplicações web independentes para estes sistemas operativos.

Podem aceder à página do projecto em https://github.com/rogerwang/node-webkit



Ora, um dos grandes problemas que, aparentemente, ninguém conseguiu resolver é o facto de que o Node.js fornece o seu próprio require, que ocupa o mesmo namespace que o require JS. Ou seja, em teoria, se pretendem utilizar toda a funcionalidade do Node Webkit, não podem utilizar o require JS. Ou, se pretendem utilizar o require JS, não podem utilizar o require do Node. Pelo menos, em teoria...

As soluções para evitar o conflito de requires que existiam eliminavam um dos requires, porque algum deles teria que ocupar o namespace, e mudar o namespace de um deles não é solução pois as bibliotecas que utilizam outras dependências carregadas pelo require e que acedem ao namespace conhecido do require.

Exemplo:

Imaginem que uma dependência do Node "A" tem outra dependência "B". Imaginem que mudaram o require do Node (em window.require) para window.requireNode) e que o require JS ficou no window.require.

Para importarem a dependência "A" irão fazer:

Código (Javascript):
var depA = requireNode("A");

O que vai acontecer é que, na consola, vão receber um erro do require JS, que não consegue carregar o "B". Isto porque, internamente, a biblioteca "A" vai pedir a dependência "B" com window.require, onde está o require JS, em vez de utilizar o window.requireNode.

Da mesma forma, se mudarem o namespace do require JS, vão ter o mesmo problema na cadeia de dependências.



Muitos podem achar que a existência de um container web já é valor suficiente para o Node Webkit, mas a realidade é que não se consegue fazer tudo sem a capacidade do Node.js, como a possibilidade de ter um servidor local para servir ranges de conteúdos dinâmicos (video, audio), inutilizando a capacidade de se poder fazer seek no conteúdo (isto é um exemplo comum, mas existem muitos outros).





Agora vou explicar o que é que eu quis dizer com "em teoria". A verdade é que, dentro de um dos contextos de um require, só necessitam verdadeiramente de utilizar esse require (o desse contexto). Logo, é perfeitamente aceitável que, chamando um require, todos os require seguintes até ao retorno do require inicial devem ser do mesmo tipo. Ou seja, é possível fazer o seguinte:


Código (Javascript):
function setupRequireFallback() {
    window.require_js = window.require;

    window.fallbackRequire = function(a, b, c, d) {
        var result;

        try {
            requireFromJS(function() { result = require(a, b, c, d); });
        } catch (err) {
            requireFromNode(function() { result = require(a, b, c, d); });
        } finally {
            window.require = window.fallbackRequire;
        }

        return result;
    }

    window.fallbackRequire.config = window.require.config;

    // Method swizzling power :)

    window.requireFromNode = function(requireCall) {
        window.require = window.requireNode;
        requireCall();
        window.require = window.fallbackRequire;
    }

    window.requireFromJS = function(requireCall) {
        window.require = window.require_js;
        requireCall();
        window.require = window.fallbackRequire;
    }

    window.require = window.fallbackRequire;
}


Portanto, aqui fica a solução.



Claro que, esta solução tem o potencial para ser desastrosa caso se misture Node.js no processo de inicialização de dependencia Javascript, mas misturar procedimentos de Node.js com Javascript não me parece boa prática e é altamente desaconselhado.

Na eventualidade de ser mesmo (expressando todas as minhas dúvidas de que seja mesmo necessário em qualquer situação) teriam que implementar uma stack de requires em que, de cada vez que fazem a troca do require, chamando o método específico (requireFromJS ou requireFromNode) em vez do fallback, devem fazer push do require actual para uma stack, e remover da stack após o carregamento da dependência.


Happy coding.

Viewing all articles
Browse latest Browse all 14700