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

Components on the Web: Frontend NE

Components on the Web: Frontend NE

Jack Franklin

April 05, 2018
Tweet

More Decks by Jack Franklin

Other Decks in Technology

Transcript

  1. @Jack_Franklin 1

    View full-size slide

  2. @Jack_Franklin 2

    View full-size slide

  3. A component is a self contained
    element made up of
    HTML, CSS and JavaScript.
    We can combine lots of
    components together to create
    user interfaces.
    @Jack_Franklin 3

    View full-size slide

  4. The plan
    1. The road to components !
    2. The theory of components "
    3. The approaches and challenges of building good
    components ✅
    4. How to introduce components to your project/
    product/app/site $
    @Jack_Franklin 4

    View full-size slide

  5. All of today's talk is
    reasonably new,
    especially within the
    context of front-end
    development
    @Jack_Franklin 5

    View full-size slide

  6. Today I'm going to talk
    you through some of my
    experiences, but I'd love
    to hear yours!
    @Jack_Franklin 6

    View full-size slide

  7. The road to components
    When we didn't know any better, we stuck to
    patterns that had served us well on the server.
    @Jack_Franklin 7

    View full-size slide

  8. @Jack_Franklin 8

    View full-size slide

  9. @Jack_Franklin 9

    View full-size slide

  10. APIs and JSON
    /api/cat-pics
    [
    { "id": 1, "name": "Fluffy", "age": 5 },
    { "id": 2, "name": "Mittens", "age": 7 }
    ]
    @Jack_Franklin 10

    View full-size slide

  11. @Jack_Franklin 11

    View full-size slide

  12. @Jack_Franklin 12

    View full-size slide

  13. MVC doesn't fit frontend
    development
    @Jack_Franklin 13

    View full-size slide

  14. This is a paragraph element (or...component?).
    This is a heading

    this is a list item

    @Jack_Franklin 14

    View full-size slide

  15. And what if we could extend the box of bricks? 1

    1 https://developers.google.com/web/fundamentals/web-components/customelements
    @Jack_Franklin 15

    View full-size slide

  16. And what if we built
    frameworks around this
    idea, rather than the MVC
    approach?
    @Jack_Franklin 16

    View full-size slide

  17. The Theory
    @Jack_Franklin 17

    View full-size slide

  18. @Jack_Franklin 18

    View full-size slide

  19. A page is a series of components
    Made up of HTML, CSS and JavaScript 2
    2
    not necessarily all three
    @Jack_Franklin 19

    View full-size slide

  20. Pages will reuse the same components
    Common elements such as buttons, form inputs,
    user avatars, tweets, etc.
    @Jack_Franklin 20

    View full-size slide

  21. As it turns out, this
    approach works pretty
    well.
    @Jack_Franklin 21

    View full-size slide

  22. @Jack_Franklin 22

    View full-size slide

  23. The ideas in React are more important than React
    itself.
    And now exist in a plethora of front end frameworks.
    @Jack_Franklin 23

    View full-size slide

  24. I'm using React today because it's what I know best.
    —But this talk is not framework specific and can
    apply to any form of components.
    —Whether we're talking Angular, Ember, Vue, web
    components, or any other system.
    @Jack_Franklin 24

    View full-size slide

  25. Approaches and
    challenges of building
    good components ✅
    @Jack_Franklin 25

    View full-size slide

  26. Components are designed
    to be a black box
    @Jack_Franklin 26

    View full-size slide

  27. "I want a carousel on my website"


    I don't need to care about how the carousel works in
    order to use it.
    @Jack_Franklin 27

    View full-size slide

  28. You should strive for
    "black box" components.
    @Jack_Franklin 28

    View full-size slide

  29. The "black box" approach
    enables working in
    isolation
    @Jack_Franklin 29

    View full-size slide

  30. @Jack_Franklin 30

    View full-size slide

  31. @Jack_Franklin 31

    View full-size slide

  32. @Jack_Franklin 32

    View full-size slide

  33. You can focus in on one component and one
    component only, without fear of breaking other parts
    of the site.
    You and your brain can focus in on the problem area
    and shut everything else out.
    @Jack_Franklin 33

    View full-size slide

  34. We keep all our component code
    in one folder, to help keep things
    isolated and to avoid directory
    jumping.
    @Jack_Franklin 34

    View full-size slide

  35. Avoid business logic
    @Jack_Franklin 35

    View full-size slide

  36. Your components should focus on presentations
    and interactions
    class SignUpToNewsletterForm extends Component {
    signUserUp() {
    // lots of
    // code here
    // to sign the user up
    // to your newsletter
    }
    render() {
    return (

    ...

    )
    }
    }
    @Jack_Franklin 36

    View full-size slide

  37. Pull any standalone logic out of your components so
    you can focus on the presentation.
    import { signUserUp } from '...'
    class SignUpToNewsletterForm extends Component {
    signUserUp() {
    signUserUp(...)
    }
    render() {
    return (

    ...

    )
    }
    }
    @Jack_Franklin 37

    View full-size slide

  38. You should keep your
    components reusable
    @Jack_Franklin 38

    View full-size slide

  39. Reusable components
    have to be configurable
    @Jack_Franklin 39

    View full-size slide

  40. !
    Hey, please build me a component to view an item of
    clothing on Thread.com
    @Jack_Franklin 40

    View full-size slide

  41. class ThreadItem extends Component {
    render() {
    return (


    {this.props.item.title}



    )
    }
    }
    @Jack_Franklin 41

    View full-size slide


  42. ! Job done! "
    @Jack_Franklin 42

    View full-size slide

  43. Oh, can we make this page show ten different
    items?







    ! Job done! "
    @Jack_Franklin 43

    View full-size slide

  44. OK but now can we make it so it shows the brand as
    well as the title

    ! Job done! "
    @Jack_Franklin 44

    View full-size slide

  45. Oh and also if it's on sale we want to show the old
    price alongside the new price

    ! Job done! "
    @Jack_Franklin 45

    View full-size slide

  46. And we need to be able to not show the item
    sentiment sometimes
    item={...}
    showBrand={true}
    showOldPriceBeforeSale={true}
    showSentiment={false}
    />
    ! Job done...
    @Jack_Franklin 46

    View full-size slide

  47. For some items we want to show the brand instead
    of the name
    item={...}
    showBrand={true}
    showBrandInsteadOfName={true}
    showOldPriceBeforeSale={true}
    showSentiment={false}
    />
    ! Job done...
    @Jack_Franklin 47

    View full-size slide

  48. !
    item={...}
    showBrand={false}
    showBrandInsteadOfName={true}
    showOldPriceBeforeSale={true}
    showSentiment={false}
    />
    Good luck understanding all these options in six
    months time...
    @Jack_Franklin 48

    View full-size slide

  49. @Jack_Franklin 49

    View full-size slide

  50. You will constantly play configurability off against
    maintainability.
    You as a developer and as a team will need to come
    up with a set of rules that suit you.
    @Jack_Franklin 50

    View full-size slide

  51. Optimise for
    developer
    readability
    @Jack_Franklin 51

    View full-size slide

  52. CSS
    @Jack_Franklin 52

    View full-size slide

  53. Every component should
    provide its styling.
    @Jack_Franklin 53

    View full-size slide

  54. @Jack_Franklin 54

    View full-size slide

  55. And none of
    them should
    conflict with
    each other.
    @Jack_Franklin 55

    View full-size slide

  56. Approaches to CSS
    —Class names per component
    —Enforced uniqueness via CSS Modules
    —CSS-in-JS
    @Jack_Franklin 56

    View full-size slide

  57. This is a big topic that I
    can only talk briefly about
    @Jack_Franklin 57

    View full-size slide

  58. Class names
    .jacks-carousel {
    }
    .jacks-carousel ul {
    }
    .jacks-carousel li {
    }
    /* and so on */
    @Jack_Franklin 58

    View full-size slide

  59. All it takes is one slip...


    @Jack_Franklin 59

    View full-size slide

  60. @Jack_Franklin 60

    View full-size slide

  61. 1. Define our CSS as normal.
    2. Import our CSS (with a build
    tool like Webpack in the
    middle).
    3. Use the classnames as
    generated at build time.
    @Jack_Franklin 61

    View full-size slide

  62. Class names are guaranteed to be unique.
    @Jack_Franklin 62

    View full-size slide

  63. CSS in JavaScript
    @Jack_Franklin 63

    View full-size slide

  64. const Button = styled.button`
    color: red;
    background: green;
    `
    class TweetButton extends React.Component {
    render() {
    return (

    New tweet!

    )
    }
    }
    @Jack_Franklin 64

    View full-size slide

  65. https://javascriptplayground.com/introduction-to-
    styled-components-react/
    @Jack_Franklin 65

    View full-size slide

  66. It's up to your team to decide what's best for you
    and your project
    There are many different solutions and many
    different libraries; experiment with a few and pick
    the ones that works best :)
    @Jack_Franklin 66

    View full-size slide

  67. When to break
    components down
    @Jack_Franklin 67

    View full-size slide

  68. Should this component
    actually be two?
    @Jack_Franklin 68

    View full-size slide

  69. Components are cheap, but not free
    —You pay in maintenance; more code and UI to
    maintain
    —You pay in complexity; another component that
    exists in your application
    —You pay in communication; this component will
    have to talk to others to get data
    @Jack_Franklin 69

    View full-size slide

  70. Components should be
    small, and you should
    have lots.
    @Jack_Franklin 70

    View full-size slide

  71. But how to know when a component is too big?
    —How many lines of code is it?
    —How many different HTML elements are there?
    —How hard is this file to understand?
    —Does the name have (or should have) an And in it?
    ItemNameAndPrice.
    @Jack_Franklin 71

    View full-size slide

  72. Allowing components to
    vary slightly !
    @Jack_Franklin 72

    View full-size slide

  73. @Jack_Franklin 73

    View full-size slide

  74. Similarities Differences
    The icons Slight visual
    variations
    The like/dislike logic
    They are displayed
    next to each other
    Basically everything
    is the same but no
    the designer knows
    best 3
    3 you should discuss if the variations make sense, but I
    guarantee you that they will at least some of the time
    @Jack_Franklin 74

    View full-size slide

  75. How do you have
    components that are 95%
    the same?
    @Jack_Franklin 75

    View full-size slide

  76. Explicitly allow component variants
    const SENTIMENT_VARIANTS = {
    QUICKVIEW_BUTTONS,
    MOBILE_ICONS,
    FADING_ICONS,
    }
    variant={SENTIMENT_VARIANTS.FADING_ICONS} />
    @Jack_Franklin 76

    View full-size slide

  77. The key here is to explicitly allow just a few
    And you can apply CSS classes accordingly.
    .itemSentiment {
    ...
    }
    .itemSentimentVariantFadingIcons {
    ...
    }
    @Jack_Franklin 77

    View full-size slide

  78. Always favour explicit
    code over implicit
    knowledge
    @Jack_Franklin 78

    View full-size slide

  79. Beware breaking the
    abstraction
    @Jack_Franklin 79

    View full-size slide

  80. We've talked about how components should be
    black boxes.
    @Jack_Franklin 80

    View full-size slide

  81. A good way to figure out if you're sticking to this is this:
    Could you take a brand new project, and place your
    component into it, with no other set up required?
    @Jack_Franklin 81

    View full-size slide

  82. But the answer cannot always be
    yes
    @Jack_Franklin 82

    View full-size slide

  83. Some of your components will
    have to talk to the rest of your
    application.
    The trick is minimising how
    many and coming up with a
    structure to it.
    Don't allow any component to
    implicitly rely on some data.
    @Jack_Franklin 83

    View full-size slide

  84. Giving components data.
    @Jack_Franklin 84

    View full-size slide

  85. 3 approaches
    —Components fetch data from your server via an
    API call
    —Components are given data from the server when
    it renders the HTML
    —Components parse data left for them in script
    tags
    @Jack_Franklin 85

    View full-size slide

  86. APIs
    1. Component initially renders a loading spinner (or
    nothing)
    2. Component fetches from /your/api/some-
    endpoint.json
    3. Component updates to show the data it has.
    4. Component updates to show an error if anything
    went wrong.
    @Jack_Franklin 86

    View full-size slide

  87. APIs
    ✅ ❌
    Ensures we always have the most up
    to date data
    Adds extra loading state
    Easy to re-fetch the data if we need
    to
    Introduces chance of error
    Component is network dependent
    Component will be slower to show
    data to the user
    @Jack_Franklin 87

    View full-size slide

  88. Data from the server


    @Jack_Franklin 88

    View full-size slide

  89. item-id="13191186"
    add-dislike="/xhr/structured-feedback2/13191186/negative"
    remove-dislike="/xhr/structured-feedback2/13191186/negative/delete"
    add-like="/xhr/structured-feedback2/13191186/positive"
    remove-like="/xhr/structured-feedback2/13191186/positive/delete"
    dislike-reasons-url="/api/negative-feedback-tags/13191186"
    sentiment="neutral">

    @Jack_Franklin 89

    View full-size slide

  90. Data from server
    ✅ ❌
    We get the data
    immediately from our
    server
    Data might be out of date
    if the user has performed
    an action since rendering
    Fewer states to worry
    about (no loading or error)
    Creates long strings of
    JSON in HTML
    @Jack_Franklin 90

    View full-size slide

  91. Data in script tags
    @Jack_Franklin 91

    View full-size slide

  92. Write a small util around your global config
    import { getConfigValue } from 'lib/global-config'
    const userIsLoggedIn = getConfigValue('user.authenticated', false)
    @Jack_Franklin 92

    View full-size slide

  93. ✅ ❌
    Useful only for data that
    needs to be globally
    available
    Can lead to a huge set of
    config if used too much.
    A good way of setting
    data that can be
    accessed from anywhere
    on the site.
    Won't be updated if the
    data changes.
    @Jack_Franklin 93

    View full-size slide

  94. Think carefully about all the different approaches and the ones that work best for each component individually.
    Type Situation
    APIs Good for data that changes and
    needs to be up to date
    Data from server Good for component specific data
    that won't change
    Global config Good for data that any component
    might need, and that won't change.
    @Jack_Franklin 94

    View full-size slide

  95. The path to components
    today !
    @Jack_Franklin 95

    View full-size slide

  96. It's easy to introduce some of these ideas to an
    existing project.
    @Jack_Franklin 96

    View full-size slide

  97. Not everything has to be a single page application
    Servers are still useful.
    @Jack_Franklin 97

    View full-size slide

  98. @Jack_Franklin 98

    View full-size slide

  99. Take Thread, for example
    —~5 years old, built as a server side Django app
    that renders HTML via templates to the client.
    —JavaScript is layered on top via plain old
    JavaScript and jQuery.
    —We now have ~50 components (give or take) and
    that number is going up all the time.
    @Jack_Franklin 99

    View full-size slide

  100. @Jack_Franklin 100

    View full-size slide

  101. Wrapping with
    web elements 4
    4 https://github.com/PixelsCommander/ReactiveElements
    @Jack_Franklin 101

    View full-size slide

  102. In our JavaScript:
    import ThreadItemCard from './components/item-card.jsx'
    document.registerReact('thread-item-card', ThreadItemCard)
    In our server's templates:

    @Jack_Franklin 102

    View full-size slide

  103. We can introduce React and our component system
    without having to rewrite a lot of functionality that
    we already have on the server.
    And when we don't need JavaScript, we can still just
    render HTML and CSS via our server (!) !
    @Jack_Franklin 103

    View full-size slide

  104. Dealing with legacy code
    CollectPlusAPI.initialise(
    $('.collect-plus-widget'),
    {
    ...
    }
    )
    @Jack_Franklin 104

    View full-size slide

  105. Wrap it in a component!
    class ReactCollectPlus extends Component {
    componentDidMount() {
    // legacy JS goes here
    CollectPlusAPI...
    }
    }

    @Jack_Franklin 105

    View full-size slide

  106. The black box abstraction
    can be used to hide away
    bad code in a layer of
    good
    @Jack_Franklin 106

    View full-size slide

  107. The "black boxyness" of
    components lets you try
    new technology
    @Jack_Franklin 107

    View full-size slide

  108. How we adopted CSS
    Modules at Thread
    @Jack_Franklin 108

    View full-size slide

  109. ! Hey, I think that CSS
    Modules might be a good
    thing, for reasons X, Y and
    Z
    @Jack_Franklin 109

    View full-size slide

  110. ! Sounds good to me,
    let's try it!
    @Jack_Franklin 110

    View full-size slide

  111. ! So I built our new
    component using it - what
    do you think?
    @Jack_Franklin 111

    View full-size slide

  112. ! Looks great, let's ship
    it and see how we find it
    on our next few projects.
    @Jack_Franklin 112

    View full-size slide

  113. After a few weeks we can
    decide either way.
    @Jack_Franklin 113

    View full-size slide

  114. Yes, all your components should be written using
    the same set of tools and techniques.
    But launching one that's built differently to learn
    about something provides a lot of value.
    @Jack_Franklin 114

    View full-size slide

  115. It's easy to get distracted talking about the benefits
    of a new tool/language in theory
    But components let you just do it.
    @Jack_Franklin 115

    View full-size slide

  116. To sum up...
    —Keep your components small and be wary of too
    much configuration
    —Beware anything that breaks the black box
    abstraction
    —Prefer explicit code over implicit knowledge of
    how your components interact
    —We're all figuring this out together, as we go.
    @Jack_Franklin 116

    View full-size slide

  117. It's a very exciting time to
    be a front end developer!
    @Jack_Franklin 117

    View full-size slide

  118. FRONTENDNE for 50% off
    https://
    javascriptplayground.com/
    testing-react-enzyme-jest/
    @Jack_Franklin 118

    View full-size slide

  119. Thank you.
    @Jack_Franklin
    speakerdeck.com/jackfranklin
    We're hiring! jack at thread dot
    com
    @Jack_Franklin 119

    View full-size slide