O que é MobileNet?

MobileNet é uma simplificação de redes neurais para possibilitar o seu uso em aplicações web, com isso podemos criar rapidamente uma aplicação de reconhecimento de images. Inicialmente com um propósito mobile-first MobileNet passou a ser utilizada pelo tensorflow.js e ml5.js

Em mais detalhes, MobileNets são uma classe de convolução de redes neurais projetadas por pesquisadores do Google. Eles foram inicialmente projetados para facilitar o usos de recursos de seu aparelho móvel onde parte da informação é processada na nuvem assim economizando recursos computacionais de seu celular.

Convolução???

Na convolução as imagens em pixels são convertidas em dados numéricos, por exemplo, a imagine que você possui 512 por 512 pixels abaixo:

Foto fellyph cintra

Nós seres humanos classificamos da seguinte forma:

  1. Homem feio
  2. Barba falha
  3. Camisa listrada
  4. Sentado numa cadeira preta

No exemplo acima fazemos a convolução da imagem de 512×512 em 4 dados. Da mesma forma com machine learning essa image será divida em pequenos recortes e esses recortes serão analisados por um grupo de pequenas rede neurais, após esse processo as imagens será traduzida em números (lista de arrays) que classificam essa imagem.

Esse processo é repetido para cara bloco por várias redes neurais até chegar um grupo de números que definem a imagem.

O nível de precisão de uma MobileNet é menor que as redes neurais tradicionais, para agilizar o tempo de processamento. mas isso é compensado pela quantidade de amostras que a MobileNet possui na nuvem.

Por padrão MobileNet utilizar o dataset ImageNet com mais de 1500.000 de imagens divididas em 1.000 categorias. Mas Google fez o código fonte MobileNet aberto com 16 pontos de verificação, com isso podemos treinar o nosso próprio modelo reutilizando a estrutura da mobileNet.

Processo de identificação com ml5.js por exemplo é bem simples, podemos passar o dataset a partir de uma webcam e as imagens pode ser para infinitas finalidades:

  • Objetos
  • Expressões faciais
  • Cores
  • Letras
  • Posições de um corpo humano

Para o modelo não importa a finalidade os objetos serão classificados em números. Assim precisamos das imagens e as labels para classifição dessas imagens

Após o treinamento podemos dizer através de uma porcentagem o que a imagem se trata.

No próximo post iremos falar mais sobre como utilizar o nosso próprio dataset com ml5.js, se ainda não conferiu o post sobre ml5.js aqui vai o link: https://blog.fellyph.com.br/javascript/introducao-ao-ml5-js/

Machine Learning descomplicado com ML5.js

Conhecida como uma biblioteca amigável para machine learning, ml5.js é uma das alternativas mais acessíveis para você que deseja se aventurar no mundo do Machine Learning. Meses atrás eu descobri esta biblioteca web através do canal coding train.

O que é machine Learning?

Antes de entramos em detalhe se você nunca ouviu falar em Machine Learning, algo que entrou no hype na computação com uma serie de recursos possíveis graça a computação na nuvem e a infinidade de dados que possuímos atualmente. Mas machine learning existe na computação desde a década de 40.

Quando umas das definições mais clássicas foram criadas por Arthur Samuels:

É o campo de estudo onde são dados aos computadores a capacidade de aprender algo sem ser explicitamente programado.

Uma ótima definição feita no canal coding train com uma simples comparação na programação clássica temos o seguinte algoritmo:

if(mouseX > 200) {
  console.log("lado direito");
} else {
  console.log("lado esquerdo");
}

Já com machine learning passamos uma série de dados:

  • 300 – direita
  • 401 – direita
  • 210 – direita
  • 100 – esquerda
  • 87 – esquerda
  • 24 – esquerda

A partir dessa série de dados o Machine Learning vai analisar esses dados e tentar fazer uma previsão de dados futuros nesse caso a quantidade de amostra é importante para o sucesso da nossa aplicação.

