Best Practices on building a UI component library for your company (David Wells) – FSF 2016

Best Practices on building a UI component library for your company (David Wells) – FSF 2016


DAVID: hello, how is everybody doing? All right. I know I’m the talk before
lunch, so bear with me. Yes, as mentioned, my name is David Wells. I’m a FullStack
developer, I work at Serverless. You might have seen our CEO, Austin, talking
about what Serverless is. Before I worked there, I worked at MuleSoft. I want to take
FullStackFest for inviting me to talk here. It is awesome to be in Barcelona. It’s always
great to travel, and the slides for my presentation can be found right there at the tiny
link. Cool. So I’m going to start off with a story. The story is about a quest. A quest
for the perfect platform user interface. Like what would be the ideal set up for a
larger project? This is something that I feel like a lot of
us strive to reach, and it steams like an unattainable goal as things are always
change, and, more specifically, like when I talk about platform UI, I mean when you’re
working with a larger team, or you’re perhaps working across multiple departments
in your organisation. How do you build a
UI that transcends those boundaries? This is the number of JavaScript frameworks
that were released this previous week: 1,972. Each one comes with its upsides and
downsides. What I have learned over the past two years
building platform UI and some mistakes to avoid, and some best practices
to take back into your own companies. Imagine in your minds what the perfect set-up
would be for your UI. Think about it for a second. What is the perfect back-end? What is the perfect
frontend? What kind of CSS set-up would you want? Start imagining that, will I will tell
you mine. First and foremost, imagine a scenario where
your UI is running out much a single code base, shared across multiple areas
of your company, shared across the marketing side is using it, the blog is using
it, the web applications are using it, the mobile apps are using it, and even you’re
using it inside of legacy applications. This
set-up is shared across teams, and across platforms, like I mentioned, mobile, desktop,
web – you name it. So that’s like an ideal set-up for me. I wanted to work
everywhere – I want it to work everywhere and have one code base to maintain and
use. The other thing is that it will be organised. What if every single lay-out, icon,
font, building block, component, button, link, whatever, you use is in one centralised
location for all developers to use? And one place where people can find things
and freely contribute to that. The other kind of core tenet that I would
strive for is like keeping things in sync, so, if we have this
one single code base to rule them all, like a
platform UI, as it were, what if your latest style change could propagate across all of
your applications all at once? That would be pretty compelling, and a huge
problem that companies with more than one application,
and a larger team, face on a pretty regular basis. So, just imagine having that kind of platform
leverage where deploying code and updates across apps is easy. Even better than that, just imagine like a
consistent brand experience for your end-user, so every single thing that they touch,
whether it is the marketing side, the blog, inside of your application, your mobile app,
everything is cohesive, and just feels like it was put together with care been then
everything, the ideal set up would be like it is also self-contained, so, imagine a world where your CSS is completely self-contained
and guaranteed not to cause conflicts with other applications, other third-party CSS
libraries – you name it – it is isolated. That
sounds pretty compelling to me. The last thing is how do we have a scaleable
solution that achieves all of these things? And that work across the company? So, scaleable
from both the people perspective, of is this code actually maintainable? And from a
tech perspective as well, like does it work everywhere? Will it handle all of our needs? Is it performant, et cetera? That’s basically what we are going to be chatting
about today. Basically, platform UI, building a component-based
architecture. And a
component-based architecture basically enables all of the things that I told you guys to
imagine or possible today with this kind of set-up that I’m going to run through. More
specifically today, we are going to be talking about a React component-based
architecture and there’s no idea why these methodologies can’t apply to your
framework of choice. Let’s explore this. It starts with a design system. So a design
system is basically a place where you formalise your user interface, the different kind of
lay-outs you have, the tonality of how your application is going to work, your brand,
a lot of people call them style guides. There are tonnes of examples out there on
the web. But it just makes things easier for both internal
and external people to consume. And build things with. There are a couple of different examples. Here’s a good one
called the Lightning Design System. They did a really, really good job basically
baking in all of the different rules for like how
to do different lay-outs for settings pages, for list
pages, for feed pages, et cetera. How all the different variations, the buttons
are managed, and stuff like that. It is basically how to do everything with
their UI framework. It is super handy, I would imagine, for everyone
inside a sales force and outside, building apps for the sales force
platform. But we are going to be talking
about today is the component library I built at MuleSoft, the one-stop shop where you
can go and see all the different components that are consumable, all the
documentation, all the different icons, all the different colours, all the variables and
mixings availability – mix-ins available to developers and some actual lay-out demos
and, like, standards around that. I’m going to skip the live demo until the
end. But,
yes, what lives in this style guide? Documentation, like I mentioned. This is both
documentation that’s written by the team, but also documentation that lives directly
in your code. So, when you’re building a React components,
if you’re using prop types, you can basically automatically generate the
documentation for your component library so you don’t have to maintain text in a different
place whenever you make a change in your code. That’s automatically reflected in basically
your living style guide. The other
thing that I put in here is a live code playground where basically you can interact with
the components, change the props, see how they act, and mix and match them
together. And we will see that in the live demo, and
then also, what is extremely important is, like usage examples, so, like
how do you actually use this component with some dummy data? So you’re basically, you’re almost writing
the code for your team so they can kind of get off building their
specific use case quickly. And then also
platform guidelines like I mentioned, like how do you show warning text, when to use
certain types of buttons, et cetera? So you have a very consistent feel, so, when
you’re – when your user is moving around to different applications, the experience feels
the same, and just a little bit of context around this. MuleSoft has around eight
different products that were kind of all bit in silos over the last couple of years, and
the – the experience wasn’t as cohesive as we wanted it to be, so that is kind of the
idea behind why we wanted to do this. Yes, cool. How how? This is like
pie-in-the-sky, yes, this sounds good, but how do we go about doing this? It is pretty
straightforward. We are going to run through these five things. We might not run through profit – maybe later, I don’t know. We will see. Yes, basically, we need to
break things down. We need to figure out how we are going to
actually handle like our CSS, like I mentioned, how we are going to
handle all the assets to be easily consumable, and then how to actually package
them and distribute them out to different teams, or to the public if you decide
maybe open-source your component library, and profit. Cool. So, this is an example of like UI, this is
a demo on the – where you start by breaking down a particular
view of your application, and start thinking about things as components. Everything on this screen is a component. So,
every single tiny little piece like the radio buttons, the chapter, the icons, the labels,
the dropdowns, et cetera, each tiny piece can
be broken out into a separate component and reused across multiple areas of your application. So basically you start thinking
about your UI in such a way where it is like how can I build this design that the
designer has given me into something with the most, like the maximum amount of code
to use? That is really what React, the kind of core
philosophy around React is how can you componentise things and make the code
easy to reuse? Then, after that, you
basically have, like – once you have all the little tiny pieces, the individual components,
how do you compose those together to create maybe more complex components? Here we have an examining of like the navbars
a component, the detail pane is a component, and the table. They’re all made up much smaller pieces, but,
for the consuming developer, they’re just pulling
in that one larger piece. This kind of riffs off
a concept called atomic design by Brad Frost. I recommend checking out his posts on
this. He like says take Adam’s tiny – atoms of your
application, then compose them into molecules, then into bigger organisms, then
into page templates and then into full, actual done pages. This inspired me to kind of follow this pattern. We don’t follow it
exactly like that, but very similarly. Here’s an example. Here are like three tiny atoms,
or components, if you will, the label, input, and a button. And, basically, you can
compose those together now to create a, let’s say, a search box for a form input, or a
modal, or, let’s say it is a marketing like copy with a button thingy on the blog or
whatever. So there are a lots of different ways that
you can use these three components and compose them together to create
basically compose components to use throughout your application. Just to stress again: everything is a.component:
I’m a component, you were a component, we are
all a component. That’s the moral of the
story. Cool. So, what does it actually look like? What does a component look like in
code? This is the anatomy in which we build components. We are basically, like, all of
our components live in a components repository. Every component gets its own folder,
every component has like a component named.js, where the source code of the
component live. The styles live in there. The tests live in there, in that same folder,
and an index file for easily importing and exporting, and we also have examples. That
examples folder is what automatically generates the documentation and live code
examples on the site that I’m going to show you. Cool, so our approach at Serverless is different
on atomic design where we have the low-level components. Those compose and do what I’m calling fragments
right now – I’m trying to find a good name. Those fragments compose into layouts, and
those layouts compose into pages. So, this is serverless.com. This is our front-end
marketing site. It is a statistically built website, complete
with React, and then we push that up to a CDN, and, yes, so we can use
the components that we are using in our applications that we are building, and in
our marketing side, in our blog, et cetera, so, if
we did ever make a change to, let’s say the button design, that would reflect
throughout the platform, not just like in our app, and we have to update, say
Wordpress if we had that as our marketing site. Under the hood, this is using the tool it is using is a stack site generator called
is phenomic. There’s a link here in the slide to
check it out. It is cool. Here’s the obligatory Peter Griffin CSS slide,
which, by law, you must put into every presentation where you
mention CSS! We will talk about handling
styles in your component library. There are challenges with CSS, right? We’ve all faced
it. How do you handle class-name collisions? If you’re using like a third-party CSS
library like bootstrap, if we want to use these components inside of a legacy application,
how do we make sure the styles don’t conflict? Like what we had to do in Mulesoft,
there were some is green field projects built with the components but there were a lot
of legacy applications used in Angular 1 with bootstrap and other stuff making the
component live inside of that application. We have to make sure we’re not messing
with their staff, and they’re not messing with our stuff, which is quite a challenge,
but it is actually pretty easily doable. This is a real quote from our favourite presidential
nominee! Namespace collisions are a threat and we must
beat that threat. If you want
your components to be standalone, we need to solve that. How do we do that? So,
basically, we use technology called Post CSS and CSS modules. This works with
welcome pack, if you have web pack. I have an hour-long presentation on how to
do CSS with React. It goes through the different variations of
how you can do styling. I’m
just focusing right now on my favourite, and the one that works best in this platform
situation which is post-CS – Post CSS and CSS modules. Post CSS is like Babel for CSS. It will turn your CSS into an abstract syntax
tree and you can manipulate that. It’s
similar to SASS and less, and more powerful, in my opinion, and you can do everything
you can do as with PostCSS. What does it look like this? This is a React component. At the top, I’m importing the styles from
the CSS file, and just normal CSS. What is
happening here is that styles that is being imported, is actually – so, it is being turned
into an object with keys on it, and those keys are basically localised class names. Now
your CSS names that you are writing normal CSS, so wrapper and the class of button
get turned into this localised class when actually it renders to the page. That’s either if
you’re rendering on runtime or if you’re rendering on the server, this is what it looks
like. This is customisable, by the way. That’s a long name. You can, for production,
you will customise that just to be the hash at the end. So, if you look at Gmail source
code or anything like that, you notice they have crazy class names that are hash
numbers. This is how you achieve something like that. The other thing that you would
want to do is, with PostCSS there is a plug-in called Initial where, basically, it turns
on a future CSS for spec for you which is all colon
initial. It will reset all inherited properties,
all CSS properties that can be inherited from apparent and reset them to the browser
defaults. When you add that to your CSS, when PostCSS
transpiles it will polyfill that for the browser, so you set that. Now you have a completely isolated component
based off this unique class name, which is awesome. It is not something we could do before
very easily. The other thing that you could do with like
PostCSS and CSS modules is use the CSS four spec today. You can use it for accessibility – yes, and
you can polyfill flex box back to IE8 if that is something
you have to support, and I feel sorry for you if
you do! So many, many things we can do with CSS modules. Not going to go through
all of this. Check out the other talk that I did at the
React meet-up in San Francisco. Do you really need this? If you answer yes to any of these questions,
then, yes, if you’re working on a team like you could implement
BEM style writing your classes. We
are humans, and humans make mistakes. This makes it so you cannot make mistakes. The class name is localised for you by a machine,
based off like an random hash, based off a file name, so, it is completely unique,
it won’t run into collisions. Are you including
any third-party CSS? Do you have to use foundation or bootstrap
or any other library that conflicts with your stuff? Yes. This will kind of make your life a lot easier. Are you running in a third-party environment? The answer to this for everyone is yes. Because
the browsers, a third-party environment, meaning anybody could instill any kind of
browser extension and theme your app however they want. If you want to stop that,
you can do this. Then, yes, so, and do you want your styles
to look right, no matter what? The answer to that should be yes. Cool. That is post-CSS in a nutshell. Really,
really like transforming how you can write your CSS. Normal, regular CSS and
automatically transpiles pile that into something that will get rid of global name spaces
and fix the main problems with CSS. It also allows you, like there are some use
cases where you do need global CSS, and it gives
you an escape hatch to do that. An
example would be like a Modahl pops open, and you want to add a class of the body
that does something, like you can do stuff like that. Cool. So how do you handle
global assets? Global assets meaning variables, mix-ins,
and icons. Variables and
mix-ins: no longer to you need to write your variables and mixins in CSS. You can to it
in JavaScript. Why not? JavaScript is eating the world, and it is
far more powerful than writing like, let’s say, a mixin function. If you write in a mixin function in Sass you’re
doing this thing that that you’re not supposed to be doing this thing. If you write it in
JavaScript, you write a JavaScript function that returns succeed. You have the full
access to the system to do whatever you want. This is how you enable this with
PostCSS. You writer two including-ins, so it is very
similar to – it is what you do in the transpilation step. I’m saying grab my mixin file and make that
globally available to all my CSS. This might be hard to see, so this is the
variable file where it is an object. I’m
defining my various, like, break points, I’m defining platform-wide indexes to use
everywhere, the colours, et cetera. Then, on the right-hand side there, we have
our mixins which a mixin is pretty much just like
multiple values at once. Interestingly,
down at the bottom, it is a function which you can pass in any value you want, or use
an MPN package to calculate a different colour or something. You can do whatever you
want. The usage in the CSS is just like – I’m justifying
– then a variable there. Similar
to SASS, but, yes. Then, what is cool about this, because it
is written? JavaScript, is
I can also use this inside of my components. Now, if I have, let’s say, state-based like
I want to add a red text to a button because something bad happened, I can import my
brand colour red from my variables file because it is just a JavaScript object. And use
that where I want to. So, cool. Running short on time, so I’m going to speed
it up a little bit. Icons: if you’re doing icons, font icons are
kind of going the way of the dinosaur. They’re not as flexible as SVG icons. SVGs are also typically lighter weight
and more flexible. For example, SVGs, it is marked up that you
can style individual, like, lines and strokes, whereas font icons
are just a single colour that you can apply different colours to, but here you can see
that we have a done of different SVG icons that are multi-coloured, and we can change
those individual colours with CSS whenever we want, or do cool animations, and yadda,
yadda. There is a build script that runs
through all the SVGs, runs it through web pack. It bundles it with a web pack plug-in
called SVGStore. It will optimise everything and create a sprite,
an you have an SVG icon sprite that gets injected into the DOM
and you can profit. If you have an SVG
sprite on the page, it is hidden, nobody can see it, but anywhere you use SVG, the use
tag and the ID of that, corresponding icon in the sprite, it will just render your icon
right there. It is just super handy. Cool. And, so, how can I build this? This is all super
cool. How can I build this stuff? At MuleSoft, it was a custom solution that
I built, but we are using some open-source things, and
maybe one day the library will actually be open-source. I think they’re working on than. But here are some other resources for
you guys. So there is a project called carte blanche
where basically will build out the component library for you. You give it a path. It is a webpack plug-in, give a path where it lives, it will generate the UI for
you, and it also will do some cool stuff like build out your examples, and like really stress-test,
what happens when all these weird properties are passed into this component? There is also a React storybook which is
very similar to this where it is kind of like writing tests, though, where you’re writing
examples for your components. React adoption from the React core team, super
handy. You could basically pass a directory of React
components as long as those React components have prop types and comments
above the prop types. They will
automatically generate, basically give you an object back for you to do whatever you
want with. That is what you’re doing – we’re doing under
the hood with our solution, or you could roll your own. Again, with React option, it is an online
tool. You can give it a
path, and it will spit back the data about that component, and then you can render out
whatever you want, so you can get creative there. Our component library uses these
two links at the bottom here, the React component illustrator and its corresponding web
pack plugin. This is using it under the hood, but it also
will grab those examples files that I showed in the component anatomy, and
it will take that example source code and also make that available to me in my,
like – in the user interface for the component library. So, people can, like, see that code interactor
with it. If you’re interested in
that, check out those two links. This is a last-minute really awful diagram
I put in here! Basically, this is kind of the idea. So you have all of these consumers, you have
one single source of truth, your component library
where your components live in there. Your mix-ins live in there, your variables
live in there, the font stuff, your typography rules, et cetera, and then, when you make
an update, you can basically problem gate that out throughout your applications. It is important to use semantic versions,
so, if there are breaking changes, you want to make
sure that those don’t actually get passed your through CI CD system, but, yes, cool. And just to get you guys started, there’s
a bunch of open-source component libraries outs there. Main have the living style guide that you
can do whatever with. You don’t need to start from scratch if you’re
working with React. There’s tonnes of
stuff to leverage, or just to see how specific components are built. Cool. So, let’s talk
about distribution. How do I get it out to my team? How do they consume it? That’s
with webpack and npm. A couple of important things to note with
this: you want to, with your component library, to building each
component separately. You don’t want to
build this massive index file or like output to this lib file, because, then, if a consuming
application is only using two components or three components or maybe four, they
would, in their bundle, they would have everything. And it is going to be rather large. It is like relatively used everywhere. It is going to be a problem, and the bundle
size is going to grow tremendously, so, what you want
to do is build each individual component separately and give it its own entry
point, basically, where then the consumer would just import button from at
your component library and the built output. — built output. Because you’re building each thing into a
flat directory structure, what that means is like now you
can externalise all of the components that each component is using. For this example, the button component, it
also uses the icon component, it also uses the tooltip component,
and, if you weren’t building these stabilitily and externalising, which is a
webpack feature, external using those, button would have the entire source code for icon,
and the entire source code for tooltip in its
built output, and then the consumer app could also be using other things that use tool
kit, and there are basically code duplications which you want to avoid. What we did to
keep the bundle sizes down is we externalised the CSS. This requires that the
consumer also uses PostCSS but it is for our team at MuleSoft, and that’s fine and
everyone can do that. This means when the actual application is
built, it will only unions the CSS that that, the application
is using. It won’t use other stuff, and you can
also pipe do down to the browser in a CSS file rather than through a JavaScript bundle,
and browsers can request multiple files concurrently, so this is a kind of performance
optimisation. Cool. Then the other kind of like core these of
this, enif I if a lot of people are consuming your components is how
do you actually know that, like what components are being used where? Like it is very hard to keep track of that
stuff manually. So, this code, you could actually probably
just grab and use, tweak a little bit, but, every time webpack builds, it will
parse through. It gives you the entire
structure of your application, all of the things that are being imported, so basically,
you can check and see okay, what components is
this consuming application actually using? And then report that back, so, we set this
up at MuleSoft to ping a lamda function, shameless plug to restore that. I actually know what version of the application
it was, what components that they were consuming,
and that basically like helps inform the team of okay, we’re making this change to
component x, y, and z, who is consuming it? When we take this change, let’s double-chose
those applications that we didn’t do something bad. It is important to have that kind of visibility
in there. Cool. And then
sell lessons learned. You want to be like very vigilant with your
component APIs. It is
super, super easy to say, like, okay, let’s add all the properties. You need to do this. You have a use case for this, you have a use
case for this. Your props start to grope
out of control, and it is really, really hard to deprecate props. So, yes, you want to be
vigilant and make sure that use higher component, basically wrapping the component in
another component if there is like some one-off use cases that you need. Don’t just
add more and more props. Don’t add things until you have use cases
for them. This is
a conversation all the time, like what about this future-use case that we don’t have yet? That we may never have. Yes, you want to avoid stuff like that. Name things well and
agree on a standard. I have a blog post PropType naming conventions. We don’t want
to reinvent API-like things if it is just mapping down to a DOM primitive. Use, like really
good naming conventions for Props, like it is a Boolean property, it is an “is” field
or has value, or whatever, or build. Yes. And avoid unnecessary abstractions. Set up linting
first, and I had to go update an entire code base later, which is painful. Test is server
side renderability early and often. This is something we didn’t do in the beginning,
and I had to go back and retro fit a lot of code. If you want a static website like I showed,
you want to make sure that you basically aren’t doing any document or window calls in
your components. But, yes, cool. So, yes, let me actually, I’m going to show
you guys the component library, and then I will wrap
up with some final thoughts. This is the
MuleSoft component library. We have this stuff generated from the source
code, there we go. This is. Okay. This is going to be hard to demo now. Basically, these are all
like working components. You can actually see the usage here of like,
okay, here is my component. Here is all the props that I’m giving it. This documentation, the prop types
and the comments are automatically generated from the code. This is a live code editor
so I can change this to danger, let’s say, and this is now a danger button. Yes, so it is
basically like this is exactly how you use this component in your application. I wrote
the code for you so you don’t have to. What this, like, allows is for really, really
quick prototyping and really, really fast basically
iterations on products. Likewise, we have
some demos, this is kind of what I showed before, and also, I can’t go back. It shows
the – we also have our typography, all of the colours, which is being automatically
generated from the JavaScript file, and printing them out, and all of our icons, and
these are all like basically SVG use tags. Let me show you guys what that looks like. Here is our SVG and here is the use tag. That is just referencing the sprite that
is down in the bottom of the page, so this means, like, you don’t want to inline it,
like icons everywhere, especially if you’re using
icons in a table or whatever, it is going to
make your DOM super heavy, so you want to keep those things down to a minimum. So that is the live demo. Cool. Some final thousand: with this set-up, you
can basically like achieve like a faster development
velocity. If everyone is consuming the
same things and contributing back to the same code base, you could do things a lot
faster. That’s not to say that everything needs like
every – like every component needs to live in the component library. We did have some use cases where project excise
had some – project x, y, and z had some things
that it needed and lived there in the repository. Sometimes, they were like, “Oh, we need that
in other things, let’s move that into the component library and use it
elsewhere.” Yes. Individuals can work on
these isolated components without worrying about breaking things. The main thing for
me is like having a multi-platform component library, so, again, targeting mobile
browser, and desktop. And having it like basically on all of our
assets, so I don’t have to maintain three different sets of CSS, I
just maintain my component library. I can use
that again on my marketing site, on my blog, on any demo apps, inside of any
application, and you name it. Yes. You can render this stuff statistically, service-side
rendering for better experience and indexability, and, yes, if you choose the static path,
so, this is again using something like Phenomic, basically, it is doing server-side
rendering, like on, in your CI system, and then it is deploying that after a CDN, so
you basically have raw scale, like out of the
box. If your application isn’t that dynamic. Which is what we are doing a lot of. So, no matter how much traffic goes to like
our site or whatever, it is on a CDN, so it doesn’t
really matter. We’re not rendering that
over and over again. Only once that build. Yes. So that, in my opinion, is like the
future stack. And I hope that was informative, and, yes,
let me know if you guys have any questions on Twitter. I’m @davidwells, and these are my favourite
pieces of technology right now. Cool! .

Leave a Reply

Your email address will not be published. Required fields are marked *