Como coletar todos os ativos estáticos (js, css) usados pelo Discourse

Estou tentando configurar um CDN para meu fórum. Como a China baniu o Fastly e muitos servidores de CDN, não posso usá-los para acelerar meu fórum. Após fazer algumas pesquisas, voltei-me para o Jsdelivr, que pode servir arquivos estáticos do npm ou de repositórios do Github.

Sei que posso usar DISCOURSE_CDN_URL no app.yml para configurar a URL. Mas antes disso, preciso coletar todos os arquivos estáticos (js, CSS) do meu fórum e enviá-los para o Github, para que o Jsdelivr possa acessá-los. Descobri que os arquivos estáticos estão localizados dentro do container Docker:

/var/www/discourse/app/assets

Então estou pensando em copiar todos os arquivos desse caminho sempre que reconstruir o app e depois enviá-los para o Github. Acho que essa ideia deve funcionar, mas a solicitação real contém um nome de hash longo que não sei como obter. Por exemplo:

ember_jquery.js se torna
ember_jquery-8ef4e572f0bf9485e6ef9a35f088729735f82434cf495fbcd5acedefbcddb363.js

Minha pergunta é:

  1. Como gerar o nome do arquivo com hash?
  2. Existe outra maneira de coletar os arquivos estáticos?

É um hash SHA1 do conteúdo do arquivo. Ele é gerado aqui:

As versões compiladas que são utilizadas são colocadas em /var/www/discourse/public/assets/.

Se você adicionar um bloco ao seu app.yml, poderá executar uma ação após a reconstrução do contêiner. Por exemplo, para fazer upload para o S3, usamos algo semelhante a:

hooks:
  after_assets_precompile:
    - exec:
        cd: $home
        cmd:
          - sudo -E -u discourse bundle exec rake s3:upload_assets

No seu caso, substitua a tarefa rake pelos comandos que você executa para enviar os ativos compilados para o GitHub quando o contêiner for construído.

Obrigado, @schleifer. Sua resposta foi muito útil. No entanto, ainda tenho algumas perguntas de acompanhamento:

  1. Onde posso encontrar a documentação para hooks como after_assets_precompile? Pesquisei na documentação do Docker e também no repositório do Discourse no GitHub, mas não encontrei nenhuma informação sobre isso. Preciso configurar os hooks chamados after_assets_precompile eu mesmo (como fazer isso?) ou eles já estão configurados pelo Discourse, como o after_code?

  2. Pelo que entendi, meu pseudocódigo ficaria assim:

     hooks:
       after_assets_precompile:
         - exec:
             cd: $home
             cmd:
               - entrar no contêiner Docker
               - cd para `/var/www/discourse/public/assets/`
               - git add, commit e push para o repositório do GitHub
    

Obrigado.

Essa é uma boa pergunta, mas não tenho uma resposta ideal para você.

O sistema de configuração usado dentro do container é:

O README lá descreve como os hooks funcionam de forma geral. Os hooks específicos disponíveis dependem de como sua instância está configurada — o arquivo principal app.yml inclui um ou mais templates. Na maioria dos casos, um deles é o web.template.yml:

É ali que o hook assets_precompile está definido (na [L159] enquanto escrevo). Conforme a documentação do pups, você pode executar outros comandos antes ou depois que ele termine, usando before_assets_precompile e after_assets_precompile, respectivamente.

Os comandos são executados dentro do container Docker, então você não precisa fazer nada para isso.

A diretiva cd: pode apontar diretamente para /var/www/discourse/public/assets/, e cada linha em cmd é executada a partir desse diretório. (Aviso: cada linha de um array cmd é executada em um shell separado, como em um Makefile).

Não tenho certeza se o conteúdo de /var/www/discourse/public/assets/ persiste entre builds, então talvez você precise criar o repositório git local e fazer um force push toda vez. A solução “mais correta” pode ser definir um volume Docker em app.yml para o diretório de assets em um volume Docker definido em app.yml como os outros e persistir fora do container.

Muito obrigado. Também descobri que alguns ativos estáticos (como CSS) são armazenados em /var/www/discourse/tmp/stylesheet-cache. No entanto, há dois outros problemas:

  1. Os usuários fazem upload de ativos, como avatares, que também são servidos pela CDN após configurar o DISCOURSE_CDN_URL. No entanto, enviar os ativos de upload para o GitHub sempre que um usuário fizer um upload não parece ser uma solução ideal.
  2. Quando o Discourse solicita um avatar de usuário, como 2_2.png, ele: 1) divide o nome do arquivo, 2) realiza algumas verificações e 3) calcula o nome real do arquivo usando hash. Se eu precisar servir o avatar do usuário, terei que implementar a mesma lógica, já que não existe um arquivo chamado 2_2.png.

Minha solução final é simples. 1) Adicionei o Nginx antes do meu fórum, como nesta postagem. 2) Coletar todos os ativos estáticos do caminho acima e enviá-los para o GitHub. 3) No arquivo de configuração do Nginx, adicionei algumas regras como:

location ~/(stylesheets|assets) {
    return 301 https://cdn.jsdelivr.net/gh/my_github/my_repo/$request_uri;
}

Obrigado novamente, @schleifer