Dentro dos tutoriais sobre ML5.js vamos falar muito sobre três items:

  1. Redes neurais – os algoritmos responsáveis por processar tarefas de Machine learning, o de temos uma entrada de dados e fazemos uma série de cálculos para ter uma saída esperada. Para identificar padrões específicos.
  2. modelos pré-treinados – modelos pre-treinados é a parte que iremos abordar 90% dos casos por que são os items em mais evidência do momento, utilizado pelas grandes empresas para identificar usuários, moderação de texto, reconhecimento de voz entre outras funcionalidades.
  3. data sets – são os grupos de dados que utilizamos para treinar os nossos modelos.

Baseado nessa rápida de alguns pontos chaves, agora vamos falar sobre ML5, a idéia é criar mais posts sobre o assunto assim quando alguns pontos dos Machine learning forem abordados traremos mais descrições

ML5.js

Ml5.js foi construída em cima do tensorFlow.js que possibilita o uso machine learning na web com o processamento de dados através da GPU, geralmente utilizado para o processamento gráfico, Mas o tensorFlow.js utiliza desse recurso para não afetar o processamento da CPU.

Com ml5.js visa atingir uma audiência que trata machine learning em mais alto nível desenvolvedores web e artistas. A biblioteca possui algoritmos e modelos que realizam a classificação de três tipos da dados imagem, sons e textos.

Para cada grupo temos umas série de funções com diferentes funcionalidades, por exemplo, a função imageClassifier() através de redes neurais conseguimos reconhecer o conteúdo da image retornando um objeto com informações sobre a imagem vindo de um modelo pre-treinado

Mas com a função imageClassifier podemos treinar o nosso próprio modelo. Outra função interessante é poseNet(), com ela conseguimos identificar poses humanas, ela pode identificar uma única pose ou múltiplos integrantes.

No geral temos 10 funções para classificação de images e 2 funções para classificação de som e 4 funções para identificação de texto.

Tensorflow.js

É uma biblioteca criada pelo Google para trabalhar machine learning no JavaScript, foi construído baseado no TensorFlow biblioteca escrita em Python. Com tensorFlow.js podemos utilizar modelos pré-treinados, para classificação de imagens, detecção de objetos, detecção de texto tóxico e reconhecimento de comandos por voz.

Ou treinar o nosso próprio modelo, ele é uma biblioteca base do ML5.js possui uma estrutura mais complexa que o ML5.js

Exemplo prático

Agora que temos uma introdução desses três items chaves vamos fazer o nosso primeiro exercício com ML5.js, quando escrevi esse tutorial a lib estava na versão 0.3.1, agora vamos escolher uma foto para testar com ml5.js, sinta-se a vontade para escolher a sua foto:

Escolhi essa imagem para realizar meu teste

Agora temos a nossa imagem vamos criar o nosso primeiro classificador de imagens:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>ML5JS project</title>
    <script src="https://unpkg.com/ml5@0.3.1/dist/ml5.min.js"></script>
</head>
<body>
    <img src="./assets/dublin.jpg" id="foto" />
    <script>
        // Passo 1: Criar uma classificador de imagems com mobileNet
        const classifier = ml5.imageClassifier('MobileNet', onModelReady);

        function onModelReady() {
            // Passo 2: Selecionar uma image
            const img = document.querySelector("#foto")

            // Passo 3: Fazer a predicção
            let prediction = classifier.predict(img, gotResults);
        }

        // Passo 4: Fazer algo quando tivemos o resultado!
        function gotResults(err, results) {
            console.log(results);
            // e aqui acontece toda a mágica
        }
    </script>
</body>
</html>

No código acima temos exemplo fazemos a classificação da imagem que escolhemos acima, primeiramente fazemos o carregamento da lib em uma CDN, após adicionamos a imagem com uma tag img em nosso markup, temos uma tag script com o código que irá analisar nossa imagem.

Dentro da tag script o primeiro comando faz a chamada de uma função imageClassifier dentro da biblioteca ML5 passando dois parâmetros:

  • modelo – nesse caso vamos utilizar o mobileNet esse modelo pre-treinado está na nuvem ele possui mais de 14 mil imagens em seu dataset
  • função de callback – o segudo parâmetro a função de callback que iremos chamar quando nosso classificador de imagens estiver pronto.

