SlideShare a Scribd company logo
1 of 103
Download to read offline
Finally, Professional
Frontend dev with:
ReactJS, Webpack & Symfony
♥’s
> Lead of the Symfony documentation team

> KnpLabs US - Symfony consulting, training & kumbaya
> Writer for KnpUniversity.com:
PHP & Symfony screencasts
packed with puns, unrelated
(but entertaining) illustrations
and coding challenges!
> Husband of the much more
talented @leannapelham
knpuniversity.com
twitter.com/weaverryan
¡Hola!
♥’s
Finally, Professional
Frontend dev with:
ReactJS, Webpack & Symfony
, ReactJS, webpack
@weaverryan
All of Modern JavaScript in
45 minutes!
ES6
the 12 new JS things they invent
during this presentation
, ES2015 , ECMAScript
, Babel
, NodeJS
npm , JSX …
… and of course …
Modern JavaScript
is a lot like…
@weaverryan
Game of Thrones
JavaScript
@weaverryan
GoT
Countless libraries and
competing standards fighting
for influence
Countless characters and
completing factions fighting
for influence
@weaverryan
You spent 6 months building
your site in <Cool.JS> only
to read on Twitter that:
“no self-respecting dev
uses that crap anymore”
That character you love and
followed for 2 seasons, was
just unceremoniously decapitated
JavaScript
GoT
@weaverryan
Plain, boring old JavaScript
JavaScript is a
(weird) language
IT JUST HAPPENS THAT BROWSERS CAN
EXECUTE THAT LANGUAGE
@weaverryan
// yay.js

var message = 'I like Java...Script';



console.log(message);
> node yay.js
I like Java...Script
NodeJS: server-side
JavaScript engine
npm: Composer
for NodeJS
@weaverryan
Follow along with the real code:
github.com/weaverryan/symfonycat-js
(hint: look at the history, each
thing we do is its own commit)
// web/js/productApp.js

var products = [

'Sheer Shears',

'Wool Hauling Basket',

'After-Shear (Fresh Cut Grass)',

'After-Shear (Morning Dew)'

];



var loopThroughProducts = function(callback) {

for (var i = 0, length = products.length; i < length; i++) {

callback(products[i]);

}

};



loopThroughProducts(function(product) {

console.log('Product: '+product);

});
{# app/Resources/views/default/products.html.twig' #}
<script src="{{ asset('js/productApp.js') }}"></script>
our store for
sheep (baaaa)
class ProductCollection

{

constructor(products) {

this.products = products;

}

}



let collection = new ProductCollection([

'Sheer Shears',

'Wool Hauling Basket',

'After-Shear (Fresh Cut Grass)',

'After-Shear (Morning Dew)',

]);

let prods = collection.getProducts();



let loopThroughProducts = function(callback) {

for (let i = 0, length = prods.length; i < length; i++) {

callback(collection.getProduct(i));

}

};



loopThroughProducts(product => console.log('Product: '+product));
what language
is this?
JavaScript
@weaverryan
ECMAScript
The official name of standard JavaScript
ES6/ES2015/Harmony
The 6th accepted (so official) version
of ECMAScript
class ProductCollection

{

constructor(products) {

this.products = products;

}

}



let collection = new ProductCollection([

'Sheer Shears',

'Wool Hauling Basket',

'After-Shear (Fresh Cut Grass)',

'After-Shear (Morning Dew)',

]);

let prods = collection.getProducts();



let loopThroughProducts = function(callback) {

for (let i = 0, length = prods.length; i < length; i++) {

callback(collection.getProduct(i));

}

};



loopThroughProducts(product => console.log('Product: '+product));
But will it run in a browser???
Maybe!
class ProductCollection

{

constructor(products) {

this.products = products;

}

}



let collection = new ProductCollection([

'Sheer Shears',

'Wool Hauling Basket',

'After-Shear (Fresh Cut Grass)',

'After-Shear (Morning Dew)',

]);

let prods = collection.getProducts();



let loopThroughProducts = function(callback) {

for (let i = 0, length = prods.length; i < length; i++) {

callback(collection.getProduct(i));

}

};



loopThroughProducts(product => console.log(product));
Proper class and
inheritance syntax
let: similar to var,
but different
function (product) {

console.log(product);

}
Now we just need to
wait 5 years for the
crappiest browsers
to support this
@weaverryan
Babel
… or do we?
A JS transpiler!
Babel is a NodeJS binary…
{

"name": "js-tutorial",

"version": "1.0.0"

}
1) Make a package.json file
2) Download babel
> npm install --save-dev babel-cli
@weaverryan
> ./node_modules/.bin/babel 
web/js/productApp.js 
-o web/builds/productApp.js
{# app/Resources/views/default/products.html.twig' #}
<script src="{{ asset('builds/productApp.js') }}"></script>
@weaverryan
> ./node_modules/.bin/babel 
web/js/productApp.js 
-o web/builds/productApp.js
{# app/Resources/views/default/products.html.twig' #}
<script src="{{ asset('builds/productApp.js') }}"></script>
But, this made no changes
js/productApp.js == builds/productApp.js
@weaverryan
Babel can transpile anything
CoffeeScript --> JavaScript
Coffee --> Tea
ES6 JS --> ES5 JS
* Each transformation is called a preset
1) Install the es2015 preset library
2) Add a .babelrc file
> npm install --save-dev babel-preset-es2015
{

"presets": [

"es2015"

]

}
@weaverryan
> ./node_modules/.bin/babel 
web/js/productApp.js 
-o web/builds/productApp.js
loopThroughProducts(

product => console.log('Product: '+product)

);
loopThroughProducts(function (product) {

return console.log('Product: ' + product);

});

source:
built:
But we can use new (or experimental) features now
@weaverryan
Modern JavaScript
has a build step
Big Takeaway #1:
@weaverryan
New to ES6:
JavaScript Modules!
The Classic Problem:
If you want to organize your JS into
multiple files, you need to manually
include all those script tags!
@weaverryan
// web/js/ProductCollection.js


class ProductCollection

{

constructor(products) {

this.products = products;

}



getProducts() {

return this.products;

}



getProduct(i) {

return this.products[i];

}

}



export ProductCollection;

@weaverryan
// web/js/productApp.js



import ProductCollection from './ProductCollection';



var collection = new ProductCollection([

'Sheer Shears',

'Wool Hauling Basket',

'After-Shear (Fresh Cut Grass)',

'After-Shear (Morning Dew)',

]);



