Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Hands on with the modern front end stack

Hands on with the modern front end stack

Slides for a workshop I gave at Dutch PHP Conference in June 2015. The accompanying code can be found at https://github.com/bensmithett/dpcon-primer

Ben Smithett

June 23, 2015
Tweet

More Decks by Ben Smithett

Other Decks in Programming

Transcript

  1. the plan • Meet the stack! • npm • Managing

    dependencies • Running tasks • JS Modules • Webpack for JS • Babel • ES6 & ES7 • React • Webpack for CSS & images
  2. the bonus plan (if we have time!) • Hot module

    reloading • Isomorphic React • Styling with JS
  3. It is a recursive bacronymic abbreviation for "npm is not

    an acronym” https:/ /docs.npmjs.com/misc/faq
  4. nested folder structure by convention, JS packages are expected to

    export a module flat folder structure no expected module format depends on npm
  5. workshop tasks •Create a new package.json with npm init •Search

    npm for React using npm search •Install & save React to your package.json with npm install
  6. without npm scripts node-sass --watch app.scss app.css karma start ./config/karma.conf.js

    http-server ./build -p 3000 --cors with npm scripts npm run sass npm test npm start
  7. workshop tasks •Run the existing npm test script •Install http-server

    from npm & add a new npm script to start a local server on port 1337
  8. the old way: expose global variables // jquery.js window.$ =

    function () { /* ... */ } // fancy_modal.js window.fancyModal = function () { /* ... */ } // my_app.js window.MyApp = { init: function () { $('.content').slideDown() fancyModal('Hello!') } }
  9. a better way: modules // my_app.js var $ = require('jquery')

    var fancyModal = require('fancy_modal') var init = function () { $(".content").slideDown() fancyModal('Hello!') } module.exports = {init: init}
  10. workshop tasks •Using CommonJS format, use the add() function from

    the supplied add.js module to add two numbers together. console.log the result •Run it with node my_app.js
  11. webpack is a module bundler // my_app.js var add =

    require("./add") console.log(add(4, 6))
  12. webpack is a module bundler // my_app.js var add =

    require("./add") console.log(add(4, 6)) •Browsers don’t have access to your local filesystem •Even if you can require individual files from the server (i.e. AMD modules) the request is asynchronous
  13. a module bundler lets you author as if you have

    access to multiple files on a filesystem but outputs a single JS file for end users
  14. workshop tasks •Build a simple bundle with webpack npm run

    03 •Open up the generated file & look at it! 03_webpack/build/bundle.js
  15. babel: transforms ES6 to equivalent ES5 `Hi ${name}. Welcome to

    ${city}!` "Hi " + name + ". Welcome to " + city + "!";
  16. babel: polyfills missing features class Australian { sayHello () {

    return “G'day" } } var _createClass = (function () { /* Babel polyfill... */ })(); function _classCallCheck(instance, Constructor) { /* Babel polyfill... */ } var Australian = (function () { function Australian() { _classCallCheck(this, Australian); } _createClass(Australian, [{ key: "sayHello", value: function sayHello() { return "G'day"; } }]); return Australian; })();
  17. babel: checks your code at compile time const speedOfLight =

    299792458 speedOfLight = 17 COMPILE ERROR Line 2: "speedOfLight" is read-only
  18. workshop tasks •Open babeljs.io/repl & play around with some new

    ES6 features! •class •const •destructuring •default function arguments •arrow functions
  19. webpack loaders module.exports = { module: { loaders: [ {

    test: /\.js$/, loaders: ["babel"] } ] } };
  20. workshop tasks Let’s build a real app! •From the root

    folder, run npm run app • If you haven’t installed Webpack, start a static web server instead •Try changing the language in entry.js congratulations! you now have a modular JS app written in ES6 syntax, compiled by Babel & bundled by Webpack!
  21. const Child = React.createClass({ render () { return <div className='child'

    /> } }) const Parent = React.createClass({ render () { return ( <div className='parent'> <Child /> <Child /> <Child /> </div> ) } })
  22. const Child = React.createClass({ render () { return <div className='child'

    /> } }) const Parent = React.createClass({ render () { return ( <div className='parent'> <Child /> <Child /> <Child /> </div> ) } })
  23. const Child = React.createClass({ render () { return <div className='child'>Name:

    {this.props.name}</div> } }) const Parent = React.createClass({ render () { return ( <div className='parent'> <Child name='Abe' /> <Child name='Cleo' /> <Child name='Gandhi' /> </div> ) } })
  24. state • Local data for each component • Can be

    changed via this.setState • Every state change causes a new render()
  25. const Counter = React.createClass({ getInitialState () { return {count: 0}

    }, increment () { this.setState({ count: this.state.count + 1 }) }, render () { return ( <button onClick={this.increment}> Count: {this.state.count} </button> ) } })
  26. workshop tasks •Build the PhotoThumb component •Render a PhotoThumb for

    each photo in the supplied data •When a PhotoThumb is clicked, store that photo in PhotoApp’s state •Build a PhotoDetail component •Pass the currently selected photo into PhotoDetail as a prop
  27. import React from 'react' const FancyButton = React.createClass({ render ()

    { return <button className='fancy-btn'>Hi</button> } })
  28. import React from 'react' import 'css/components/fancy-btn' const FancyButton = React.createClass({

    render () { return <button className='fancy-btn'>Hi</button> } })
  29. workshop tasks •Configure webpack so that it can require CSS

    •Style the app, requiring each component’s CSS dependencies
  30. Hot Module Replacement exchanges, adds, or removes modules while an

    application is running without a page reload.
  31. Reminder Webpack bundles all of your individual modules into a

    giant array and looks a module up in that array whenever another module requires it
  32. Hot Module Replacement Small client runtime polls dev server When

    a file changes, client runtime loads new version Module stored in array is updated
  33. Advantages Real time updates as you edit JS views &

    CSS Client state is maintained (even if you had to click 5 things to get it in that state)
  34. Generate real HTML on the server When client JS loads,

    mount onto server- rendered HTML, adding event listeners Reuse the same React components on the client & server!
  35. var myStyles = { color: colors.red, backgroundColor: signedInUser ? colors.green

    : colors.grey, backgroundImage: CDNPathFor('forest_bg.png'), width: Math.round(viewportSize / 2) + 'px' }
  36. var totalCols = 12 var gridColClasses = {} for (var

    i = 1; i <= totalCols; i++) { gridColClasses['col-' + i] = { width: ((100 / totalCols) * i) + '%' } }
  37. var styles = { border: '2px solid #0f0', height: '100px',

    width: '100px', float: left } var PhotoThumb = React.createClass({ render () { return ( <div style={styles}> <img src={this.props.src} /> </div> ) } })