Quando nosso modelo estiver pronto vamos chamar a função onModelReady dentro dela selecionamos a imagem que queremos analisar e com o nosso classificador de imagens(classifier) requisitamos a previsão da imagem. novamente passando dois parâmetros a imagens que iremos analisar e a função de callback.

Quando executamos o nosso código em um browser o resultado será o seguinte:

screenshot to console do browser

Um resultado meio estranho se traduzirmos o resultado temos label como “mastro” ou “poste” com confidência de 0.76 ou seja 76%. Como podemos ver temos uma farbrica no fundo com duas chamines.

A escolha da imagem foi proposital para a gente entender como funciona a analise de images, como falamos anteriormente MobileNet é um modelo pré-treinado mas ele tem uma base de 14 mil imagens o problema nessa caso será que o dentro dessas 14 mil imagens não treinamos o nosso modelo para identificar fábricas.

Se fizermos um segundo teste com essa imagem:

Segunda tentativa

O resultado será o seguinte:

Agora temos o resultado classificado como “beer glass”(copo de cerveja) com uma confidência de 94%, então como podemos ver não existe uma mágica por trás do Machine Learning.

Com isso entendemos que precisão é baseada na quantidade de informação em que meu dataset detém. Por isso empresas que detem uma grande base de informação conseguem aplicar o tecnologia a várias soluções.

Caso queira conferir mais tutoriais sobre JavaScript aqui confira o link: https://blog.fellyph.com.br/category/javascript/

Para esse post vamos ficando por aqui a idéia que em breve estarei postando um vídeo em meu canal. Se ainda não segue o canal aqui está o link: https://www.youtube.com/user/fdangellys

Trabalhando com amp-youtube

No post anterior como utilizar nosso primeiro componente o amp-img neste post vamos entender um pouco mais sobre componentes AMP e como utiliza-los. Primeiramente existem três tipos de componentes:

  • Built-in são os componentes base da biblioteca como amp-img e amp-pixel.
  • Extended componentes que precisa de um script extra para executar geralmente atendem a problemas mais específicos amp-twitter, amp-youtube, amp-analytics.
  • Experimental Componentes que estão em fase de teste

Assim como web components todos os componentes AMP precisam de javascript para serem executados, com a diferença que alguns estão presente em seu core como amp-img e outros precisam de um script extra. Essa técnica a reduzir o tamanho de sua aplicação porque carregamos somente os componentes que necessitamos.

Navegando pelo repositório de componentes

Para saber qual componentes devemos utilizar a documentação será o nosso melhor aliado acessando o endereço https://amp.dev/documentation/components/ você encontrará a lista de componentes existentes e a descrição de como eles se comportam.

aqui temos um exemplo de uma página da documentação

Na documentação você irá as seguintes respostas :

  • O que o componente faz: descrição(description)
  • Como usar o componente: comportamento(behavior)
  • Como customizar o componente: atributos(attributes)
  • Como estilizar o componente: estilização(styling)
  • O componente precisa de uma script tag extra: scripts requeridos(required script)
  • Qual layout o componente suporta: Layouts

Adicionando um componente extended

Agora que temos uma introdução sobre components, vamos utilizar o nosso código boilerplate vamos adicionar uma componente amp-youtube:

<!DOCTYPE html>
<html amp>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,minimum-scale=1">
    <meta name="description" content="Este é um Boilerplate AMP.">
    <link rel="preload" as="script" href="https://cdn.ampproject.org/v0.js">
    <script async src="https://cdn.ampproject.org/v0.js"></script>
    <title>Components AMP</title>
    <style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
    <link rel="canonical" href=".">
    <script async custom-element="amp-youtube" src="https://cdn.ampproject.org/v0/amp-youtube-0.1.js"></script>
  </head>
  <body>
    <h2>Components AMP</h2>
    <amp-youtube
    data-videoid="ZqQ5UXjZukY"
    width="480" height="270"></amp-youtube>
  </body>
