Adiar o carregamento de JavaScript em Themes e Components

Graças ao @david, temos um padrão muito limpo para carregamento “eager” de JavaScript em temas.

Isso significa que basta colocar arquivos *.js.es6 no diretório javascripts e funciona exatamente como os plugins, o que é glorioso.

Por exemplo, é assim que você cria um inicializador agora, com 100% de equivalência aos plugins:

  • Crie um arquivo chamado /javascripts/discourse/initializers/my-init.js.es6
import { withPluginApi } from "discourse/lib/plugin-api";

function initialize(api) {
  // inicialização via api aqui
}

export default {
  name: "discourse-otp",

  initialize() {
    withPluginApi("0.8.28", initialize);
  }
};

Esta é uma funcionalidade extremamente importante, pois agora podemos dividir temas grandes e complexos em muitas partes, obter linting, destaque de sintaxe e tudo o mais de bom.

No entanto, em alguns casos, podemos querer enviar opcionalmente um payload JS.

Por exemplo, digamos que estamos decorando posts, mas apenas posts com markdown muito específico. Não há sentido em baixar uma biblioteca elaborada de 100KB até sabermos que vamos usá-la.

Contornei isso no meu componente seguindo essa mudança sofisticada:

https://github.com/discourse/discourse/commit/719a93c312b9caa6c71de22d67f1ce1a78c1c8b2

Com:

import loadScript from "discourse/lib/load-script";

function generateOtp($elem) {
  loadScript(settings.theme_uploads.jsotp).then(() => {
     // conteúdo vai aqui
  });
}

Isso significou que:

  1. Eu precisei adicionar .js às “extensões autorizadas do tema”
  2. Eu precisei adicionar uma exceção à CSP para o ativo específico em “content security policy script src”
  3. Eu precisei nomear o ativo no meu about.json

Como escritor de componente de tema, isso é simplesmente muita fricção, pois você não tem chance no jogo de distribuição exigindo esse nível de ninja.

Estou pensando que, para tornar isso utilizável, temos 2 alternativas das quais podemos escolher:

  1. Podemos ensinar o sistema a aplicar CSP automaticamente aos ativos .js em temas ativos e, por padrão, permitir que temas façam upload de .js

  2. Podemos migrar para algo como javascript_cache que os temas JS não defer usam.

Estou meio que inclinado para a opção 1, pois adicionar .js às extensões autorizadas do tema parece trivial e o CSP automático não deve ser impossível.

@pmusaraj / @Johani / @Osama, alguma opinião sobre isso?

The ability to reference theme uploads in JS is a great addition! :100:

This makes a lot of sense to me because anything you can do in a .js file can already be done in files in the javascripts folder of the theme. So, I don’t see any harm in allowing themes to have .js uploads by default.

Revivendo isto porque a única coisa que resta aqui é ensinar CSP a permitir uploads de js de temas. Arquivos js foram permitidos por padrão como uploads de temas há algum tempo.

Se os uploads de js de temas não forem bloqueados pelo CSP, componentes como Image Annotator - Allows you to annotate images in the previewer não precisarão carregar suas dependências na página inicial (~170kb compactado). Esse componente, por exemplo, só precisará carregar essas dependências se o compositor for aberto. Além disso, ele nunca precisa carregá-los para usuários anônimos.

Além disso, essa mudança “permitiria” que os temas tivessem arquivos web worker que podem fazer um trabalho pesado fora da thread principal.

Permitir entre aspas acima porque você pode tê-los como blobs, mas é muito mais agradável tê-los em arquivos separados em vez de mexer com javascript em uma string.

Tenho boas notícias aqui, é um pouco complicado de implementar, mas finalmente vamos dar suporte a ativos JS locais para casos em que queremos usar web workers em componentes de tema.

Não há outra maneira limpa de fazer isso passar pelo CSP, servir arquivos de worker do mesmo domínio resolve o grande problema aqui.

Nota… isso já foi lançado :confetti_ball: