# Configuração da Compilação
A configuração do webpack para um projeto SSR será semelhante a um projeto client-only. Se você não estiver familiarizado com a configuração do webpack, poderá encontrar mais informações na documentação do Vue CLI (opens new window) ou configurando o Vue Loader manualmente (opens new window).
# Principais Diferenças com Compilações Client-Only
- Precisamos criar um manifest do webpack (opens new window) para nosso código do lado do servidor. Este é um arquivo JSON que o webpack mantém para rastrear como todos os módulos são mapeados para os pacotes finais. 
- Devemos externalizar dependências de aplicativos (opens new window). Isso torna a compilação do servidor muito mais rápida e gera um arquivo de pacote menor. Ao fazer isso, temos que excluir dependências que precisam ser processadas pelo webpack (como arquivos - .css. ou- .vue).
- Precisamos alterar o target (opens new window) do webpack para Node.js. Isso permite que o webpack lide com importações dinâmicas de maneira apropriada ao Node, e também diz ao - vue-loaderpara emitir código orientado ao servidor ao compilar componentes Vue.
- Ao construir uma entrada de servidor, precisaríamos definir uma variável de ambiente para indicar que estamos trabalhando com SSR. Pode ser útil adicionar alguns - scriptsao- package.jsondo projeto:
"scripts": {
  "build:client": "vue-cli-service build --dest dist/client",
  "build:server": "SSR=1 vue-cli-service build --dest dist/server",
  "build": "npm run build:client && npm run build:server",
}
2
3
4
5
# Exemplo de Configuração
Abaixo está um vue.config.js de exemplo que adiciona renderização SSR a um projeto Vue CLI, mas pode ser adaptado para qualquer compilação com webpack.
const { WebpackManifestPlugin } = require('webpack-manifest-plugin')
const nodeExternals = require('webpack-node-externals')
const webpack = require('webpack')
module.exports = {
  chainWebpack: webpackConfig => {
    // Precisamos desabilitar o cache loader, caso contrário a compilação do cliente
    // usará componentes em cache da compilação do servidor
    webpackConfig.module.rule('vue').uses.delete('cache-loader')
    webpackConfig.module.rule('js').uses.delete('cache-loader')
    webpackConfig.module.rule('ts').uses.delete('cache-loader')
    webpackConfig.module.rule('tsx').uses.delete('cache-loader')
    if (!process.env.SSR) {
      // Aponta a entrada para o arquivo de entrada do cliente do seu aplicativo
      webpackConfig
        .entry('app')
        .clear()
        .add('./src/entry-client.js')
      return
    }
    // Aponta a entrada para o arquivo de entrada do servidor do seu aplicativo
    webpackConfig
      .entry('app')
      .clear()
      .add('./src/entry-server.js')
    // Permite que o webpack lide com importações dinâmicas ao estilo Node
    // e também diz ao `vue-loader` para emitir código orientado ao servidor ao
    // compilar componentes Vue.
    webpackConfig.target('node')
    // Isso diz ao pacote do servidor para usar exportações no estilo Node
    webpackConfig.output.libraryTarget('commonjs2')
    webpackConfig
      .plugin('manifest')
      .use(new WebpackManifestPlugin({ fileName: 'ssr-manifest.json' }))
    // https://webpack.js.org/configuration/externals/#function
    // https://github.com/liady/webpack-node-externals
    // Externaliza dependências do app. Compila a parte do servidor mais rápido
    // e gera um arquivo de pacote menor.
    // Não externalize dependências que precisam ser processadas pelo webpack.
    // Você deve permitir deps que modificam o `global` (ex.: polyfills)
    webpackConfig.externals(nodeExternals({ allowlist: /\.(css|vue)$/ }))
    webpackConfig.optimization.splitChunks(false).minimize(false)
    webpackConfig.plugins.delete('preload')
    webpackConfig.plugins.delete('prefetch')
    webpackConfig.plugins.delete('progress')
    webpackConfig.plugins.delete('friendly-errors')
    webpackConfig.plugin('limit').use(
      new webpack.optimize.LimitChunkCountPlugin({
        maxChunks: 1
      })
    )
  }
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# Limitações do Externals
Observe que na opção externals estamos permitindo arquivos CSS. Isso ocorre porque o CSS importado das dependências ainda deve ser tratado pelo webpack. Se estiver importando qualquer outro tipo de arquivo que também dependa do webpack (ex.: *.vue, *.sass), você deve adicioná-los à lista de permissões também.
Se estiver usando runInNewContext: 'once' ou runInNewContext: true, então você também precisa colocar polyfills na lista de permissões que modificam global, ex.: babel-polyfill. Isso ocorre porque ao usar o novo modo de contexto, o código dentro de um pacote de servidor tem seu próprio objeto global. Como você realmente não precisa disso no servidor, é mais fácil importá-lo na entrada do cliente.
# Gerando clientManifest
 Além do pacote do servidor, também podemos gerar um manifesto da compilação do cliente. Com o manifesto do cliente e o pacote do servidor, o renderizador agora tem informações das compilações do servidor e do cliente. Dessa forma, ele pode inferir e injetar automaticamente diretivas de preload / prefetch (opens new window), tags <link> e <script> no HTML renderizado.
Os benefícios são duplos:
- Ele pode substituir o - html-webpack-pluginpara injetar os URLs de assets corretos quando houver hashes em seus nomes de arquivos gerados.
- Ao renderizar um pacote que aproveita os recursos de divisão de código sob demanda do webpack, podemos garantir que os fragmentos ideais sejam preloaded / prefetched e também injetar de forma inteligente as tags - <script>para os fragmentos assíncronos necessários e evitar solicitações em cascata no cliente, assim melhorando o TTI (time-to-interactive).