// ...
{# app/Resources/views/default/products.html.twig' #}
<script src="{{ asset('builds/productApp.js') }}"></script>
// web/js/productApp.js



import ProductCollection from './ProductCollection';



var collection = new ProductCollection([

'Sheer Shears',

'Wool Hauling Basket',

'After-Shear (Fresh Cut Grass)',

'After-Shear (Morning Dew)',

]);



// ...
{# app/Resources/views/default/products.html.twig' #}
<script src="{{ asset('builds/productApp.js') }}"></script>
> ./node_modules/.bin/babel 
web/js/productApp.js 
-o web/builds/productApp.js
Module loading in a
browser is hard to do
@weaverryan
@weaverryan
Introducing…
@weaverryan
Webpack!
• bundler
• module loader
• all-around nice guy
Install webpack
> npm install --save-dev webpack
@weaverryan
Use require instead of import/export *
* I’ll tell you why later
// web/js/ProductCollection.js

class ProductCollection

{

// ...

}



module.exports = ProductCollection;

// web/js/productApp.js

var ProductCollection = require('./ProductCollection');



// ...
Go webpack Go!
> ./node_modules/.bin/webpack 
web/js/productApp.js 
web/builds/productApp.js
The one built file contains
the code from both source files
Optional config to make it easier to use:
// webpack.config.js

module.exports = {

entry: {

product: './web/js/productApp.js'

},

output: {

path: './web/builds',

filename: '[name].js',

publicPath: '/builds/'

}

};

builds/product.js
{# app/Resources/views/default/products.html.twig' #}
<script src="{{ asset('builds/product.js') }}"></script>
> ./node_modules/.bin/webpack
@weaverryan
Wait!
We lost our ES6->ES5
transformation!!!
@weaverryan
Hey webpack!
Yo! When you load .js files,
can you run them through
Babel for me?
- kthxbai <3 Ryan
webpack loaders allow you to transform files
as they’re loaded
1) Install the babel-loader
2) Activate the loader in webpack.config.js
> npm install --save-dev babel-loader
module.exports = {

// ...

module: {

loaders: [

{

test: /.js$/,

loader: "babel-loader",
exclude: /node_modules/

}

]

}

};

> ./node_modules/.bin/webpack
@weaverryan
Module loading
+
ES6 Support
Use import/export now if you prefer
// web/js/ProductCollection.js

class ProductCollection

{

// ...

}



export default ProductCollection;

// web/js/productApp.js

import ProductCollection from './ProductCollection';



// ...

> ./node_modules/.bin/webpack
@weaverryan
@weaverryan
Dev Tools
… because life is too short to run
webpack after every change you make
> npm install webpack-dev-server --save-dev
> ./node_modules/.bin/webpack-dev-server 
--content-base=./web/
@weaverryan
1) Install the webpack-dev-server
2) Run that!
http://localhost:8080
- static assets are served
- compiled assets are served dynamically
Wait!
@weaverryan
Don’t I need to update all my script tags?
<script

src="{{ asset('builds/product.js') }}">
<script

src="http://localost:8080/builds/product.js">
# app/config/config.yml

framework:

assets:

base_url: http://localhost:8080
Boom!
@weaverryan
… or the real solution
@weaverryan
# app/config/parameters.yml

parameters:

# ...

use_webpack_dev_server: true

class AppKernel extends Kernel

{

// ...



public function registerContainerConfiguration(LoaderInterface $loader)

{

// ...



$loader->load(function(ContainerBuilder $container) {

if ($container->getParameter('use_webpack_dev_server')) {

$container->loadFromExtension('framework', [

'assets' => [

'base_url' => 'http://localhost:8080'

]

]);

}

});

}

}
… or the real solution
@weaverryan
@weaverryan
Status Update
we can:
• use ES6 features
• import and export modules
@weaverryan
CSS: An un-handled
dependency of your JS app
Could we do this?
// web/js/productApp.js

import ProductCollection from './ProductCollection';



// could this somehow load that CSS for us?

import '../css/productApp.css';



// ...
Loader!
module.exports = {

// ...

module: {

loaders: [

{

test: /.js$/,

exclude: /node_modules/,

loader: "babel-loader"

}

]

}

};

webpack loaders allow you to transform files
as they’re loaded
Remember:
1) Install the css-loader
2) Activate the loader just for this file
> npm install css-loader --save-dev
import 'css!../css/productApp.css';
this transforms the CSS into a JS data-
structure… but does nothing with it
1) Install the style-loader
> npm install style-loader --save-dev
import 'style!css!../css/productApp.css';
inlines the CSS on the page in
a style tag
2) Activate both loaders for this file
Yes,
@weaverryan
the one JS file now holds the contents of
two JS files and a CSS file
{# app/Resources/views/default/products.html.twig' #}
<script src="{{ asset('builds/product.js') }}"></script>
Move the loader to config to simplify
import '../css/productApp.css';
// webpack.config.js
module.exports = {

// ...

module: {

loaders: [

// ...

{

test: /.css$/,

loader: "style!css"

}

]

},

};

@weaverryan
Ah, but what should my
image paths look like?
/* productApp.css */

.product-price {

color: green;

background-image: url('../images/logo.png');

}

http://example.com/products/5/photos/../images/logo.png
http://example.com/products/5/photos
This broke webpack!
Yes, webpack parses the CSS and tries to
load file imports and url() references
(i.e. to images & fonts)
1) Install the file-loader & url-loader
> npm install file-loader url-loader --save-dev
2) Activate the loader for .png files
// webpack.config.js
// ...
loaders: [

// ...

{

test: /.png/,

loader: "url-loader?limit=10000"

}

]

{

test: /.png/,

loader: "url-loader?limit=10000"

}
For .png files < 10kb
image is turned into a “data url”
and inlined in the CSS
For .png files > 10kb
image is copied to builds/ and the
new URL is written into the CSS
Stop
@weaverryan
thinking of your JavaScript as
random code that executes
Start
@weaverryan
thinking of your JavaScript as
a single application with dependencies
that are all packaged up together
@weaverryan
Unleashing the Power of
NodeJS and ReactJS
Like Composer,
NodeJS has a lot of
third-party libraries
@weaverryan
… and we can use them
lodash
@weaverryan
JavaScript utility library
1) Install it
> npm install lodash --save-dev
2) Use it
// web/js/productApp.js

// ...

import _ from 'lodash';



_.each(collection.getProducts(), function(product) {

// ...

});
@weaverryan
'./ProductCollection'
vs
'lodash'
@weaverryan
ReactJS
// web/js/productApp.js

import React from 'react';

import ReactDOM from 'react-dom';



var ProductApp = React.createClass({

render: function() {

return (

<h1>Yay!</h1>

)

}

});
??????
$(document).ready(function() {

ReactDOM.render(

<ProductApp/>,

document.getElementById('product-app')

);

});


<ProductApp myName="Ryan" /> 

JSX
React.createElement(

ProductApp,

{

myName: "Ryan"

}

)
This is not real EcmaScript,
but babel can handle it
… but it doesn’t yet
1) Install the babel preset
> npm install --save-dev babel-preset-react
2) Add the preset in .babelrc
@weaverryan
{

"presets": [

"es2015",

"react"

]

}
… nope - still not working
// productApp.js

import React from 'react';

import ReactDOM from 'react-dom';



var ProductApp = React.createClass({

render: function() {

return (

<h1>Yay!</h1>

)

}

});



$(document).ready(function() {

ReactDOM.render(

<ProductApp/>,

document.getElementById('product-app')

);

});

> npm install --save-dev react react-dom
… nope - still not working
It’s alive, but huge!
*file size would be much smaller in reality,
due to missing uglify and other production settings
@weaverryan
ReactJS is pretty easy
The setup to get here
is tough
React-101: props
@weaverryan
// web/js/Components/ProductList.js

