Ao longo dos anos, as extensões do navegador nos permitiram personalizar nossa experiência na web. No início, as extensões consistiam em pequenos widgets e emblemas de notificação, mas conforme a tecnologia evoluiu, as extensões tornaram-se profundamente integradas aos sites. Agora existem até extensões que são aplicativos completos.

Com as extensões se tornando cada vez mais complexas, os desenvolvedores criaram soluções que permitiram que ferramentas pré-existentes escalonassem e se adaptassem. Frameworks como React, por exemplo, melhoram o desenvolvimento da web e até são usados ​​-em vez do vanilla JavaScript-para construir extensões da web.

O que são extensões do Chrome?

Para saber mais sobre as extensões do navegador , vamos dar uma olhada no Google Chrome. Uma extensão do Chrome é um sistema feito de diferentes módulos (ou componentes), onde cada módulo fornece diferentes tipos de interação com o navegador e o usuário. Exemplos de módulos incluem scripts de segundo plano , scripts de conteúdo , e página de opções e Elementos de IU .

Neste tutorial, construiremos uma extensão de navegador usando Chrome e React. Esta postagem do blog cobrirá:

Como usar o React para construir elementos da IU Como criar scripts de conteúdo para interagir com sites Como usar o TypeScript em toda a solução

Construindo uma extensão do Chrome

Antes Quando entrarmos na implementação, vamos apresentar nossa extensão do Chrome: a extensão do validador de SEO. Esta extensão analisa sites para detectar problemas técnicos comuns na implementação de metadados de SEO e na estrutura de um site.

Nossa extensão executará um conjunto de verificações predefinidas na página atual DOM e revelar quaisquer problemas detectados.

A primeira etapa para construir nossa extensão é criar um aplicativo React. Você pode verificar o código neste repositório GitHub .

Criando um aplicativo React com Create React App (CRA)

Criar um aplicativo React com suporte TypeScript é fácil usando CRA .

npx create-react-app chrome-react-seo-extension–template typescript

Agora, com nosso aplicativo esqueleto instalado e funcionando, podemos transformá-lo em uma extensão.

Convertendo o aplicativo React em uma extensão do Chrome

Como uma extensão do Chrome é um aplicativo da web, não precisamos ajustar o código do aplicativo. No entanto, precisamos garantir que o Chrome possa carregar nosso aplicativo.

Configuração da extensão

Todas as configurações das extensões pertencem ao arquivo manifest.js, que está atualmente em nossa pasta pública.

Este arquivo é gerado automaticamente pelo CRA. No entanto, para ser válido para uma extensão, ela deve seguir as diretrizes de extensão . Atualmente, existem duas versões de arquivos de manifesto compatíveis com o Chrome v2 e v3, mas neste guia usaremos a v3.

Vamos primeiro atualizar o arquivo public/manifest.json com o seguinte código:

{“name”:”Chrome React SEO Extension”,”description”:”O poder do React e do TypeScript para construir extensões interativas do Chrome”,”version”:”1.0″,”manifest_version”: 3,”action”: {“default_popup”:”index.html”,”default_title”:”Abra o pop-up”},”icons”: {“16″:”logo192.png”,”48″:”logo192.png”,”128″:”logo192.png”}}

A seguir, vamos detalhar cada campo:

nome: este é o nome da descrição da extensão: descrição da versão da extensão: versão atual da extensão manifest_version: versão para o manifesto formato que desejamos usar em nossa ação de projeto: ações permitem que você personalize o botões que aparecem no e a barra de ferramentas do Chrome, que geralmente dispara um pop-up com a extensão da IU. Em nosso caso, definimos que queremos que nosso botão inicie um pop-up com o conteúdo de nosso index.html, que hospeda nossos ícones de aplicativo: conjunto de ícones de extensão

Construindo seu aplicativo

Para construir um aplicativo React, simplesmente execute:

npm run build

Este comando chama react-scripts para construir nosso aplicativo, gerando a saída na pasta build. Mas o que exatamente está acontecendo lá?

Quando o React constrói nosso aplicativo, ele gera uma série de arquivos para nós. Vamos dar uma olhada em um exemplo:

Como podemos ver, o CRA compactou o código do aplicativo em alguns arquivos JavaScript para chunks, main e runtime. Além disso, gerou um arquivo com todos os nossos estilos, nosso index.html e todos os recursos de nossa pasta pública, incluindo o manifest.json.

Isso parece ótimo, mas se tentássemos em Chrome, começaríamos a receber erros da Política de segurança de conteúdo (CSP). Isso ocorre porque quando o CRA constrói o aplicativo, ele tenta ser eficiente e, para evitar adicionar mais arquivos JavaScript, ele coloca algum código JavaScript embutido diretamente na página HTML. Em um site, isso não é um problema-mas não será executado em uma extensão.

