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. 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
  2. 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
  3. All of today's talk is reasonably new, especially within the

    context of front-end development @Jack_Franklin 5
  4. Today I'm going to talk you through some of my

    experiences, but I'd love to hear yours! @Jack_Franklin 6
  5. 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
  6. APIs and JSON /api/cat-pics [ { "id": 1, "name": "Fluffy",

    "age": 5 }, { "id": 2, "name": "Mittens", "age": 7 } ] @Jack_Franklin 10
  7. <p>This is a paragraph element (or...<em>component?</em>).</p> <h1>This is a heading</h1>

    <ul> <li>this is a list item</li> </ul> @Jack_Franklin 14
  8. And what if we could extend the box of bricks?

    1 <thread-user-avatar src="/img/jack.png"></thread-user-avatar> 1 https://developers.google.com/web/fundamentals/web-components/customelements @Jack_Franklin 15
  9. And what if we built frameworks around this idea, rather

    than the MVC approach? @Jack_Franklin 16
  10. A page is a series of components Made up of

    HTML, CSS and JavaScript 2 2 not necessarily all three @Jack_Franklin 19
  11. Pages will reuse the same components Common elements such as

    buttons, form inputs, user avatars, tweets, etc. @Jack_Franklin 20
  12. The ideas in React are more important than React itself.

    And now exist in a plethora of front end frameworks. @Jack_Franklin 23
  13. 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
  14. "I want a carousel on my website" <jacks-custom-fancy-carousel speed="1000" infinite-playback>

    </jacks-custom-fancy-carousel> I don't need to care about how the carousel works in order to use it. @Jack_Franklin 27
  15. 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
  16. We keep all our component code in one folder, to

    help keep things isolated and to avoid directory jumping. @Jack_Franklin 34
  17. 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 ( <form> ... </form> ) } } @Jack_Franklin 36
  18. 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 ( <form> ... </form> ) } } @Jack_Franklin 37
  19. ! Hey, please build me a component to view an

    item of clothing on Thread.com @Jack_Franklin 40
  20. class ThreadItem extends Component { render() { return ( <div>

    <ItemImage item={this.props.item} /> <h5>{this.props.item.title}</h5> <ItemPrice item={this.props.item} /> <ItemSentiment item={this.props.item} liked={this.props.item.liked === true} /> </div> ) } } @Jack_Franklin 41
  21. Oh, can we make this page show ten different items?

    <ul> <li><ThreadItem item={...} /></li> <li><ThreadItem item={...} /></li> <li><ThreadItem item={...} /></li> <li><ThreadItem item={...} /></li> <li><ThreadItem item={...} /></li> </ul> ! Job done! " @Jack_Franklin 43
  22. OK but now can we make it so it shows

    the brand as well as the title <ThreadItem item={...} showBrand={true} /> ! Job done! " @Jack_Franklin 44
  23. Oh and also if it's on sale we want to

    show the old price alongside the new price <ThreadItem item={...} showBrand={true} showOldPriceBeforeSale={true} /> ! Job done! " @Jack_Franklin 45
  24. And we need to be able to not show the

    item sentiment sometimes <ThreadItem item={...} showBrand={true} showOldPriceBeforeSale={true} showSentiment={false} /> ! Job done... @Jack_Franklin 46
  25. For some items we want to show the brand instead

    of the name <ThreadItem item={...} showBrand={true} showBrandInsteadOfName={true} showOldPriceBeforeSale={true} showSentiment={false} /> ! Job done... @Jack_Franklin 47
  26. 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
  27. This is a big topic that I can only talk

    briefly about @Jack_Franklin 57
  28. All it takes is one slip... <!-- this is not

    a carousel but the styling is pretty similar and I'm under time pressure so I'll just use it anyway --> <div class="jacks-carousel"> @Jack_Franklin 59
  29. 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
  30. const Button = styled.button` color: red; background: green; ` class

    TweetButton extends React.Component { render() { return ( <Button> New tweet! </Button> ) } } @Jack_Franklin 64
  31. 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
  32. 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
  33. 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
  34. 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
  35. Explicitly allow component variants const SENTIMENT_VARIANTS = { QUICKVIEW_BUTTONS, MOBILE_ICONS,

    FADING_ICONS, } <ThreadSentiment variant={SENTIMENT_VARIANTS.FADING_ICONS} /> @Jack_Franklin 76
  36. The key here is to explicitly allow just a few

    And you can apply CSS classes accordingly. .itemSentiment { ... } .itemSentimentVariantFadingIcons { ... } @Jack_Franklin 77
  37. 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
  38. 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
  39. 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
  40. 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
  41. 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
  42. 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
  43. Write a small util around your global config import {

    getConfigValue } from 'lib/global-config' const userIsLoggedIn = getConfigValue('user.authenticated', false) @Jack_Franklin 92
  44. ✅ ❌ 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
  45. 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
  46. It's easy to introduce some of these ideas to an

    existing project. @Jack_Franklin 96
  47. 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
  48. In our JavaScript: import ThreadItemCard from './components/item-card.jsx' document.registerReact('thread-item-card', ThreadItemCard) In

    our server's templates: <thread-item-card item="{...}"></thread-item-card> @Jack_Franklin 102
  49. 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
  50. Wrap it in a component! class ReactCollectPlus extends Component {

    componentDidMount() { // legacy JS goes here CollectPlusAPI... } } <thread-collect-plus ...></thread-collect-plus> @Jack_Franklin 105
  51. The black box abstraction can be used to hide away

    bad code in a layer of good @Jack_Franklin 106
  52. ! Hey, I think that CSS Modules might be a

    good thing, for reasons X, Y and Z @Jack_Franklin 109
  53. ! So I built our new component using it -

    what do you think? @Jack_Franklin 111
  54. ! Looks great, let's ship it and see how we

    find it on our next few projects. @Jack_Franklin 112
  55. 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
  56. 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
  57. 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
  58. It's a very exciting time to be a front end

    developer! @Jack_Franklin 117