</html>
example amp-youtube

Atenção para dois items o script que importamos para renderizar nosso componente youtube amp-youtube-0.1.js e por fim a tag amp-youtube ela será responsável exibir nosso youtube vídeo.

Componente amp-youtube

É um componente extended responsável por exibir vídeos no youtube por isso além das dimensões um requisito obrigatório é o id do nosso video, podemos achar na url do video que queremos compartilhar, exemplo, ‘https://www.youtube.com/watch?v=ZqQ5UXjZukY‘ a propriedade v é o id do nosso vídeo ou seja precisamos apenas do id ‘ZqQ5UXjZukY‘ para adicionar em nosso componente aceita uma série de parâmetros:

  • data-videoid: id do video do youtube
  • layout: tipo do layout que iremos trabalhar, exemplo, no código anterior o video respeita as dimensões definidas no componente mas caso adicionarmos a propriedade layout como responsive nosso componente ira sempre se adaptar ao componente pai e a largura da tela.
  • width e height: as dimensões do nosso video lembrando sempre respeitando a proporção 16:9.
  • data-live-channelid: o id da sua transmissão ao vivo, nesse caso precisamos de uma propriedade diferente para nosso componente reconhecer uma transmissão ao vivo
  • autoplay: se o atributo estiver presente e o browser suportar o vídeo irá tocar automaticamente
  • loop: se o atributo estiver presente o video irá tocar em loop
  • dock: adiciona a versão do vídeo minimizada, quando o usuário realiza o scroll do conteúdo e o video sai da área visível do browser. Para habilitar este recurso precisamos de um componente extra o amp-video-docking exemplo a seguir.

Video dock

Video dock foi introduzido pelo youtube recentemente ele permite o usuário acompanhar o vídeo um pequeno popup no canto superior direito enquanto realizar o scroll no conteúdo. Ele pode ser integrado com outros componentes: amp-youtube amp-video, amp-video-iframe, amp-dailymotion.

Para utilizar o dock precisamos de dois passos básicos carregar o script necessário e o atributo dock em nosso vídeo. Também podemos adicionar docks customizados, mas para esse tutorial vamos utilizar o dock padrão. Como podemos ver no código abaixo:

<amp-youtube
      data-videoid="ZqQ5UXjZukY"
      width="480" height="270"
      dock
      layout="responsive"></amp-youtube>

Placeholder image

Podemos adicionar uma imagem de placeholder ela irá aparece no local do vídeo enquanto ele carrega, para isso em nosso componente amp-youtube vamos adicionar um componente amp-img com uma propriedade para placeholder para especificar que a image é um placeholder de um amp-youtube como podemos ver no código abaixo:

<amp-youtube
      data-videoid="ZqQ5UXjZukY"
      width="480" height="270"
      layout="responsive">
      <amp-img placeholder
        layout="fill"
        width="480"
        height="270"
        src="./assets/images/cover_image.png"></amp-img>
</amp-youtube>

Essas são algumas das possibilidades que podemos fazer com amp-youtube se quiser saber mais sobre o componente acesso o link: https://amp.dev/documentation/components/amp-youtube/?format=websites

Esse material faz parte do curso de AMP em meu canal do youtube para acompanhar as aulas assine o canal:

https://www.youtube.com/channel/UCPaufJocHYVHj44iwXG95PA?view_as=subscriber

Mais vídeos sobre AMP você irá encontrar aqui.

Como trabalhar com imagens no AMP

Quando trabalhamos com AMP temos restrição na utilização de algumas tag HTML e ia tag img se encontra nessa lista. A principal razão é que imagens são responsáveis pela maior parcela no tamanho total de uma aplicação. Por isso o framework tem um cuidado especial no carregamento de images para isso utilizamos o componente amp-img, responsável por série de melhorias em nossa aplicação, por exemplo, lazy-loading e compressão.