import React from 'react';



var ProductList = React.createClass({

// ...

});



module.exports = ProductList;

// web/js/productApp.js

import ReactDOM from 'react-dom';

import ProductList from './Components/ProductList';



$(document).ready(function() {

ReactDOM.render(

<ProductList message="Great Products!" />,

document.getElementById('product-app')

);

});

It’s a prop!
// web/js/Components/ProductList.js

import React from 'react';



var ProductList = React.createClass({

render: function() {

return (

<h1>{this.props.message}</h1>

)

}

});



module.exports = ProductList;

hello again prop!
collection props
@weaverryan
// web/js/productApp.js



var startingProducts = [

'Sheer Shears',

'Wool Hauling Basket',

'After-Shear (Fresh Cut Grass)',

'After-Shear (Morning Dew)',

];



$(document).ready(function() {

ReactDOM.render(

<ProductList initialProducts={startingProducts} />,

document.getElementById('product-app')

);

});

// web/js/Components/ProductApp.js

import _ from 'lodash';



var ProductList = React.createClass({

render: function() {

var productRows = [];

_.each(this.props.initialProducts, function(product) {

productRows.push(

<tr>

<td>{product}</td>

<td className="product-price">

{Math.round(Math.random()*50)}

</td>

</tr>

);

});



// ...

}

});
// web/js/Components/ProductApp.js

import _ from 'lodash';



var ProductList = React.createClass({

render: function() {

var productRows = [];

// ...



return (

<div>

<h1>{this.props.message}</h1>



<table className="table">

<tbody>{productRows}</tbody>

</table>

</div>

)

}

});
React 101: initial data
@weaverryan
// web/js/productApp.js



var startingProducts = [

'Sheer Shears',

'Wool Hauling Basket',

'After-Shear (Fresh Cut Grass)',

'After-Shear (Morning Dew)',

];



$(document).ready(function() {

ReactDOM.render(

<ProductList initialProducts={startingProducts} />,

document.getElementById('product-app')

);

});

@weaverryan
{# app/Resources/views/default/products.html.twig #}

<script>

window.startingProducts = [

'Sheer Shears',

'Wool Hauling Basket',

'After-Shear (Fresh Cut Grass)',

'After-Shear (Morning Dew)',

];

</script>
// web/js/productApp.js

var startingProducts = window.startingProducts;



$(document).ready(function() {

ReactDOM.render(

<ProductApp initialProducts={startingProducts} />,

document.getElementById('product-app')

);

});
React 101: state
@weaverryan
var ProductApp = React.createClass({

render: function() {

return (

<div>

<h1>{this.props.message}</h1>

</div>

)

}

});
var ProductApp = React.createClass({

render: function() {

return (

<div>

<h1>{this.state.message}</h1>
<button onClick={this.handleClick}>

New Message

</button>

</div>

)

}

});
var ProductApp = React.createClass({


getInitialState: function() {

return {

message: 'Product List!';

}

}



// ...

}
var ProductApp = React.createClass({

render: function() {

return (

<div>

<h1>{this.state.message}</h1>
<button onClick={this.handleClick}>

New Message

</button>

</div>

)

}

});
var ProductApp = React.createClass({



handleClick: function(e) {

e.preventDefault();



this.setState({

message: 'New Message!'

})

},



// ...

}
@weaverryan
Putting it all together
@weaverryan
ES6/ES2015/ECMAScript 2015
The newest version of Javascript,
not supported by all browsers
@weaverryan
Babel
A tool that can transform JavaScript
to different JavaScript
presets
A) ES6 js to “old” JS
B) JSX to raw JS
@weaverryan
Webpack
A tool that follows imports to bundle
JavaScript, CSS, and anything else you
dream up into one JavaScript package
loaders
A) JS through Babel
B) CSS to inlined styles
C) images copied, paths used
@weaverryan
ReactJS
A nifty frontend framework where you pass
around and render props (immutable)
and state (mutable)
… but the JavaScript
world moves quickly…
Ryan Weaver
@weaverryan
THANK YOU!

More Related Content

What's hot

Node JS Express : Steps to Create Restful Web App
Node JS Express : Steps to Create Restful Web AppNode JS Express : Steps to Create Restful Web App
Node JS Express : Steps to Create Restful Web AppEdureka!
 
Future of Web Apps: Google Gears
Future of Web Apps: Google GearsFuture of Web Apps: Google Gears
Future of Web Apps: Google Gearsdion
 
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
 
Immutable Deployments with AWS CloudFormation and AWS Lambda
Immutable Deployments with AWS CloudFormation and AWS LambdaImmutable Deployments with AWS CloudFormation and AWS Lambda
Immutable Deployments with AWS CloudFormation and AWS LambdaAOE
 
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
 
Mobile Open Day: React Native: Crossplatform fast dive
Mobile Open Day: React Native: Crossplatform fast diveMobile Open Day: React Native: Crossplatform fast dive
Mobile Open Day: React Native: Crossplatform fast diveepamspb
 
Grand Rapids PHP Meetup: Behavioral Driven Development with Behat
Grand Rapids PHP Meetup: Behavioral Driven Development with BehatGrand Rapids PHP Meetup: Behavioral Driven Development with Behat
Grand Rapids PHP Meetup: Behavioral Driven Development with BehatRyan Weaver
 
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
 
Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Eric Palakovich Carr
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Elena Kolevska
 
Introduction to AngularJS For WordPress Developers
Introduction to AngularJS For WordPress DevelopersIntroduction to AngularJS For WordPress Developers
Introduction to AngularJS For WordPress DevelopersCaldera Labs
 
From Hacker to Programmer (w/ Webpack, Babel and React)
From Hacker to Programmer (w/ Webpack, Babel and React)From Hacker to Programmer (w/ Webpack, Babel and React)
From Hacker to Programmer (w/ Webpack, Babel and React)Joseph Chiang
 
Containers & Dependency in Ember.js
Containers & Dependency in Ember.jsContainers & Dependency in Ember.js
Containers & Dependency in Ember.jsMatthew Beale
 
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry PiGrâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry PiJérémy Derussé
 
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
 
Real World Lessons in Progressive Web Application & Service Worker Caching
Real World Lessons in Progressive Web Application & Service Worker CachingReal World Lessons in Progressive Web Application & Service Worker Caching
Real World Lessons in Progressive Web Application & Service Worker CachingChris Love
 

What's hot (20)

Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
 
Node JS Express : Steps to Create Restful Web App
Node JS Express : Steps to Create Restful Web AppNode JS Express : Steps to Create Restful Web App
Node JS Express : Steps to Create Restful Web App
 
Future of Web Apps: Google Gears
Future of Web Apps: Google GearsFuture of Web Apps: Google Gears
Future of Web Apps: Google Gears
 
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
 
The JavaFX Ecosystem
The JavaFX EcosystemThe JavaFX Ecosystem
The JavaFX Ecosystem
 
