PHP

25 out, 2019

Criando seu primeiro App com Symfony e Vue.js usando o Webpack

Publicidade

Neste tutorial, mostrarei como configurar um aplicativo robusto e moderno usando Symfony e Vue.js, descomplicando as coisas quando há a dependência entre bibliotecas.

Integrando o Webpack – um empacotador de módulos estáticos para aplicações JavaScript modernas – através do wrapper Webpack do Symfony, o Encore do Symfony, que é um gerador de configuração para Webpack; uma API simples de um dos melhores frameworks PHP, ampliando as possibilidade dentro do controle total sobre a configuração: da estrutura de diretórios às bibliotecas externas, quase tudo pode ser personalizado.

Quando acoplado ao Vue.js, uma estrutura JavaScript para construir interfaces com o usuário, o Symfony se torna um grande concorrente para o fornecimento de aplicativos sofisticados.

Pré-requisito

Para entender esse artigo é importante que você já tenha experiência básica com a criação de projeto com o framework Symfony utilizando o Composer, e o básico sobre Vue.js usando o sistema Ubuntu.

Nós utilizaremos o Composer para criar o projeto Symfony com a estrutura básica; e para adicionar o Vue.js ao projeto, utilizaremos o Yarn – gerenciador de pacotes para Javascript – que funciona exatamente como o NPM e o Bower, abrangendo, inclusive, as bibliotecas que estão presentes nestes gerenciadores.

Versões utilizadas:

PHP 7.2.19 – https://www.php.net/manual/pt_BR/install.php

Composer 1.7.3 – https://getcomposer.org/download/

Node.js 10.16.3  – https://github.com/nodesource/distributions/blob/master/README.md#installation-instructions

Yarn 1.17.3 ou superior – https://yarnpkg.com/lang/pt-br/docs/install/#debian-stable

Versão das estruturas do aplicativo:

Symfony 4.3 – que será instalado via Composer

Vue.js 2.6.10 – que será adicionado ao projeto por meio do Yarn

Criando o projeto com estrutura mínima

Quando vamos trabalhar com API, console application, microservices ou uma aplicação web pequena, geralmente não precisamos de todos os recursos disponibilizados para uma estrutura de um projeto em Symfony. Para iniciarmos, crie o diretório:

$ mkdir meu-projeto && cd meu-projeto 

Para criar o novo aplicativo Symfony usando o Composer com uma estrutura enxuta, execute o comando logo abaixo. Não esqueça o ponto (.) para que se monte a estrutura dentro do diretório do projeto, no caso meu-projeto:

$ composer create-project symfony/skeleton . 

Veja, uma estrutura enxuta, com poucas dependências declaradas no composer.json:

...

   "require": {
        "php": "^7.1.3",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "symfony/console": "4.3.*",
        "symfony/dotenv": "4.3.*",
        "symfony/flex": "^1.3.1",
        "symfony/framework-bundle": "4.3.*",
        "symfony/yaml": "4.3.*"
    },

…

Symfony – Controller e View

Precisamos de uma interface do cliente. A página que exibirá nosso aplicativo Vue.js precisará de uma configuração de rota, e isso pode ser feito adicionando o código abaixo ao arquivo config/routes.yaml. Observe que este arquivo indica que determinado padrão de URL deve ser direcionado para o método index do controlador.

index:
    path: /
    controller: App\Controller\IndexController::index

Onde está esse controlador? Ele precisa ser criado! Com o nome IndexController.php em src/Controller. Seu conteúdo deve ser este:


<?php
    
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class IndexController extends AbstractController
{

    public function index()
    {
        return $this->render('index.html.twig');
    }
}

O método index() da classe IndexController renderizará um template. Precisaremos instalar o Twig, que é um mecanismo de templating poderoso e flexível, desenvolvido pelo SensioLabs. 