Os componentes AMP utilizam web components um conjunto de 4 apis web nativas que permitem a criação de blocos reutilizáveis. A plataforma possui uma série de componentes que agilizam o processo de criação de nossa aplicação. Os componentes priorizam accessibilidade e performance, caso queira conferir a lista completa só acessar a página de catálogo de components, mas para esse tutorial vamos especificamente iremos utilizar <amp-img>.

amp-img

Parece um componente simples mas tem uma série de melhorias de performance com lazy-load, resize e compressão de images. Mas para a redimensionamento de image acontecer precisamos sempre especificar a altura e a largura das imagens. O componente espera os seguintes parâmetros:

  • alt – texto alternativo assim como tag img precisa para produzir um conteúdo mais acessível.
  • width e height – necessário para definir as dimensões de nossa imagem
  • src – assim uma uma tag img define o endereço de nossa imagem
  • layout – estilo de layout que a image terá, AMP possui os seguintes formatos: fill, fixed, fixed-height, flex-item, intrinsic, nodisplay, responsive

Assim que sabemos como utilizar amp-img nosso componente ficará da seguinte forma:

<amp-img src="./assets/images/caipirinha.webp" 
    alt="About Caipirinha"
    width="700" 
    height="526" 
    layout="responsive">
</amp-img>

Fallback

WebP formato 25% a 30% menor que os formatos tradicionais, mas surgiu recentemente e atualmente é suportado por 80% dos broswers(Ago 2019), como podemos ver na imagem abaixo:

Caso queiramos utilizar Webp sem penalizar os usuários dos browsers antigos podemos adicionar um fallback em nosso amp-img sinalizado pela propriedade fallback. e a utilização ficará da seguinte forma:

<amp-img src="./assets/images/caipirinha.webp" alt="Sobre Caipirinha"
          width="700" height="526" layout="responsive">
            <amp-img alt="Sobre Caipirinha"
            fallback
            width="700"
            height="526"
            layout="responsive"
            src="./assets/images/caipirinha.jpeg"></amp-img>
        </amp-img>

Como podemos ver acima isso mesmo o componente de fallback fica dentro do nosso componente principal assim o AMP ficará responsável de verificar se o browser do usuário possui suporte ou não para o formato webp e carregar apenas uma imagem.

Esse post faz parte do conteúdo auxiliar do curso de AMP. Mais posts sobre AMP você confere aqui. Exercícios e exemplos você irá encontrar no meu github. Próximo post iremos falar mais sobre AMP components, caso tenha alguma dúvida deixe um comentário.

Criando primeira página AMP

Novo curso em meu canal do YouTube sobre AMP já está no ar:

Nos primeiros vídeos e posts eu fiz a apresentação do nosso projeto. Agora vamos aprender a criar nossa primeira página AMP e vez quais os requisitos básicos para publicar nossa primeira página AMP.

Requisitos básicos

  1. Primeiro precisamos sinalizar que temos conteúdo amp através de um emoji de raio ou adicionando a palavra AMP em nossa tag HTML
  2. Carregar o script do AMP
  3. Utilizar ferramentas como AMP validador para deixar nossa página 100% compatível

AMP validator

AMP validator é importante por duas razões:

  1. Manter a qualidade do seu código como acessibilidade e performance
  2. Somente conteúdo válido AMP será entregue pelo AMP cache
  3. Não fique desmotivado caso tenho uma série de erros de validação isso é um sinal que você terá uma série de melhorias em seu código

Para utilizar o AMP validator você pode utilizar 4 versões:

Vamos utilizar um simples código HTML para fazer nossa primeira conversão, para ativar o validator precisamos adicionar o atributo amp na tag Para validator reconhecer o conteúdo adicionamos em nossa tag HTML o parâmetro amp:

<!DOCTYPE html>
<html amp>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,minimum-scale=1">
    <meta name="description" content="nossa primeira página amp">
  <head>
    <title>Como validar uma página AMP</title>
  </head>
  <body>
    Olá AMP
  </body>
</html>

Quando testamos o código acima no validator web temos o seguinte retorno:

web amp validator

