Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.
Finally, Professional
Frontend dev with:
ReactJS, Webpack & Symfony
♥’s
> Lead of the Symfony documentation team

> KnpLabs US - Symfony consulting, training & kumbaya
> Writer for KnpUniversity...
♥’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 pr...
Modern JavaScript
is a lot like…
@weaverryan
Game of Thrones
JavaScript
@weaverryan
GoT
Countless libraries and
competing standards fighting
for influence
Countless characters and
compl...
@weaverryan
You spent 6 months building
your site in <Cool.JS> only
to read on Twitter that:
“no self-respecting dev
uses ...
@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
N...
@weaverryan
Follow along with the real code:
github.com/weaverryan/symfonycat-js
(hint: look at the history, each
thing we...
// web/js/productApp.js

var products = [

'Sheer Shears',

'Wool Hauling Basket',

'After-Shear (Fresh Cut Grass)',

'Aft...
class ProductCollection

{

constructor(products) {

this.products = products;

}

}



let collection = new ProductCollec...
@weaverryan
ECMAScript
The official name of standard JavaScript
ES6/ES2015/Harmony
The 6th accepted (so official) version
of E...
class ProductCollection

{

constructor(products) {

this.products = products;

}

}



let collection = new ProductCollec...
class ProductCollection

{

constructor(products) {

this.products = products;

}

}



let collection = new ProductCollec...
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
> ...
> ./node_modules/.bin/babel 
web/js/productApp.js 
-o web/builds/productApp.js
{# app/Resources/views/default/products.htm...
> ./node_modules/.bin/babel 
web/js/productApp.js 
-o web/builds/productApp.js
{# app/Resources/views/default/products.htm...
Babel can transpile anything
CoffeeScript --> JavaScript
Coffee --> Tea
ES6 JS --> ES5 JS
* Each transformation is called a ...
1) Install the es2015 preset library
2) Add a .babelrc file
> npm install --save-dev babel-preset-es2015
{

"presets": [

"...
> ./node_modules/.bin/babel 
web/js/productApp.js 
-o web/builds/productApp.js
loopThroughProducts(

product => console.lo...
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 tag...
// web/js/ProductCollection.js


class ProductCollection

{

constructor(products) {

this.products = products;

}



getP...
// web/js/productApp.js



import ProductCollection from './ProductCollection';



var collection = new ProductCollection(...
// web/js/productApp.js



import ProductCollection from './ProductCollection';



var collection = new ProductCollection(...
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

...
Go webpack Go!
> ./node_modules/.bin/webpack 
web/js/productApp.js 
web/builds/productApp.js
The one built file contains
th...
Optional config to make it easier to use:
// webpack.config.js

module.exports = {

entry: {

product: './web/js/productApp...
> ./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 yo...
1) Install the babel-loader
2) Activate the loader in webpack.config.js
> npm install --save-dev babel-loader
module.export...
> ./node_modules/.bin/webpack
@weaverryan
Module loading
+
ES6 Support
Use import/export now if you prefer
// web/js/ProductCollection.js

class ProductCollection

{

// ...

}



export defaul...
> ./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)...
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...
# 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)

{

/...
@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 l...
module.exports = {

// ...

module: {

loaders: [

{

test: /.js$/,

exclude: /node_modules/,

loader: "babel-loader"

}

...
1) Install the css-loader
2) Activate the loader just for this file
> npm install css-loader --save-dev
import 'css!../css/...
1) Install the style-loader
> npm install style-loader --save-dev
import 'style!css!../css/productApp.css';
inlines the CS...
Yes,
@weaverryan
the one JS file now holds the contents of
two JS files and a CSS file
{# app/Resources/views/default/product...
Move the loader to config to simplify
import '../css/productApp.css';
// webpack.config.js
module.exports = {

// ...

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

.product-price {

color: green;

backgroun...
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 file...
{

test: /.png/,

loader: "url-loader?limit=10000"

}
For .png files < 10kb
image is turned into a “data url”
and inlined i...
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...
@weaverryan
ReactJS
// web/js/productApp.js

import React from 'react';

import ReactDOM from 'react-dom';



var ProductApp = React.createCla...


<ProductApp myName="Ryan" /> 

JSX
React.createElement(

ProductApp,

{

myName: "Ryan"

}

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

"pres...
… nope - still not working
// productApp.js

import React from 'react';

import ReactDOM from 'react-dom';



var ProductApp = React.createClass({

r...
> 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.cr...
// web/js/productApp.js

import ReactDOM from 'react-dom';

import ProductList from './Components/ProductList';



$(docum...
// web/js/Components/ProductList.js

import React from 'react';



var ProductList = React.createClass({

render: function...
collection props
@weaverryan
// web/js/productApp.js



var startingProducts = [

'Sheer Shears',

'Wool Hauling Basket',
...
// web/js/Components/ProductApp.js

import _ from 'lodash';



var ProductList = React.createClass({

render: function() {...
// web/js/Components/ProductApp.js

import _ from 'lodash';



var ProductList = React.createClass({

render: function() {...
React 101: initial data
@weaverryan
// web/js/productApp.js



var startingProducts = [

'Sheer Shears',

'Wool Hauling Ba...
@weaverryan
{# app/Resources/views/default/products.html.twig #}

<script>

window.startingProducts = [

'Sheer Shears',

...
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...
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...
var ProductApp = React.createClass({



handleClick: function(e) {

e.preventDefault();



this.setState({

message: 'New ...
@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 ...
@weaverryan
Webpack
A tool that follows imports to bundle
JavaScript, CSS, and anything else you
dream up into one JavaScr...
@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!
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony Cat 2016)
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony Cat 2016)
Prochain SlideShare
Chargement dans…5
×

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

11 041 vues

Publié le

If you're like me, you know that being a great backend developer isn't enough. To make *truly* great applications, we need to spend significant time in an area that's moving at a lightning pace: frontend development.
This talk is for you: the backend developer that wants to hook their API's up to rich, interactive JavaScript frontends. To do that, first, we need to demystify a lot of new terms, like ES6/ES2015, ECMAScript, JSX, Babel and the idea that modern JavaScript (surprise) *requires* a build step.
With this in mind, I'll give you a brief introduction into Webpack & the modular development it finally allows.
But the real star is ReactJS. In the frontend world, you never know what new tech will *win*, but React is a star. I'll give you enough of an intro to get you rolling on your project.
The new frontend dev world is huge! Consider the starting line down an exciting new journey.

Publié dans : Technologie

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

  1. 1. Finally, Professional Frontend dev with: ReactJS, Webpack & Symfony ♥’s
  2. 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. 3. ♥’s Finally, Professional Frontend dev with: ReactJS, Webpack & Symfony
  4. 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. 5. Modern JavaScript is a lot like… @weaverryan Game of Thrones
  6. 6. JavaScript @weaverryan GoT Countless libraries and competing standards fighting for influence Countless characters and completing factions fighting for influence
  7. 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
  8. 8. @weaverryan Plain, boring old JavaScript
  9. 9. JavaScript is a (weird) language IT JUST HAPPENS THAT BROWSERS CAN EXECUTE THAT LANGUAGE
  10. 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. 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. 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. 13. 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
  14. 14. @weaverryan ECMAScript The official name of standard JavaScript ES6/ES2015/Harmony The 6th accepted (so official) version of ECMAScript
  15. 15. 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!
  16. 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)); Proper class and inheritance syntax let: similar to var, but different function (product) {
 console.log(product);
 }
  17. 17. Now we just need to wait 5 years for the crappiest browsers to support this
  18. 18. @weaverryan Babel … or do we? A JS transpiler!
  19. 19. 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
  20. 20. > ./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
  21. 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> But, this made no changes js/productApp.js == builds/productApp.js @weaverryan
  22. 22. Babel can transpile anything CoffeeScript --> JavaScript Coffee --> Tea ES6 JS --> ES5 JS * Each transformation is called a preset
  23. 23. 1) Install the es2015 preset library 2) Add a .babelrc file > npm install --save-dev babel-preset-es2015 {
 "presets": [
 "es2015"
 ]
 } @weaverryan
  24. 24. > ./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:
  25. 25. But we can use new (or experimental) features now @weaverryan Modern JavaScript has a build step Big Takeaway #1:
  26. 26. @weaverryan New to ES6: JavaScript Modules!
  27. 27. The Classic Problem: If you want to organize your JS into multiple files, you need to manually include all those script tags! @weaverryan
  28. 28. // web/js/ProductCollection.js 
 class ProductCollection
 {
 constructor(products) {
 this.products = products;
 }
 
 getProducts() {
 return this.products;
 }
 
 getProduct(i) {
 return this.products[i];
 }
 }
 
 export ProductCollection;
 @weaverryan
  29. 29. // 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>
  30. 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> > ./node_modules/.bin/babel web/js/productApp.js -o web/builds/productApp.js
  31. 31. Module loading in a browser is hard to do @weaverryan
  32. 32. @weaverryan Introducing…
  33. 33. @weaverryan Webpack! • bundler • module loader • all-around nice guy
  34. 34. Install webpack > npm install --save-dev webpack @weaverryan
  35. 35. 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');
 
 // ...
  36. 36. 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
  37. 37. 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>
  38. 38. > ./node_modules/.bin/webpack @weaverryan
  39. 39. Wait! We lost our ES6->ES5 transformation!!! @weaverryan
  40. 40. 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
  41. 41. 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/
 }
 ]
 }
 };

  42. 42. > ./node_modules/.bin/webpack @weaverryan
  43. 43. Module loading + ES6 Support
  44. 44. Use import/export now if you prefer // web/js/ProductCollection.js
 class ProductCollection
 {
 // ...
 }
 
 export default ProductCollection;
 // web/js/productApp.js
 import ProductCollection from './ProductCollection';
 
 // ...

  45. 45. > ./node_modules/.bin/webpack @weaverryan
  46. 46. @weaverryan Dev Tools … because life is too short to run webpack after every change you make
  47. 47. > 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!
  48. 48. http://localhost:8080 - static assets are served - compiled assets are served dynamically
  49. 49. 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">
  50. 50. # app/config/config.yml
 framework:
 assets:
 base_url: http://localhost:8080 Boom! @weaverryan
  51. 51. … or the real solution @weaverryan # app/config/parameters.yml
 parameters:
 # ...
 use_webpack_dev_server: true

  52. 52. 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
  53. 53. @weaverryan Status Update we can: • use ES6 features • import and export modules
  54. 54. @weaverryan CSS: An un-handled dependency of your JS app
  55. 55. 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!
  56. 56. module.exports = {
 // ...
 module: {
 loaders: [
 {
 test: /.js$/,
 exclude: /node_modules/,
 loader: "babel-loader"
 }
 ]
 }
 };
 webpack loaders allow you to transform files as they’re loaded Remember:
  57. 57. 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
  58. 58. 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
  59. 59. 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>
  60. 60. Move the loader to config to simplify import '../css/productApp.css'; // webpack.config.js module.exports = {
 // ...
 module: {
 loaders: [
 // ...
 {
 test: /.css$/,
 loader: "style!css"
 }
 ]
 },
 };

  61. 61. @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
  62. 62. This broke webpack! Yes, webpack parses the CSS and tries to load file imports and url() references (i.e. to images & fonts)
  63. 63. 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"
 }
 ]

  64. 64. {
 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
  65. 65. Stop @weaverryan thinking of your JavaScript as random code that executes
  66. 66. Start @weaverryan thinking of your JavaScript as a single application with dependencies that are all packaged up together
  67. 67. @weaverryan Unleashing the Power of NodeJS and ReactJS
  68. 68. Like Composer, NodeJS has a lot of third-party libraries @weaverryan … and we can use them
  69. 69. lodash @weaverryan JavaScript utility library
  70. 70. 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'
  71. 71. @weaverryan ReactJS
  72. 72. // 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')
 );
 });
  73. 73. 
 <ProductApp myName="Ryan" /> 
 JSX React.createElement(
 ProductApp,
 {
 myName: "Ryan"
 }
 ) This is not real EcmaScript, but babel can handle it
  74. 74. … but it doesn’t yet
  75. 75. 1) Install the babel preset > npm install --save-dev babel-preset-react 2) Add the preset in .babelrc @weaverryan {
 "presets": [
 "es2015",
 "react"
 ]
 }
  76. 76. … nope - still not working
  77. 77. // 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')
 );
 });

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

  82. 82. // 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!
  83. 83. // 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!
  84. 84. 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')
 );
 });

  85. 85. // 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>
 );
 });
 
 // ...
 }
 });
  86. 86. // 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>
 )
 }
 });
  87. 87. 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')
 );
 });

  88. 88. @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')
 );
 });
  89. 89. React 101: state @weaverryan
  90. 90. var ProductApp = React.createClass({
 render: function() {
 return (
 <div>
 <h1>{this.props.message}</h1>
 </div>
 )
 }
 });
  91. 91. var ProductApp = React.createClass({
 render: function() {
 return (
 <div>
 <h1>{this.state.message}</h1> <button onClick={this.handleClick}>
 New Message
 </button>
 </div>
 )
 }
 });
  92. 92. var ProductApp = React.createClass({ 
 getInitialState: function() {
 return {
 message: 'Product List!';
 }
 }
 
 // ...
 }
  93. 93. var ProductApp = React.createClass({
 render: function() {
 return (
 <div>
 <h1>{this.state.message}</h1> <button onClick={this.handleClick}>
 New Message
 </button>
 </div>
 )
 }
 });
  94. 94. var ProductApp = React.createClass({
 
 handleClick: function(e) {
 e.preventDefault();
 
 this.setState({
 message: 'New Message!'
 })
 },
 
 // ...
 }
  95. 95. @weaverryan Putting it all together
  96. 96. @weaverryan ES6/ES2015/ECMAScript 2015 The newest version of Javascript, not supported by all browsers
  97. 97. @weaverryan Babel A tool that can transform JavaScript to different JavaScript presets A) ES6 js to “old” JS B) JSX to raw JS
  98. 98. @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
  99. 99. @weaverryan ReactJS A nifty frontend framework where you pass around and render props (immutable) and state (mutable)
  100. 100. … but the JavaScript world moves quickly…
  101. 101. Ryan Weaver @weaverryan THANK YOU!

×