Thoughts About Front-End Development

I love receiving or making designs and then actualizing them in the browser. That is why I have spent most of my career with Front-end responsibilities. It is rewarding work that connects you with incredible collaborators.



But Front-end work is not easy, and because it is non-trivial I get asked about my methodology. So here you will find thoughts about Front-end development that are universal between projects that are mature, new or hastily written.



I've organized my notes into 3 sections:



  1. Problems
  2. Ideas
  3. Frequently asked questions





Problems

We can never have a "perfect" situation for too long in a growing system. Even stacks that feel great in the beginning will lose their allure. This is the nature of our work and we must try our best to persist as many qualities as possible. Here are the problems that I optimize for:





#1 "Our website is slow."

This problem is perpetual and your users will be the first to notice. Because it is a recurring problem, people find performance issues to be a great place to onboard others to a codebase and get contributions from people of all skill levels. Some websites take many seconds to render the UI. Other times there may be an excessive amount of loaders to compensate for the initial page load. Whatever it is, we have to improve on it.





#2 "The codebase is too complex."

When more contributors commit lines of code into the codebase, the codebase starts to lose simplicity and can become unfamiliar to original collaborators. In addition, when people leave jobs or pass on their work, new contributors can find it hard to understand all the changes without the original context.



The outcome is known infamously as technical debt. Some examples of this in the Front-end include multiple ways to write components, unfinished refactors, unnecessary round trips for data, local state setting hacks, and unnecessary usage of important while writing CSS.





#3 "We have state, and it is all over the place."

You cannot build a useful product without using state. But state is the root of all problems in the application and UI logic of your codebase. Without discipline or proper tooling, this can make any codebase unpredictable.





#4 "Our UIs look different in each browser"

UI elements such as the scrollbar or select menu can appear differently in the mainstream browsers: Chrome, Safari, FireFox, and Internet Explorer and their mobile counterparts.



This problem can be related to...





#5 "What you implemented looks nothing like the design."

Designers are often disappointed when the final product looks nothing like what was presented. This may not ruin your collaboration with other engineers, but leads to visual designers no longer wanting to work with you or your company.



It is a Front-end developers's obligation to ensure the design is implemented as thoughtfully as possible.





#6 "We are using technology that is no longer supported."

Teams have resource constraints, and therefore tend to use technologies that replace the need to hire specialists. Those technologies come in the form of services like Algolia, or frameworks such as Apollo GraphQL.



It is scary to use frameworks like Angular 1.X and find out it is discontinued while you are in the middle of Front-end development. Another example: when RethinkDB shut down, it forced teams to find a new long term direction for their stack.





#7 "Something broke, where are the Front-end tests?"

It is unfortunate enough that something broke for your users, but lacking tests in the codebase can frustrate members of your team.



There are different testing frameworks and strategies that can help you (such as TDD). Ask yourself: what do I need in order to be confident about the reliability of my product?





Ideas

No idea or solution solves all problems, but here are some of the tactics that I try in combination with each other:



Establish trust with your peers.

  • It is painful sometimes to be rotated into a team with people who aren't philosophically aligned with you (Redux versus MobX, React versus Vue). But someone has to put the effort into developing a relationship, and if you're reading this it might as well be you.
  • You want to have good habits and EQ around conflict.
  • Interviews are a great place to test the waters. Protect yourself.
  • Helps with: Everything



Establish what simple and familiar mean to your team.

  • Build cadence with small and easy to read pull requests. Even for trivial things.
  • If you're leading, produce a document or materials that communicates your vision for the codebase from now to 6 months.
  • Helps with: #2—"The codebase is too complex."



Spend time optimizing for layout and paint performance.

  • I've written about this in detail here.
  • JavaScript in the browser isn't always super performant, so be careful when using popular main thread animation libraries like GSAP.
  • Be weary of using too many infinite animations.
  • Helps with: #1—"Our website is slow." #5—"What you implemented looks nothing like the design."



Implement a timer.

  • If you can't measure that the site is performing better, you're going to build bad habits. You need to be able to share improvements.
  • Some frameworks or libraries can give you this functionality for minimal effort. Check out the Node docs.
  • For this product: I am able to measure ~200ms response in Zeit logs and ~750ms full page load speed in Chrome Inspector. Makes me happy.
  • Helps with: #1—"Our website is slow."



