Slide 1

Slide 1 text

@Jack_Franklin 1

Slide 2

Slide 2 text

@Jack_Franklin 2

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

@Jack_Franklin 8

Slide 9

Slide 9 text

@Jack_Franklin 9

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

@Jack_Franklin 11

Slide 12

Slide 12 text

@Jack_Franklin 12

Slide 13

Slide 13 text

MVC doesn't fit frontend development @Jack_Franklin 13

Slide 14

Slide 14 text

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

This is a heading

  • this is a list item
@Jack_Franklin 14

Slide 15

Slide 15 text

And what if we could extend the box of bricks? 1 1 https://developers.google.com/web/fundamentals/web-components/customelements @Jack_Franklin 15

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

The Theory @Jack_Franklin 17

Slide 18

Slide 18 text

@Jack_Franklin 18

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

@Jack_Franklin 22

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

Approaches and challenges of building good components ✅ @Jack_Franklin 25

Slide 26

Slide 26 text

Components are designed to be a black box @Jack_Franklin 26

Slide 27

Slide 27 text

"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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

@Jack_Franklin 30

Slide 31

Slide 31 text

@Jack_Franklin 31

Slide 32

Slide 32 text

@Jack_Franklin 32

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

Avoid business logic @Jack_Franklin 35

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

You should keep your components reusable @Jack_Franklin 38

Slide 39

Slide 39 text

Reusable components have to be configurable @Jack_Franklin 39

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

class ThreadItem extends Component { render() { return (
{this.props.item.title}
) } } @Jack_Franklin 41

Slide 42

Slide 42 text

! Job done! " @Jack_Franklin 42

Slide 43

Slide 43 text

Oh, can we make this page show ten different items?
! Job done! " @Jack_Franklin 43

Slide 44

Slide 44 text

OK but now can we make it so it shows the brand as well as the title ! Job done! " @Jack_Franklin 44

Slide 45

Slide 45 text

Oh and also if it's on sale we want to show the old price alongside the new price ! Job done! " @Jack_Franklin 45

Slide 46

Slide 46 text

And we need to be able to not show the item sentiment sometimes ! Job done... @Jack_Franklin 46

Slide 47

Slide 47 text

For some items we want to show the brand instead of the name ! Job done... @Jack_Franklin 47

Slide 48

Slide 48 text

! Good luck understanding all these options in six months time... @Jack_Franklin 48

Slide 49

Slide 49 text

@Jack_Franklin 49

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

Optimise for developer readability @Jack_Franklin 51

Slide 52

Slide 52 text

CSS @Jack_Franklin 52

Slide 53

Slide 53 text

Every component should provide its styling. @Jack_Franklin 53

Slide 54

Slide 54 text

@Jack_Franklin 54

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

All it takes is one slip...

Slide 60

Slide 60 text

@Jack_Franklin 60

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

Class names are guaranteed to be unique. @Jack_Franklin 62

Slide 63

Slide 63 text

CSS in JavaScript @Jack_Franklin 63

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

When to break components down @Jack_Franklin 67

Slide 68

Slide 68 text

Should this component actually be two? @Jack_Franklin 68

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

Allowing components to vary slightly ! @Jack_Franklin 72

Slide 73

Slide 73 text

@Jack_Franklin 73

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

Always favour explicit code over implicit knowledge @Jack_Franklin 78

Slide 79

Slide 79 text

Beware breaking the abstraction @Jack_Franklin 79

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

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

Slide 82

Slide 82 text

But the answer cannot always be yes @Jack_Franklin 82

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

Giving components data. @Jack_Franklin 84

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

Data from the server @Jack_Franklin 88

Slide 89

Slide 89 text

@Jack_Franklin 89

Slide 90

Slide 90 text

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

Slide 91

Slide 91 text

Data in script tags @Jack_Franklin 91

Slide 92

Slide 92 text

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

Slide 93

Slide 93 text

✅ ❌ 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

Slide 94

Slide 94 text

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

Slide 95

Slide 95 text

The path to components today ! @Jack_Franklin 95

Slide 96

Slide 96 text

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

Slide 97

Slide 97 text

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

Slide 98

Slide 98 text

@Jack_Franklin 98

Slide 99

Slide 99 text

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

Slide 100

Slide 100 text

@Jack_Franklin 100

Slide 101

Slide 101 text

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

Slide 102

Slide 102 text

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

Slide 103

Slide 103 text

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

Slide 104

Slide 104 text

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

Slide 105

Slide 105 text

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

Slide 106

Slide 106 text

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

Slide 107

Slide 107 text

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

Slide 108

Slide 108 text

How we adopted CSS Modules at Thread @Jack_Franklin 108

Slide 109

Slide 109 text

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

Slide 110

Slide 110 text

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

Slide 111

Slide 111 text

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

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

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

Slide 114

Slide 114 text

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

Slide 115

Slide 115 text

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

Slide 116

Slide 116 text

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

Slide 117

Slide 117 text

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

Slide 118

Slide 118 text

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

Slide 119

Slide 119 text

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