Kent C. Dodds

Utah

wife, 4 kids, & a dog

PayPal, Inc.

Tools of modern JavaScript Projects

Please Stand...

if you are able ❤️ ♿️

What this talk is

  • Opinionated
  • Experienced

What this talk is not

  • Covering everything you need for every application
  • Perfect for every scenario

Let's
Get
STARTED!

What makes a

tool "good" ?

  1. Does the job you need
  2. Wide "pit of success"

What is a

"pit of success" ?

What makes a "pit of success" wide?

  1. Simple
  2. Automatic

Before we get to tools...

How do we get them?

  1. Ubiquitous
  2. Fast
  3. Reliable
  4. De-facto

Let's start with the user interface

  • Fast and easy to build and maintain
  • Great community of educational material, support, and libraries
  • Transferrable skills (small domain-specific API)
  • "Easy to reason about..." 🙃

Handy Libraries

axios

react-intl

How about code optimization?

  • Use the latest features of JavaScript without worrying about browser support.
  • Precompile code at build time.
  • Easily integrate with other tools we want to use

Great babel plugins/presets

babel-preset-env

babel-plugin-lodash

babel-plugin-transform-react-remove-prop-types

babel-plugin-module-resolver

babel-plugin-transform-react-constant-elements

babel-plugin-react-intl

babel-plugin-preval

babel-plugin-console

See awesome-babel for more

babel-plugin-codegen

What about the build pipeline?

  • Load only the things we need when they're needed
  • Allows us to structure things in a way that's easy to maintain
  • Easily integrate with other tools we want to use

Related Tools

react-loadable

webpack-config-utils

html-webpack-plugin

offline-plugin

See awesome-webpack for more

How about code quality?

  • Reduces the number of tests we need to write
  • Increases our confidence when refactoring
  • Brings static types to JavaScript
  • Can quickly add it to an existing codebase and get value
  • Easily integrate with other tools we want to use

What about discouraging suboptimal patterns?

  • Reduces the number of tests we need to write
  • Increases our confidence when refactoring
  • Totally pluggable, allowing us to do custom pattern checks
  • Easily integrate with other tools we want to use

ESLint

ESLint

Helpful configs & plugins

eslint-plugin-jest

eslint-plugin-jsx-a11y

eslint-plugin-security

eslint-plugin-react

eslint-plugin-babel

eslint-plugin-import

And tools to improve development workflow?

  • Eliminates need to argue over code format.
  • Formats code for you automatically as you go.
  • Integrates well with all major editors.

Supporting Tools

lint-staged 🚫💩

husky 🐶

lint-staged 🚫💩

husky 🐶

What about debugging?

  • Great debugging experience, even in production
  • Allows for extensibility
  • Ubiquitous

Handy extensions and tips

react devtools

redux devtools

a11y devtools

node --inspect

react devtools

node --inspect

How do we test our JavaScript?

  • Straightforward and minimal setup required
  • Integrates seamlessly with existing tools
  • Easy to write unit and integration tests (especially async)
  • Quick feedback on broken tests that is easy to triage
  • Extremely fast even for large codebases

Helpful Jest Companion

react-testing-library 🐐

Ok, but what about End-to-End?

  • NOT FLAKEY
  • Test debuggability
  • Mocking/Proxying capabilities
  • Quick feedback on broken tests that is easy to triage

debbugging

import generateArticleData from '../../other/generate/article'
import {visitApp, sel, loginAsNewUser} from '../utils'

describe('Posts', () => {
  let cleanupUser
  before(() => {
    return loginAsNewUser().then(({cleanup}) => {
      cleanupUser = cleanup
    })
  })

  after(() => {
    return cleanupUser()
  })

  it('should allow you to create new posts', () => {
    const {title, description, body, tagList} = generateArticleData()
    const shortBody = body.slice(0, 10)
    visitApp('/editor')

    // create the post
    fillInPostDetails({title, description, body: shortBody, tagList})
    cy.get(sel('submit')).click()

    // validate the post
    validatePostDetails({title, body: shortBody, tagList})

    // edit the post
    cy.get(sel('edit')).click()
    const newDetails = {
      title: `${title}_`,
      description: `${description}_`,
      body: `${shortBody}_`,
      // TODO handle changing tags
    }
    fillInPostDetails(newDetails)
    cy.get(sel('submit')).click()

    validatePostDetails(Object.assign({}, newDetails, {tagList}))
  })
})

function fillInPostDetails({title, description, body, tagList = []}) {
  cy.get(sel('title')).clear().type(title)
  cy.get(sel('description')).clear().type(description)
  cy.get(sel('body')).clear().type(body)

  tagList.forEach(tag => {
    cy.get(sel('tags')).type(tag).type('{enter}')
  })
}

function validatePostDetails({title, body, tagList = []}) {
  cy.get(sel('title')).should('contain.text', title)
  cy.get(sel('body')).should('contain.text', `${body}\n`)
  tagList.forEach((tag, index) => {
    cy
      .get(`${sel('tags')} li:nth-child(${index + 1})`)
      .should('contain.text', tag)
  })
}

Shoutout to some other random tools

nps

create-react-app

GitHub

babel-codemod

now.sh

netlify

cross-env

npx

Next.js

Gatsby

nps

npx

create-react-app

babel-codemod

now.sh

And That's All 😀

... we have time for

Thank you!