
(
Ilustração )
Os desenvolvedores sênior da web Anton e Alexei continuam a história da difícil luta com o Nuxt. Na rodada anterior da batalha contra essa estrutura, eles mostraram como iniciar um projeto no Nuxt para que todos ficassem felizes. Em um novo artigo, falaremos sobre a aplicação real do framework.Começamos a reescrever o projeto com uma enorme dívida técnica. O público mensal era de 6 a 7 milhões de visitantes únicos, mas a plataforma existente causou muitos problemas. Portanto, decidiu-se mandá-la para a aposentadoria. Obviamente, o desempenho era a nossa maior preocupação, mas eu também não queria desperdiçar SEO.
Após algumas rodadas de discussão, eles decidiram não confiar na abordagem tradicional apenas com a renderização do lado do servidor - mas não se prender na renderização do lado do cliente. Como resultado, começamos a criar uma solução baseada no
Nuxt.js.Bom velho Nuxt.js
Adotamos a “estrutura para estrutura” baseada no
Vue.js, já conhecida
no último artigo, para a criação de aplicativos cliente-servidor universais. No nosso caso, o aplicativo trabalha em conjunto com uma API bastante complicada (os meandros dos microsserviços, mas sobre isso em outro momento) e várias camadas de cache, torna o conteúdo editável pelos editores e retorna o conteúdo já estático para um desempenho extremamente rápido. Ótimo, certo?
De fato, não há nada de novo aqui. Mas o que torna o Nuxt.js interessante é a capacidade de iniciar rapidamente um projeto com a renderização cliente-servidor. Às vezes você precisa ir contra a estrutura estabelecida da estrutura. Foi o que fizemos.
Não há tempo para explicar, crie uma vez, implante muitos!
Um dia, um techlide se aproximou de nós e ficou intrigado: sempre que fazemos alterações no repositório, precisamos construir cada um dos ambientes (ambientes de desenvolvimento, palco e prod) separadamente. Foi lento. Mas qual é a diferença entre essas construções? Sim, apenas em variáveis de ambiente! E o que ele pediu para fazer parecia lógico e razoável. Mas nossa primeira reação foi: O_o
A estratégia Build, uma vez implantada, faz sentido no mundo do desenvolvimento de software. Mas no mundo do Javascript ... Temos uma bateria inteira de compiladores, transpilers, pré e pós-processadores, além de testes e linters. Tudo isso leva tempo para configurá-los para cada um dos ambientes. Além disso, existem muitos problemas em potencial de vazamento de dados confidenciais (segredos, chaves de API etc.) que podem ser armazenados em configurações.
E começamos
Obviamente, começamos com uma pesquisa no Google. Depois conversamos com os mantenedores do Nuxt.js, mas sem muito sucesso. O que fazer - eu tive que criar uma solução sozinha e não copiá-la do StackOverflow (essa é a base da nossa atividade, certo?).
Vamos descobrir como o Nuxt.js faz isso.
O Nuxt.js possui um arquivo de configuração com o nome esperado nuxt.config.js. É usado para transferir programaticamente configurações para o aplicativo:
const config = require('nuxt.config.js') const nuxt = new Nuxt(config)
É possível definir o ambiente através de variáveis env. Em geral, uma prática bastante comum é conectar o arquivo de configuração dinamicamente. Então tudo isso é transferido para o webpack definePlugin e pode ser usado no cliente e no servidor, algo como isto:
process.env.propertyName
// ou
context.env.propertyName.
Essas variáveis são
ativadas durante a montagem, mais informações aqui:
página env do Nuxt.js.Você notou o webpack? Sim, isso significa compilação, e não é isso que queremos.
Vamos tentar de forma diferente
Entender como o Nuxt.js funciona significa para nós:
- não podemos mais usar o env dentro do nuxt.config.js;
- quaisquer outras variáveis dinâmicas (por exemplo, dentro de head.meta) devem ser passadas para o objeto nuxt.config.js em tempo de execução.
Código no server / index.js:
const config = require('../nuxt.config.js')
Mude para:
Onde utils / extendedNuxtConfig.js:
import config from 'config' import get from 'lodash/get'
Nós nem percebemos o elefante
Bem, resolvemos o problema de obter variáveis dinâmicas fora da propriedade env do objeto de configuração no nuxt.config.js. Mas o problema original ainda não está resolvido.
Havia uma suposição de que algum resumo do sharedEnv.js seria usado para:
- cliente - crie um arquivo env.js que será baixado globalmente (window.env.envKey),
- servidor - é importado para os módulos, quando necessário,
- código isomórfico, algo como
context.isClient? window.env [chave]: global.sharedEnv [chave].
De alguma forma, não é ótimo. Essa abstração resolveria o problema mais sério - o vazamento de dados confidenciais no aplicativo cliente, pois seria necessário agregar o valor conscientemente.
A Vuex nos ajudará
Ao investigar o problema, percebemos que o repositório Vuex é exportado para um objeto de janela. Essa solução é forçada a suportar o isomorfismo de Nuxt, js. O Vuex é um data warehouse inspirado no Flux, projetado especificamente para aplicativos Vue.js.
Bem, por que não usá-lo para nossas variáveis compartilhadas? Essa é uma abordagem mais orgânica - os dados em um repositório global nos convêm.
Vamos começar com server / utils / sharedEnv.js:
import config from 'config' const sharedEnv = {
O código acima será executado durante a inicialização do servidor. Em seguida, adicione-o ao repositório Vuex:
const getSharedEnv = () => process.server ? require('~/server/utils/sharedEnv').default || {} : {}
Vamos confiar no fato de que o nuxtServerInit é iniciado durante, hmm, a inicialização do servidor. Há alguma dificuldade: preste atenção ao método getSharedEnv, aqui verifique se a execução repetida no servidor foi adicionada.
O que aconteceu
Agora temos variáveis comuns que podem ser extraídas em componentes como este:
this. $ store.state.sharedEnv.canonicalDomain
Vitória!Oh não. E os plugins?
Alguns plug-ins requerem variáveis de ambiente para serem configurados. E quando queremos usá-los:
Vue.use (MyPlugin, {someEnvOption: 'Não há acesso ao repositório vuex'})
Ótimo, condição de corrida, o Vue.js tenta se inicializar antes que o Nuxt.js registre sharedEnvobject no repositório do Vuex.
Embora a função que registra plug-ins forneça acesso ao objeto Context que contém o link do repositório, sharedEnv ainda está vazio. Isso é resolvido de maneira simples - vamos tornar o plug-in uma função assíncrona e aguardar a execução do nuxtServerInit:
import Vue from 'vue' import MyPlugin from 'my-plugin' export default async (context) => {
Agora é a vitória.