Spaghettify transforma qualquer site HTML estático em um aplicativo de página única com navegação orientada por AJAX e elementos DOM com recursos de persistência. Para fazer isso, ele implementa um interceptor DOM e um processador de afunilamento de middleware que captura eventos de clique em link, busca cada documento solicitado via XHR e digere a resposta transmitindo-a por meio de uma série de funções de middlware antes de atualizar o documento do navegador.
Essas funções de middleware são manipuladores de E/S conectáveis que observam o Princípio de Responsabilidade Única e conformam um pipeline completo de etapas, que podem ser categorizadas em ganchos de middleware onBeforeComplete
, que NÃO alteram o DOM da página atual, e ganchos de middleware onAfterComplete
que aplicam suas alterações (portanto, mutação) diretamente no DOM da página atual após ter sido injetado.
Todo o projeto é construído em TypeScript e implementa vários polyfills e estratégias de codificação para estender o suporte a navegadores legados antigos, como MSIE11.
Os requisitos mínimos para execução deste projeto, seja em modo de desenvolvimento ou produção, e seus scripts de desenvolvimento são node v12.16.0
e npm v.6.14.15
ou versões posteriores. Provavelmente este projeto funcionará perfeitamente em versões mais antigas do node
e npm
, mas recomendamos o uso das versões LTS mais recentes.
Este projeto depende de BabelJS e Webpack para compilar código no modo dev, executar compilações que atendem aos arquivos do site de demonstração e lidar com otimizações de código.
Toda a interação com BabelJS
e Webpack
foi abstraída em scripts npm personalizados para sua conveniência.
Como primeira etapa para gerar um ambiente de desenvolvimento ou construção de produção, execute yarn
ou npm install
para extrair todas as dependências necessárias para este projeto.
Execute yarn build
ou npm run build
na janela do terminal.
O empacotador do projeto navegará por toda a árvore do aplicativo e criará o artefato JavaScript na pasta /dist
, empacotado como spaghettify.js
. Outros pacotes úteis também serão salvos lá para sua conveniência.
Posso buscar o Spaghettify no registro npm? No momento em que este livro foi escrito, as prioridades do projeto eram aumentar um pouco mais a cobertura dos testes e ampliar os recursos da API com suporte estendido para ganchos de middleware fornecidos pelo usuário. Por enquanto, o Spaghettify deve ser consumido como uma dependência do navegador, mas distribuí-lo como um pacote NPM está no roteiro. Por favor, volte em breve para atualizações.
Você pode instanciar e interagir com o Spaghettify por meio de uma API conveniente com alternâncias globais, interceptadores de rota, exclusões e sinalizadores de atributos de persistência de estado e, por último, mas não menos importante, indicadores e manipuladores de progresso de carregamento.
Depois de compilar o Spaghettify com sucesso, você pode importá-lo e instanciá-lo em seu aplicativo da seguinte maneira:
< script type =" text/javascript " src =" /dist/spaghettify.js " > </ script >
< script type =" text/javascript " >
new Spaghettify ( {
enabled : true ,
routes : [ '*.html' , 'content/*' ] ,
excludeByAttr : 'no-spa' ,
loadProgress : true ,
persistAttr : 'data-persist' ,
} ) ;
</ script >
Como você pode ver, o Spaghettify pode receber um objeto de configuração na instanciação. Observe que todos os campos são opcionais e até mesmo todo o objeto de configuração também é opcional. Se não for fornecido, o Spaghettify será instanciado com as opções padrão conforme descrito na tabela abaixo.
O objeto de configurações do Spaghettify pode ser resumido da seguinte forma:
Campo | Tipo | Padrão | Descrição |
---|---|---|---|
enabled | Boolean | true | Habilita ou desabilita o Spaghettify na instanciação |
routes | String[] | ['*'] | Define padrões para rotas a serem interceptadas e atendidas através do Spaghettify. Suporta tokens globais. |
excludeByAttr | String | undefined | Define um token de atributo de dados de exclusão (com ou sem o prefixo data- ). Links decorados com este atributo serão ignorados pelo Spaghettify |
loadProgress | Function Boolean | false | Ativa ou não uma barra de progresso integrada. Também pode ser necessário um manipulador de função que receberá um número inteiro de progresso percentual após o carregamento. |
persistAttr | String | undefined | Define um atributo de dados do sinalizador de persistência do estado da UI (com ou sem o prefixo data- ). Os elementos decorados com este atributo persistirão em seu estado durante a navegação da página. |
Observe que todas as opções de configuração (e a própria carga útil das opções) são opcionais e assumirão o valor padrão se não forem declaradas explicitamente.
Spaghettify interage com seu documento atual vinculando internamente manipuladores de eventos a links qualificados. Para evitar vazamentos de memória ou se você quiser parar o Spaghettify até que ele seja reinstalado novamente, você deverá destruí-lo da seguinte maneira:
< script type =" text/javascript " >
// First, we instantiate Spaghettify
const spa = new Spaghettify ( ) ;
// Then we dispose it after use
spa . destroy ( ) ;
</ script >
Todos os links são configurados pelo Spaghettify como sujeitos a serem interceptados. O mecanismo interno de gerenciamento de eventos avaliará se o link é elegível para ser tratado como uma solicitação AJAX ou não, testando o valor href do link em relação aos tokens glob routes
.
No entanto, podemos ignorar esta etapa antecipadamente configurando a opção excludeByAttr
com um valor de atributo, com o prefixo data-
ou não.
No entanto, e por uma questão de semântica, o Spaghettify considerará apenas os elementos do link configurados com o atributo completo.
< script type =" text/javascript " >
new Spaghettify ( {
excludeByAttr : 'skip-me' ,
} ) ;
</ script >
<!-- Spaghettify will disregard the following link -->
< a href =" foo.html " data-skip-me > Skip this link </ a >
O atributo configurado pode ser preenchido com qualquer valor ou nenhum. O Spaghettify irá desconsiderar esse valor de qualquer maneira.
Como já vimos, a opção de configuração loadProgress
pode assumir um valor primitivo Boolean
ou um manipulador de função .
< script type =" text/javascript " >
new Spaghettify ( {
loadProgress : true ,
} ) ;
</ script >
Se não for configurado explicitamente ou definido como false
, nenhum indicador da barra de progresso será exibido. Se fornecido como true
, o Spaghettify mostrará um indicador animado de barra de progresso vermelha na parte superior da janela de visualização. A barra de progresso mostra o progresso real do download.
No entanto, os consumidores podem querer implementar suas próprias soluções visuais para renderizar informações sobre o progresso do download. Spaghettify os cobre fornecendo um manipulador de progresso de carregamento que esperará um parâmetro de valor inteiro em sua assinatura, que assumirá valores de 0
a 100
conforme as páginas são solicitadas e baixadas via HXR.
< script type =" text/javascript " >
new Spaghettify ( {
loadProgress : function onLoad ( progress ) {
console . log ( progress ) ; // Will log values from 0 to 100
} ,
} ) ;
</ script >
Spaghettify implementa uma API experimental para persistir o estado em nós DOM anotados e selecionados na navegação da página. Para fazer isso, você só precisa configurar um token de valor na opção persistAttr
e então anotar os elementos DOM cujo estado você deseja que seja persistido com o atributo data-
equivalente com um valor exclusivo cada:
< script type =" text/javascript " >
new Spaghettify ( {
persistAttr : 'persist-id' ,
} ) ;
</ script >
< input type =" text " data-persist-id =" my-input " />
Você pode prefixar explicitamente o valor com data-
ou não, mas o Spaghettify exigirá que você anote os elementos DOM para persistirem com a sintaxe completa do atributo de dados.
Observação : os valores dos atributos devem ser exclusivos. Spaghettify lançará uma exceção se mais de um elemento de tipo diferente estiver configurado com o mesmo valor de atributo.
Vale ressaltar que a persistência será aplicada em uma base completa do DOM Node
, portanto abrangerá não apenas o HTML interno do elemento, mas também o estado nativo tocado para controles de entrada. E tudo isso independentemente das alterações no HTML externo.
Você pode gerar um ambiente de desenvolvimento executando yarn dev
ou npm run dev
no console.
O sistema irá gerar todos os artefatos e servir o site sandbox (mais detalhes abaixo) de http://localhost:3000 (ou qualquer outra porta de sua escolha se você anexar o --port=PORT
ao comando dev
, onde PORT
é a porta desejada) no modo watch , então o aplicativo será recompilado após alterações no código-fonte.
O site sandbox é um aplicativo da web pequeno e supersimplista que serve como playground e arena de testes para depuração do Spaghettify em um ambiente ao vivo. Apresenta um estilo bastante simplista, através de um conjunto de páginas diferentes e hierárquicas que descrevem os seguintes recursos principais:
index.html
principal contém uma instância do Spaghettify inline para fins de demonstração. Todos os outros documentos implementam essa instância como um script importado. Você não precisa importar o Spaghettify em cada documento, apenas no de entrada. No entanto, isso permite iniciar o Spaghettify a partir de qualquer documento após recarregar a janela do navegador para fins de demonstração. Em um cenário real de produção, o Spaghettify pode (e deve) ser importado e instanciado apenas uma vez no local de entrada./sandbox
e uma subpasta filha /sandbox/content
para que os contribuidores possam brincar com seletores de link apontando para subpastas, se necessário./sandbox/content
apresentam JavaScript personalizado embutido ou importado que o Spaghettify irá digerir, reinjetar e executar quando necessário. ESLint está atualmente habilitado na base de código Spaghettify e uma auditoria de linting será acionada após a construção do projeto. Você pode configurar seu IDE para fornecer avaliação de linting automaticamente à medida que você introduz alterações. Além disso, você pode acionar o linting de código a qualquer momento executando npm run lint
ou yarn lint
no console do terminal.
Você pode introduzir testes na base de código ou executar os existentes executando npm test
ou yarn test
em seu console de terminal. Os dados de cobertura de código são coletados e armazenados em um documento convenientemente formatado em /coverage/lcov-report
. Para relatórios de cobertura na tela, anexe o parâmetro --coverage
ao comando test
.
Você também pode verificar online um relatório abrangente de cobertura de teste em Macacões.
Copyright 2021 Pablo Deeleman
É concedida permissão, gratuitamente, a qualquer pessoa que obtenha uma cópia deste software e dos arquivos de documentação associados (o "Software"), para negociar o Software sem restrições, incluindo, sem limitação, os direitos de usar, copiar, modificar, mesclar , publicar, distribuir, sublicenciar e/ou vender cópias do Software e permitir que as pessoas a quem o Software seja fornecido o façam, sujeito às seguintes condições:
O aviso de direitos autorais acima e este aviso de permissão serão incluídos em todas as cópias ou partes substanciais do Software.
O SOFTWARE É FORNECIDO "COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO ÀS GARANTIAS DE COMERCIALIZAÇÃO, ADEQUAÇÃO A UM DETERMINADO FIM E NÃO VIOLAÇÃO. EM HIPÓTESE ALGUMA OS AUTORES OU DETENTORES DE DIREITOS AUTORAIS SERÃO RESPONSÁVEIS POR QUALQUER RECLAMAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, SEJA EM UMA AÇÃO DE CONTRATO, ATO ILÍCITO OU DE OUTRA FORMA, DECORRENTE DE, OU EM CONEXÃO COM O SOFTWARE OU O USO OU OUTRAS NEGOCIAÇÕES NO SOFTWARE.