Slide 1

Slide 1 text

Marcel Gonçalves dos Santos @marcelgsantos Symfony Encore gerenciando assets com

Slide 2

Slide 2 text

pensandonaweb.com.br desenvolvedor web full-stack Marcel Gonçalves dos Santos @marcelgsantos

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

@femugsp sp.femug.com

Slide 5

Slide 5 text

@phpsp phpsp.org.br bit.ly/vemproslackphpsp

Slide 6

Slide 6 text

Interaja nas mídias sociais!
 
 - fale sobre o evento, palestrantes e conteúdo - tire fotos do evento e publique
 - interaja com outros participantes do evento - tire dúvidas ou dê feedbacks para os palestrantes

Slide 7

Slide 7 text

1. seguir @marcelgsantos no Twitter
 2. tuitar utilizando as hashtags #Symfony_Live, #Encore e #PHP
 3. não vale tuíte em branco e retuíte
 4. ler e preencher este simples formulário
 bit.ly/sorteio-sflive-2019 Concorra a um livro da Casa do Código!

Slide 8

Slide 8 text

O que são assets?

Slide 9

Slide 9 text

os assets são elementos estáticos que compõem uma aplicação web

Slide 10

Slide 10 text

os assets são scripts, folhas de estilos, imagens e fontes

Slide 11

Slide 11 text

O que é genciamento de assets?

Slide 12

Slide 12 text

o gerenciamento de assets é um conjunto de procedimentos realizados sobre os assets…

Slide 13

Slide 13 text

…que os tornam "prontos" para serem utilizados pela sua aplicação

Slide 14

Slide 14 text

assemelha-se a um processo de build

Slide 15

Slide 15 text

JavaScript - module bundling - transpiling - geração de sourcemaps - tree-shaking ou dead code elimination - minificação
 - cache busting

Slide 16

Slide 16 text

CSS - pré-processamento (Sass, Less ou Stylus) - geração de sourcemaps - pós-processamento (vendor-prefixes) - ajustar o caminho de imagens e fontes - minificação - cache busting

Slide 17

Slide 17 text

imagens e fontes - otimização de imagens (redução da
 qualidade e remoção de metadados) - codificação em base64 - cache busting

Slide 18

Slide 18 text

gerais - copiar e remover arquivos - notificar processo de compilação - atualizar o navegador (após salvar)

Slide 19

Slide 19 text

todos estes procedimentos fazem parte de um desenvolvimento front-end robusto e moderno

Slide 20

Slide 20 text

Um pouco da história do front-end

Slide 21

Slide 21 text

o desenvolvimento front-end evoluiu muito nos últimos anos

Slide 22

Slide 22 text

Parte 1 - código JavaScript em um “arquivão” - variáveis globais por todo lado - inclusão manual de bibliotecas - preocupação com a ordem de inclusão - vários pontos de entrada na aplicação - pouca preocupação com versionamento
 - minificação manual ou inexistente

Slide 23

Slide 23 text

Problemas - tudo!

Slide 24

Slide 24 text

Parte 2 - organização em módulos (revealing 
 module pattern) - simulação de namespaces (com objetos)
 - gerenciamento de dependências
 - concatenação de módulos
 - melhor organização de códigos

Slide 25

Slide 25 text

Problemas - concatenação de módulos de 
 forma manual e propensa a erros
 - gerenciamento de dependências imaturo

Slide 26

Slide 26 text

Parte 3 - organização em módulos (CommonJS e AMD) - gerenciamento de dependências ganhando
 maturidade (NPM)
 - resolução de dependências automatizada 
 (Browserify e Require.js)
 - automação de tarefas com Gulp

Slide 27

Slide 27 text

Problemas - especificação de módulos oficial ainda
 pouco utilizada
 - muitas bibliotecas sem suporte 
 (necessidade de utilização de Shims)

Slide 28

Slide 28 text

Parte 4 - organização em módulos (ES2015) - gerenciamento de dependências maduro 
 e robusto (NPM e Yarn)
 - resolução de dependências automatizada
 (Webpack)
 - automação de tarefas com NPM Scripts

Slide 29

Slide 29 text

Problemas - dificuldade na compreensão de inúmeros termos e ferramentas
 - configuração complicada do Webpack

Slide 30

Slide 30 text

loader: "babel-loader", options: { presets: ['env'] } } }, "//html-loader { test: /\.html$/, use: ['html-loader'] } ] }, plugins: [ new CleanWebpackPlugin(['dist']), "//html-webpack-plugin instantiation new HtmlWebpackPlugin({ template: 'index.html' }) ], devServer: { contentBase: path.resolve("__dirname, "./dist/assets/media"), compress: true, port: 12000, stats: 'errors-only', open: true }, devtool: 'inline-source-map' } module.exports = config;

