{
  "$type": "site.standard.document",
  "canonicalUrl": "https://johnnyreilly.com/posts/typescript-and-high-cpu-usage-watch",
  "description": "High CPU usage in watch mode on idle due to TypeScripts fs.watchFile. fs.watch recommended instead. Env variable controls file watching.",
  "path": "/posts/typescript-and-high-cpu-usage-watch",
  "publishedAt": "2019-05-23T00:00:00.000Z",
  "site": "at://did:plc:yy3apqjlms24kso7ahn7lbmb/site.standard.publication/3mova7c4nho2b",
  "tags": [
    "fork-ts-checker-webpack-plugin",
    "webpack",
    "typescript"
  ],
  "textContent": "I'm one of the maintainers of the fork-ts-checker-webpack-plugin. Hi there!\n\n\n\nRecently, various issues have been raised against create-react-app (which uses fork-ts-checker-webpack-plugin) as well as against the plugin itself. They've been related to the level of CPU usage in watch mode on idle; i.e. it's high!\n\n- https://github.com/Realytics/fork-ts-checker-webpack-plugin/issues/236\n- https://github.com/facebook/create-react-app/issues/6792\n\nWhy High?\n\nNow, under the covers, the fork-ts-checker-webpack-plugin uses the TypeScript watch API.\n\nThe marvellous John (not me - another John) did some digging and discovered the root cause came down to the way that the TypeScript watch API watches files:\n\n> TS uses internally the fs.watch and fs.watchFile API functions of nodejs for their watch mode. The latter function is even not recommended by nodejs documentation for performance reasons, and urges to use fs.watch instead.\n>\n> NodeJS doc:\n>\n> > Using fs.watch() is more efficient than fs.watchFile and fs.unwatchFile. fs.watch should be used instead of fs.watchFile and fs.unwatchFile when possible.\n\n\"there is another\"\n\nJohn also found that there are other file watching behaviours offered by TypeScript. What's more, the file watching behaviour is _configurable with an environment variable_. That's right, if an environment variable called TSC_WATCHFILE is set, it controls the file watching approach used. Big news!\n\nJohn did some rough benchmarking of the performance of the different options that be set on his PC running linux 64 bit. Here's how it came out:\n\nAs you can see, the default performs poorly. On the other hand, an option like UseFsEventsWithFallbackDynamicPolling is comparative greasy lightning.\n\nworkaround!\n\nTo get this better experience into your world now, you could just set an environment variable on your machine. However, that doesn't scale; let's instead look at introducing the environment variable into your project explicitly.\n\nWe're going to do this in a cross platform way using cross-env. This is a mighty useful utility by Kent C Dodds which allows you to set environment variables in a way that will work on Windows, Mac and Linux. Imagine it as the jQuery of the environment variables world :-)\n\nLet's add it as a devDependency:\n\nThen take a look at your package.json. You've probably got a start script that looks something like this:\n\nOr if you're a create-react-app user maybe this:\n\nPrefix your start script with cross-env TSC_WATCHFILE=UseFsEventsWithFallbackDynamicPolling. This will, when run, initialise an environment variable called TSC_WATCHFILE with the value UseFsEventsWithFallbackDynamicPolling. Then it will start your development server as it did before. When TypeScript is fired up by webpack it will see this environment variable and use it to configure the file watching behaviour to one of the more performant options.\n\nSo, in the case of a create-react-app user, your finished start script would look like this:\n\nThe Future\n\nThere's a possibility that the default watch behaviour may change in TypeScript in future. It's currently under discussion, you can read more here.",
  "title": "TypeScript and high CPU usage - watch don't stare!"
}