Immutable Deployments with AWS CloudFormation and AWS Lambda
Immutable Deployments with AWS CloudFormation and AWS LambdaImmutable Deployments with AWS CloudFormation and AWS Lambda
Immutable Deployments with AWS CloudFormation and AWS Lambda
 
Writing Pluggable Software
Writing Pluggable SoftwareWriting Pluggable Software
Writing Pluggable Software
 
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
 
Mobile Open Day: React Native: Crossplatform fast dive
Mobile Open Day: React Native: Crossplatform fast diveMobile Open Day: React Native: Crossplatform fast dive
Mobile Open Day: React Native: Crossplatform fast dive
 
Grand Rapids PHP Meetup: Behavioral Driven Development with Behat
Grand Rapids PHP Meetup: Behavioral Driven Development with BehatGrand Rapids PHP Meetup: Behavioral Driven Development with Behat
Grand Rapids PHP Meetup: Behavioral Driven Development with Behat
 
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
 
Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5
 
WebGUI Developers Workshop
WebGUI Developers WorkshopWebGUI Developers Workshop
WebGUI Developers Workshop
 
Introduction to AngularJS For WordPress Developers
Introduction to AngularJS For WordPress DevelopersIntroduction to AngularJS For WordPress Developers
Introduction to AngularJS For WordPress Developers
 
From Hacker to Programmer (w/ Webpack, Babel and React)
From Hacker to Programmer (w/ Webpack, Babel and React)From Hacker to Programmer (w/ Webpack, Babel and React)
From Hacker to Programmer (w/ Webpack, Babel and React)
 
Containers & Dependency in Ember.js
Containers & Dependency in Ember.jsContainers & Dependency in Ember.js
Containers & Dependency in Ember.js
 
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry PiGrâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
 
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...
 
Real World Lessons in Progressive Web Application & Service Worker Caching
Real World Lessons in Progressive Web Application & Service Worker CachingReal World Lessons in Progressive Web Application & Service Worker Caching
Real World Lessons in Progressive Web Application & Service Worker Caching
 

Similar to Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony Cat 2016)

Symfony Live 2018 - Développez votre frontend avec ReactJS et Symfony Webpack...
Symfony Live 2018 - Développez votre frontend avec ReactJS et Symfony Webpack...Symfony Live 2018 - Développez votre frontend avec ReactJS et Symfony Webpack...
Symfony Live 2018 - Développez votre frontend avec ReactJS et Symfony Webpack...Alain Hippolyte
 
Webpack Encore Symfony Live 2017 San Francisco
Webpack Encore Symfony Live 2017 San FranciscoWebpack Encore Symfony Live 2017 San Francisco
Webpack Encore Symfony Live 2017 San FranciscoRyan Weaver
 
Ruby on Rails survival guide of an aged Java developer
Ruby on Rails survival guide of an aged Java developerRuby on Rails survival guide of an aged Java developer
Ruby on Rails survival guide of an aged Java developergicappa
 
(2018) Webpack Encore - Asset Management for the rest of us
(2018) Webpack Encore - Asset Management for the rest of us(2018) Webpack Encore - Asset Management for the rest of us
(2018) Webpack Encore - Asset Management for the rest of usStefan Adolf
 
BOF2644 Developing Java EE 7 Scala apps
BOF2644 Developing Java EE 7 Scala appsBOF2644 Developing Java EE 7 Scala apps
BOF2644 Developing Java EE 7 Scala appsPeter Pilgrim
 
A few good JavaScript development tools
A few good JavaScript development toolsA few good JavaScript development tools
A few good JavaScript development toolsSimon Kim
 
Jazoon12 355 aleksandra_gavrilovska-1
Jazoon12 355 aleksandra_gavrilovska-1Jazoon12 355 aleksandra_gavrilovska-1
Jazoon12 355 aleksandra_gavrilovska-1Netcetera
 
Intro to ES6 and why should you bother !
Intro to ES6 and why should you bother !Intro to ES6 and why should you bother !
Intro to ES6 and why should you bother !Gaurav Behere
 
Webpack Encore - Asset Management for the rest of us
Webpack Encore - Asset Management for the rest of usWebpack Encore - Asset Management for the rest of us
Webpack Encore - Asset Management for the rest of usStefan Adolf
 
Angular JS in 2017
Angular JS in 2017Angular JS in 2017
Angular JS in 2017Ayush Sharma
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyDavid Padbury
 
(Declarative) Jenkins Pipelines
(Declarative) Jenkins Pipelines(Declarative) Jenkins Pipelines
(Declarative) Jenkins PipelinesSteffen Gebert
 
Testing - Selenium? Rich-Clients? Containers?
Testing - Selenium? Rich-Clients? Containers?Testing - Selenium? Rich-Clients? Containers?
Testing - Selenium? Rich-Clients? Containers?Tobias Schneck
 
Ruby on Rails Kickstart 101 & 102
Ruby on Rails Kickstart 101 & 102Ruby on Rails Kickstart 101 & 102
Ruby on Rails Kickstart 101 & 102Heng-Yi Wu
 
Deploying Docker (Provisioning /w Docker + Chef/Puppet) - DevopsDaysPGH
Deploying Docker (Provisioning /w Docker + Chef/Puppet) - DevopsDaysPGHDeploying Docker (Provisioning /w Docker + Chef/Puppet) - DevopsDaysPGH
Deploying Docker (Provisioning /w Docker + Chef/Puppet) - DevopsDaysPGHErica Windisch
 
20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdev20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdevFrank Rousseau
 
RichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile DevicesRichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile DevicesPavol Pitoňák
 

Similar to Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony Cat 2016) (20)

Symfony Live 2018 - Développez votre frontend avec ReactJS et Symfony Webpack...
Symfony Live 2018 - Développez votre frontend avec ReactJS et Symfony Webpack...Symfony Live 2018 - Développez votre frontend avec ReactJS et Symfony Webpack...
Symfony Live 2018 - Développez votre frontend avec ReactJS et Symfony Webpack...
 
Webpack Encore Symfony Live 2017 San Francisco
Webpack Encore Symfony Live 2017 San FranciscoWebpack Encore Symfony Live 2017 San Francisco
Webpack Encore Symfony Live 2017 San Francisco
 
Ruby on Rails survival guide of an aged Java developer
Ruby on Rails survival guide of an aged Java developerRuby on Rails survival guide of an aged Java developer
Ruby on Rails survival guide of an aged Java developer
 
(2018) Webpack Encore - Asset Management for the rest of us
(2018) Webpack Encore - Asset Management for the rest of us(2018) Webpack Encore - Asset Management for the rest of us
(2018) Webpack Encore - Asset Management for the rest of us
 
BOF2644 Developing Java EE 7 Scala apps
BOF2644 Developing Java EE 7 Scala appsBOF2644 Developing Java EE 7 Scala apps
BOF2644 Developing Java EE 7 Scala apps
 
A few good JavaScript development tools
A few good JavaScript development toolsA few good JavaScript development tools
A few good JavaScript development tools
 
Play framework
Play frameworkPlay framework
Play framework
 
