/ typescript

Supercharging Frontend Development with VS Code

These past few days, I dove into Visual Studio Code and TypeScript in an attempt to get a better workflow going with GraphQL / React apps. It's been a few months since evaluating the tools I use for developing every day apps, and I've found some amazing stuff. If you implement all these things and switch to VS Code, you're going to be shocked at how many bugs you catch even before saving a file!

ESLint + GraphQL!

This is the biggest developer life hack I've ever come across. Using GraphQL is the gift that never stops giving. Thanks to apollo-codegen you can generate types on the client side from your GraphQL schema! It looks like this:

//  This file was automatically generated and should not be edited.

export type announcementsQuery = {
  // Daily announcements
  announcements: Array<{
    title: string;
  } | null> | null;
};
/* tslint:enable */

It will only generate types for queries you're actually using, instead of adding types for things not in use on the frontend.

As if that wasn't cool enough, we can take this a step further. Using the graphql schema dump, we can generate eslint errors when writing queries with eslint-plugin-graphql. This will happen as you are typing out fields inside of a query!

query-1

Types

As I alluded to in the last example, static typing is awesome. Instead of rambling about all of TypeScript's features, I'm going to show you the 3 step process it takes to implement and how it's so useful.

  1. Rename .js files to .tsx
  2. Add some interfaces
  3. Use the interfaces!

Here's an example:

interface MessageProps {
  name: string;
}

export default ({ name }: MessageProps) => (
  <p className={styles.container}>
    Say hello to <Link to="/about/zach">{name}</Link>
  </p>
);

Now any time I import this component, I will get an error if I don't supply a name prop, if I don't pass it as a string, or if I try to pass other props. This is huge if you ever refactor your code and have props that are no longer used, or when a new dev comes in. VS Code also lets you right click and peek at the type defintion from anywhere. My other favorite features include enabling noUnusedLocals and noUnusedParameters in my TypeScript config. This will show warnings for unsed code.

Precommit checks

Running prettier, eslint, and jest can be very useful. Sometimes a team member will make a small commit to my app but not have my tooling. This way when they commit, things will still get formatted and checked for linting errors. Here's how I do it.

Add this to your package.json

"lint-staged": {
    "*.test.tsx": [
      "jest"
    ],
    "*.{js,tsx,ts}": [
      "prettier --single-quote --trailing-comma es5 --write",
      "eslint",
      "git add"
    ]
  },

Now run: npm install lint-staged husky --save-dev

That's it, now these things will be ran when the corresponding file types are staged for a commit. If something fails, it will not let you commit.

Debugging Setup

VS Code has this really cool launch config that lets you start your apps with the press of a button. No more npm starting your server, and create react app, AND opening the browser. We can put all of this into one file and start it with a single button press. On top of this, we can set breakpoints right in our editor, and have any console errors jump directly to the line in our code with the error below it! Here's an example config that I'm using:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Server",
      "type": "node",
      "request": "launch",
      "program": "${workspaceRoot}/node_modules/.bin/webpack-dev-server",
      "args": ["--hot", "--inline", "--config", "config/dev.config.js"],
      "outFiles": ["${workspaceRoot}/build/*"],
      "stopOnEntry": false,
      "cwd": "${workspaceRoot}",
      "env": {
        "NODE_ENV": "development"
      },
      "console": "internalConsole",
      "sourceMaps": true
    },
    {
      "name": "Browser",
      "type": "chrome",
      "request": "launch",
      "url": "http://localhost:8080/",
      "webRoot": "${workspaceRoot}/"
    }
  ],
  "compounds": [
    {
      "name": "Server/Browser",
      "configurations": ["Server", "Browser"]
    }
  ]
}

If you are using webpack like me, make sure devtool: 'eval-source-map' is in your config. If you use anything below that in the sourcemap chart, breakpoints will not work and stack traces will go to the wrong location in your code.

After adding this launch config (read more about the feature here) simply open up the debugger tab and hit start!

Conclusion

Think about a new developer joining your team. You now have so many awesome things in place, they can get up and running immediately. Download VS Code, hit start in the debugger, app is running. Want to change some data that is displayed? Have them edit a GraphQL query and immediately be told if that variable is in the schema or not. Have them use a component you made for list items, they can hover over the component and see what props it takes. Try using something else, immediate error. Now they're ready to commit.... did it break something? On precommit, linting and tests will run! I hope this helps somebody out there. If you have any other neat things to level up my development environment, leave a comment or tweet me @zachcodes!