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

Intro to Ember & Ember CLI

Intro to Ember & Ember CLI

From the April 2015 EmberATX meetup in Austin, TX.

tehviking

April 24, 2015
Tweet

More Decks by tehviking

Other Decks in Programming

Transcript

  1. w e l c o
    m e t o t
    h e n e x
    t l e v e l

    View full-size slide

  2. Ember CLI:
    UP AND RUNNING!
    The stuff you need
    to build next-level
    native web apps

    View full-size slide

  3. Brandon Hays @tehviking
    This one guy
    The
    Frontside

    View full-size slide

  4. Welcome to training

    View full-size slide

  5. WHAT WE’LL COVER:
    ¶ Ember CLI basics
    ¶ Building an app with CLI
    ¶ Migrating to Ember-CLI

    View full-size slide

  6. Prerequisites
    ¶ git
    ¶ node
    ¶ admin access

    View full-size slide

  7. WHY ember?
    It’s our favorite framework, sure.
    But why?

    View full-size slide

  8. Ember lets me
    focus on our
    unique business
    problems, not
    boilerplate code
    i just wanna code!

    View full-size slide

  9. Let the community tackle shared problems.

    View full-size slide

  10. I don’t want to
    spend my limited
    time on earth
    shaving yaks.
    WHY ember?

    View full-size slide

  11. how devs
    see their
    custom
    build
    pipeline

    View full-size slide

  12. their
    actual
    custom
    build
    pipeline

    View full-size slide

  13. Let’s see, we have
    a community, a
    shared problem, and
    Ember philosophy...
    so what do we do?

    View full-size slide

  14. An opinionated suite of command line
    tools for building Ember apps.
    Enter ember cli.

    View full-size slide

  15. I get to code, not shave yaks.
    WHY ember cli?
    >

    View full-size slide

  16. “You should begin moving
    your app to Ember CLI as
    soon as possible.”
    - Tom Dale, Javascript Ombudsman
    WHY ember cli?

    View full-size slide

  17. So let’s get up to speed.
    And get back to what we like: making stuff.

    View full-size slide

  18. PART 1: CLI BASICS

    View full-size slide

  19. the pleasure
    º Generators
    º Fast builds
    º Add-on ecosystem
    º Testing integration
    º ES6, Sass support

    View full-size slide

  20. THE PAIN
    ‡ Learning ES6 modules
    ‡ Cryptic error messages like “cannot find
    file tmp/3n8glcv7cv6sgs
    ‡ Migrating existing apps to Ember-CLI

    View full-size slide

  21. THE PAIN
    ‡ Migrating existing
    apps to Ember-CLI

    View full-size slide

  22. basic concepts
    - Installing
    - Generating
    - Using ES6 modules
    - Folder structure
    - Assets
    - Testing
    - Deployment

    View full-size slide

  23. Installing
    npm install -g ember-cli
    ember new cool-app

    View full-size slide

  24. GENERATORS &
    BLUEPRINTS

    View full-size slide

  25. LMGTFY
    ember generate route images
    ember generate component pixelate-image
    and my favorite...
    ember generate acceptance-test images
    (...let me generate that for you)

    View full-size slide

  26. Ember GENERATORS
    Controller
    Model
    Route
    Resource
    Template
    Mixin
    Component
    Helper
    Initializer
    Adapter
    Serializer
    Service
    Transform
    Util
    View

    View full-size slide

  27. Ember GENERATORS
    Acceptance-test*
    Adapter-test
    Component-test
    Controller-test
    Helper-test
    Initializer-test
    Mixin-test
    Model-test
    Route-test
    Serializer-test
    Service-test
    Transform-test
    Util-test
    View-test
    *(All but this are generated
    automatically)

    View full-size slide

  28. Ember GENERATORS
    Addon
    In-repo-addon (& lib)
    App
    Blueprint
    Http-mock
    Http-proxy
    Server
    Test-helper
    Plus custom generators
    from installed addons
    ...Or create your own

    View full-size slide

  29. ES6 Modules:
    getting out of
    dependency hell

    View full-size slide

  30. game over, globals!

    View full-size slide

  31. App.ImagesRoute = Ember.Route.extend({

    model: function() {

    return App.imageData();

    }

    });
    app/routes/images-route.js
    From globals...

    View full-size slide

  32. App.ImagesRoute = Ember.Route.extend({

    model: function() {

    return App.imageData();

    }

    });
    app/routes/images-route.js
    From globals...
    Ember is global
    imageData comes from global App
    (at least, we hope)

    View full-size slide

  33. import Ember from 'ember';

    import imageData from '../utils/image-data';


    var ImagesRoute = Ember.Route.extend({

    model: function() {

    return imageData();

    }

    });
    export default ImagesRoute;
    app/routes/images.js
    TO ES6 Modules

    View full-size slide

  34. import Ember from 'ember';

    import imageData from '../utils/image-data';


    var ImagesRoute = Ember.Route.extend({

    model: function() {

    return imageData();

    }

    });
    export default ImagesRoute;
    app/routes/images.js
    to ES6 Modules
    Ember comes from ember.js

    View full-size slide

  35. import Ember from 'ember';

    import imageData from '../utils/image-data';


    var ImagesRoute = Ember.Route.extend({

    model: function() {

    return imageData();

    }

    });
    export default ImagesRoute;
    app/routes/images.js
    to ES6 Modules
    imageData comes from ../utils

    View full-size slide

  36. import Ember from 'ember';

    import imageData from '../utils/image-data';


    var ImagesRoute = Ember.Route.extend({

    model: function() {

    return imageData();

    }

    });
    export default ImagesRoute;
    app/routes/images.js
    to ES6 Modules
    export so others can import

    View full-size slide

  37. Opinionated
    framework,
    opinionated
    structure
    Folder structure

    View full-size slide

  38. app/routes/images.js
    app/routes/images/show.js
    app/controllers/images.js
    app/controllers/images/show.js
    app/templates/images.hbs
    app/templates/images/show.hbs
    old-school folders

    View full-size slide

  39. app/images/route.js
    app/images/controller.js
    app/images/template.hbs
    app/images/show/route.js
    app/images/show/controller.js
    app/images/show/template.hbs
    New-school Pods

    View full-size slide

  40. ember generate resource foo --pod
    and if you want, in your env:
    podModulePrefix: 'pixelfy-me/pods'
    Maybe you’ll like it

    View full-size slide

  41. Asset compilation
    Where did your files go?

    View full-size slide

  42. - assets/pixelfy-me.js (app)
    - assets/vendor.js (vendored js)
    Asset compilation

    View full-size slide

  43. app.import("vendor/my-stuff/cool-utility.js");
    app.import("bower_components/pixelate/pixelate.js");

    app.import("bower_components/JavaScript-MD5/js/md5.js");

    Brocfile.js
    VENDORING ASSETS

    View full-size slide

  44. TESTING
    Awesome test helpers
    Awesome test generators
    QUnit & Mocha support

    View full-size slide

  45. Build & ship to S3/CloudFront
    Heroku Buildpack
    Existing asset pipeline
    Deployment

    View full-size slide

  46. The smartest
    DevOps engineer
    is our collective
    community
    ember cli ends the build
    tool yak shave

    View full-size slide

  47. EMBER ROUTER &
    NESTED ROUTES

    View full-size slide

  48. DATA, UI, STATE,
    URLs, IN PERFECT
    HARMONY

    View full-size slide

  49. ApplicationRoute (generated): ‘/’
    ProductRoute: ‘/:id’
    Rendered into products {{outlet}}
    URL: / products / 230
    ProductsRoute: ‘/products’
    Rendered into application {{outlet}}

    View full-size slide

  50. ACTION HANDLING
    ProductController
    {{action “add”}} ProductRoute
    ProductsRoute
    ApplicationRoute

    View full-size slide

  51. EMBER COMPONENTS

    View full-size slide


  52. EMBER COMPONENTS
    OF THE NEAR FUTURE

    View full-size slide


  53. {{each people as |person|}}
    {{person.name}}
    {{/each}}

    EMBER COMPONENTS
    OF THE NEAR FUTURE

    View full-size slide

  54. COMPUTED
    PROPERTIES &
    COMPUTED MACROS

    View full-size slide

  55. COMPUTED
    PROPERTIES
    app/controllers/cart.js
    export default Ember.Controller.extend({

    cartItemSubtotals: Ember.computed.mapBy("model.cartItems", "subtotal"),

    orderSubtotal: Ember.computed.sum("cartItemSubtotals"),

    shippingCost: Ember.computed(function() {

    return 0;

    }),

    orderTax: Ember.computed("orderSubtotal", function() {

    var taxCents = (this.get("orderSubtotal") * 100) * 0.0825;

    return taxCents / 100;

    }),

    orderTotal: Ember.computed("orderTax", "orderSubtotal", function() {

    return this.get("orderSubtotal") + this.get("orderTax");

    }),

    });

    View full-size slide

  56. COMPUTED MACROS
    app/controllers/cart.js
    export default Ember.Controller.extend({

    cartItemSubtotals: Ember.computed.mapBy("model.cartItems", "subtotal"),

    orderSubtotal: Ember.computed.sum("cartItemSubtotals"),

    shippingCost: Ember.computed(function() {

    return 0;

    }),

    orderTax: Ember.computed("orderSubtotal", function() {

    var taxCents = (this.get("orderSubtotal") * 100) * 0.0825;

    return taxCents / 100;

    }),

    orderTotal: Ember.computed("orderTax", "orderSubtotal", function() {

    return this.get("orderSubtotal") + this.get("orderTax");

    }),

    });

    View full-size slide

  57. IF YOU UNDERSTAND:
    • Generating with Ember CLI
    • Router & Routes
    • Components
    • Computed Properties
    YOU CAN BUILD AWESOME STUFF

    View full-size slide

  58. Ember CLI lets me
    focus on our
    unique business
    problems, not janky
    build systems
    i just wanna code!

    View full-size slide

  59. so let’s code.

    View full-size slide

  60. Questions & break

    View full-size slide

  61. Let’s build an app!
    Pixelfy Me

    View full-size slide

  62. look out, batman!
    it’s the
    pixeler!
    Shut up,
    Robin!
    Worst.
    Villain.
    Ever.

    View full-size slide

  63. Let’s build
    an app!

    View full-size slide

  64. Let’s build an app!
    npm install -g ember-cli

    View full-size slide

  65. Let’s build an app!
    ember new pixelfy-me
    cd pixelfy-me
    git remote add origin https://github.com/thefrontside/pixelfy-me.git
    git fetch --tags
    open the folder in your text editor of choice

    View full-size slide

  66. Task 1: List Images
    What we’ll do:
    Generate Images resource
    Write Model hook for Images Route
    Install helper for image data
    Display images on Images page

    View full-size slide

  67. git checkout task-1
    npm install
    bower install
    (Stuck? You can git checkout at any task with
    git checkout task-)
    Task 1: List Images

    View full-size slide

  68. Generate Images
    resource
    ember generate resource images
    (NOTE: don’t overwrite that hbs file!)

    View full-size slide

  69. import Ember from 'ember';


    export default Ember.Object.extend({

    url: ""

    });

    app/models/image.js
    “downgrade” model

    View full-size slide

  70. import Ember from 'ember';


    export default Ember.Route.extend({

    model: function() {

    return imageData();

    }

    });


    app/routes/images.js
    Load data in model hook
    KABOOOOOM!
    (doesn’t exist)

    View full-size slide

  71. kinda magic custom
    addon
    ember install cowboyd/ember-cli-sample-image-data

    View full-size slide

  72. import Ember from 'ember';
    import imageData from 'ember-cli-sample-image-data';


    export default Ember.Route.extend({

    model: function() {

    return imageData();

    }

    });


    app/routes/images.js
    import it in the route

    View full-size slide

  73. ...
    "8": {

    id: "8",

    url: "/img/yeezus.jpg"

    }

    };

    if(arguments.length) {

    return Image.create(images[id]);

    } else {

    var imagesArray = Object.keys(images).map(function(k){

    return Image.create(images[k]);

    });

    return imagesArray;

    }

    inside the addon’s hidden volcano lair...
    P.S. it’s not really that magical

    View full-size slide

  74. check it out
    ember server
    check localhost:4200

    View full-size slide

  75. need to fast forward?
    git reset --hard task-2

    View full-size slide

  76. Let’s talk about what just happened:
    - Generated a route & model
    - Tweaked the route & model slightly
    - Installed an addon
    - Used ES6 to include the addon helper
    That loads images!

    View full-size slide

  77. task 2: show image
    What we’ll do:
    Generate images/show route
    Add dynamic segment to show route
    Write Model hook for Images Show Route
    Link to Image from Images page
    Display image on Image Show section

    View full-size slide

  78. Generate Images show
    route
    ember generate route images/show
    (again, don’t overwrite that hbs file!)

    View full-size slide

  79. Router.map(function() {

    this.resource('images', function() {

    this.route('show', {path: ":id"});

    });

    });

    app/router.js
    Add dynamic segment

    View full-size slide

  80. import Ember from 'ember';

    import imageData from 'ember-cli-sample-image-data';


    export default Ember.Route.extend({

    model: function(params) {

    return imageData(params.id);

    }

    });
    app/routes/images/show.js
    Add model hook & import
    statement

    View full-size slide

  81. {{#each image in model}}


    {{#link-to "images.show" image}}


    {{/link-to}}


    {{/each}}

    app/templates/images.hbs
    link to image from
    images template

    View full-size slide





  82. ! Implement pixelate-image here !



    app/templates/images/show.hbs
    Display image in the
    show template

    View full-size slide

  83. To recap what we just built:
    - Generated a nested route with /
    - Used a dynamic segment
    - Re-used ES6 for our imageData helper
    - Edited template files to display stuff
    images/show done!

    View full-size slide

  84. task 3: pixelatE
    What we’ll do:
    Install pixelate-image component
    Wrap image in pixelate component
    Install {{emberx-slider}} component
    Drop in {{x-slider}} component

    View full-size slide

  85. install pixelate
    component addon
    ember install cowboyd/ember-cli-pixelate-image

    View full-size slide

  86. need to fast forward?
    git reset --hard task-3

    View full-size slide

  87. install x-slider
    component addon
    ember install emberx-slider

    View full-size slide



  88. {{pixelate-image src=model.url value=pixelatePercentage}}



    app/templates/images/show.hbs
    Drop in pixelate-image
    component

    View full-size slide


  89. {{x-slider value=pixelatePercentage}}


    app/templates/images/show.hbs
    Drop in emberx-slider
    component

    View full-size slide

  90. what? that worked?!
    Did we mention
    Ember Addons are
    pretty great?

    View full-size slide

  91. Let’s look at what we did:
    - Installed pixelate-image custom addon
    - Installed emberx-slider addon
    - Tied the two together to make MAGIC
    So yeah

    View full-size slide

  92. task 4: Style it
    What we’ll do:
    Install ember-cli-sass addon
    Install bootstrap-sass bower package
    rename app.css to app.scss
    include bootstrap
    include custom SCSS

    View full-size slide

  93. install sass addon
    ember install ember-cli-sass

    View full-size slide

  94. install bootstrap-sass
    bower install --save-dev bootstrap-sass

    View full-size slide

  95. rename app.css
    mv app/styles/app.css app/styles/app.scss

    View full-size slide

  96. COPY & PASTE CSS FILES
    Files are here (grab the tar file):
    http://bit.ly/cli-training-styles
    - app.scss
    - _bootswatch.scss
    - bootstrap_imports.scss
    - bootstrap_variables.scss
    Copy or move them to app/styles

    View full-size slide

  97. need to fast forward?
    git reset --hard task-5

    View full-size slide

  98. Now we have a fully styled app!
    - Installed ember-cli-sass to compile Sass
    - Installed bootstrap-sass
    - Used Sass @include for granular control
    so stylin’

    View full-size slide

  99. task 5: test it
    Add karma, karma-cil, karma-mocha, karma-chai-
    plugins, karma-chrome-launcher, karma-ember-
    preprocessor, karma-mocha, karma-phantomjs-
    launcher, karma-junit-reporter to package.json
    Compile and install PhantomJS
    npm install
    Install ember-mocha-adapter and chai-jquery via
    Bower
    Set up a karma.conf file
    In your karma.conf:
    Customize your frameworks section in karma.conf
    to include mocha, chai, sinon-chai, and chai-jquery
    Set up a Grunt task to build your Sass on each
    test run
    Include your vendor dependencies in karma.conf
    Include your code in files section
    Debug file load order issues
    Add & configure handlebars karma preprocessor
    Then, create test-helper.js & include it in
    karma.conf
    In your test-helper.js:
    Configure chai and mocha defaults
    Set Ember.testing to true
    Set App.setupForTesting to true
    Call App.injectTestHelpers()
    Set up app on each test run
    Tear down app after each test run
    Ensure beforeEach and afterEach use the run loop
    Use the .done() callback for async beforeEach
    What we’ll do:

    View full-size slide

  100. task 5: test it
    j/k lol ;)
    ember generate acceptance-test images
    ember test

    View full-size slide

  101. ha! ha! ha!
    But seriously, this was real
    http://bit.ly/karma-sad-lol

    View full-size slide

  102. task 5: test it
    What we’ll do:
    Generate “images” acceptance test
    Remove generated Ember Data test
    Write an assertion
    Run the tests

    View full-size slide

  103. generate the test
    ember generate acceptance-test images

    View full-size slide

  104. remove ember data
    test
    rm tests/unit/models/image-test.js
    (We’re not using Ember data)

    View full-size slide

  105. test('visiting /images', function(assert) {

    visit('/images');


    andThen(function() {

    assert.equal(Ember.$(".spec-gallery-image").length, 8);

    });

    });

    tests/acceptance/images-test.js
    basic acceptance test

    View full-size slide

  106. run tests
    $ ember test --serve
    1..14
    # tests 14
    # pass 14
    # fail 0
    # ok

    View full-size slide

  107. look at all the yaks i
    have to shave

    View full-size slide

  108. bonus: gravatars
    What we’ll do:
    git checkout bonus-stage
    Set up gravatar route & link
    Handle download action
    install JavaScript-md5 bower component
    Pixelate images in the gravatar template

    View full-size slide

  109. set up gravatar route
    ember generate route gravatar

    View full-size slide

  110. downloadImage: function() {

    var link = document.createElement("a");

    var uri = Ember.$("img.pixelated-image").attr("src");

    link.download = "pixelfy.png";

    link.href = uri;

    link.click();

    }

    app/routes/gravatar.js
    handle download image

    View full-size slide

  111. {{#link-to "gravatar" tagName="li"}}

    {{#link-to "gravatar"}}

    Gravatar

    {{/link-to}}

    {{/link-to}}

    app/templates/application.hbs
    Link to gravatar route

    View full-size slide

  112. Install Md5 package
    bower install --save-dev JavaScript-MD5

    View full-size slide

  113. var app = new EmberApp();


    app.import("bower_components/JavaScript-MD5/js/md5.js");


    module.exports = app.toTree();

    Brocfile.js
    import md5 in brocfile

    View full-size slide

  114. window",
    "-Promise",
    "md5"
    ],
    "browser": true,
    ...

    Brocfile.js
    add md5 to .jshintrc

    View full-size slide

  115. Preview:


    app/templates/gravatar.hbs
    Add gravatar to template

    View full-size slide



  116. {{x-slider value=pixelatePercentage}}


    app/templates/gravatar.hbs
    Add slider to template

    View full-size slide



  117. {{pixelate-image src=base64Url value=pixelatePercentage}}



    app/templates/gravatar.hbs
    Add pixelate to template

    View full-size slide

  118. This was more complicated.
    - Set up gravatar route
    - Handled download action
    - Installed bower component
    - Included lib in Brocfile and .jshintrc
    - Mixed pixelate and gravatar together
    It’s done!

    View full-size slide

  119. Now we can get
    back to focusing
    on moving fast and
    shipping, with a
    better set of tools
    i just wanna code!

    View full-size slide

  120. @tehviking
    THANKS!
    The
    Frontside

    View full-size slide

  121. always remember!

    View full-size slide