Em nosso projeto, em vez de começarmos com um aplicativo volumoso com todos os recursos possíveis que você possa precisar, nós começamos com um aplicativo Symfony pequeno, simples e rápido. Sendo assim, cada pacote precisa ser instalado conforme caminhamos; no controle total do que adicionar. 

Vamos instalar o Twig via Composer:

$  composer require twig

Podemos agora criar templates Twig dentro do novo diretório templates. Temos que criar o arquivo index.html.twig com o conteúdo:

{% extends 'base.html.twig' %}

{% block title %} Seja bem-vindo !{% endblock %}
{% block body %}
	<h1>Seja bem-vindo!</h1>
	<div id="app"></div>
{% endblock %}

Para auxiliar no desenvolvimento, dentro da pasta do projeto rode o servidor web embutido do PHP. Especificando a raiz de documento explicitamente, com a opção -t

$ php -S localhost:8000 -t public 

Já é possível visualizar algo acessando localhost:8000.

Continuando, precisaremos editar o arquivo base.html.twig, que explicarei logo a seguir. Veja como ficou:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>{% block title %}{% endblock %}</title>
        {% block stylesheets %}
            {{ encore_entry_link_tags('app') }}
        {% endblock %}
    </head>
    <body>
        {% block body %}{% endblock %}
        {% block javascripts %}
            {{ encore_entry_script_tags('app') }}
        {% endblock %}
    </body>
</html>

Explicando o código

Você pode precisar de várias tags script e link em seu modelo. Para resolver esse problema, o Encore gera um novo arquivo entrypoints.js que contém todos os arquivos JavaScript e CSS necessários para cada “entrada”. Sendo as funções do Twig, encore_entry_link_tags() e encore_entry_script_tags() as responsáveis por gerarem as URLs relativas. Se você atualizar o URL localhost:8000 um erro será exibido, pois ainda não existe o entrypoints.js no projeto. Erro:

An exception has been thrown during the rendering of a template (“Could not find the entrypoints file from Webpack: the file “/home/code/www/meu-projeto/public/build/entrypoints.json” does not exist.”).

Como o Encore não está instalado e rodando, nenhum dos dois arquivos de configuração foram gerados: entrypoints.json e manifest.json. O primeiro arquivo – entrypoints.json – é usado pelos encore_entry_script_tags() e encore_entry_link_tags() Twig helpers. Se você os estiver usando, seus arquivos CSS e JavaScript serão renderizados com o novo nome de arquivo versionado, como veremos mais à frente.

Webpack Encore – Adicionando o Vue.js ao projeto

Para termos os recursos do Vue.js, precisamos adicioná-lo ao projeto. O Symfony vem com uma biblioteca de JavaScript puro – chamada Webpack Encore – que torna o trabalho com CSS e JavaScript muito mais inteligente. O Webpack Encore é uma maneira mais simples de integrar o Webpack ao seu aplicativo. Em sua essência, o webpack é um empacotador de módulos estáticos para aplicativos JavaScript modernos. Quando o webpack processa seu aplicativo, ele cria internamente um gráfico de dependência que mapeia todos os módulos de que seu projeto precisa e gera um ou mais pacotes configuráveis. Até aqui pode parecer um exagero, mas no geral é tudo bem rápido. Quando se tem contato pela primeira vez, é preciso esmiuçar esses conceitos.

Instale o WebPack Encore ao projeto Symfony executando o comando abaixo:

$ composer require encore

Visualize o arquivo package.json que foi gerado.

{
    "devDependencies": {
        "@symfony/webpack-encore": "^0.28.0",
        "core-js": "^3.0.0",
        "regenerator-runtime": "^0.13.2",
        "webpack-notifier": "^1.6.0"
    },
    "license": "UNLICENSED",
    "private": true,
    "scripts": {
        "dev-server": "encore dev-server",
        "dev": "encore dev",
        "watch": "encore dev --watch",
        "build": "encore production --progress"
    }
}

Instale as dependências – o gerenciador de pacotes