Portanto, precisamos dizer ao CRA para colocar o código extra em um arquivo separado para nós, configurando um variável de ambiente chamada INLINE_RUNTIME_CHUNK.

Porque esta variável de ambiente é particular e se aplica apenas à compilação, não o adicionaremos ao arquivo.env. Em vez disso, atualizaremos nosso comando build no arquivo package.json.

Sua seção de scripts package.json atualmente se parece com isto:

Edite o comando de compilação da seguinte forma:

“build”: “INLINE_RUNTIME_CHUNK=false react-scripts build”,

Se você reconstruir seu projeto, o index.html gerado não conterá nenhuma referência ao código JavaScript embutido.

Carregando a extensão em seu navegador

Agora estamos prontos para carregar a extensão no Chrome. Este processo é relativamente simples. Primeiro, visite chrome://extensions/em seu navegador Chrome e ative o modo de desenvolvedor:

Em seguida, clique em Carregar descompactado e selecione sua pasta de compilação. Sua extensão agora está carregada e listada na página de extensões. Deve ser semelhante a:

Além disso, um novo botão deve aparecer na barra de ferramentas de extensões. Se você clicar nele, verá o aplicativo de demonstração React como um pop-up.

Criando o pop-up

O ícone de ação é o principal ponto de entrada para nossa extensão. Quando pressionado, ele abre um pop-up que contém index.html.

Em nossa implementação atual, vejo dois problemas principais: o pop-up é muito pequeno e está renderizando a página de demonstração do React.

A primeira etapa é redimensionar o pop-up para um tamanho maior para que ele possa conter as informações que desejamos apresentar ao usuário. Tudo o que precisamos fazer é ajustar a largura e altura do elemento do corpo.

Abra o arquivo index.css gerado pelo React e altere o elemento do corpo para conter largura e altura.

body {width: 600px; altura: 400px;…}

Agora, volte ao Chrome. Você não verá nenhuma diferença aqui porque nossa extensão só funciona com o código compilado, o que significa que para ver qualquer alteração na extensão em si, devemos reconstruir o código. Esta é uma desvantagem considerável. Para minimizar o trabalho, geralmente executo extensões como aplicativos da web e apenas as executo como extensões para teste.

Após a reconstrução, o Chrome perceberá as mudanças automaticamente e atualizará a extensão para você. Agora deve ter a seguinte aparência:

Se você tiver algum problema e suas alterações não forem aplicáveis, analise a página de extensões do Chrome para ver se há erros em sua extensão ou force manualmente um recarregamento.

Projetando a IU

O design da IU acontece inteiramente no aplicativo React usando os componentes, funções e estilos que você conhece e adora, e não vamos nos concentrar na criação da própria tela.

Vamos pular diretamente em nosso App.tsx com nosso código atualizado:

import React from’react’; import’./App.css’; function App () {return (

Extensão SEO construída com React!

  • Título 90 caracteres
    O título da página
  • Título principal 1
    O título principal da página (H1)

); } exportar aplicativo padrão;

Adicione alguns estilos para que fiquem assim:

Parece melhor, mas ainda não está lá. No código do componente, codificamos permanentemente o título da página, o cabeçalho principal e as validações.

Do jeito que está, nossa extensão funciona bem isoladamente como um aplicativo React puro. Mas o que acontece se quisermos interagir com a página que o usuário está visitando? Agora precisamos fazer a extensão interagir com o navegador.

Acessando o conteúdo do site

Nosso código React é executado isoladamente dentro do pop-up sem entender nada sobre as informações do navegador, guias e sites que o usuário está visitando. O aplicativo React não pode alterar diretamente o conteúdo do navegador, guias ou sites. No entanto, ele pode acessar a API do navegador por meio de um objeto global injetado chamado chrome.

O A API do Chrome permite que nossa extensão interaja com praticamente qualquer coisa no navegador, incluindo acessar e alterar guias e os sites que eles hospedam, embora permissões serão necessárias para essas tarefas.

No entanto, se você explorar a API, não encontrará métodos para extrair informações do DOM de um site, então, como podemos acessar propriedades como o título ou o número de manchetes de um site? A resposta está nos scripts de conteúdo.

Scripts de conteúdo são arquivos JavaScript especiais executados no contexto de páginas da web e têm acesso total aos elementos, objetos e métodos DOM. Isso os torna perfeitos para nosso caso de uso.

Mas a questão restante é: como nosso aplicativo React interage com esses scripts de conteúdo?

Usando a passagem de mensagens

