SlideShare a Scribd company logo

Keeping the frontend under control with Symfony and Webpack

Ignacio Martín
Ignacio Martín
Ignacio MartínSenior software developer at Limenius

Webpack tutorial with tips for Symfony users. Topics covered include: current frontend trends, setup, loaders, dev tools, optimization in production, bundle splitting and tips and tricks for using webpack with existing projects. Symfony Munich Meetup 2016.

Keeping the frontend under control with Symfony and Webpack

1 of 90
Download to read offline
Keeping the frontend
under control with
Symfony and Webpack
Nacho Martín
@nacmartin
nacho@limenius.com
Munich Symfony Meetup
October’16
I write code at Limenius
We build tailor made projects
using mainly Symfony
and React.js
So we have been figuring out how to organize better
the frontend
Nacho Martín
nacho@limenius.com @nacmartin
Why do we need this?
Assetic?
No module loading
No bundle orientation
Not a standard solution for frontenders
Other tools simply have more manpower
behind
Written before the Great Frontend Revolution
Building the Pyramids: 130K man years
Writing JavaScript: 10 man days
JavaScript

Recommended

Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...Ryan Weaver
 
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and more
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and moreSymfony Guard Authentication: Fun with API Token, Social Login, JWT and more
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and moreRyan Weaver
 
Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)Ryan Weaver
 
Symfony tips and tricks
Symfony tips and tricksSymfony tips and tricks
Symfony tips and tricksJavier Eguiluz
 
The Coolest Symfony Components you’ve never heard of - DrupalCon 2017
The Coolest Symfony Components you’ve never heard of - DrupalCon 2017The Coolest Symfony Components you’ve never heard of - DrupalCon 2017
The Coolest Symfony Components you’ve never heard of - DrupalCon 2017Ryan Weaver
 
Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3Kris Wallsmith
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasminePaulo Ragonha
 

More Related Content

What's hot

Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsSymfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsIgnacio Martín
 
Guard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful SecurityGuard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful SecurityRyan Weaver
 
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)Javier Eguiluz
 