No caso esteja utilizando a extensão Chrome o retorno será através de um ícone no topo superior direito.

AMP Cache

AMP cache é utilizado por mecanismos de busca como Bing e Google eles realizam o preload da primeira página de sua aplicação assim realizando o carregamento quase que instantâneo de sua aplicação.

AMP cache realiza optimização automática de sua aplicação com:

  • Cache images e fonts
  • Comprime images
  • Converte images em formatos como Webp caso o browser suporte
  • Limpeza do HTML para prevenir ataques XSS

Anatomia de uma página AMP

Todas as páginas AMP iniciam com o mesmo código base com requisitos obrigatórios:

  • Atributo AMP na tag html
  • viewport tag
  • Chamada para AMP JavaScript
  • Boilerplate CSS

Esse código é chamado de AMP boilerplate, podemos gerar o nosso código boilerplate através da página amp.dev/boilerplate lá podemos realizar uma série de configurações em nosso código base, chamada de fontes, suporte a service worker, SEO e Google Analytics:

Tela de configuração do amp boilerplate

Como vimos na validação anterior apenas um markup básico não é suficiente para criar uma página válida AMP. Aplicando as regras que vimos anteriormente a nossa estrutura básica ficará da seguinte forma:

<!DOCTYPE html>
<html amp>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,minimum-scale=1">
    <meta name="description" content="Este é um Boilerplate AMP.">
    <link rel="preload" as="script" href="https://cdn.ampproject.org/v0.js">
    <script async src="https://cdn.ampproject.org/v0.js"></script>
    <title>Como validar uma página AMP</title>
    <style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
    <link rel="canonical" href=".">
  </head>
  <body>
    Olá AMP
  </body>
</html>

Agora temos uma versão válida AMP, como qualquer arquivo HTML uma página AMP precisa de uma tag head e tag body. Mas com uma atenção a três items. A script tag que carrega o script do AMP, canonical tag que iremos entrar em detalhes posteriormente e uma tag stile com o CSS boilerplate do AMP. Com isso temos o seguinte resultado:

Canonical tag

Um dos pré requisitos para ter uma página AMP válida é a tag canonical ela é responsável por informar se conteúdo carregado possui uma versão não AMP, para o mecanismos de busca não identificar sua página AMP como conteúdo duplicado. Caso possua apenas a versão AMP aponte para própria página. em nosso caso na linha 11 definimos nossa propriedade com “.”

Viewport meta responsável por definir como sua aplicação vai responder visualmente a múltiplos devices. Na linha 10 temos o CSS responsável por esconder o conteúdo da página enquanto a aplicação é processada pelo JavaScript do AMP. Você não precisa editar esse arquivo mantenha do jeito que copiar.

Por fim temos o carregamento do JS do AMP, a primeira tag “link” na linha 7 é responsável por realizar o preload do script e na linha seguinte tag “script” realiza o carregamento detalhe para async dentro da tag ele determina que nosso script será carregado de forma assíncrona.

CSS

Ok, temos nosso markup básico mas caso queiramos carregar um arquivo CSS teremos um seguinte erro no validator:

Mensagem não ajuda muito mas isso significa que a tag link com AMP só é válida para fonts e além disso para um set específico de fontes:

  • Fonts.com: https://fast.fonts.net
  • Google Fonts: https://fonts.googleapis.com
  • Font Awesome: https://maxcdn.bootstrapcdn.com
  • Typekithttps://use.typekit.net/

No caso do style customizado teremos que adicionar de forma Inline, isso é um requisito para reduzir o número de requisições e também ajudar no cache de sua aplicação. Além disso ele precisa ser adicionado em uma tag <style amp-custom> e os requisitos são os seguintes

  • 50kb por tag
  • Somente uma tag por página
  • O uso de !important é totalmente proibido
  • Seletores CSS não podem começar com ‘-amp-‘

O projeto usado no curso está no repositório: https://github.com/fellyph/the-best-caipirinha/ as aulas serão separadas por branches, no próximo post vamos ver como trabalhar com imagens e AMP.