Mudanças principais futuras que podem quebrar alguns temas/componentes (12 de abril)

Na próxima semana, vou mesclar este PR que permite que temas e componentes tenham testes QUnit, mas também altera a forma como o JavaScript dos temas é processado/transpilado pelo Discourse. Fazer essas alterações de maneira compatível com versões anteriores é muito difícil sem reescrever grande parte do código principal (o que pode, inclusive, introduzir outras incompatibilidades), então as alterações podem quebrar o JavaScript dos seus temas/componentes ao atualizar seu site.

Neste post, vou explicar quais são as alterações que podem afetar seus temas/componentes e o que você precisa fazer para corrigi-los.

1. JavaScript dentro de tags <script type="text/discourse-plugin"> será invocado com o modo estrito ativado

Essa alteração não afeta código JS que não esteja dentro de tags <script type="text/discourse-plugin">. Você está completamente seguro dessa alteração se seu código estiver em tags <script> regulares ou em arquivos .js independentes.

A maneira mais fácil de saber se seu tema/componente é afetado por essa alteração é envolver seu código JS em uma Expressão de Função Imediatamente Invocada (IIFE) e adicionar "use strict"; no topo do seu código. Por exemplo, digamos que seu código de tema atualmente se pareça com isso:

<script type="text/discourse-plugin" version="0.8.11">
  a = 5;
  console.log(a);
</script>

Após envolvê-lo em uma IIFE, ele deve ficar assim ("use strict"; é importante porque ativa o modo estrito e queremos testar como nosso código se comporta nesse modo):

<script type="text/discourse-plugin" version="0.8.11">
  (function() {
    "use strict";
    a = 5;
    console.log(a);
  })();
</script>

Se seu componente parar de funcionar após fazer isso, ele quebrará ao atualizar seu site. Para corrigir seu código, recomendo fortemente que você primeiro leia a documentação do MDN sobre o modo estrito do JavaScript e verifique se seu tema/componente faz algo proibido no modo estrito. Se fizer, você precisará refatorar seu código para que não faça nada proibido.

O erro mais provável que você verá é ReferenceError ao declarar uma variável sem a palavra-chave var (ou let/const). No exemplo acima, a linha a = 5; lançará uma exceção ReferenceError no modo estrito porque esquecemos de adicionar var. O código ficará assim após corrigi-lo:

<script type="text/discourse-plugin" version="0.8.11">
  (function() {
    "use strict";
    var a = 5;
    console.log(a);
  })();
</script>

Quando terminar de testar/corrigir seu código, sinta-se à vontade para remover a IIFE e a linha "use strict";.

2. Os caminhos dos módulos JavaScript dos temas serão prefixados com os IDs dos temas.

Há algum tempo, adicionamos um novo recurso que permitiu que o JavaScript dos temas fosse dividido em vários arquivos, e preciso dar um pouco de contexto sobre como esse recurso funciona para explicar a mudança que está por vir.

Quando um tema/componente que vem com arquivos JavaScript independentes é instalado em uma instância do Discourse, o Discourse percorre todos os arquivos JavaScript e cria um módulo JavaScript para cada um. Cada módulo precisa ter um identificador único (também conhecido como caminho), então o Discourse usa o caminho do arquivo (com pequenas alterações) como o caminho do módulo.

Por exemplo, se seu tema/componente tiver um arquivo em javascripts/discourse/helpers/my-helper.js, o Discourse criará um módulo para esse arquivo e atribuirá discourse/helpers/my-helper como seu caminho, e o módulo conterá uma versão transpilada do JavaScript dentro do arquivo original.

A vantagem dos módulos é que você pode importar classes/funções/objetos etc. de um módulo para outro. Por exemplo, você pode importar uma função chamada xyz de my-helper para outros módulos usando uma instrução import assim:

// javascripts/discourse/controllers/my-theme-controller.js

import { xyz } from "discourse/helpers/my-helper";

O PR que vou mesclar na próxima semana adicionará um prefixo aos caminhos dos módulos dos temas. Então, em nosso exemplo, my-helper mudará de discourse/helpers/my-helper para discourse/theme-<theme_id>/helpers/my-helper. Isso significa que nossa instrução import deixará de funcionar porque o caminho do módulo terá mudado. Para corrigir, precisamos apenas alterar o caminho na instrução import de absoluto para relativo, assim:

// javascripts/discourse/controllers/my-theme-controller.js

import { xyz } from "../helpers/my-helper";

Agora nossa instrução import deve funcionar novamente. Veja esses PRs 1 e 2 para exemplos reais de componentes afetados pela alteração (2) e como foram corrigidos.

Novamente, isso só afeta seu tema/componente se ele importar de um de seus próprios módulos; importar módulos principais não é afetado por essa alteração.

Espero que isso ajude. Se tiver alguma dúvida, por favor, me avise!

31 curtidas

Obrigado pelo resumo detalhado :slight_smile:

Isso afetará os caminhos “absolutos” para arquivos em um plugin usado em um componente de tema? Por exemplo, componentes de tema que funcionam com o plugin layouts exigem todos os helpers no próprio plugin layouts assim

requirejs('discourse/plugins/discourse-layouts/discourse/lib/layouts')

Veja, por exemplo, o widget de lista de categorias layouts.

Parece que a mudança de caminho aqui alinha com a namespace de ativos no pipeline de ativos do plugin (usando IDs de tema em vez de nomes de plugin), e que os caminhos de ativos do plugin usados em um componente de tema permanecerão os mesmos. E que um require como o acima ainda funcionará. Está correto?

7 curtidas

Sim, está correto :+1:

6 curtidas

@loginerror, acho que você vai achar este tópico útil :wink:

7 curtidas

@Terrapop
Acho que você tinha preocupações sobre isso.

5 curtidas

Nós já corrigimos nosso código quando isso foi publicado por um período limitado.

5 curtidas