O próximo passo será instalar todas as dependências listadas no package.json; e o Yarn é uma maneira que temos de agilizar a instalação de algumas dependências. Há um número crescente de diferentes maneiras de instalar o Yarn, você pode simplesmente usar o comando npm para isso, porém recomendo seguir os passos listados no site oficial. Link no início do artigo, em pré-requisito.

Tudo certo, Yarn rodando, vamos para o comando:

$ yarn install

Isso é mais comumente usado logo após você baixar o código de um projeto ou quando outro desenvolvedor adicionou uma dependência nova que você precisa baixar; assim, instala todas as dependências listadas no package.json em sua pasta local node_modules. Agora vamos adicionar os pacotes necessários para o Vue.js:

$ yarn add vue vue-loader vue-template-compiler

Precisamos ativar o carregador Vue, para que qualquer arquivo componente .vue possa ser compilado. Para isso use o ponto de entrada, que indica qual módulo o webpack deve usar para iniciar a construção do gráfico interno de dependência. O webpack.config.js aceita múltiplos pontos de entrada. Abra o arquivo webpack.config.js e adicione .enableVueLoader() logo após a linha que contém .enableSingleRuntimeChunk() 

// but, you probably want this, unless you're building a single-page app
.enableSingleRuntimeChunk()
.enableVueLoader()
Com servidor interno do PHP rodando, php -S localhost:8000 -t public. Abra uma outra aba no terminal e execute o comando:
$ yarn encore dev-server

Com seu arquivo entrypoints.json gerado, ao atualizar a página, a mensagem de erro de exceção deixa de ser exibida e ao olharmos o código-fonte da página, podemos perceber que os helpers serviram nossa página; o encore_entry_script_tags() adicionou corretamente os Js.

Ao introduzir um sistema de “compilação” para JavaScript, como estamos fazendo, sempre que você altera um arquivo .vue, é necessário executar novamente o Encore. Porém, segundo a documentação do Symfony, durante o desenvolvimento, em vez de usar yarn encore dev –watch, você pode usar o yarn encore dev-server.

Atualizando instantaneamente o navegador quando forem feitas modificações no CSS/JS no código-fonte, o que é quase comparável à mudança de estilos diretamente nas ferramentas de desenvolvimento do navegador. Então no terminal Linux, geralmente deixo uma nova aba e rodo o comando. Mas adiante, ao criar e modificar seus componentes .vue isso será melhor entendido.

Vue – Modo básico

Logo a seguir, temos o exemplo mais básico do uso do Vue.js, aplicado a um arquivo HTML. A página deve mostrar uma mensagem “Hello World!”.

<html>
  <body>
    <div id="example">
      <p>{{ hello }}</p>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script>
        new Vue({
            el: '#example',
            data: { hello: 'Hello World!' }
        })
    </script>
  </body>
</html>

Vamos subir o nível e trabalhar criando componentes. Enquanto o Symfony cuidará de todas as operações de back-end, o Vue.js cuidará da renderização DOM do front-end. 

Diretório para os componentes

Trabalharemos com componentes de arquivo único, de extensão .vue que contém 3 partes de código: HTML, CSS e JavaScript. Pode parecer complicado, mas os componentes de arquivo único são uma ótima maneira de criar componentes independentes que têm tudo o que precisam em um único arquivo. Criaremos um componente principal App.vue para o aplicativo hospedar nossos outros componentes, como por exemplo o componente OlaMsg.vue. Antes, é preciso criar uma pasta chamada components em assets/js, ficando assim: assets/js/components. Em seguida, crie os arquivos App.vue e OlaMsg.vue na pasta components que você acabou de criar. Veja como é uma estrutura básica para os arquivos do tipo .vue:

<template>
...
</template>

<script>
...
</script>

<style>
...
</style>

Instância Vue

Toda aplicação Vue é iniciada com a criação de uma nova instância Vue, a função Vue. Precisamos reconhecer os componentes e para isso, abra e adicione o código abaixo ao arquivo: assets/js/app.js 

import Vue from 'vue';
import App from './components/App';