Slide 31

Slide 31 text

O que é Webpack?

Slide 32

Slide 32 text

o Webpack é um module bundler, ou seja, uma ferramenta que empacota o seu código JavaScript e CSS

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

a sua instalação é feita através do NPM

Slide 35

Slide 35 text

O que é Node.js e NPM?

Slide 36

Slide 36 text

o Node.js é uma plataforma que permite a execução de código JavaScript no back-end

Slide 37

Slide 37 text

o Node.js é o V8 (engine JavaScript do Chrome) + biblioteca padrão + event loop

Slide 38

Slide 38 text

o NPM é o gerenciador de dependências do mundo JavaScript

Slide 39

Slide 39 text

ele é utilizado tanto para o back-end quanto para o front-end

Slide 40

Slide 40 text

O que é o Symfony Encore?

Slide 41

Slide 41 text

o Symfony Encore é um gerador de configuração para o Webpack

Slide 42

Slide 42 text

ele envolve o Webpack e fornece uma API simples e poderosa para o gerenciamento de assets

Slide 43

Slide 43 text

var Encore = require('@symfony/webpack-encore'); Encore .setOutputPath('public/build') .setPublicPath('/build') .addEntry('app', './assets/js/app.js'); module.exports = Encore.getWebpackConfig();

Slide 44

Slide 44 text

ele é inspirado pelo Webpacker e Mix, porém preserva o espírito do Webpack usando suas funcionalidades, conceitos e convenções

Slide 45

Slide 45 text

foi feito pela Symfony e funciona perfeitamente com o Symfony ❤

Slide 46

Slide 46 text

ele é uma biblioteca JavaScript, porém, que pode ser instalado através do Composer

Slide 47

Slide 47 text

composer require encore

Slide 48

Slide 48 text

No content

Slide 49

Slide 49 text

ao ser instalado pelo Composer, obtém-se os arquivos package.json e webpack.config.js e um diretório assets

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

deve-se executar npm install para a instalação do Webpack Encore e suas dependências

Slide 52

Slide 52 text

npm install

Slide 53

Slide 53 text

as dependências são instaladas em um diretório node_modules e as dependências são registradas no package.json

Slide 54

Slide 54 text

o arquivo package.json possui a dependência @symfony/webpack-encore e contém scripts como dev-server, dev, watch e build

Slide 55

Slide 55 text

{ "devDependencies": { "@symfony/webpack-encore": "^0.27.0", "core-js": "^3.0.0", "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" } }

Slide 56

Slide 56 text

o arquivo webpack.config.js é o arquivo de configuração do Webpack

Slide 57

Slide 57 text

var Encore = require('@symfony/webpack-encore'); Encore .setOutputPath('public/build') .setPublicPath('/build') .addEntry('app', './assets/js/app.js'); module.exports = Encore.getWebpackConfig();

Slide 58

Slide 58 text

o arquivo webpack.config.js fornecido pelo Encore é muito bem documentado

Slide 59

Slide 59 text

"// enables Sass/SCSS support "//.enableSassLoader() "// uncomment if you use TypeScript "//.enableTypeScriptLoader() "// uncomment to get integrity="""..." attributes on your script & link t "// requires WebpackEncoreBundle 1.4 or higher "//.enableIntegrityHashes() "// uncomment if you're having problems with a jQuery plugin "//.autoProvidejQuery() "// uncomment if you use API Platform Admin (composer req api-admin) "//.enableReactPreset() "//.addEntry('admin', './assets/js/admin.js') ; module.exports = Encore.getWebpackConfig();

Slide 60

Slide 60 text

Utilização de módulos em JavaScript

Slide 61

Slide 61 text

o JavaScript evoluiu e projetos passaram a ser organizados em módulos ao invés de apenas um arquivo

Slide 62

Slide 62 text

módulos em JavaScript podem conter classes, funções, objetos e variáveis que existem apenas no escopo do módulo

Slide 63

Slide 63 text

para torná-los utilizáveis fora do escopo do módulo deve-se exportar o que é desejado

Slide 64

Slide 64 text

