SlideShare a Scribd company logo
1 of 93
Download to read offline
Develop your frontend
web app with Webpack
Encore and ReactJS
Hi ! I’m Alain
Senior Dev
Mobility Work
@Al0ne_H
Thanks Ryan
$ symfony live thanks @weaverryan
Love sent to
💖 @weaverryan
Encore Webpack…
Webpack Encore
, ReactJS, webpack
All of modern JavaScript in 40
minutes!
ES6
the 12 new JS things they invent
during this presentation
, ES2015 , ECMAScript
, Babel
, NodeJS
yarn , modules …
… and of course …
JAVASCRIPT FATIGUE
Javascript
Fatigue
• Choice paralysis
• Feeling that we become obsolete if
don’t use the newest tools
• Frustrated with a lack of
documentation or… StackOverflow
snippets
// yay.js

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



console.log(message);
> node yay.js
I like Java...Script
NodeJS: server-side
JavaScript engine
yarn/npm: Composer
for NodeJS
// 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>
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 = callback => {

for (let prod of prods) {

callback(prods);

}

};



loopThroughProducts(product => console.log('Product: '+product));
what language
is this?
JavaScript
ECMAScript
The official name of standard JavaScript
ES6/ES2015/Harmony
The 6th accepted (so official) version
of ECMAScript
Proper class and
inheritance syntax
let: similar to var,
but more hipster
function (product) {

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

}
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 = callback => {

for (let prod of prods) {

callback(prods);

}

};



loopThroughProducts(product => console.log('Product: '+product));
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 = callback => {

for (let prod of prods) {

callback(prods);

}

};



loopThroughProducts(product => console.log('Product: '+product));
But will it run in a browser???
Maybe!
Now we just need to
wait 5 years for the
worst browsers
to support this
Babel
… or do we?
A JS transpiler!
{

"devDependencies": {

"babel-cli": "^6.10.1"

}

}
Babel is a NodeJS binary…
… package.json
> yarn add --dev babel-cli
Babel can transpile anything
CoffeeScript --> JavaScript
Coffee --> Tea
ES6 JS --> ES5 JS
* you configure what you want to transpile
Draft ES features --> ES5 JS
> ./node_modules/.bin/babel 
web/js/productApp.js 
-o web/build/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
Modern JavaScript
has a build step
Big Takeaway #1:
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!
// web/js/ProductCollection.js


class ProductCollection

{

constructor(products) {

this.products = products;

}



getProducts() {

return this.products;

}



getProduct(i) {

return this.products[i];

}

}



export default ProductCollection;

// 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
Introducing…
@weaverryan
Webpack!
• bundler
• module loader
• all-around nice guy
Install webpack
> yarn add --dev webpack
// web/js/ProductCollection.js


class ProductCollection

{

// ...

}



export default ProductCollection;

// web/js/productApp.js



import ProductCollection from './ProductCollection';



// …
Go webpack Go!
> ./node_modules/.bin/webpack 
web/js/productApp.js 
web/build/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/build',

filename: '[name].js',

publicPath: '/build/'

}

};