Vue.config.productionTip = false

new Vue({
  el: '#app',
  components: { App },
  template: '<App/>'
})

Os componentes

Lembre-se que componente .vue contém 3 partes de código: HTML, CSS e JavaScript. 

Essa é a estrutura básica da aparência de um componente de arquivo único. Colocaremos a marcação HTML na <template>, nosso código JavaScript na <script> e nossos estilos na seção <styles>. E o que nós queremos? Uma aplicação que nos exiba uma mensagem “Olá! Aqui está seu aplicativo Vue.js”. E quem definirá a mensagem será o componente OlaMsg.vue, sendo o App.vue o componente principal. Nós importaremos o componente OlaMsg.vue, que será referenciado em nosso App.vue. É uma dependência, e as coisas ficam mais interessante para o tutorial. Veja como ficará o conteúdo dos arquivos.

Você preencherá o arquivo App.vue com o seguinte conteúdo:

<template>
    <div>
        <h1><span>Minha página inicial</span></h1>
        <ola-msg></ola-msg>
    </div>    
</template>

<!-- componente OlaMsg incluído -->
<script>
    import OlaMsg from './OlaMsg';
    export default {
        name: 'App',
        components: {
            OlaMsg
        }
    }
</script>

<!-- adicione o atributo “scoped” para limitar o CSS apenas a este componente -->
<style scoped>
    span {  color: chocolate;  }
</style>

Segundo o documento guia do Vue, nomes de componentes devem ser sempre multi-palavras, exceto pelo componente App raiz e componentes internos fornecidos pelo Vue. Isto previne conflitos com elementos HTML existentes e futuros, visto que todos os elementos HTML são formados por apenas uma única palavra. Em nosso App.vue, utilizamos a tag <ola-msg>, relacionado ao componente a ser incluído e nomeado como OlaMsg.vue.

Com servidor interno do PHP rodando e seus built assets sendo servidos pelo Encore. Invoque o URL localhost:8000. Você verá a primeira mudança, o texto “Minha página inicial”.

Seguindo, você preencherá o arquivo OlaMsg.vue com o seguinte conteúdo:

<template>
    <h2>
        <span>
            {{ msg }}
        </span>
    </h2>
</template>

<script>
    export default {
    name: 'OlaMsg',
    data() {
        return {
        	msg: 'Olá! Aqui está seu aplicativo Vue.js'
        }
    }
    }
</script>

<!-- adicione o atributo “scoped” para limitar o CSS apenas a este componente -->
<style scoped>
    span {  color: blue;  }
</style>

Invoque o URL localhost:8000. E, Shazam!!! Olá! Aqui está seu aplicativo Vue.js.

Finalizando

Vale lembrar que o comando yarn encore dev-server, serve os recursos construídos e realmente não grava nenhum arquivo compilado CSS e JS em disco. Não à toa que se você cancelar(Ctrl+C) o serviço webpack-dev-server, que está rodando, o projeto não exibirá na tela os recursos disponibilizados pelos seus componentes Vue, somente o conteúdo do template Twig. Porém ao final do projeto, você pode rodar:
$ yarn run encore production

Files written to public/build – Depois de executar o Encore “production”, 100% dos arquivos que você precisa estarão em public/build. Qualquer alteração feita em seus componentes, não serão atualizadas. Sendo necessário voltar ao modo de desenvolvimento: yarn encore dev-server.

Se desejar o código, você pode ir até o meu repositório no GitHub – https://github.com/fabianofm/symfony-vue-imasters

“A satisfação está no esforço e não apenas na realização final.” ― Mahatma Gandhi

Abraços, até a próxima.

Referências

https://symfony.com/doc/current/frontend/encore/dev-server.html

https://symfony.com/doc/current/frontend/encore/versioning.html#load-manifest-files
https://br.vuejs.org/v2/style-guide/index.html
https://yarnpkg.com/lang/pt-br/docs/cli/install/
https://webpack.js.org/concepts/