Ship the smallest bundle size possible.

  • Pick a view library like Preact, where small bundle sizes are part of the philosophy.
  • Delete unused code, even if you may use it in the future.
  • Don't require entire libraries in cases where you only need a couple of methods. MomentJS is an example of a library with a lot of bloat.
  • Do code splitting and tree shaking with your build tool (Webpack/Browserify) or pick a framework that has an asset building implementation that does it for you.
  • Configure Uglify. Learn how to configure your tools to get the most out of them.
  • Helps with: #1—"Our website is slow." #2—"The codebase is too complex."



Write performant and predictable CSS.

  • I have written about this in detail here.
  • Plenty of CSS-in-JS tools do auto-prefixing and class name generation. Look into PostCSS if you're writing CSS with a Webpack setup.
  • If you work on the Front-end, you must know your CSS.
  • Helps with: #1—"Our website is slow." #2—"The codebase is too complex." #4—"Our UIs look different in each browser" #5—"What you implemented looks nothing like the design."



Create meaningful conventions that are easy to understand.

  • Use the english language carefully, write methods that are self documenting in their signature.
  • Create a filesystem structure that represents the boundaries of your codebase. Here is a super basic example.
Root
 |
 |-- common
 |-- components
 |-- pages
 |-- index.js
 |-- package.json



  • Don't hesitate to put README.md throughout your codebase to explain the purpose of a folder or file. Don't hesitate to put comments to describe problematic codepaths.
  • Helps with: #2—"The codebase is too complex." #3—"We have state, and it is all over the place."



Avoid local state.

  • I use local state for forms I know are used once. Examples of this are the login, signup or forgot password forms.
  • When you avoid local state, you can do nifty things with your global state such as save entire state objects in bug reports and reload the steps that lead to the exception.
  • More predictable outcomes in your code when state changes from a centralized place.
  • Use stateless components / plain function components whenever possible.
/* React Example */

const MyComponent = name => {
  return <h1>Hello {name}</h1>
}



  • Helps with: #1—"Our website is slow." #2—"The codebase is too complex." #3—"We have state, and it is all over the place."



Try JavaScript on both client and server.

  • Your entire team only has to learn one language to be productive on both the client and server. It is a lot more productive than traditional JavaScript/Python, JavaScript/PHP, JavaScript/Ruby setups.
  • Works well with hosting services like Zeit.
  • Helps with: #2—"The codebase is too complex."



Use server-side rendering.

  • Prevent caveats around SEO.
  • Fast initial loads which is great for performance.
  • Client can just focus on hydrating components (binding events).
  • Helps with: #1—"Our website is slow."



Pick libraries that are actively downloaded, updated, and discussed.

  • NPM is a great resource for tracking activity. Take a look at SlateJS and look at the weekly downloads and open issues to get a pulse for the health of a project.
  • The GitHub repository is a great place to see if a project is still active.
  • Find one other person who has used the technology in production and take notes about their usage.
  • Helps with: #2—"The codebase is too complex." #6—"We are using technology that is no longer supported."

Use a popular state management solution for global state.

  • This product uses Redux. Although I'm looking into replacing it with React 16.3 context provider.
  • Another very popular choice is MobX.
  • Using a JavaScript object exclusively as a form of state could be fun as an experienced team. I’ve seen some experts joke about this. Don’t do this if you don’t know what a deep copy and shallow copy are.
  • Helps with: #2—"The codebase is too complex." #6—"We are using technology that is no longer supported."



Implement instantaneous subsequent page loads.

  • Most modern JavaScript frameworks support a routing library built in to make this fairly easy, such as NextJS.
  • window.location.href does not give you this.
  • Helps with: #1—"Our website is slow."



Don't allow server side secrets to appear in the client JavaScript or HTML document.

  • No-brainer. View source to double check. Don't compromise your services or your users.
  • Helps with: Saving you a face full of tears or getting fired. 😭