import $ from 'jquery'; import Utils from './helpers/utils'; class Subscription { constructor(container) { let $container = $(container); this.$form = $container.find('#subscription-form'); } init() { this.$form.find('#cep').on('blur', this.findAddress.bind(this)); this.$form.find('#query').on('click',this.findAddress.bind(this)); } "// findAddress implementation""... } export default Subscription;

Slide 65

Slide 65 text

pode-se instalar qualquer biblioteca utilizando o NPM para gerenciamento de dependências

Slide 66

Slide 66 text

npm install jquery

Slide 67

Slide 67 text

os módulos instalados via NPM são referenciado pelo nome e módulos da aplicação são iniciados com ./

Slide 68

Slide 68 text

import $ from 'jquery'; import Subscription from ‘./components/subscription';

Slide 69

Slide 69 text

var Encore = require('@symfony/webpack-encore'); Encore .setOutputPath('public/build') .setPublicPath('/build') .addEntry('app', './assets/js/app.js'); module.exports = Encore.getWebpackConfig();

Slide 70

Slide 70 text

./node_modules/.bin/encore dev

Slide 71

Slide 71 text

{ "devDependencies": { "@symfony/webpack-encore": "^0.27.0", "core-js": "^3.0.0", "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" } }

Slide 72

Slide 72 text

npm run dev

Slide 73

Slide 73 text

Gerar um bundle com múltiplos arquivos

Slide 74

Slide 74 text

ao gerar o bundle o Webpack pode gerar mais de um arquivo de bundle

Slide 75

Slide 75 text

a funcionalidade do Encore que permite esse comportamento é splitEntryChunks()

Slide 76

Slide 76 text

var Encore = require('@symfony/webpack-encore'); Encore .setOutputPath('public/build') .setPublicPath('/build')
 .splitEntryChunks() .addEntry('app', './assets/js/app.js'); module.exports = Encore.getWebpackConfig();

Slide 77

Slide 77 text

os arquivos gerados podem ser, por exemplo, vendors-app.js e app.js

Slide 78

Slide 78 text

o arquivo vendors-app.js contém o código de vendors importados como jQuery e Bootstrap

Slide 79

Slide 79 text

para fazer parte do bundle de vendors deve satisfazer algumas condições como estar em node_modules e ser maior que 30kB

Slide 80

Slide 80 text

e por que o Webpack faz a seperação de arquivos de bundle?

Slide 81

Slide 81 text

para fazer o cache de arquivos de terceiros por um longo período de tempo

Slide 82

Slide 82 text

porém, torna um pouco mais complicado para incluir tags de script e style no HTML

Slide 83

Slide 83 text

para facilitar a inclusão de tags script e style no HTML, o Encore fornece funções helpers

Slide 84

Slide 84 text

encore_entry_link_tags('app') encore_entry_script_tags('app')

Slide 85

Slide 85 text

{% block title %}Welcome to SymfonyLive Brasil '19{% endblock %} " {% block stylesheets %} {{ encore_entry_link_tags('app') }} {% endblock %} " """
 {% block javascripts %} {{ encore_entry_script_tags('app') }} {% endblock %} " "

Slide 86

Slide 86 text

o Encore sabe quais arquivos precisam ser incluídos através do arquivo entrypoints.json

Slide 87

Slide 87 text

ele é apenas um mapeamento para cada entrypoint correspondente em JavaScript e CSS

Slide 88

Slide 88 text

{ "entrypoints": { "app": { "js": [ "/build/vendors~app.js", "/build/app.js" ], "css": [ "/build/app.css" ] } } }

Slide 89

Slide 89 text

o Webpack possui um modo watch que permite ouvir alterações no sistema de arquivos e iniciar a execução

Slide 90

Slide 90 text

npm run watch

Slide 91

Slide 91 text

Utilização de pré-processadores em CSS

Slide 92

Slide 92 text

a utilização de pré-processadores CSS como Sass, Less ou Stylus é importante para projeto front-end moderno

Slide 93

Slide 93 text

essas ferramentas traz mais poder, flexibilidade e produtividade

Slide 94

Slide 94 text

"// Sass utilities @import "helpers/variables"; @import "helpers/functions"; @import "helpers/mixins"; @import "helpers/placeholders"; "// Vendors and external stylesheets @import "vendors/slider"; @import "vendors/tipsy"; "// Base stuff @import "base/reset"; @import "base/typography"; "// Layout related stylesheets @import "layout/site/header"; @import "layout/site/footer"; @import "layout/site/navigation"; @import "layout/site/content"; @import "layout/site/forms";

Slide 95

Slide 95 text

.cart { @extend %clearfix; &-list { display: flex; flex-wrap: wrap; justify-content: center; } &-item { list-style-type: none; margin: 0 10px 15px; max-width: 90px;
 }
 }

Slide 96

Slide 96 text

porém é necessário um processo de build para transformar o código em CSS

Slide 97

Slide 97 text

para habilitar o suporte a Sass no Encore basta utilizar enableSassLoader()

Slide 98

Slide 98 text

var Encore = require('@symfony/webpack-encore'); Encore .setOutputPath('public/build') .setPublicPath('/build')
 .enableSassLoader()
 .splitEntryChunks() .addEntry('app', './assets/js/app.js'); module.exports = Encore.getWebpackConfig();

Slide 99

Slide 99 text

npm install sass-loader node-sass "--save-dev

Slide 100

Slide 100 text

nem todos os módulos são instalados por padrão, isso torna o projeto mais enxuto e dependências são instaladas se necessárias

Slide 101

Slide 101 text

Problemas com bibliotecas antigas

Slide 102

Slide 102 text

as bibliotecas modernas podem ser retornadas de forma global e adicionada no objeto window ou retornada como objeto e atribuída a uma variável local

Slide 103

Slide 103 text

não é uma boa prática utilizar objetos globais em códigos JavaScript

Slide 104

Slide 104 text

porém existem inúmeras bibliotecas que ainda não utilizam a abordagem mais moderna e esperam um objeto global como $ ou jQuery

Slide 105

Slide 105 text

os plugins de jQuery são a maioria destas bibliotecas que possuem práticas antiquadas

Slide 106

Slide 106 text

os plugins de jQuery como o Bootstrap modificam o objeto jQuery e adiciona funcionalidades a ele

Slide 107

Slide 107 text

utiliza-se a funcionalidade autoProvidejQuery() do Encore para corrigir este problema

Slide 108

Slide 108 text

var Encore = require('@symfony/webpack-encore'); Encore .setOutputPath('public/build') .setPublicPath('/build')
 .splitEntryChunks() .autoProvidejQuery() .addEntry('app', './assets/js/app.js'); module.exports = Encore.getWebpackConfig();

Slide 109

Slide 109 text

ele basicamente reescreve o código quebrado para que funcione corretamente

Slide 110

Slide 110 text

Cópia de arquivos e ajuste de caminhos

Slide 111

Slide 111 text

o Encore possui a funcionalidade de cópia de arquivos, ideal para copiar imagens de assets para public

Slide 112

Slide 112 text

var Encore = require('@symfony/webpack-encore'); Encore .setOutputPath('public/build') .setPublicPath('/build')
 .splitEntryChunks() .copyFiles({ from: './assets/images', to: 'images/[path][name].[hash:8].[ext]' }) .addEntry('app', './assets/js/app.js'); module.exports = Encore.getWebpackConfig();

Slide 113

Slide 113 text

o Encore faz a verificação e ajusta os caminhos de imagens e fontes em CSS para o caminho do diretório de saída

Slide 114

Slide 114 text

Build para produção

Slide 115

Slide 115 text

npm run build

Slide 116

Slide 116 text

o build de produção costuma demorar mais que o build de desenvolvimento

Slide 117

Slide 117 text

os arquivos são minificados e não possuem os sourcemaps

Slide 118

Slide 118 text

var Encore = require('@symfony/webpack-encore'); Encore .setOutputPath('public/build') .setPublicPath('/build')
 .splitEntryChunks() .enableSourceMaps(!Encore.isProduction()) .addEntry('app', './assets/js/app.js'); module.exports = Encore.getWebpackConfig();

Slide 119

Slide 119 text

pode-se adicionar um hash no nome dos arquivos de assets para lidar com cache busting

Slide 120

Slide 120 text

var Encore = require('@symfony/webpack-encore'); Encore .setOutputPath('public/build') .setPublicPath('/build')
 .splitEntryChunks() .enableVersioning(true) .addEntry('app', './assets/js/app.js'); module.exports = Encore.getWebpackConfig();

Slide 121

Slide 121 text

var Encore = require('@symfony/webpack-encore'); Encore .setOutputPath('public/build') .setPublicPath('/build')
 .splitEntryChunks() .enableVersioning(Encore.isProduction()) .addEntry('app', './assets/js/app.js'); module.exports = Encore.getWebpackConfig();

Slide 122

Slide 122 text

Conclusão

Slide 123

Slide 123 text

1. utilize um workflow moderno de desenvolvimento front-end com módulos e processo de build 2. deixe tarefas repetitivas para ferramentas como o Webpack 3. utilize o Webpack Encore para facilitar a configuração do Webpack

Slide 124

Slide 124 text

Referências

Slide 125

Slide 125 text

bit.ly/referencias-palestra-encore

Slide 126

Slide 126 text

Avalie!

Slide 127

Slide 127 text

bit.ly/avalie-palestra-encore

Slide 128

Slide 128 text

@marcelgsantos speakerdeck.com/marcelgsantos Obrigado. Perguntas?