Passagem de mensagens é uma técnica que permite que diferentes scripts executados em diferentes contextos se comuniquem com uns aos outros. As mensagens no Chrome não se limitam a scripts de conteúdo e scripts de pop-up, e a passagem de mensagens também permite mensagens de extensão cruzada, mensagens regulares de site para extensão e mensagens de aplicativos nativos.

Como você pode esperar, as mensagens estabelecem uma conexão entre duas partes, em que uma das partes envia uma solicitação e a outra parte pode enviar uma resposta, também conhecida como solicitações únicas. Existem também outros tipos de mensagens, sobre os quais você pode ler na documentação oficial .

Vamos colocar a API de transmissão de mensagens em prática, construindo nosso sistema de mensagens dentro de nossa extensão.

Configurando o projeto

Interagir com a API de transmissão de mensagens para nossos requisitos requer três coisas:

Acesso aos scripts de conteúdo de permissões da API do Chrome

O API do Chrome pode ser acessada por meio do objeto chrome globalmente disponível em nosso aplicativo React. Por exemplo, poderíamos usá-lo diretamente para consultar informações sobre as guias do navegador por meio da chamada de API chrome.tabs.query.

Tentar isso levantará erros de tipo em nosso projeto, já que nosso projeto não sabe de nada sobre este objeto de cromo. Portanto, a primeira coisa que precisamos fazer é instalar os tipos adequados:

npm install @ types/chrome–save-dev

Em seguida, precisamos informar ao Chrome sobre permissões exigidas pela extensão. Fazemos isso no arquivo de manifesto por meio da propriedade permissions.

Como nossa extensão só precisa de acesso à guia atual, precisamos apenas de uma permissão: activeTab.

Atualize seu manifesto para inclua uma nova chave de permissões:

“permissions”: [“activeTab”],

Por último, precisamos construir o script de conteúdo para reunir todas as informações de que precisamos sobre os sites.

Construindo scripts de conteúdo em arquivos JavaScript separados

Já aprendemos que os scripts de conteúdo são arquivos JavaScript especiais executados no contexto de páginas da web, e esses scripts são diferentes e isolados do aplicativo React.

No entanto, quando explicamos como o CRA constrói nosso código, aprendemos que o React irá gerar apenas um arquivo com o código do aplicativo. Então, como podemos gerar dois arquivos, um para o aplicativo React e outro para os scripts de conteúdo?

Eu conheço duas maneiras. O primeiro envolve a criação de um arquivo JavaScript diretamente na pasta pública para que seja excluído do processo de construção e copiado como está para a saída. No entanto, não podemos usar o TypeScript aqui, o que é muito lamentável.

Felizmente, há um segundo método: poderíamos atualizar as configurações de compilação do CRA e solicitar que ele gere dois arquivos para nós. Isso pode ser feito com a ajuda de uma biblioteca adicional chamada Craco .

O CRA realiza toda a mágica necessária para executar e construir aplicativos React, mas encapsula todas as configurações, configurações de construção e outros arquivos em sua biblioteca. O Craco nos permite substituir alguns desses arquivos de configuração sem ter que ejetar o projeto .

Para instalar o Craco, basta executar:

npm install @ craco/craco–save

Em seguida, crie um arquivo craco.config.js na raiz diretório do seu projeto. Neste arquivo, substituiremos as configurações de construção de que precisamos.

Vamos ver como o arquivo deve ficar:

module.exports={webpack: {configure: (webpackConfig, {env, caminhos} )=> {return {… webpackConfig, entrada: {main: [env===’development’&& require.resolve (‘react-dev-utils/webpackHotDevClient’), paths.appIndexJs].filter (booleano), conteúdo:’./src/chromeServices/DOMEvaluator.ts’,}, saída: {… webpackConfig.output, nome do arquivo:’static/js/[nome].js’,}, otimização: {… webpackConfig. otimização, runtimeChunk: false,}}},}}

CRA utiliza webpack para construir o aplicativo. Neste arquivo, substituímos as configurações existentes por uma nova entrada. Esta entrada pegará o conteúdo de./src/chromeServices/DOMEvaluator.ts e o construirá separadamente do resto no arquivo de saída static/js/[nome].js, onde o nome é o conteúdo, a chave de onde fornecemos a fonte arquivo.

Neste ponto, o Craco está instalado e configurado, mas não está sendo usado. Em seu package.json, é necessário editar seu script de construção mais uma vez para isto:

“build”:”INLINE_RUNTIME_CHUNK=false craco build”,

A única mudança que fizemos foi substituir os react-scripts por craco. Estamos quase terminando agora. Pedimos ao craco para construir um novo arquivo para nós, mas nunca o criamos. Voltaremos a isso mais tarde. Por enquanto, saiba que um arquivo de chave está faltando e, enquanto isso, não é possível construir.