Add types when it helps.

  • Sometimes tracking down function arguments can be a real pain if you're not using all of the latest ES2015 features.
  • It may feel like overkill to use a type system with GraphQL.
  • Types can be added to JavaScript with flow, or you can use TypeScript which is a superset of ES5 JavaScript.
  • Know your teammates, some people won't work in a codebase without types.
  • Helps with: #2—"The codebase is too complex." #7—"Something broke, where are the Front-end tests?"



Install every mainstream browser.

  • If the browser is popular, someone is going to use it to visit your website. You have no choice but to make sure your website works.
  • Don't go chasing old versions of Internet Explorer, there are more important things to do.
  • Mobile browsers are just important as desktop browsers.
  • Helps with: #4—"Our UIs look different in each browser" #5—"What you implemented looks nothing like the design."



Use only necessary tests.

  • Some code is obvious and doesn't need to be tested IMO. Don't over test.
  • My favorite tests to write are with Google Chrome's Puppeteer to do end to end testing. You can also try an online service like Cypress.
  • I will make sure to test authentication flows, changing settings, and any other experience a user will go through that is not part of the core experience.
  • Helps with: #7—"Something broke, where are the Front-end tests?"





FAQ

These questions and answers may only be relevant for 2018 and reflect some common questions I get on the internet.





"What do you think about Svelte?"

I think its very legit, but I haven't tried it yet. I'm waiting for Svelte to become more mainstream before adopting it into my projects.





"What about other React alternatives, any worth using?"

I love Preact. A lot of people who felt abandoned in the Angular 1.X camp have moved over to Vue, which is also worth checking out.





"Whats the deal with CSS-in-JS?"

I think it rocks, I personally can't go back to SASS or LESS even though I wrote both for years. Using Emotion or Styled Components feels really intuitive. You also get freebies, such as auto prefixing, and O(1) lookup from class names you would have gotten from manually writing CSS classes or if you used something like Tachyons. If you're in a company that still has designers writing CSS and you're using React, it is super easy transition to Emotion. However I can't say the same about Aphrodite because of how annoying it is to use commas in JavaScript objects.





"Are you using GraphQL and Apollo-React?"

Yes and no, at my work it is the logical choice because there are multiple contributors with various backgrounds. There is a lot of momentum here and people are genuinely excited about the technology.



GraphQL is great at preventing the number of roundtrips for your application. In addition, GraphQL can act as a type system to avoid the implementation of Flow or TypeScript. When using Apollo-React you don't really need to use Redux on the client (in some cases). We are currently using GraphQL subscriptions for our Expo Dev Tools and I am excited to see how well they age.



There are some “gotcha” moments. You have to be careful not to add unnecessary fields to your queries that can cause expensive joins or sub query calls. You also need to invest some time into properly setting up GraphQL. Versions are always changing so you need to keep up and maybe even send pull requests. GraphQL queries need to go through a GraphQL client because it isn't a protocol.



And there is more, mutations with optimistic responses can cause side effects if you aren't careful, you can accidentally wipe out a cached value in the original query. You'll want to make sure to pick a client setting you fully understand for determining network behavior and caching. Writing the complete schema before you know what you want can be tedious, and you're going to need more server-side logic to verify and parse the parameters unless you go with a solution like Prisma.

For independent projects I tend to stick to REST because it is just a protocol and I like the simplicity. For authentication (with cookies or JWTs) and file upload I also stick with REST. My package.json dependencies section thanks me for it.





"I really like NextJS."

I am probably the biggest NextJS fanboy on the internet right now. After writing a ton of custom Webpack configurations and my own server-side rendering, I am so happy to use a framework that does the heavily lifting for me.



My biggest project with NextJS is showcased here. This site you are on is written with NextJS. Their team maintains up to date examples, when I started using the framework I referenced custom-server-express and with-emotion.



If you're a beginner, check out my example codebase for NextJS + Postgres. I personally don’t use sequelize but found it easier to explain to new developers.





🙏—Hope This Helps

Don't hesitate to reach out to me on Twitter if you want to. More than willing to lend a helping hand.

Hey! My name is Jim and I love to build websites. If you like building websites too hit me up on Twitter.

icon twitter
icon facebook-official

To start a thread please sign in. Threads will only appear on posts if the author permits.