build/product.js
{# app/Resources/views/default/products.html.twig' #}
<script src="{{ asset('build/product.js') }}"></script>
> ./node_modules/.bin/webpack
> yarn run webpack
Great!
Now let’s add more
features to Webpack!
Features, features, features, features, features
• babel transpiling
• dev server
• production optimizations
• CSS handling
• Sass/LESS
• PostCSS
• React
• Vue
• versioning
• source maps
• image handling
• extract text
• shared entry
• jQuery providing
• TypeScript
• friendly errors
No Problem
var path = require("path");

var process = require('process');

var webpack = require('webpack');

var production = process.env.NODE_ENV === 'production';



// helps load CSS to their own file

var ExtractPlugin = require('extract-text-webpack-plugin');

var CleanPlugin = require('clean-webpack-plugin');

var ManifestPlugin = require('webpack-manifest-plugin');



var plugins = [

new ExtractPlugin('[name]-[contenthash].css'), // <=== where should content be piped



// put vendor_react stuff into its own file

// new webpack.optimize.CommonsChunkPlugin({

// name: 'vendor_react',

// chunks: ['vendor_react'],

// minChunks: Infinity, // avoid anything else going in here

// }),

new webpack.optimize.CommonsChunkPlugin({

name: 'main', // Move dependencies to the "main" entry

minChunks: Infinity, // How many times a dependency must come up before being extracted

}),

new ManifestPlugin({

filename: 'manifest.json',

// prefixes all keys with builds/, which allows us to refer to

// the paths as builds/main.css in Twig, instead of just main.css

basePath: 'builds/'

}),

];



if (production) {

plugins = plugins.concat([

// This plugin looks for similar chunks and files

// and merges them for better caching by the user

new webpack.optimize.DedupePlugin(),



// This plugins optimizes chunks and modules by

// how much they are used in your app

new webpack.optimize.OccurenceOrderPlugin(),



// This plugin prevents Webpack from creating chunks

// that would be too small to be worth loading separately

new webpack.optimize.MinChunkSizePlugin({

minChunkSize: 51200, // ~50kb

}),



// This plugin minifies all the Javascript code of the final bundle

new webpack.optimize.UglifyJsPlugin({

mangle: true,

compress: {

warnings: false, // Suppress uglification warnings

},

sourceMap: false

}),



// This plugins defines various variables that we can set to false

// in production to avoid code related to them from being compiled

// in our final bundle

new webpack.DefinePlugin({

__SERVER__: !production,

__DEVELOPMENT__: !production,

__DEVTOOLS__: !production,

'process.env': {

BABEL_ENV: JSON.stringify(process.env.NODE_ENV),

'NODE_ENV': JSON.stringify('production')

},

}),

new CleanPlugin('web/builds', {

root: path.resolve(__dirname , '..')

}),

]);

}





module.exports = {

entry: {

main: './main',

video: './video',

checkout_login_registration: './checkout_login_registration',

team_pricing: './team_pricing',

credit_card: './credit_card',

team_subscription: './team_subscription',

track_organization: './track_organization',

challenge: './challenge',

workflow: './workflow',

code_block_styles: './code_block_styles',

content_release: './content_release',

script_editor: './script_editor',

sweetalert2_legacy: './sweetalert2_legacy',

admin: './admin',

admin_user_refund: './admin_user_refund',



// vendor entry points to be extracted into their own file

// we do this to keep main.js smaller... but it's a pain

// because now we need to manually add the script tag for

// this file is we use react or react-dom

// vendor_react: ['react', 'react-dom'],

},

output: {

path: path.resolve(__dirname, '../web/builds'),

filename: '[name]-[hash].js',

chunkFilename: '[name]-[chunkhash].js',

// in dev, make all URLs go through the webpack-dev-server

// things *mostly* work without this, but AJAX calls for chunks

// are made to the local, Symfony server without this

publicPath: production ? '/builds/' : 'http://localhost:8090/builds/'

},

plugins: plugins,

module: {

loaders: [

{

test: /.js$/,

exclude: /node_modules/,

loader: "babel-loader"

},

{

test: /.scss/,

loader: ExtractPlugin.extract('style', 'css!sass'),

},

{

test: /.css/,

loader: ExtractPlugin.extract('style', 'css'),

},

{

test: /.(png|gif|jpe?g|svg?(?v=[0-9].[0-9].[0-9])?)$/i,

loader: 'url?limit=10000',

},

{

// the ?(?v=[0-9].[0-9].[0-9])? is for ?v=1.1.1 format

test: /.woff(2)?(?v=[0-9].[0-9].[0-9])?$/,

// Inline small woff files and output them below font/.

// Set mimetype just in case.

loader: 'url',

query: {

prefix: 'font/',

limit: 5000,

mimetype: 'application/font-woff'

},

//include: PATHS.fonts

},

{

test: /.ttf?(?v=[0-9].[0-9].[0-9])?$|.eot?(?v=[0-9].[0-9].[0-9])?$/,

loader: 'file',

query: {

name: '[name]-[hash].[ext]',

// does this do anything?

prefix: 'font/',

},

//include: PATHS.fonts

},

{

test: /.json$/,

loader: "json-loader"

},

]

},

node: {

fs: 'empty'

},

debug: !production,

devtool: production ? false : 'eval',

devServer: {

hot: true,

port: 8090,

// tells webpack-dev-server where to serve public files from

contentBase: '../web/',

headers: { "Access-Control-Allow-Origin": "*" }

},

};

*** not visible here:
the 1000 ways you
can shot yourself
in the foot
Hello Webpack Encore
Let’s start over
> rm -rf package.json yarn.lock node_modules/
… and let’s start simple
// assets/js/app.js


console.log(‘Hello World !’);

> yarn add @symfony/webpack-encore --dev
Step 1: Install Encore
Step 2: webpack.config.js
var Encore = require('@symfony/webpack-encore');



Encore

.setOutputPath('web/build/')

.setPublicPath('/build')



// will output as web/build/app.js

.addEntry('app', './assets/js/app.js')



.enableSourceMaps(!Encore.isProduction())

;



module.exports = Encore.getWebpackConfig();

> yarn run encore dev --watch
{# base.html.twig #}

<script src="{{ asset('build/app.js') }}"></script>
Yea… but I need
my jQuery’s!
// assets/js/app.js

import $ from 'jquery';



$(document).ready(function() {

$('h1').append('I love big text!');

});

// assets/js/app.js

const $ = require('jquery');



$(document).ready(function() {

$('h1').append('I love big text!');

});

> yarn run encore dev
> yarn add jquery --dev
@weaverryan
CSS: An un-handled dependency of your
JS app
Could we do this?
// assets/js/app.js
// ...

require('../css/cool-app.css');



$(document).ready(function() {

$('h1').append('I love big text!');

});

> yarn run encore dev —watch
{# base.html.twig #}

<link ... href="{{ asset('build/app.css') }}">
Want Bootstrap?
> yarn add bootstrap
@weaverryan
/* assets/css/cool-app.css */

@import "~bootstrap/dist/css/bootstrap.css";

/* ... */
> yarn run encore dev --watch
But what about images & fonts?
/* assets/css/cool-app.css */

.product-price {

color: green;

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

}

> yarn add bootstrap
/* assets/css/cool-app.css */

@import "~bootstrap/dist/css/bootstrap.css";

/* ... */
> yarn run encore dev --watch
images & fonts are copied to build/ and
the new URL is written into the CSS
Stop
thinking of your JavaScript as
random code that executes
Start
thinking of your JavaScript as
a single application with dependencies
that are all packaged up together
Sass instead of CSS?
> yarn run encore dev
// assets/js/app.js

// ...

require('../css/app.scss');
> yarn add sass-loader node-sass --dev
// webpack.config.js



Encore

// ...



.enableSassLoader()
But I want page-specific
CSS and JS files!
// assets/js/productApp.js

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

import $ from 'jquery';



$(document).ready(function() {

console.log('product page loaded!');

});

// webpack.config.js



Encore

// ...



.addEntry('app', './assets/js/app.js')

.addEntry('productApp', './assets/js/productApp.js')
{# product.html.twig #}

{% block stylesheets %}

{{ parent() }}



<link href="{{ asset('build/productApp.css') }}">

{% endblock %}



{% block javascripts %}

{{ parent() }}



<script src="{{ asset('build/productApp.js') }}"></script>

{% endblock %}

> yarn run encore dev --watch
Wait!
You have too many jQuery-ies!
jQuery is in here
… and also here
// webpack.config.js



Encore

// ...



.createSharedEntry('app', './assets/js/app.js')

.addEntry('productApp', './assets/js/productApp.js')
{# base.html.twig #}

<script src="{{ asset('build/manifest.js') }}"></script>

<script src="{{ asset('build/app.js') }}"></script>
Asset Versioning
// webpack.config.js



Encore

// ...



.enableVersioning()
Amazing! Automatic
Cache Busting!!!
… oh wait…
manifest.json to the rescue!
{

"build/app.css": "/build/app.3666e24a0be80f22bd8f31c43a70b14f.css",

"build/app.js": "/build/app.f18c7a7f2785d99e0c25.js",

"build/images/logo.png": "/build/images/logo.482c1dc2.png",

"build/manifest.js": "/build/manifest.d41d8cd98f00b204e980.js",

"build/productApp.css": "/build/productApp.01f416c68486810b3cb9.css",

"build/productApp.js": "/build/productApp.1af5d8e89a35e521309b.js"

}
{# base.html.twig #}

<script src="{{ asset('build/manifest.js') }}"></script>

<script src="{{ asset('build/app.js') }}"></script>
manifest.json to the rescue!
# app/config/config.yml
# config/packages/framework.yaml

framework:

# ...

assets:

json_manifest_path: '%kernel.project_dir%/web/build/manifest.json'
… so add long-term
caching…
Passing Data
into JavaScript
{# products.html.twig #}

<div id="product-app"

data-products="{{ products|json_encode|e('html_attr') }}">

</div>
// assets/js/productApp.js



const root = document.getElementById('product-app');

const startingProducts = root.dataset.products;

This presentation needs
more buzz words
React!
// assets/js/productApp.js



import React from 'react';

import ReactDOM from 'react-dom';

import ProductApp from './Components/ProductApp';

import $ from 'jquery';



$(document).ready(function() {

const root = document.getElementById('product-app');

const startingProducts = root.dataset['products'];



ReactDOM.render(

<ProductApp message="Great Products!”
initialProducts={startingProducts} />,


root

);

});
// webpack.config.js



Encore

// ...

.enableReactPreset()

;
> yarn add --dev react react-dom babel-preset-react
• React & Preact
• Vue
• TypeScript
• Code splitting
• source maps
• versioning
• Sass/LESS/Stylus
• minification
… and is the life of any party …
An Encore of Features
Deployment?
… the dirty way…
install Node on production and
execute encore there
the happier way!
run Encore on some *other* machine
and copy your build/ directory
Putting it all together
ES6/ES2015/ECMAScript 2015
The newest version of Javascript,
not supported by all browsers
Babel
A tool that can transform JavaScript
to different JavaScript
A) ES6 js to “old” JS
B) React to raw JS
Webpack
A tool that follows imports to bundle
JavaScript, CSS, and anything else you
dream up into one JavaScript package
Webpack Encore
A tool that makes configuring
webpack not suck
So go write some
amazing JavaScript!
Alain Hippolyte
@Al0neh_H
THANK YOU!
https://joind.in/talk/33621

More Related Content

Similar to Symfony Live 2018 - Développez votre frontend avec ReactJS et Symfony Webpack Encore

Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...Ryan Weaver
 
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
 
(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
 
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
 
SenchaCon 2016: The Modern Toolchain - Ross Gerbasi
SenchaCon 2016: The Modern Toolchain - Ross Gerbasi   SenchaCon 2016: The Modern Toolchain - Ross Gerbasi
SenchaCon 2016: The Modern Toolchain - Ross Gerbasi Sencha
 
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
 
A few good JavaScript development tools
A few good JavaScript development toolsA few good JavaScript development tools
A few good JavaScript development toolsSimon Kim
 
20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdev20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdevFrank Rousseau
 
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013Carlos Sanchez
 
OpenSource ToolChain for the Hybrid Cloud
OpenSource ToolChain for the Hybrid CloudOpenSource ToolChain for the Hybrid Cloud
OpenSource ToolChain for the Hybrid CloudIsaac Christoffersen
 
The Peanut Butter Cup of Web-dev: Plack and single page web apps
The Peanut Butter Cup of Web-dev: Plack and single page web appsThe Peanut Butter Cup of Web-dev: Plack and single page web apps
The Peanut Butter Cup of Web-dev: Plack and single page web appsJohn Anderson
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasminePaulo Ragonha
 
Building and deploying React applications
Building and deploying React applicationsBuilding and deploying React applications
Building and deploying React applicationsAstrails
 
[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVCAlive Kuo
 
Harmonious Development: Via Vagrant and Puppet
Harmonious Development: Via Vagrant and PuppetHarmonious Development: Via Vagrant and Puppet
Harmonious Development: Via Vagrant and PuppetAchieve Internet
 
Jazoon12 355 aleksandra_gavrilovska-1
Jazoon12 355 aleksandra_gavrilovska-1Jazoon12 355 aleksandra_gavrilovska-1
Jazoon12 355 aleksandra_gavrilovska-1Netcetera
 
From Dev to DevOps - FOSDEM 2012
From Dev to DevOps - FOSDEM 2012From Dev to DevOps - FOSDEM 2012
From Dev to DevOps - FOSDEM 2012Carlos Sanchez
 
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
 

Similar to Symfony Live 2018 - Développez votre frontend avec ReactJS et Symfony Webpack Encore (20)

Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
 
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
 
(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
 
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
 
SenchaCon 2016: The Modern Toolchain - Ross Gerbasi
SenchaCon 2016: The Modern Toolchain - Ross Gerbasi   SenchaCon 2016: The Modern Toolchain - Ross Gerbasi
SenchaCon 2016: The Modern Toolchain - Ross Gerbasi
 
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
 
Play framework
Play frameworkPlay framework
Play framework
 
A few good JavaScript development tools
A few good JavaScript development toolsA few good JavaScript development tools
A few good JavaScript development tools
 
20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdev20130528 solution linux_frousseau_nopain_webdev
20130528 solution linux_frousseau_nopain_webdev
 
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
 
OpenSource ToolChain for the Hybrid Cloud
OpenSource ToolChain for the Hybrid CloudOpenSource ToolChain for the Hybrid Cloud
OpenSource ToolChain for the Hybrid Cloud
 
The Peanut Butter Cup of Web-dev: Plack and single page web apps
The Peanut Butter Cup of Web-dev: Plack and single page web appsThe Peanut Butter Cup of Web-dev: Plack and single page web apps
The Peanut Butter Cup of Web-dev: Plack and single page web apps
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
Building and deploying React applications
Building and deploying React applicationsBuilding and deploying React applications
Building and deploying React applications
 
[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC
 
Harmonious Development: Via Vagrant and Puppet
Harmonious Development: Via Vagrant and PuppetHarmonious Development: Via Vagrant and Puppet
Harmonious Development: Via Vagrant and Puppet
 
infra-as-code
infra-as-codeinfra-as-code
infra-as-code
 
Jazoon12 355 aleksandra_gavrilovska-1
Jazoon12 355 aleksandra_gavrilovska-1Jazoon12 355 aleksandra_gavrilovska-1
Jazoon12 355 aleksandra_gavrilovska-1
 
From Dev to DevOps - FOSDEM 2012
From Dev to DevOps - FOSDEM 2012From Dev to DevOps - FOSDEM 2012
From Dev to DevOps - FOSDEM 2012
 
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)
 

Recently uploaded

2022 AWS DNA Hackathon 장애 대응 솔루션 jarvis.
2022 AWS DNA Hackathon 장애 대응 솔루션 jarvis.2022 AWS DNA Hackathon 장애 대응 솔루션 jarvis.
2022 AWS DNA Hackathon 장애 대응 솔루션 jarvis.elesangwon
 
Katarzyna Lipka-Sidor - BIM School Course
Katarzyna Lipka-Sidor - BIM School CourseKatarzyna Lipka-Sidor - BIM School Course
Katarzyna Lipka-Sidor - BIM School Coursebim.edu.pl
 
Energy Awareness training ppt for manufacturing process.pptx
Energy Awareness training ppt for manufacturing process.pptxEnergy Awareness training ppt for manufacturing process.pptx
Energy Awareness training ppt for manufacturing process.pptxsiddharthjain2303
 
Virtual memory management in Operating System
Virtual memory management in Operating SystemVirtual memory management in Operating System
Virtual memory management in Operating SystemRashmi Bhat
 
DEVICE DRIVERS AND INTERRUPTS SERVICE MECHANISM.pdf
DEVICE DRIVERS AND INTERRUPTS  SERVICE MECHANISM.pdfDEVICE DRIVERS AND INTERRUPTS  SERVICE MECHANISM.pdf
DEVICE DRIVERS AND INTERRUPTS SERVICE MECHANISM.pdfAkritiPradhan2
 
Cost estimation approach: FP to COCOMO scenario based question
Cost estimation approach: FP to COCOMO scenario based questionCost estimation approach: FP to COCOMO scenario based question
Cost estimation approach: FP to COCOMO scenario based questionSneha Padhiar
 
SOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATIONSOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATIONSneha Padhiar
 
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENTFUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENTSneha Padhiar
 
CS 3251 Programming in c all unit notes pdf
CS 3251 Programming in c all unit notes pdfCS 3251 Programming in c all unit notes pdf
CS 3251 Programming in c all unit notes pdfBalamuruganV28
 
Research Methodology for Engineering pdf
Research Methodology for Engineering pdfResearch Methodology for Engineering pdf
Research Methodology for Engineering pdfCaalaaAbdulkerim
 
Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________Romil Mishra
 
Python Programming for basic beginners.pptx
Python Programming for basic beginners.pptxPython Programming for basic beginners.pptx
Python Programming for basic beginners.pptxmohitesoham12
 
Artificial Intelligence in Power System overview
Artificial Intelligence in Power System overviewArtificial Intelligence in Power System overview
Artificial Intelligence in Power System overviewsandhya757531
 
Levelling - Rise and fall - Height of instrument method
Levelling - Rise and fall - Height of instrument methodLevelling - Rise and fall - Height of instrument method
Levelling - Rise and fall - Height of instrument methodManicka Mamallan Andavar
 
11. Properties of Liquid Fuels in Energy Engineering.pdf
11. Properties of Liquid Fuels in Energy Engineering.pdf11. Properties of Liquid Fuels in Energy Engineering.pdf
11. Properties of Liquid Fuels in Energy Engineering.pdfHafizMudaserAhmad
 
Comprehensive energy systems.pdf Comprehensive energy systems.pdf
Comprehensive energy systems.pdf Comprehensive energy systems.pdfComprehensive energy systems.pdf Comprehensive energy systems.pdf
Comprehensive energy systems.pdf Comprehensive energy systems.pdfalene1
 
System Simulation and Modelling with types and Event Scheduling
System Simulation and Modelling with types and Event SchedulingSystem Simulation and Modelling with types and Event Scheduling
System Simulation and Modelling with types and Event SchedulingBootNeck1
 
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor CatchersTechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catcherssdickerson1
 
Engineering Drawing section of solid
Engineering Drawing     section of solidEngineering Drawing     section of solid
Engineering Drawing section of solidnamansinghjarodiya
 
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...Erbil Polytechnic University
 

Recently uploaded (20)

2022 AWS DNA Hackathon 장애 대응 솔루션 jarvis.
2022 AWS DNA Hackathon 장애 대응 솔루션 jarvis.2022 AWS DNA Hackathon 장애 대응 솔루션 jarvis.
2022 AWS DNA Hackathon 장애 대응 솔루션 jarvis.
 
Katarzyna Lipka-Sidor - BIM School Course
Katarzyna Lipka-Sidor - BIM School CourseKatarzyna Lipka-Sidor - BIM School Course
Katarzyna Lipka-Sidor - BIM School Course
 
Energy Awareness training ppt for manufacturing process.pptx
Energy Awareness training ppt for manufacturing process.pptxEnergy Awareness training ppt for manufacturing process.pptx
Energy Awareness training ppt for manufacturing process.pptx
 
Virtual memory management in Operating System
Virtual memory management in Operating SystemVirtual memory management in Operating System
Virtual memory management in Operating System
 
DEVICE DRIVERS AND INTERRUPTS SERVICE MECHANISM.pdf
DEVICE DRIVERS AND INTERRUPTS  SERVICE MECHANISM.pdfDEVICE DRIVERS AND INTERRUPTS  SERVICE MECHANISM.pdf
DEVICE DRIVERS AND INTERRUPTS SERVICE MECHANISM.pdf
 
Cost estimation approach: FP to COCOMO scenario based question
Cost estimation approach: FP to COCOMO scenario based questionCost estimation approach: FP to COCOMO scenario based question
Cost estimation approach: FP to COCOMO scenario based question
 
SOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATIONSOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATION
 
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENTFUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
 
CS 3251 Programming in c all unit notes pdf
CS 3251 Programming in c all unit notes pdfCS 3251 Programming in c all unit notes pdf
CS 3251 Programming in c all unit notes pdf
 
Research Methodology for Engineering pdf
Research Methodology for Engineering pdfResearch Methodology for Engineering pdf
Research Methodology for Engineering pdf
 
Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________
 
Python Programming for basic beginners.pptx
Python Programming for basic beginners.pptxPython Programming for basic beginners.pptx
Python Programming for basic beginners.pptx
 
Artificial Intelligence in Power System overview
Artificial Intelligence in Power System overviewArtificial Intelligence in Power System overview
Artificial Intelligence in Power System overview
 
Levelling - Rise and fall - Height of instrument method
Levelling - Rise and fall - Height of instrument methodLevelling - Rise and fall - Height of instrument method
Levelling - Rise and fall - Height of instrument method
 
11. Properties of Liquid Fuels in Energy Engineering.pdf
11. Properties of Liquid Fuels in Energy Engineering.pdf11. Properties of Liquid Fuels in Energy Engineering.pdf
11. Properties of Liquid Fuels in Energy Engineering.pdf
 
Comprehensive energy systems.pdf Comprehensive energy systems.pdf
Comprehensive energy systems.pdf Comprehensive energy systems.pdfComprehensive energy systems.pdf Comprehensive energy systems.pdf
Comprehensive energy systems.pdf Comprehensive energy systems.pdf
 
System Simulation and Modelling with types and Event Scheduling
System Simulation and Modelling with types and Event SchedulingSystem Simulation and Modelling with types and Event Scheduling
System Simulation and Modelling with types and Event Scheduling
 
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor CatchersTechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
 
Engineering Drawing section of solid
Engineering Drawing     section of solidEngineering Drawing     section of solid
Engineering Drawing section of solid
 
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...
 

Symfony Live 2018 - Développez votre frontend avec ReactJS et Symfony Webpack Encore

  • 1. Develop your frontend web app with Webpack Encore and ReactJS
  • 2. Hi ! I’m Alain Senior Dev Mobility Work @Al0ne_H
  • 3. Thanks Ryan $ symfony live thanks @weaverryan Love sent to 💖 @weaverryan
  • 6. , ReactJS, webpack All of modern JavaScript in 40 minutes! ES6 the 12 new JS things they invent during this presentation , ES2015 , ECMAScript , Babel , NodeJS yarn , modules … … and of course …
  • 8. Javascript Fatigue • Choice paralysis • Feeling that we become obsolete if don’t use the newest tools • Frustrated with a lack of documentation or… StackOverflow snippets
  • 9. // yay.js
 var message = 'I like Java...Script';
 
 console.log(message); > node yay.js I like Java...Script NodeJS: server-side JavaScript engine yarn/npm: Composer for NodeJS
  • 10. // 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>
  • 11.
  • 12. 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 = callback => {
 for (let prod of prods) {
 callback(prods);
 }
 };
 
 loopThroughProducts(product => console.log('Product: '+product)); what language is this? JavaScript
  • 13. ECMAScript The official name of standard JavaScript ES6/ES2015/Harmony The 6th accepted (so official) version of ECMAScript
  • 14. Proper class and inheritance syntax let: similar to var, but more hipster function (product) {
 console.log(‘Product: ‘ +product);
 } 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 = callback => {
 for (let prod of prods) {
 callback(prods);
 }
 };
 
 loopThroughProducts(product => console.log('Product: '+product));
  • 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 = callback => {
 for (let prod of prods) {
 callback(prods);
 }
 };
 
 loopThroughProducts(product => console.log('Product: '+product)); But will it run in a browser??? Maybe!
  • 16. Now we just need to wait 5 years for the worst browsers to support this
  • 17. Babel … or do we? A JS transpiler!
  • 18. {
 "devDependencies": {
 "babel-cli": "^6.10.1"
 }
 } Babel is a NodeJS binary… … package.json > yarn add --dev babel-cli
  • 19. Babel can transpile anything CoffeeScript --> JavaScript Coffee --> Tea ES6 JS --> ES5 JS * you configure what you want to transpile Draft ES features --> ES5 JS
  • 20. > ./node_modules/.bin/babel web/js/productApp.js -o web/build/productApp.js loopThroughProducts(
 product => console.log('Product: '+product)
 ); loopThroughProducts(function (product) {
 return console.log('Product: ' + product);
 });
 source: built:
  • 21. But we can use new (or experimental) features now Modern JavaScript has a build step Big Takeaway #1:
  • 23. The Classic Problem: If you want to organize your JS into multiple files, you need to manually include all those script tags!
  • 24. // web/js/ProductCollection.js 
 class ProductCollection
 {
 constructor(products) {
 this.products = products;
 }
 
 getProducts() {
 return this.products;
 }
 
 getProduct(i) {
 return this.products[i];
 }
 }
 
 export default ProductCollection;

  • 25. // 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
  • 26.
  • 27. Module loading in a browser is hard to do
  • 29. @weaverryan Webpack! • bundler • module loader • all-around nice guy
  • 30. Install webpack > yarn add --dev webpack
  • 31. // web/js/ProductCollection.js 
 class ProductCollection
 {
 // ...
 }
 
 export default ProductCollection;
 // web/js/productApp.js
 
 import ProductCollection from './ProductCollection';
 
 // …
  • 32. Go webpack Go! > ./node_modules/.bin/webpack web/js/productApp.js web/build/productApp.js The one built file contains the code from both source files
  • 33. Optional config to make it easier to use: // webpack.config.js
 module.exports = {
 entry: {
 product: './web/js/productApp.js'
 },
 output: {
 path: './web/build',
 filename: '[name].js',
 publicPath: '/build/'
 }
 };
 build/product.js {# app/Resources/views/default/products.html.twig' #} <script src="{{ asset('build/product.js') }}"></script>
  • 35. Great! Now let’s add more features to Webpack!
  • 36. Features, features, features, features, features • babel transpiling • dev server • production optimizations • CSS handling • Sass/LESS • PostCSS • React • Vue • versioning • source maps • image handling • extract text • shared entry • jQuery providing • TypeScript • friendly errors
  • 38. var path = require("path");
 var process = require('process');
 var webpack = require('webpack');
 var production = process.env.NODE_ENV === 'production';
 
 // helps load CSS to their own file
 var ExtractPlugin = require('extract-text-webpack-plugin');
 var CleanPlugin = require('clean-webpack-plugin');
 var ManifestPlugin = require('webpack-manifest-plugin');
 
 var plugins = [
 new ExtractPlugin('[name]-[contenthash].css'), // <=== where should content be piped
 
 // put vendor_react stuff into its own file
 // new webpack.optimize.CommonsChunkPlugin({
 // name: 'vendor_react',
 // chunks: ['vendor_react'],
 // minChunks: Infinity, // avoid anything else going in here
 // }),
 new webpack.optimize.CommonsChunkPlugin({
 name: 'main', // Move dependencies to the "main" entry
 minChunks: Infinity, // How many times a dependency must come up before being extracted
 }),
 new ManifestPlugin({
 filename: 'manifest.json',
 // prefixes all keys with builds/, which allows us to refer to
 // the paths as builds/main.css in Twig, instead of just main.css
 basePath: 'builds/'
 }),
 ];
 
 if (production) {
 plugins = plugins.concat([
 // This plugin looks for similar chunks and files
 // and merges them for better caching by the user
 new webpack.optimize.DedupePlugin(),
 
 // This plugins optimizes chunks and modules by
 // how much they are used in your app
 new webpack.optimize.OccurenceOrderPlugin(),
 
 // This plugin prevents Webpack from creating chunks
 // that would be too small to be worth loading separately
 new webpack.optimize.MinChunkSizePlugin({
 minChunkSize: 51200, // ~50kb
 }),
 
 // This plugin minifies all the Javascript code of the final bundle
 new webpack.optimize.UglifyJsPlugin({
 mangle: true,
 compress: {
 warnings: false, // Suppress uglification warnings
 },
 sourceMap: false
 }),
 
 // This plugins defines various variables that we can set to false
 // in production to avoid code related to them from being compiled
 // in our final bundle
 new webpack.DefinePlugin({
 __SERVER__: !production,
 __DEVELOPMENT__: !production,
 __DEVTOOLS__: !production,
 'process.env': {
 BABEL_ENV: JSON.stringify(process.env.NODE_ENV),
 'NODE_ENV': JSON.stringify('production')
 },
 }),
 new CleanPlugin('web/builds', {
 root: path.resolve(__dirname , '..')
 }),
 ]);
 }
 
 
 module.exports = {
 entry: {
 main: './main',
 video: './video',
 checkout_login_registration: './checkout_login_registration',
 team_pricing: './team_pricing',
 credit_card: './credit_card',
 team_subscription: './team_subscription',
 track_organization: './track_organization',
 challenge: './challenge',
 workflow: './workflow',
 code_block_styles: './code_block_styles',
 content_release: './content_release',
 script_editor: './script_editor',
 sweetalert2_legacy: './sweetalert2_legacy',
 admin: './admin',
 admin_user_refund: './admin_user_refund',
 
 // vendor entry points to be extracted into their own file
 // we do this to keep main.js smaller... but it's a pain
 // because now we need to manually add the script tag for
 // this file is we use react or react-dom
 // vendor_react: ['react', 'react-dom'],
 },
 output: {
 path: path.resolve(__dirname, '../web/builds'),
 filename: '[name]-[hash].js',
 chunkFilename: '[name]-[chunkhash].js',
 // in dev, make all URLs go through the webpack-dev-server
 // things *mostly* work without this, but AJAX calls for chunks
 // are made to the local, Symfony server without this
 publicPath: production ? '/builds/' : 'http://localhost:8090/builds/'
 },
 plugins: plugins,
 module: {
 loaders: [
 {
 test: /.js$/,
 exclude: /node_modules/,
 loader: "babel-loader"
 },
 {
 test: /.scss/,
 loader: ExtractPlugin.extract('style', 'css!sass'),
 },
 {
 test: /.css/,
 loader: ExtractPlugin.extract('style', 'css'),
 },
 {
 test: /.(png|gif|jpe?g|svg?(?v=[0-9].[0-9].[0-9])?)$/i,
 loader: 'url?limit=10000',
 },
 {
 // the ?(?v=[0-9].[0-9].[0-9])? is for ?v=1.1.1 format
 test: /.woff(2)?(?v=[0-9].[0-9].[0-9])?$/,
 // Inline small woff files and output them below font/.
 // Set mimetype just in case.
 loader: 'url',
 query: {
 prefix: 'font/',
 limit: 5000,
 mimetype: 'application/font-woff'
 },
 //include: PATHS.fonts
 },
 {
 test: /.ttf?(?v=[0-9].[0-9].[0-9])?$|.eot?(?v=[0-9].[0-9].[0-9])?$/,
 loader: 'file',
 query: {
 name: '[name]-[hash].[ext]',
 // does this do anything?
 prefix: 'font/',
 },
 //include: PATHS.fonts
 },
 {
 test: /.json$/,
 loader: "json-loader"
 },
 ]
 },
 node: {
 fs: 'empty'
 },
 debug: !production,
 devtool: production ? false : 'eval',
 devServer: {
 hot: true,
 port: 8090,
 // tells webpack-dev-server where to serve public files from
 contentBase: '../web/',
 headers: { "Access-Control-Allow-Origin": "*" }
 },
 };
 *** not visible here: the 1000 ways you can shot yourself in the foot
  • 40. Let’s start over > rm -rf package.json yarn.lock node_modules/
  • 41. … and let’s start simple // assets/js/app.js 
 console.log(‘Hello World !’);

  • 42. > yarn add @symfony/webpack-encore --dev Step 1: Install Encore
  • 43. Step 2: webpack.config.js var Encore = require('@symfony/webpack-encore');
 
 Encore
 .setOutputPath('web/build/')
 .setPublicPath('/build')
 
 // will output as web/build/app.js
 .addEntry('app', './assets/js/app.js')
 
 .enableSourceMaps(!Encore.isProduction())
 ;
 
 module.exports = Encore.getWebpackConfig();

  • 44. > yarn run encore dev --watch {# base.html.twig #}
 <script src="{{ asset('build/app.js') }}"></script>
  • 45. Yea… but I need my jQuery’s!
  • 46. // assets/js/app.js
 import $ from 'jquery';
 
 $(document).ready(function() {
 $('h1').append('I love big text!');
 });

  • 47. // assets/js/app.js
 const $ = require('jquery');
 
 $(document).ready(function() {
 $('h1').append('I love big text!');
 });

  • 48. > yarn run encore dev
  • 49. > yarn add jquery --dev
  • 50. @weaverryan CSS: An un-handled dependency of your JS app
  • 51. Could we do this? // assets/js/app.js // ...
 require('../css/cool-app.css');
 
 $(document).ready(function() {
 $('h1').append('I love big text!');
 });

  • 52. > yarn run encore dev —watch {# base.html.twig #}
 <link ... href="{{ asset('build/app.css') }}">
  • 54. > yarn add bootstrap @weaverryan /* assets/css/cool-app.css */
 @import "~bootstrap/dist/css/bootstrap.css";
 /* ... */ > yarn run encore dev --watch
  • 55. But what about images & fonts? /* assets/css/cool-app.css */
 .product-price {
 color: green;
 background-image: url('../images/logo.png');
 }

  • 56. > yarn add bootstrap /* assets/css/cool-app.css */
 @import "~bootstrap/dist/css/bootstrap.css";
 /* ... */ > yarn run encore dev --watch
  • 57. images & fonts are copied to build/ and the new URL is written into the CSS
  • 58. Stop thinking of your JavaScript as random code that executes
  • 59. Start thinking of your JavaScript as a single application with dependencies that are all packaged up together
  • 61. > yarn run encore dev // assets/js/app.js
 // ...
 require('../css/app.scss');
  • 62. > yarn add sass-loader node-sass --dev // webpack.config.js
 
 Encore
 // ...
 
 .enableSassLoader()
  • 63. But I want page-specific CSS and JS files!
  • 64. // assets/js/productApp.js
 import '../css/productApp.css';
 import $ from 'jquery';
 
 $(document).ready(function() {
 console.log('product page loaded!');
 });

  • 65. // webpack.config.js
 
 Encore
 // ...
 
 .addEntry('app', './assets/js/app.js')
 .addEntry('productApp', './assets/js/productApp.js') {# product.html.twig #}
 {% block stylesheets %}
 {{ parent() }}
 
 <link href="{{ asset('build/productApp.css') }}">
 {% endblock %}
 
 {% block javascripts %}
 {{ parent() }}
 
 <script src="{{ asset('build/productApp.js') }}"></script>
 {% endblock %}

  • 66. > yarn run encore dev --watch
  • 67. Wait! You have too many jQuery-ies!
  • 68. jQuery is in here … and also here
  • 69. // webpack.config.js
 
 Encore
 // ...
 
 .createSharedEntry('app', './assets/js/app.js')
 .addEntry('productApp', './assets/js/productApp.js')
  • 70. {# base.html.twig #}
 <script src="{{ asset('build/manifest.js') }}"></script>
 <script src="{{ asset('build/app.js') }}"></script>
  • 74. manifest.json to the rescue! {
 "build/app.css": "/build/app.3666e24a0be80f22bd8f31c43a70b14f.css",
 "build/app.js": "/build/app.f18c7a7f2785d99e0c25.js",
 "build/images/logo.png": "/build/images/logo.482c1dc2.png",
 "build/manifest.js": "/build/manifest.d41d8cd98f00b204e980.js",
 "build/productApp.css": "/build/productApp.01f416c68486810b3cb9.css",
 "build/productApp.js": "/build/productApp.1af5d8e89a35e521309b.js"
 } {# base.html.twig #}
 <script src="{{ asset('build/manifest.js') }}"></script>
 <script src="{{ asset('build/app.js') }}"></script>
  • 75. manifest.json to the rescue! # app/config/config.yml # config/packages/framework.yaml
 framework:
 # ...
 assets:
 json_manifest_path: '%kernel.project_dir%/web/build/manifest.json'
  • 76. … so add long-term caching…
  • 78. {# products.html.twig #}
 <div id="product-app"
 data-products="{{ products|json_encode|e('html_attr') }}">
 </div> // assets/js/productApp.js
 
 const root = document.getElementById('product-app');
 const startingProducts = root.dataset.products;

  • 79. This presentation needs more buzz words React!
  • 80. // assets/js/productApp.js
 
 import React from 'react';
 import ReactDOM from 'react-dom';
 import ProductApp from './Components/ProductApp';
 import $ from 'jquery';
 
 $(document).ready(function() {
 const root = document.getElementById('product-app');
 const startingProducts = root.dataset['products'];
 
 ReactDOM.render(
 <ProductApp message="Great Products!” initialProducts={startingProducts} />, 
 root
 );
 });
  • 81.
  • 82. // webpack.config.js
 
 Encore
 // ...
 .enableReactPreset()
 ; > yarn add --dev react react-dom babel-preset-react
  • 83. • React & Preact • Vue • TypeScript • Code splitting • source maps • versioning • Sass/LESS/Stylus • minification … and is the life of any party … An Encore of Features
  • 85. … the dirty way… install Node on production and execute encore there
  • 86. the happier way! run Encore on some *other* machine and copy your build/ directory
  • 87. Putting it all together
  • 88. ES6/ES2015/ECMAScript 2015 The newest version of Javascript, not supported by all browsers
  • 89. Babel A tool that can transform JavaScript to different JavaScript A) ES6 js to “old” JS B) React to raw JS
  • 90. Webpack A tool that follows imports to bundle JavaScript, CSS, and anything else you dream up into one JavaScript package
  • 91. Webpack Encore A tool that makes configuring webpack not suck
  • 92. So go write some amazing JavaScript!