[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress Development[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress DevelopmentAdam Tomat
 
Laravel 8 export data as excel file with example
Laravel 8 export data as excel file with exampleLaravel 8 export data as excel file with example
Laravel 8 export data as excel file with exampleKaty Slemon
 
Building Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJSBuilding Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJSAntonio Peric-Mazar
 
Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...
Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...
Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...Caldera Labs
 
Refresh Austin - Intro to Dexy
Refresh Austin - Intro to DexyRefresh Austin - Intro to Dexy
Refresh Austin - Intro to Dexyananelson
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony AppsKris Wallsmith
 
Introduction to AngularJS For WordPress Developers
Introduction to AngularJS For WordPress DevelopersIntroduction to AngularJS For WordPress Developers
Introduction to AngularJS For WordPress DevelopersCaldera Labs
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Elena Kolevska
 
HTML5 JavaScript APIs
HTML5 JavaScript APIsHTML5 JavaScript APIs
HTML5 JavaScript APIsRemy Sharp
 
Caldera Learn - LoopConf WP API + Angular FTW Workshop
Caldera Learn - LoopConf WP API + Angular FTW WorkshopCaldera Learn - LoopConf WP API + Angular FTW Workshop
Caldera Learn - LoopConf WP API + Angular FTW WorkshopCalderaLearn
 
Creating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of todayCreating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of todaygerbille
 
OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010ikailan
 
The road to Ember.js 2.0
The road to Ember.js 2.0The road to Ember.js 2.0
The road to Ember.js 2.0Codemotion
 

What's hot (20)

Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsSymfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worlds
 
Laravel 101
Laravel 101Laravel 101
Laravel 101
 
Guard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful SecurityGuard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful Security
 
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
 
[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress Development[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress Development
 
Laravel 8 export data as excel file with example
Laravel 8 export data as excel file with exampleLaravel 8 export data as excel file with example
Laravel 8 export data as excel file with example
 
Building Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJSBuilding Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJS
 
Sane Async Patterns
Sane Async PatternsSane Async Patterns
Sane Async Patterns
 
Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...
Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...
Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...
 
Refresh Austin - Intro to Dexy
Refresh Austin - Intro to DexyRefresh Austin - Intro to Dexy
Refresh Austin - Intro to Dexy
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 
Introduction to AngularJS For WordPress Developers
Introduction to AngularJS For WordPress DevelopersIntroduction to AngularJS For WordPress Developers
Introduction to AngularJS For WordPress Developers
 
Ember - introduction
Ember - introductionEmber - introduction
Ember - introduction
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5
 
Symfony2 and AngularJS
Symfony2 and AngularJSSymfony2 and AngularJS
Symfony2 and AngularJS
 
HTML5 JavaScript APIs
HTML5 JavaScript APIsHTML5 JavaScript APIs
HTML5 JavaScript APIs
 
Caldera Learn - LoopConf WP API + Angular FTW Workshop
Caldera Learn - LoopConf WP API + Angular FTW WorkshopCaldera Learn - LoopConf WP API + Angular FTW Workshop
Caldera Learn - LoopConf WP API + Angular FTW Workshop
 
Creating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of todayCreating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of today
 
OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010
 
The road to Ember.js 2.0
The road to Ember.js 2.0The road to Ember.js 2.0
The road to Ember.js 2.0
 

Viewers also liked

Migrating to Symfony 3.0
Migrating to Symfony 3.0Migrating to Symfony 3.0
Migrating to Symfony 3.0nicolas.grekas
 
High Quality Symfony Bundles tutorial - Dutch PHP Conference 2014
High Quality Symfony Bundles tutorial - Dutch PHP Conference 2014High Quality Symfony Bundles tutorial - Dutch PHP Conference 2014
High Quality Symfony Bundles tutorial - Dutch PHP Conference 2014Matthias Noback
 
Integrating React.js Into a PHP Application
Integrating React.js Into a PHP ApplicationIntegrating React.js Into a PHP Application
Integrating React.js Into a PHP ApplicationAndrew Rota
 
Get Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP StreamsGet Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP StreamsDavey Shafik
 
Techniques d'accélération des pages web
Techniques d'accélération des pages webTechniques d'accélération des pages web
Techniques d'accélération des pages webJean-Pierre Vincent
 
Automation using-phing
Automation using-phingAutomation using-phing
Automation using-phingRajat Pandit
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP GeneratorsMark Baker
 
The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)Matthias Noback
 
WordCamp Cantabria - Código mantenible con WordPress
WordCamp Cantabria  - Código mantenible con WordPressWordCamp Cantabria  - Código mantenible con WordPress
WordCamp Cantabria - Código mantenible con WordPressAsier Marqués
 
Top tips my_sql_performance
Top tips my_sql_performanceTop tips my_sql_performance
Top tips my_sql_performanceafup Paris
 
Why elasticsearch rocks!
Why elasticsearch rocks!Why elasticsearch rocks!
Why elasticsearch rocks!tlrx
 
Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015Marcello Duarte
 
Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015Bruno Boucard
 
Writing infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQLWriting infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQLGabriele Bartolini
 

Viewers also liked (20)

Migrating to Symfony 3.0
Migrating to Symfony 3.0Migrating to Symfony 3.0
Migrating to Symfony 3.0
 
High Quality Symfony Bundles tutorial - Dutch PHP Conference 2014
High Quality Symfony Bundles tutorial - Dutch PHP Conference 2014High Quality Symfony Bundles tutorial - Dutch PHP Conference 2014
High Quality Symfony Bundles tutorial - Dutch PHP Conference 2014
 
Integrating React.js Into a PHP Application
Integrating React.js Into a PHP ApplicationIntegrating React.js Into a PHP Application
Integrating React.js Into a PHP Application
 
Introduction to Redux
Introduction to ReduxIntroduction to Redux
Introduction to Redux
 
Get Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP StreamsGet Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP Streams
 
Diving deep into twig
Diving deep into twigDiving deep into twig
Diving deep into twig
 
Elastic Searching With PHP
Elastic Searching With PHPElastic Searching With PHP
Elastic Searching With PHP
 
Techniques d'accélération des pages web
Techniques d'accélération des pages webTechniques d'accélération des pages web
Techniques d'accélération des pages web
 
Automation using-phing
Automation using-phingAutomation using-phing
Automation using-phing
 
PHP5.5 is Here
PHP5.5 is HerePHP5.5 is Here
PHP5.5 is Here
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP Generators
 
The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)
 
WordCamp Cantabria - Código mantenible con WordPress
WordCamp Cantabria  - Código mantenible con WordPressWordCamp Cantabria  - Código mantenible con WordPress
WordCamp Cantabria - Código mantenible con WordPress
 
Doctrine2 sf2Vigo
Doctrine2 sf2VigoDoctrine2 sf2Vigo
Doctrine2 sf2Vigo
 
Mocking Demystified
Mocking DemystifiedMocking Demystified
Mocking Demystified
 
Top tips my_sql_performance
Top tips my_sql_performanceTop tips my_sql_performance
Top tips my_sql_performance
 
Why elasticsearch rocks!
Why elasticsearch rocks!Why elasticsearch rocks!
Why elasticsearch rocks!
 
Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015
 
Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015
 
Writing infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQLWriting infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQL
 

Similar to Keeping the frontend under control with Symfony and Webpack

Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017Elyse Kolker Gordon
 
Django + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar DjangoDjango + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar DjangoJavier Abadía
 
Vue routing tutorial getting started with vue router
Vue routing tutorial getting started with vue routerVue routing tutorial getting started with vue router
Vue routing tutorial getting started with vue routerKaty Slemon
 
Building and deploying React applications
Building and deploying React applicationsBuilding and deploying React applications
Building and deploying React applicationsAstrails
 
The Future of CSS with Web components
The Future of CSS with Web componentsThe Future of CSS with Web components
The Future of CSS with Web componentsdevObjective
 
The Future of CSS with Web Components
The Future of CSS with Web ComponentsThe Future of CSS with Web Components
The Future of CSS with Web ComponentsColdFusionConference
 
Front End Development for Back End Java Developers - Jfokus 2020
Front End Development for Back End Java Developers - Jfokus 2020Front End Development for Back End Java Developers - Jfokus 2020
Front End Development for Back End Java Developers - Jfokus 2020Matt Raible
 
20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdev20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdevFrank Rousseau
 
How Bitbucket Pipelines Loads Connect UI Assets Super-fast
How Bitbucket Pipelines Loads Connect UI Assets Super-fastHow Bitbucket Pipelines Loads Connect UI Assets Super-fast
How Bitbucket Pipelines Loads Connect UI Assets Super-fastAtlassian
 
Single Page JavaScript WebApps... A Gradle Story
Single Page JavaScript WebApps... A Gradle StorySingle Page JavaScript WebApps... A Gradle Story
Single Page JavaScript WebApps... A Gradle StoryKon Soulianidis
 
Warsaw Frontend Meetup #1 - Webpack
Warsaw Frontend Meetup #1 - WebpackWarsaw Frontend Meetup #1 - Webpack
Warsaw Frontend Meetup #1 - WebpackRadosław Rosłaniec
 
A Gentle Introduction to Angular Schematics - Angular SF 2019
A Gentle Introduction to Angular Schematics - Angular SF 2019A Gentle Introduction to Angular Schematics - Angular SF 2019
A Gentle Introduction to Angular Schematics - Angular SF 2019Matt Raible
 
How to Webpack your Django!
How to Webpack your Django!How to Webpack your Django!
How to Webpack your Django!David Gibbons
 
RESS – Responsive Webdesign and Server Side Components
RESS – Responsive Webdesign and Server Side ComponentsRESS – Responsive Webdesign and Server Side Components
RESS – Responsive Webdesign and Server Side ComponentsSven Wolfermann
 
Build Your Own CMS with Apache Sling
Build Your Own CMS with Apache SlingBuild Your Own CMS with Apache Sling
Build Your Own CMS with Apache SlingBob Paulin
 

Similar to Keeping the frontend under control with Symfony and Webpack (20)

Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017
 
Django + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar DjangoDjango + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar Django
 
Vue routing tutorial getting started with vue router
Vue routing tutorial getting started with vue routerVue routing tutorial getting started with vue router
Vue routing tutorial getting started with vue router
 
Building and deploying React applications
Building and deploying React applicationsBuilding and deploying React applications
Building and deploying React applications
 
Death of a Themer
Death of a ThemerDeath of a Themer
Death of a Themer
 
The Future of CSS with Web components
The Future of CSS with Web componentsThe Future of CSS with Web components
The Future of CSS with Web components
 
The Future of CSS with Web Components
The Future of CSS with Web ComponentsThe Future of CSS with Web Components
The Future of CSS with Web Components
 
Front End Development for Back End Java Developers - Jfokus 2020
Front End Development for Back End Java Developers - Jfokus 2020Front End Development for Back End Java Developers - Jfokus 2020
Front End Development for Back End Java Developers - Jfokus 2020
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
 
20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdev20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdev
 
How Bitbucket Pipelines Loads Connect UI Assets Super-fast
How Bitbucket Pipelines Loads Connect UI Assets Super-fastHow Bitbucket Pipelines Loads Connect UI Assets Super-fast
How Bitbucket Pipelines Loads Connect UI Assets Super-fast
 
Single Page JavaScript WebApps... A Gradle Story
Single Page JavaScript WebApps... A Gradle StorySingle Page JavaScript WebApps... A Gradle Story
Single Page JavaScript WebApps... A Gradle Story
 
Warsaw Frontend Meetup #1 - Webpack
Warsaw Frontend Meetup #1 - WebpackWarsaw Frontend Meetup #1 - Webpack
Warsaw Frontend Meetup #1 - Webpack
 
Nodejs.meetup
Nodejs.meetupNodejs.meetup
Nodejs.meetup
 
A Gentle Introduction to Angular Schematics - Angular SF 2019
A Gentle Introduction to Angular Schematics - Angular SF 2019A Gentle Introduction to Angular Schematics - Angular SF 2019
A Gentle Introduction to Angular Schematics - Angular SF 2019
 
How to Webpack your Django!
How to Webpack your Django!How to Webpack your Django!
How to Webpack your Django!
 
RESS – Responsive Webdesign and Server Side Components
RESS – Responsive Webdesign and Server Side ComponentsRESS – Responsive Webdesign and Server Side Components
RESS – Responsive Webdesign and Server Side Components
 
Build Your Own CMS with Apache Sling
Build Your Own CMS with Apache SlingBuild Your Own CMS with Apache Sling
Build Your Own CMS with Apache Sling
 
Google app engine by example
Google app engine by exampleGoogle app engine by example
Google app engine by example
 
Presentation Tier optimizations
Presentation Tier optimizationsPresentation Tier optimizations
Presentation Tier optimizations
 

More from Ignacio Martín

Elixir/OTP for PHP developers
Elixir/OTP for PHP developersElixir/OTP for PHP developers
Elixir/OTP for PHP developersIgnacio Martín
 
Introduction to React Native Workshop
Introduction to React Native WorkshopIntroduction to React Native Workshop
Introduction to React Native WorkshopIgnacio Martín
 
Server side rendering with React and Symfony
Server side rendering with React and SymfonyServer side rendering with React and Symfony
Server side rendering with React and SymfonyIgnacio Martín
 
Symfony 4 Workshop - Limenius
Symfony 4 Workshop - LimeniusSymfony 4 Workshop - Limenius
Symfony 4 Workshop - LimeniusIgnacio Martín
 
Server Side Rendering of JavaScript in PHP
Server Side Rendering of JavaScript in PHPServer Side Rendering of JavaScript in PHP
Server Side Rendering of JavaScript in PHPIgnacio Martín
 
Extending Redux in the Server Side
Extending Redux in the Server SideExtending Redux in the Server Side
Extending Redux in the Server SideIgnacio Martín
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React AlicanteIgnacio Martín
 
React Native Workshop - React Alicante
React Native Workshop - React AlicanteReact Native Workshop - React Alicante
React Native Workshop - React AlicanteIgnacio Martín
 
Asegurando APIs en Symfony con JWT
Asegurando APIs en Symfony con JWTAsegurando APIs en Symfony con JWT
Asegurando APIs en Symfony con JWTIgnacio Martín
 
Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Ignacio Martín
 
Integrating React.js with PHP projects
Integrating React.js with PHP projectsIntegrating React.js with PHP projects
Integrating React.js with PHP projectsIgnacio Martín
 
Integrando React.js en aplicaciones Symfony (deSymfony 2016)
Integrando React.js en aplicaciones Symfony (deSymfony 2016)Integrando React.js en aplicaciones Symfony (deSymfony 2016)
Integrando React.js en aplicaciones Symfony (deSymfony 2016)Ignacio Martín
 
Adding Realtime to your Projects
Adding Realtime to your ProjectsAdding Realtime to your Projects
Adding Realtime to your ProjectsIgnacio Martín
 

More from Ignacio Martín (15)

Elixir/OTP for PHP developers
Elixir/OTP for PHP developersElixir/OTP for PHP developers
Elixir/OTP for PHP developers
 
Introduction to React Native Workshop
Introduction to React Native WorkshopIntroduction to React Native Workshop
Introduction to React Native Workshop
 
Server side rendering with React and Symfony
Server side rendering with React and SymfonyServer side rendering with React and Symfony
Server side rendering with React and Symfony
 
Symfony 4 Workshop - Limenius
Symfony 4 Workshop - LimeniusSymfony 4 Workshop - Limenius
Symfony 4 Workshop - Limenius
 
Server Side Rendering of JavaScript in PHP
Server Side Rendering of JavaScript in PHPServer Side Rendering of JavaScript in PHP
Server Side Rendering of JavaScript in PHP
 
Extending Redux in the Server Side
Extending Redux in the Server SideExtending Redux in the Server Side
Extending Redux in the Server Side
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React Alicante
 
React Native Workshop - React Alicante
React Native Workshop - React AlicanteReact Native Workshop - React Alicante
React Native Workshop - React Alicante
 
Asegurando APIs en Symfony con JWT
Asegurando APIs en Symfony con JWTAsegurando APIs en Symfony con JWT
Asegurando APIs en Symfony con JWT
 
Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6
 
Integrating React.js with PHP projects
Integrating React.js with PHP projectsIntegrating React.js with PHP projects
Integrating React.js with PHP projects
 
Integrando React.js en aplicaciones Symfony (deSymfony 2016)
Integrando React.js en aplicaciones Symfony (deSymfony 2016)Integrando React.js en aplicaciones Symfony (deSymfony 2016)
Integrando React.js en aplicaciones Symfony (deSymfony 2016)
 
Adding Realtime to your Projects
Adding Realtime to your ProjectsAdding Realtime to your Projects
Adding Realtime to your Projects
 
Symfony 2 CMF
Symfony 2 CMFSymfony 2 CMF
Symfony 2 CMF
 
Presentacion git
Presentacion gitPresentacion git
Presentacion git
 

Recently uploaded

history of tau gamma architect.1968.....
history of tau gamma architect.1968.....history of tau gamma architect.1968.....
history of tau gamma architect.1968.....josephiigo
 
[Hackersuli]Privacy on the blockchain
[Hackersuli]Privacy on the blockchain[Hackersuli]Privacy on the blockchain
[Hackersuli]Privacy on the blockchainhackersuli
 
Earn 3000 dollars per month
Earn 3000 dollars per monthEarn 3000 dollars per month
Earn 3000 dollars per monthplaycorea108
 
APAN 57: APNIC Report at APAN 57, Bangkok, Thailand
APAN 57: APNIC Report at APAN 57, Bangkok, ThailandAPAN 57: APNIC Report at APAN 57, Bangkok, Thailand
APAN 57: APNIC Report at APAN 57, Bangkok, ThailandAPNIC
 
UGBINTERNETBANKING FACILITY LAUNCHED.pptx
UGBINTERNETBANKING FACILITY LAUNCHED.pptxUGBINTERNETBANKING FACILITY LAUNCHED.pptx
UGBINTERNETBANKING FACILITY LAUNCHED.pptxRiteshsahu101
 
Modern Red Teaming - subverting mature defenses on a budget
Modern Red Teaming - subverting mature defenses on a budgetModern Red Teaming - subverting mature defenses on a budget
Modern Red Teaming - subverting mature defenses on a budgetmatt806068
 

Recently uploaded (9)

B1 Evaluation.docx
B1 Evaluation.docxB1 Evaluation.docx
B1 Evaluation.docx
 
history of tau gamma architect.1968.....
history of tau gamma architect.1968.....history of tau gamma architect.1968.....
history of tau gamma architect.1968.....
 
[Hackersuli]Privacy on the blockchain
[Hackersuli]Privacy on the blockchain[Hackersuli]Privacy on the blockchain
[Hackersuli]Privacy on the blockchain
 
Earn 3000 dollars per month
Earn 3000 dollars per monthEarn 3000 dollars per month
Earn 3000 dollars per month
 
APAN 57: APNIC Report at APAN 57, Bangkok, Thailand
APAN 57: APNIC Report at APAN 57, Bangkok, ThailandAPAN 57: APNIC Report at APAN 57, Bangkok, Thailand
APAN 57: APNIC Report at APAN 57, Bangkok, Thailand
 
INTERNET
INTERNETINTERNET
INTERNET
 
UGBINTERNETBANKING FACILITY LAUNCHED.pptx
UGBINTERNETBANKING FACILITY LAUNCHED.pptxUGBINTERNETBANKING FACILITY LAUNCHED.pptx
UGBINTERNETBANKING FACILITY LAUNCHED.pptx
 
Modern Red Teaming - subverting mature defenses on a budget
Modern Red Teaming - subverting mature defenses on a budgetModern Red Teaming - subverting mature defenses on a budget
Modern Red Teaming - subverting mature defenses on a budget
 
Riesgos online
Riesgos onlineRiesgos online
Riesgos online
 

Keeping the frontend under control with Symfony and Webpack

  • 1. Keeping the frontend under control with Symfony and Webpack Nacho Martín @nacmartin nacho@limenius.com Munich Symfony Meetup October’16
  • 2. I write code at Limenius We build tailor made projects using mainly Symfony and React.js So we have been figuring out how to organize better the frontend Nacho Martín nacho@limenius.com @nacmartin
  • 3. Why do we need this?
  • 4. Assetic? No module loading No bundle orientation Not a standard solution for frontenders Other tools simply have more manpower behind Written before the Great Frontend Revolution
  • 5. Building the Pyramids: 130K man years
  • 6. Writing JavaScript: 10 man days JavaScript
  • 7. Making JavaScript great: NaN man years JavaScript
  • 11. Tendency Task runners Bundlers Task runners + understanding of require(ments)
  • 12. Tendency Task runners Bundlers Task runners + understanding of require(ments)
  • 13. Package management in JS Server Side (node.js) Bower Client side (browser) Used to be
  • 14. Package management in JS Server Side (node.js) Bower Client side (browser) Used to be Now Everywhere
  • 15. Module loaders Server Side (node.js) Client side (browser) Used to be
  • 16. Module loaders Server Side (node.js) Client side (browser) Used to be Now Everywhere &ES6 Style
  • 17. Summarizing Package manager Module loader Module bundler
  • 18. Setup
  • 22. NPM setup $ npm init $ cat package.json { "name": "webpacksf", "version": "1.0.0", "description": "Webpack & Symfony example", "main": "client/js/index.js", "directories": { "test": "client/js/tests" }, "scripts": { "test": "echo "Error: no test specified" && exit 1" }, "author": "Nacho Martín", "license": "MIT" }
  • 23. Install Webpack $ npm install -g webpack $ npm install --save-dev webpack Or, to install it globally
  • 24. First example var greeter = require('./greeter.js') greeter('Nacho'); client/js/index.js
  • 25. First example var greeter = require('./greeter.js') greeter('Nacho'); client/js/index.js var greeter = function(name) { console.log('Hi '+name+'!'); } module.exports = greeter; client/js/greeter.js
  • 26. First example var greeter = require('./greeter.js') greeter('Nacho'); client/js/index.js var greeter = function(name) { console.log('Hi '+name+'!'); } module.exports = greeter; client/js/greeter.js
  • 27. Webpack without configuration $ webpack client/js/index.js web/assets/build/hello.js Hash: 4f4f05e78036f9dc67f3 Version: webpack 1.13.2 Time: 100ms Asset Size Chunks Chunk Names hi.js 1.59 kB 0 [emitted] main [0] ./client/js/index.js 57 bytes {0} [built] [1] ./client/js/greeter.js 66 bytes {0} [built]
  • 28. Webpack without configuration <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>{% block title %}Webpack & Symfony!{% endblock %}</title> {% block stylesheets %}{% endblock %} <link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" /> </head> <body> {% block body %}{% endblock %} {% block javascripts %} <script src="{{ asset('assets/build/hello.js') }}"></script> {% endblock %} </body> </html> app/Resources/base.html.twig
  • 29. Webpack config module.exports = { entry: { hello: './client/js/index.js' }, output: { publicPath: '/assets/build/', path: './web/assets/build', filename: '[name].js' } }; webpack.config.js
  • 30. Webpack config module.exports = { entry: { hello: './client/js/index.js' }, output: { publicPath: '/assets/build/', path: './web/assets/build', filename: '[name].js' } }; webpack.config.js
  • 32. Now that we have modules, What about using modern JavaScript? (without caring about IE support)
  • 33. Now that we have modules, What about using modern JavaScript? (without caring about IE support)
  • 34. JavaScript ES2015 •Default Parameters •Template Literals •Arrow Functions •Promises •Block-Scoped Constructs Let and Const •Classes •Modules •…
  • 35. Why Babel matters import Greeter from './greeter.js'; let greeter = new Greeter('Hi'); greeter.greet('gentlemen'); class Greeter { constructor(salutation = 'Hello') { this.salutation = salutation; } greet(name = 'Nacho') { const greeting = `${this.salutation}, ${name}!`; console.log(greeting); } } export default Greeter; client/js/index.js client/js/greeter.js
  • 36. Install babel $ npm install --save-dev babel-core babel-loader babel-preset-es2015
  • 37. Install babel $ npm install --save-dev babel-core babel-loader babel-preset-es2015 module.exports = { entry: { hello: './client/js/index.js' }, output: { publicPath: '/assets/build/', path: './web/assets/build', filename: '[name].js' }, module: { loaders: [ { test: /.js$/, loader: 'babel-loader', exclude: /node_modules/ }, ] } }; webpack.config.js
  • 38. Install babel $ npm install --save-dev babel-core babel-loader babel-preset-es2015 module.exports = { entry: { hello: './client/js/index.js' }, output: { publicPath: '/assets/build/', path: './web/assets/build', filename: '[name].js' }, module: { loaders: [ { test: /.js$/, loader: 'babel-loader', exclude: /node_modules/ }, ] } }; webpack.config.js
  • 39. Install babel $ npm install --save-dev babel-core babel-loader babel-preset-es2015 module.exports = { entry: { hello: './client/js/index.js' }, output: { publicPath: '/assets/build/', path: './web/assets/build', filename: '[name].js' }, module: { loaders: [ { test: /.js$/, loader: 'babel-loader', exclude: /node_modules/ }, ] } }; webpack.config.js .babelrc { "presets": ["es2015"] }
  • 40. Install babel $ npm install --save-dev babel-core babel-loader babel-preset-es2015 module.exports = { entry: { hello: './client/js/index.js' }, output: { publicPath: '/assets/build/', path: './web/assets/build', filename: '[name].js' }, module: { loaders: [ { test: /.js$/, loader: 'babel-loader', exclude: /node_modules/ }, ] } }; webpack.config.js .babelrc { "presets": ["es2015"] }
  • 44. Loading styles: raw* loaders: [ //… { test: /.css$/i, loader: 'raw'}, ] exports.push([module.id, "body {n line-height: 1.5;n padding: 4em 1em;n}nnh2 {n margin-top: 1em;n padding-top: 1em;n}nnh1,nh2,nstrong {n color: #333;n}nna {n color: #e81c4f;n}nn", ""]); Embeds it into JavaScript, but… *(note: if you are reading the slides, don’t use this loader for css. Use css loader, that will be explained later)
  • 45. Chaining styles: style loaders: [ //… { test: /.css$/i, loader: ’style!raw'}, ]
  • 46. CSS loader header { background-image: url("../img/header.jpg"); } Problem
  • 47. CSS loader header { background-image: url("../img/header.jpg"); } url(image.png) => require("./image.png") url(~module/image.png) => require("module/image.png") We want Problem
  • 48. CSS loader header { background-image: url("../img/header.jpg"); } url(image.png) => require("./image.png") url(~module/image.png) => require("module/image.png") We want Problem loaders: [ //… { test: /.css$/i, loader: ’style!css'}, ] Solution
  • 49. File loaders { test: /.jpg$/, loader: 'file-loader' }, { test: /.png$/, loader: 'url-loader?limit=10000' }, Copies file as [hash].jpg, and returns the public url If file < 10Kb: embed it in data URL. If > 10Kb: use file-loader
  • 50. Using loaders When requiring a file In webpack.config.js, verbose { test: /.png$/, loader: "url-loader", query: { limit: "10000" } } require("url-loader?limit=10000!./file.png"); { test: /.png$/, loader: 'url-loader?limit=10000' }, In webpack.config.js, compact
  • 51. SASS { test: /.scss$/i, loader: 'style!css!sass'}, In webpack.config.js, compact $ npm install --save-dev sass-loader node-sass Also { test: /.scss$/i, loaders: [ 'style', 'css', 'sass' ] },
  • 52. Embedding CSS in JS is good in Single Page Apps What if I am not writing a Single Page App?
  • 53. ExtractTextPlugin var ExtractTextPlugin = require("extract-text-webpack-plugin"); const extractCSS = new ExtractTextPlugin('stylesheets/[name].css'); const config = { //… module: { loaders: [ { test: /.css$/i, loader: extractCSS.extract(['css'])}, //… ] }, plugins: [ extractCSS, //… ] }; {% block stylesheets %} <link href="{{asset('assets/build/stylesheets/hello.css')}}" rel="stylesheet"> {% endblock %} app/Resources/base.html.twig webpack.config.js
  • 54. ExtractTextPlugin var ExtractTextPlugin = require("extract-text-webpack-plugin"); const extractCSS = new ExtractTextPlugin('stylesheets/[name].css'); const config = { //… module: { loaders: [ { test: /.css$/i, loader: extractCSS.extract(['css'])}, //… ] }, plugins: [ extractCSS, //… ] }; {% block stylesheets %} <link href="{{asset('assets/build/stylesheets/hello.css')}}" rel="stylesheet"> {% endblock %} app/Resources/base.html.twig webpack.config.js { test: /.scss$/i, loader: extractCSS.extract(['css','sass'])}, Also
  • 56. Webpack-watch $ webpack --watch Simply watches for changes and recompiles the bundle
  • 57. Webpack-dev-server $ webpack-dev-server —inline http://localhost:8080/webpack-dev-server/ Starts a server. The browser opens a WebSocket connection with it and reloads automatically when something changes.
  • 58. Webpack-dev-server config Sf {% block javascripts %} <script src="{{ asset('assets/build/hello.js', 'webpack') }}"></script> {% endblock %} app/Resources/base.html.twig framework: assets: packages: webpack: base_urls: - "%assets_base_url%" app/config/config_dev.yml parameters: #… assets_base_url: 'http://localhost:8080' app/config/parameters.yml
  • 59. Webpack-dev-server config Sf {% block javascripts %} <script src="{{ asset('assets/build/hello.js', 'webpack') }}"></script> {% endblock %} app/Resources/base.html.twig framework: assets: packages: webpack: base_urls: - "%assets_base_url%" app/config/config_dev.yml framework: assets: packages: webpack: ~ app/config/config.yml parameters: #… assets_base_url: 'http://localhost:8080' app/config/parameters.yml
  • 60. Optional web-dev-server Kudos Ryan Weaver class AppKernel extends Kernel { public function registerContainerConfiguration(LoaderInterface $loader) { //… $loader->load(function($container) { if ($container->getParameter('use_webpack_dev_server')) { $container->loadFromExtension('framework', [ 'assets' => [ 'base_url' => 'http://localhost:8080' ] ]); } }); } }
  • 61. Hot module replacement output: { publicPath: 'http://localhost:8080/assets/build/', path: './web/assets/build', filename: '[name].js' }, Will try to replace the code without even page reload $ webpack-dev-server --hot --inline
  • 62. Hot module replacement output: { publicPath: 'http://localhost:8080/assets/build/', path: './web/assets/build', filename: '[name].js' }, Will try to replace the code without even page reload Needs full URL (so only in dev), or… $ webpack-dev-server --hot --inline
  • 63. Hot module replacement output: { publicPath: 'http://localhost:8080/assets/build/', path: './web/assets/build', filename: '[name].js' }, $ webpack-dev-server --hot --inline --output-public-path http://localhost:8080/assets/build/ Will try to replace the code without even page reload Needs full URL (so only in dev), or… $ webpack-dev-server --hot --inline
  • 64. SourceMaps const devBuild = process.env.NODE_ENV !== ‘production'; /… if (devBuild) { console.log('Webpack dev build'); config.devtool = 'eval-source-map'; } else {
  • 65. SourceMaps const devBuild = process.env.NODE_ENV !== ‘production'; /… if (devBuild) { console.log('Webpack dev build'); config.devtool = 'eval-source-map'; } else { eval source-map hidden-source-map inline-source-map eval-source-map cheap-source-map cheap-module-source-map Several options:
  • 66. Notifier $ npm install --save-dev webpack-notifier module.exports = { //… plugins: [ new WebpackNotifierPlugin(), ] }; webpack.config.js
  • 67. Notifier $ npm install --save-dev webpack-notifier module.exports = { //… plugins: [ new WebpackNotifierPlugin(), ] }; webpack.config.js
  • 68. Notifier $ npm install --save-dev webpack-notifier module.exports = { //… plugins: [ new WebpackNotifierPlugin(), ] }; webpack.config.js
  • 70. Optimization options var WebpackNotifierPlugin = require('webpack-notifier'); var webpack = require(‘webpack'); const devBuild = process.env.NODE_ENV !== 'production'; const config = { entry: { hello: './client/js/index.js' }, //… }; if (devBuild) { console.log('Webpack dev build'); config.devtool = 'eval-source-map'; } else { console.log('Webpack production build'); config.plugins.push( new webpack.optimize.DedupePlugin() ); config.plugins.push( new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }) ); } module.exports = config;
  • 71. Optimization options var WebpackNotifierPlugin = require('webpack-notifier'); var webpack = require(‘webpack'); const devBuild = process.env.NODE_ENV !== 'production'; const config = { entry: { hello: './client/js/index.js' }, //… }; if (devBuild) { console.log('Webpack dev build'); config.devtool = 'eval-source-map'; } else { console.log('Webpack production build'); config.plugins.push( new webpack.optimize.DedupePlugin() ); config.plugins.push( new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }) ); } module.exports = config; $ export NODE_ENV=production; webpack
  • 72. Optimization options var WebpackNotifierPlugin = require('webpack-notifier'); var webpack = require(‘webpack'); const devBuild = process.env.NODE_ENV !== 'production'; const config = { entry: { hello: './client/js/index.js' }, //… }; if (devBuild) { console.log('Webpack dev build'); config.devtool = 'eval-source-map'; } else { console.log('Webpack production build'); config.plugins.push( new webpack.optimize.DedupePlugin() ); config.plugins.push( new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }) ); } module.exports = config; $ export NODE_ENV=production; webpack
  • 73. Bundle visualizer $ webpack --json > stats.json https://chrisbateman.github.io/webpack-visualizer/
  • 74. Bundle visualizer $ webpack --json > stats.json https://chrisbateman.github.io/webpack-visualizer/
  • 75. More than one bundle
  • 76. Separate entry points var config = { entry: { front: './assets/js/front.js', admin: './assets/js/admin.js', }, output: { publicPath: '/assets/build/', path: './web/assets/build/', filename: '[name].js' },
  • 77. Vendor bundles var config = { entry: { front: './assets/js/front.js', admin: './assets/js/admin.js', 'vendor-admin': [ 'lodash', 'moment', 'classnames', 'react', 'redux', ] }, plugins: [ extractCSS, new webpack.optimize.CommonsChunkPlugin({ name: 'vendor-admin', chunks: ['admin'], filename: 'vendor-admin.js', minChunks: Infinity }),
  • 78. Common Chunks var CommonsChunkPlugin = require(“webpack/lib/optimize/CommonsChunkPlugin”); module.exports = { entry: { page1: "./page1", page2: "./page2", }, output: { filename: "[name].chunk.js" }, plugins: [ new CommonsChunkPlugin("commons.chunk.js") ] } Produces page1.chunk.js, page2.chunk.js and commons.chunk.js
  • 79. On demand loading class Greeter { constructor(salutation = 'Hello') { this.salutation = salutation; } greet(name = 'Nacho', goodbye = true) { const greeting = `${this.salutation}, ${name}!`; console.log(greeting); if (goodbye) { require.ensure(['./goodbyer'], function(require) { var goodbyer = require('./goodbyer'); goodbyer(name); }); } } } export default Greeter; module.exports = function(name) { console.log('Goodbye '+name); } greeter.js goodbyer.js
  • 80. On demand loading class Greeter { constructor(salutation = 'Hello') { this.salutation = salutation; } greet(name = 'Nacho', goodbye = true) { const greeting = `${this.salutation}, ${name}!`; console.log(greeting); if (goodbye) { require.ensure(['./goodbyer'], function(require) { var goodbyer = require('./goodbyer'); goodbyer(name); }); } } } export default Greeter; module.exports = function(name) { console.log('Goodbye '+name); } greeter.js goodbyer.js
  • 81. Hashes output: { publicPath: '/assets/build/', path: './web/assets/build', filename: '[name].js', chunkFilename: "[id].[hash].bundle.js" },
  • 82. Chunks are very configurable https://webpack.github.io/docs/optimization.html
  • 84. Provide plugin plugins: [ new webpack.ProvidePlugin({ _: 'lodash', $: 'jquery', }), ] $("#item") _.find(users, { 'age': 1, 'active': true }); These just work without requiring them:
  • 85. Exposing jQuery { test: require.resolve('jquery'), loader: 'expose?$!expose?jQuery' }, Exposes $ and jQuery globally in the browser
  • 86. Dealing with a mess require('imports?define=>false&exports=>false!blueimp-file-upload/js/vendor/jquery.ui.widget.js'); require('imports?define=>false&exports=>false!blueimp-load-image/js/load-image-meta.js'); require('imports?define=>false&exports=>false!blueimp-file-upload/js/jquery.iframe-transport.js'); require('imports?define=>false&exports=>false!blueimp-file-upload/js/jquery.fileupload.js'); require('imports?define=>false&exports=>false!blueimp-file-upload/js/jquery.fileupload-process.js'); require('imports?define=>false&exports=>false!blueimp-file-upload/js/jquery.fileupload-image.js'); require('imports?define=>false&exports=>false!blueimp-file-upload/js/jquery.fileupload.js'); require('imports?define=>false&exports=>false!blueimp-file-upload/js/jquery.fileupload-validate.js'); require('imports?define=>false&exports=>false!blueimp-file-upload/js/jquery.fileupload-ui.js'); Broken packages that are famous have people that have figured out how to work with them
  • 87. CopyWebpackPlugin for messes new CopyWebpackPlugin([ { from: './client/messyvendors', to: './../mess' } ]), For vendors that are broken, can’t make work with Webpack but I still need them (during the transition)
  • 89. Summary: • What is Webpack • Basic setup • Loaders are the bricks of Webpack • Have nice tools in Dev environment • Optimize in Prod environment • Split your bundle as you need • Tips and tricks
  • 90. MADRID · NOV 27-28 · 2015 Thanks! @nacmartin nacho@limenius.com http://limenius.com