Jazoon12 355 aleksandra_gavrilovska-1
Jazoon12 355 aleksandra_gavrilovska-1Jazoon12 355 aleksandra_gavrilovska-1
Jazoon12 355 aleksandra_gavrilovska-1
 
Intro to ES6 and why should you bother !
Intro to ES6 and why should you bother !Intro to ES6 and why should you bother !
Intro to ES6 and why should you bother !
 
Webpack Encore - Asset Management for the rest of us
Webpack Encore - Asset Management for the rest of usWebpack Encore - Asset Management for the rest of us
Webpack Encore - Asset Management for the rest of us
 
Angular JS in 2017
Angular JS in 2017Angular JS in 2017
Angular JS in 2017
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight Guy
 
(Declarative) Jenkins Pipelines
(Declarative) Jenkins Pipelines(Declarative) Jenkins Pipelines
(Declarative) Jenkins Pipelines
 
The JavaFX Ecosystem
The JavaFX EcosystemThe JavaFX Ecosystem
The JavaFX Ecosystem
 
Testing - Selenium? Rich-Clients? Containers?
Testing - Selenium? Rich-Clients? Containers?Testing - Selenium? Rich-Clients? Containers?
Testing - Selenium? Rich-Clients? Containers?
 
Ruby on Rails Kickstart 101 & 102
Ruby on Rails Kickstart 101 & 102Ruby on Rails Kickstart 101 & 102
Ruby on Rails Kickstart 101 & 102
 
Nashorn
NashornNashorn
Nashorn
 
Deploying Docker (Provisioning /w Docker + Chef/Puppet) - DevopsDaysPGH
Deploying Docker (Provisioning /w Docker + Chef/Puppet) - DevopsDaysPGHDeploying Docker (Provisioning /w Docker + Chef/Puppet) - DevopsDaysPGH
Deploying Docker (Provisioning /w Docker + Chef/Puppet) - DevopsDaysPGH
 
20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdev20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdev
 
RichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile DevicesRichFaces - Testing on Mobile Devices
RichFaces - Testing on Mobile Devices
 

More from Ryan Weaver

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
 
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
 
Guard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful SecurityGuard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful SecurityRyan Weaver
 
Twig: Friendly Curly Braces Invade Your Templates!
Twig: Friendly Curly Braces Invade Your Templates!Twig: Friendly Curly Braces Invade Your Templates!
Twig: Friendly Curly Braces Invade Your Templates!Ryan Weaver
 
Master the New Core of Drupal 8 Now: with Symfony and Silex
Master the New Core of Drupal 8 Now: with Symfony and SilexMaster the New Core of Drupal 8 Now: with Symfony and Silex
Master the New Core of Drupal 8 Now: with Symfony and SilexRyan Weaver
 
Silex: Microframework y camino fácil de aprender Symfony
Silex: Microframework y camino fácil de aprender SymfonySilex: Microframework y camino fácil de aprender Symfony
Silex: Microframework y camino fácil de aprender SymfonyRyan Weaver
 
Drupal 8: Huge wins, a Bigger Community, and why you (and I) will Love it
Drupal 8: Huge wins, a Bigger Community, and why you (and I) will Love itDrupal 8: Huge wins, a Bigger Community, and why you (and I) will Love it
Drupal 8: Huge wins, a Bigger Community, and why you (and I) will Love itRyan Weaver
 
Cool like a Frontend Developer: Grunt, RequireJS, Bower and other Tools
Cool like a Frontend Developer: Grunt, RequireJS, Bower and other ToolsCool like a Frontend Developer: Grunt, RequireJS, Bower and other Tools
Cool like a Frontend Developer: Grunt, RequireJS, Bower and other ToolsRyan Weaver
 
The Wonderful World of Symfony Components
The Wonderful World of Symfony ComponentsThe Wonderful World of Symfony Components
The Wonderful World of Symfony ComponentsRyan Weaver
 
A PHP Christmas Miracle - 3 Frameworks, 1 app
A PHP Christmas Miracle - 3 Frameworks, 1 appA PHP Christmas Miracle - 3 Frameworks, 1 app
A PHP Christmas Miracle - 3 Frameworks, 1 appRyan Weaver
 
Symfony2: Get your project started
Symfony2: Get your project startedSymfony2: Get your project started
Symfony2: Get your project startedRyan Weaver
 
Symony2 A Next Generation PHP Framework
Symony2 A Next Generation PHP FrameworkSymony2 A Next Generation PHP Framework
Symony2 A Next Generation PHP FrameworkRyan Weaver
 
Hands-on with the Symfony2 Framework
Hands-on with the Symfony2 FrameworkHands-on with the Symfony2 Framework
Hands-on with the Symfony2 FrameworkRyan Weaver
 
Being Dangerous with Twig (Symfony Live Paris)
Being Dangerous with Twig (Symfony Live Paris)Being Dangerous with Twig (Symfony Live Paris)
Being Dangerous with Twig (Symfony Live Paris)Ryan Weaver
 
Being Dangerous with Twig
Being Dangerous with TwigBeing Dangerous with Twig
Being Dangerous with TwigRyan Weaver
 
Doctrine2 In 10 Minutes
Doctrine2 In 10 MinutesDoctrine2 In 10 Minutes
Doctrine2 In 10 MinutesRyan Weaver
 
Dependency Injection: Make your enemies fear you
Dependency Injection: Make your enemies fear youDependency Injection: Make your enemies fear you
Dependency Injection: Make your enemies fear youRyan Weaver
 
The Art of Doctrine Migrations
The Art of Doctrine MigrationsThe Art of Doctrine Migrations
The Art of Doctrine MigrationsRyan Weaver
 

More from Ryan Weaver (19)

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 2017
 
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 more
 
Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)
 
Guard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful SecurityGuard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful Security
 
Twig: Friendly Curly Braces Invade Your Templates!
Twig: Friendly Curly Braces Invade Your Templates!Twig: Friendly Curly Braces Invade Your Templates!
Twig: Friendly Curly Braces Invade Your Templates!
 
Master the New Core of Drupal 8 Now: with Symfony and Silex
Master the New Core of Drupal 8 Now: with Symfony and SilexMaster the New Core of Drupal 8 Now: with Symfony and Silex
Master the New Core of Drupal 8 Now: with Symfony and Silex
 
Silex: Microframework y camino fácil de aprender Symfony
Silex: Microframework y camino fácil de aprender SymfonySilex: Microframework y camino fácil de aprender Symfony
Silex: Microframework y camino fácil de aprender Symfony
 
Drupal 8: Huge wins, a Bigger Community, and why you (and I) will Love it
Drupal 8: Huge wins, a Bigger Community, and why you (and I) will Love itDrupal 8: Huge wins, a Bigger Community, and why you (and I) will Love it
Drupal 8: Huge wins, a Bigger Community, and why you (and I) will Love it
 
Cool like a Frontend Developer: Grunt, RequireJS, Bower and other Tools
Cool like a Frontend Developer: Grunt, RequireJS, Bower and other ToolsCool like a Frontend Developer: Grunt, RequireJS, Bower and other Tools
Cool like a Frontend Developer: Grunt, RequireJS, Bower and other Tools
 