Dizendo ao Chrome onde encontrar scripts de conteúdo

Fizemos todo esse trabalho para gerar um novo arquivo chamado content.js como parte de nosso projeto de construção, mas o Chrome não sabe o que fazer com ele, ou mesmo que existe.

Precisamos configurar nossa extensão de forma que o navegador sabe sobre esse arquivo, e que ele deve ser injetado como um script de conteúdo. Naturalmente, fazemos isso no arquivo de manifesto.

Na especificação do manifesto, há um seção sobre content_scripts . É uma matriz de scripts, e cada script deve conter o local do arquivo e em quais sites devem ser injetados.

Vamos adicionar uma nova seção no arquivo manifest.json:

“content_scripts”: [ {“corresponde”: [“http://*/*”,”https://*/*”],”js”: [“./static/js/content.js”]}],

Com essas configurações, o Chrome injetará o arquivo content.js em qualquer site usando protocolos HTTP ou HTTPS.

Desenvolvendo o script de conteúdo DOMEvaluator

Conforme as configurações, bibliotecas e configurações vão, nós estão prontos. A única coisa que falta é criar nosso script de conteúdo DOMEvaluator e usar a API de mensagens para receber solicitações e passar informações para os componentes React.

Veja como nosso projeto será:

Primeiro, vamos criar o arquivo ausente. Na pasta src, crie uma pasta chamada chromeServices e um arquivo chamado DOMEvaluator.ts

Um arquivo de script de conteúdo básico seria parecido com este:

import {DOMMessage, DOMMessageResponse} from’../types’;//Função chamada quando uma nova mensagem é recebida const messagesFromReactAppListener=(msg: DOMMessage, sender: chrome.runtime.MessageSender, sendResponse: (response: DOMMessageResponse)=> void)=> {console.log (‘[content.js]. Mensagem recebida’, msg); const headlines=Array.from (document.getElementsByTagName <"h1"> (“h1”)).map (h1=> h1.innerText);//Prepare o objeto de resposta com informações sobre a resposta const do site: DOMMessageResponse={title: document.title, headlines}; sendResponse (resposta); }/** * Disparado quando uma mensagem é enviada de um processo de extensão ou um script de conteúdo. */chrome.runtime.onMessage.addListener (messagesFromReactAppListener);

Existem três linhas principais de código:

Registrando um ouvinte de mensagem Declaração de função de ouvinte (messagesFromReactAppListener) sendResponse (definido como um parâmetro da função de ouvinte)

Agora que nossa função pode receber mensagens e despachar uma resposta, vamos passar para o lado React das coisas.

Componente React App

Nosso aplicativo agora está pronto para interagir com a API do Chrome e enviar mensagens para nossos scripts de conteúdo.

Como o código aqui é mais complexo, vamos dividi-lo em partes que podemos juntar no final.

O envio de uma mensagem para um script de conteúdo exige que identifiquemos qual site irá recebê-la. Se você se lembra de uma seção anterior, concedemos à extensão acesso apenas à guia atual, portanto, vamos obter uma referência a essa guia.

Obter a guia atual é fácil e bom documentado . Simplesmente consultamos a coleção de guias com certos parâmetros e obtemos um retorno de chamada com todas as referências encontradas.

chrome.tabs && chrome.tabs.query ({active: true, currentWindow: true}, (tabs)=> {//Função de retorno de chamada});

Com a referência à guia, podemos enviar uma mensagem que pode ser selecionada automaticamente pelos scripts de conteúdo em execução nesse site.

chrome.tabs.sendMessage (//Current tab ID tabs [0]. id || 0,//Tipo de mensagem {type:’GET_DOM’} como DOMMessage,//Callback executado quando o script de conteúdo envia uma resposta (resposta: DOMMessageResponse)=> {…});

Algo importante está acontecendo aqui: quando enviamos uma mensagem, fornecemos o objeto de mensagem e, dentro desse objeto de mensagem, estou definindo uma propriedade chamada type. Essa propriedade pode ser usada para separar mensagens diferentes que executariam códigos e respostas diferentes no outro lado. Pense nisso como um despacho e uma redução ao trabalhar com estados.

Além disso, observe que no script de conteúdo, no momento não estou validando o tipo de mensagem que ele recebe. Se você deseja ter acesso ao código completo, verifique a chrome-react-seo-extension GitHub.

Conclusão

Hoje, apresentamos muitos novos conceitos e ideias, de como as extensões funcionam, seus diferentes módulos e como se comunicam. Também construímos uma extensão fantástica, fazendo uso de todo o poder do React e do TypeScript. Obrigado pela leitura!