The Wonderful World of Symfony Components
The Wonderful World of Symfony ComponentsThe Wonderful World of Symfony Components
The Wonderful World of Symfony Components
 
A PHP Christmas Miracle - 3 Frameworks, 1 app
A PHP Christmas Miracle - 3 Frameworks, 1 appA PHP Christmas Miracle - 3 Frameworks, 1 app
A PHP Christmas Miracle - 3 Frameworks, 1 app
 
Symfony2: Get your project started
Symfony2: Get your project startedSymfony2: Get your project started
Symfony2: Get your project started
 
Symony2 A Next Generation PHP Framework
Symony2 A Next Generation PHP FrameworkSymony2 A Next Generation PHP Framework
Symony2 A Next Generation PHP Framework
 
Hands-on with the Symfony2 Framework
Hands-on with the Symfony2 FrameworkHands-on with the Symfony2 Framework
Hands-on with the Symfony2 Framework
 
Being Dangerous with Twig (Symfony Live Paris)
Being Dangerous with Twig (Symfony Live Paris)Being Dangerous with Twig (Symfony Live Paris)
Being Dangerous with Twig (Symfony Live Paris)
 
Being Dangerous with Twig
Being Dangerous with TwigBeing Dangerous with Twig
Being Dangerous with Twig
 
Doctrine2 In 10 Minutes
Doctrine2 In 10 MinutesDoctrine2 In 10 Minutes
Doctrine2 In 10 Minutes
 
Dependency Injection: Make your enemies fear you
Dependency Injection: Make your enemies fear youDependency Injection: Make your enemies fear you
Dependency Injection: Make your enemies fear you
 
The Art of Doctrine Migrations
The Art of Doctrine MigrationsThe Art of Doctrine Migrations
The Art of Doctrine Migrations
 

Recently uploaded

Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesZilliz
 

Recently uploaded (20)

Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector Databases
 

Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony Cat 2016)

  • 1. Finally, Professional Frontend dev with: ReactJS, Webpack & Symfony ♥’s
  • 2. > Lead of the Symfony documentation team
 > KnpLabs US - Symfony consulting, training & kumbaya > Writer for KnpUniversity.com: PHP & Symfony screencasts packed with puns, unrelated (but entertaining) illustrations and coding challenges! > Husband of the much more talented @leannapelham knpuniversity.com twitter.com/weaverryan ¡Hola!
  • 3. ♥’s Finally, Professional Frontend dev with: ReactJS, Webpack & Symfony
  • 4. , ReactJS, webpack @weaverryan All of Modern JavaScript in 45 minutes! ES6 the 12 new JS things they invent during this presentation , ES2015 , ECMAScript , Babel , NodeJS npm , JSX … … and of course …
  • 5. Modern JavaScript is a lot like… @weaverryan Game of Thrones
  • 6. JavaScript @weaverryan GoT Countless libraries and competing standards fighting for influence Countless characters and completing factions fighting for influence
  • 7. @weaverryan You spent 6 months building your site in <Cool.JS> only to read on Twitter that: “no self-respecting dev uses that crap anymore” That character you love and followed for 2 seasons, was just unceremoniously decapitated JavaScript GoT
  • 9. JavaScript is a (weird) language IT JUST HAPPENS THAT BROWSERS CAN EXECUTE THAT LANGUAGE
  • 10. @weaverryan // yay.js
 var message = 'I like Java...Script';
 
 console.log(message); > node yay.js I like Java...Script NodeJS: server-side JavaScript engine npm: Composer for NodeJS
  • 11. @weaverryan Follow along with the real code: github.com/weaverryan/symfonycat-js (hint: look at the history, each thing we do is its own commit)
  • 12. // web/js/productApp.js
 var products = [
 'Sheer Shears',
 'Wool Hauling Basket',
 'After-Shear (Fresh Cut Grass)',
 'After-Shear (Morning Dew)'
 ];
 
 var loopThroughProducts = function(callback) {
 for (var i = 0, length = products.length; i < length; i++) {
 callback(products[i]);
 }
 };
 
 loopThroughProducts(function(product) {
 console.log('Product: '+product);
 }); {# app/Resources/views/default/products.html.twig' #} <script src="{{ asset('js/productApp.js') }}"></script> our store for sheep (baaaa)
  • 13.
  • 14. class ProductCollection
 {
 constructor(products) {
 this.products = products;
 }
 }
 
 let collection = new ProductCollection([
 'Sheer Shears',
 'Wool Hauling Basket',
 'After-Shear (Fresh Cut Grass)',
 'After-Shear (Morning Dew)',
 ]);
 let prods = collection.getProducts();
 
 let loopThroughProducts = function(callback) {
 for (let i = 0, length = prods.length; i < length; i++) {
 callback(collection.getProduct(i));
 }
 };
 
 loopThroughProducts(product => console.log('Product: '+product)); what language is this? JavaScript
  • 15. @weaverryan ECMAScript The official name of standard JavaScript ES6/ES2015/Harmony The 6th accepted (so official) version of ECMAScript
  • 16. class ProductCollection
 {
 constructor(products) {
 this.products = products;
 }
 }
 
 let collection = new ProductCollection([
 'Sheer Shears',
 'Wool Hauling Basket',
 'After-Shear (Fresh Cut Grass)',
 'After-Shear (Morning Dew)',
 ]);
 let prods = collection.getProducts();
 
 let loopThroughProducts = function(callback) {
 for (let i = 0, length = prods.length; i < length; i++) {
 callback(collection.getProduct(i));
 }
 };
 
 loopThroughProducts(product => console.log('Product: '+product)); But will it run in a browser??? Maybe!
  • 17. class ProductCollection
 {
 constructor(products) {
 this.products = products;
 }
 }
 
 let collection = new ProductCollection([
 'Sheer Shears',
 'Wool Hauling Basket',
 'After-Shear (Fresh Cut Grass)',
 'After-Shear (Morning Dew)',
 ]);
 let prods = collection.getProducts();
 
 let loopThroughProducts = function(callback) {
 for (let i = 0, length = prods.length; i < length; i++) {
 callback(collection.getProduct(i));
 }
 };
 
 loopThroughProducts(product => console.log(product)); Proper class and inheritance syntax let: similar to var, but different function (product) {
 console.log(product);
 }
  • 18. Now we just need to wait 5 years for the crappiest browsers to support this
  • 19. @weaverryan Babel … or do we? A JS transpiler!
  • 20. Babel is a NodeJS binary… {
 "name": "js-tutorial",
 "version": "1.0.0"
 } 1) Make a package.json file 2) Download babel > npm install --save-dev babel-cli @weaverryan
  • 21. > ./node_modules/.bin/babel web/js/productApp.js -o web/builds/productApp.js {# app/Resources/views/default/products.html.twig' #} <script src="{{ asset('builds/productApp.js') }}"></script> @weaverryan
  • 22. > ./node_modules/.bin/babel web/js/productApp.js -o web/builds/productApp.js {# app/Resources/views/default/products.html.twig' #} <script src="{{ asset('builds/productApp.js') }}"></script> But, this made no changes js/productApp.js == builds/productApp.js @weaverryan
  • 23. Babel can transpile anything CoffeeScript --> JavaScript Coffee --> Tea ES6 JS --> ES5 JS * Each transformation is called a preset
  • 24. 1) Install the es2015 preset library 2) Add a .babelrc file > npm install --save-dev babel-preset-es2015 {
 "presets": [
 "es2015"
 ]
 } @weaverryan
  • 25. > ./node_modules/.bin/babel web/js/productApp.js -o web/builds/productApp.js loopThroughProducts(
 product => console.log('Product: '+product)
 ); loopThroughProducts(function (product) {
 return console.log('Product: ' + product);
 });
 source: built:
  • 26. But we can use new (or experimental) features now @weaverryan Modern JavaScript has a build step Big Takeaway #1:
  • 28. The Classic Problem: If you want to organize your JS into multiple files, you need to manually include all those script tags! @weaverryan
  • 29. // web/js/ProductCollection.js 
 class ProductCollection
 {
 constructor(products) {
 this.products = products;
 }
 
 getProducts() {
 return this.products;
 }
 
 getProduct(i) {
 return this.products[i];
 }
 }
 
 export ProductCollection;
 @weaverryan
  • 30. // web/js/productApp.js
 
 import ProductCollection from './ProductCollection';
 
 var collection = new ProductCollection([
 'Sheer Shears',
 'Wool Hauling Basket',
 'After-Shear (Fresh Cut Grass)',
 'After-Shear (Morning Dew)',
 ]);
 
 // ... {# app/Resources/views/default/products.html.twig' #} <script src="{{ asset('builds/productApp.js') }}"></script>
  • 31. // web/js/productApp.js
 
 import ProductCollection from './ProductCollection';
 
 var collection = new ProductCollection([
 'Sheer Shears',
 'Wool Hauling Basket',
 'After-Shear (Fresh Cut Grass)',
 'After-Shear (Morning Dew)',
 ]);
 
 // ... {# app/Resources/views/default/products.html.twig' #} <script src="{{ asset('builds/productApp.js') }}"></script> > ./node_modules/.bin/babel web/js/productApp.js -o web/builds/productApp.js
  • 32.
  • 33. Module loading in a browser is hard to do @weaverryan
  • 35. @weaverryan Webpack! • bundler • module loader • all-around nice guy
  • 36. Install webpack > npm install --save-dev webpack @weaverryan
  • 37. Use require instead of import/export * * I’ll tell you why later // web/js/ProductCollection.js
 class ProductCollection
 {
 // ...
 }
 
 module.exports = ProductCollection;
 // web/js/productApp.js
 var ProductCollection = require('./ProductCollection');
 
 // ...
  • 38. Go webpack Go! > ./node_modules/.bin/webpack web/js/productApp.js web/builds/productApp.js The one built file contains the code from both source files
  • 39. Optional config to make it easier to use: // webpack.config.js
 module.exports = {
 entry: {
 product: './web/js/productApp.js'
 },
 output: {
 path: './web/builds',
 filename: '[name].js',
 publicPath: '/builds/'
 }
 };
 builds/product.js {# app/Resources/views/default/products.html.twig' #} <script src="{{ asset('builds/product.js') }}"></script>
  • 41. Wait! We lost our ES6->ES5 transformation!!! @weaverryan
  • 42. Hey webpack! Yo! When you load .js files, can you run them through Babel for me? - kthxbai <3 Ryan webpack loaders allow you to transform files as they’re loaded
  • 43. 1) Install the babel-loader 2) Activate the loader in webpack.config.js > npm install --save-dev babel-loader module.exports = {
 // ...
 module: {
 loaders: [
 {
 test: /.js$/,
 loader: "babel-loader", exclude: /node_modules/
 }
 ]
 }
 };

  • 46. Use import/export now if you prefer // web/js/ProductCollection.js
 class ProductCollection
 {
 // ...
 }
 
 export default ProductCollection;
 // web/js/productApp.js
 import ProductCollection from './ProductCollection';
 
 // ...

  • 48. @weaverryan Dev Tools … because life is too short to run webpack after every change you make
  • 49. > npm install webpack-dev-server --save-dev > ./node_modules/.bin/webpack-dev-server --content-base=./web/ @weaverryan 1) Install the webpack-dev-server 2) Run that!
  • 50. http://localhost:8080 - static assets are served - compiled assets are served dynamically
  • 51. Wait! @weaverryan Don’t I need to update all my script tags? <script
 src="{{ asset('builds/product.js') }}"> <script
 src="http://localost:8080/builds/product.js">
  • 53. … or the real solution @weaverryan # app/config/parameters.yml
 parameters:
 # ...
 use_webpack_dev_server: true

  • 54. class AppKernel extends Kernel
 {
 // ...
 
 public function registerContainerConfiguration(LoaderInterface $loader)
 {
 // ...
 
 $loader->load(function(ContainerBuilder $container) {
 if ($container->getParameter('use_webpack_dev_server')) {
 $container->loadFromExtension('framework', [
 'assets' => [
 'base_url' => 'http://localhost:8080'
 ]
 ]);
 }
 });
 }
 } … or the real solution @weaverryan
  • 55. @weaverryan Status Update we can: • use ES6 features • import and export modules
  • 57. Could we do this? // web/js/productApp.js
 import ProductCollection from './ProductCollection';
 
 // could this somehow load that CSS for us?
 import '../css/productApp.css';
 
 // ... Loader!
  • 58. module.exports = {
 // ...
 module: {
 loaders: [
 {
 test: /.js$/,
 exclude: /node_modules/,
 loader: "babel-loader"
 }
 ]
 }
 };
 webpack loaders allow you to transform files as they’re loaded Remember:
  • 59. 1) Install the css-loader 2) Activate the loader just for this file > npm install css-loader --save-dev import 'css!../css/productApp.css'; this transforms the CSS into a JS data- structure… but does nothing with it
  • 60. 1) Install the style-loader > npm install style-loader --save-dev import 'style!css!../css/productApp.css'; inlines the CSS on the page in a style tag 2) Activate both loaders for this file
  • 61. Yes, @weaverryan the one JS file now holds the contents of two JS files and a CSS file {# app/Resources/views/default/products.html.twig' #} <script src="{{ asset('builds/product.js') }}"></script>
  • 62. Move the loader to config to simplify import '../css/productApp.css'; // webpack.config.js module.exports = {
 // ...
 module: {
 loaders: [
 // ...
 {
 test: /.css$/,
 loader: "style!css"
 }
 ]
 },
 };

  • 63. @weaverryan Ah, but what should my image paths look like? /* productApp.css */
 .product-price {
 color: green;
 background-image: url('../images/logo.png');
 }
 http://example.com/products/5/photos/../images/logo.png http://example.com/products/5/photos
  • 64. This broke webpack! Yes, webpack parses the CSS and tries to load file imports and url() references (i.e. to images & fonts)
  • 65. 1) Install the file-loader & url-loader > npm install file-loader url-loader --save-dev 2) Activate the loader for .png files // webpack.config.js // ... loaders: [
 // ...
 {
 test: /.png/,
 loader: "url-loader?limit=10000"
 }
 ]

  • 66. {
 test: /.png/,
 loader: "url-loader?limit=10000"
 } For .png files < 10kb image is turned into a “data url” and inlined in the CSS For .png files > 10kb image is copied to builds/ and the new URL is written into the CSS
  • 67. Stop @weaverryan thinking of your JavaScript as random code that executes
  • 68. Start @weaverryan thinking of your JavaScript as a single application with dependencies that are all packaged up together
  • 69. @weaverryan Unleashing the Power of NodeJS and ReactJS
  • 70. Like Composer, NodeJS has a lot of third-party libraries @weaverryan … and we can use them
  • 72. 1) Install it > npm install lodash --save-dev 2) Use it // web/js/productApp.js
 // ...
 import _ from 'lodash';
 
 _.each(collection.getProducts(), function(product) {
 // ...
 }); @weaverryan './ProductCollection' vs 'lodash'
  • 74. // web/js/productApp.js
 import React from 'react';
 import ReactDOM from 'react-dom';
 
 var ProductApp = React.createClass({
 render: function() {
 return (
 <h1>Yay!</h1>
 )
 }
 }); ?????? $(document).ready(function() {
 ReactDOM.render(
 <ProductApp/>,
 document.getElementById('product-app')
 );
 });
  • 75. 
 <ProductApp myName="Ryan" /> 
 JSX React.createElement(
 ProductApp,
 {
 myName: "Ryan"
 }
 ) This is not real EcmaScript, but babel can handle it
  • 76. … but it doesn’t yet
  • 77. 1) Install the babel preset > npm install --save-dev babel-preset-react 2) Add the preset in .babelrc @weaverryan {
 "presets": [
 "es2015",
 "react"
 ]
 }
  • 78. … nope - still not working
  • 79. // productApp.js
 import React from 'react';
 import ReactDOM from 'react-dom';
 
 var ProductApp = React.createClass({
 render: function() {
 return (
 <h1>Yay!</h1>
 )
 }
 });
 
 $(document).ready(function() {
 ReactDOM.render(
 <ProductApp/>,
 document.getElementById('product-app')
 );
 });

  • 80. > npm install --save-dev react react-dom … nope - still not working
  • 81. It’s alive, but huge! *file size would be much smaller in reality, due to missing uglify and other production settings
  • 82. @weaverryan ReactJS is pretty easy The setup to get here is tough
  • 83. React-101: props @weaverryan // web/js/Components/ProductList.js
 import React from 'react';
 
 var ProductList = React.createClass({
 // ...
 });
 
 module.exports = ProductList;

  • 84. // web/js/productApp.js
 import ReactDOM from 'react-dom';
 import ProductList from './Components/ProductList';
 
 $(document).ready(function() {
 ReactDOM.render(
 <ProductList message="Great Products!" />,
 document.getElementById('product-app')
 );
 });
 It’s a prop!
  • 85. // web/js/Components/ProductList.js
 import React from 'react';
 
 var ProductList = React.createClass({
 render: function() {
 return (
 <h1>{this.props.message}</h1>
 )
 }
 });
 
 module.exports = ProductList;
 hello again prop!
  • 86. collection props @weaverryan // web/js/productApp.js
 
 var startingProducts = [
 'Sheer Shears',
 'Wool Hauling Basket',
 'After-Shear (Fresh Cut Grass)',
 'After-Shear (Morning Dew)',
 ];
 
 $(document).ready(function() {
 ReactDOM.render(
 <ProductList initialProducts={startingProducts} />,
 document.getElementById('product-app')
 );
 });

  • 87. // web/js/Components/ProductApp.js
 import _ from 'lodash';
 
 var ProductList = React.createClass({
 render: function() {
 var productRows = [];
 _.each(this.props.initialProducts, function(product) {
 productRows.push(
 <tr>
 <td>{product}</td>
 <td className="product-price">
 {Math.round(Math.random()*50)}
 </td>
 </tr>
 );
 });
 
 // ...
 }
 });
  • 88. // web/js/Components/ProductApp.js
 import _ from 'lodash';
 
 var ProductList = React.createClass({
 render: function() {
 var productRows = [];
 // ...
 
 return (
 <div>
 <h1>{this.props.message}</h1>
 
 <table className="table">
 <tbody>{productRows}</tbody>
 </table>
 </div>
 )
 }
 });
  • 89. React 101: initial data @weaverryan // web/js/productApp.js
 
 var startingProducts = [
 'Sheer Shears',
 'Wool Hauling Basket',
 'After-Shear (Fresh Cut Grass)',
 'After-Shear (Morning Dew)',
 ];
 
 $(document).ready(function() {
 ReactDOM.render(
 <ProductList initialProducts={startingProducts} />,
 document.getElementById('product-app')
 );
 });

  • 90. @weaverryan {# app/Resources/views/default/products.html.twig #}
 <script>
 window.startingProducts = [
 'Sheer Shears',
 'Wool Hauling Basket',
 'After-Shear (Fresh Cut Grass)',
 'After-Shear (Morning Dew)',
 ];
 </script> // web/js/productApp.js
 var startingProducts = window.startingProducts;
 
 $(document).ready(function() {
 ReactDOM.render(
 <ProductApp initialProducts={startingProducts} />,
 document.getElementById('product-app')
 );
 });
  • 92. var ProductApp = React.createClass({
 render: function() {
 return (
 <div>
 <h1>{this.props.message}</h1>
 </div>
 )
 }
 });
  • 93. var ProductApp = React.createClass({
 render: function() {
 return (
 <div>
 <h1>{this.state.message}</h1> <button onClick={this.handleClick}>
 New Message
 </button>
 </div>
 )
 }
 });
  • 94. var ProductApp = React.createClass({ 
 getInitialState: function() {
 return {
 message: 'Product List!';
 }
 }
 
 // ...
 }
  • 95. var ProductApp = React.createClass({
 render: function() {
 return (
 <div>
 <h1>{this.state.message}</h1> <button onClick={this.handleClick}>
 New Message
 </button>
 </div>
 )
 }
 });
  • 96. var ProductApp = React.createClass({
 
 handleClick: function(e) {
 e.preventDefault();
 
 this.setState({
 message: 'New Message!'
 })
 },
 
 // ...
 }
  • 98. @weaverryan ES6/ES2015/ECMAScript 2015 The newest version of Javascript, not supported by all browsers
  • 99. @weaverryan Babel A tool that can transform JavaScript to different JavaScript presets A) ES6 js to “old” JS B) JSX to raw JS
  • 100. @weaverryan Webpack A tool that follows imports to bundle JavaScript, CSS, and anything else you dream up into one JavaScript package loaders A) JS through Babel B) CSS to inlined styles C) images copied, paths used
  • 101. @weaverryan ReactJS A nifty frontend framework where you pass around and render props (immutable) and state (mutable)
  • 102. … but the JavaScript world moves quickly…