God banishes Adam and Eve from the Garden of Eden (source)


Prologue

4 But the serpent said to the woman, “You will not surely die.

5 For God knows that when you eat of it your eyes will be opened, and you will be like God, knowing good and evil.”

Genesis 3


Having react-script eject-ed ourselves from the Eden of create-react-app, here’s a few tips on how to speed up your Frontend Typescript builds! 🙃🐑

Tips

1. Profile your webpack build using speed-measure-webpack-plugin (or equivalent)

  • Use speed-measure-webpack-plugin to get insight into the webpack build step.
  • Tackle the loaders/plugins that take the longest times (if possible)

See more:

  • speed-measure-webpack-plugin (link)

2. Remove eslint-loader (or equivalent) during webpack dev/prd build steps

  • Linters can slow down your build times significantly once your project becomes sufficiently large.
  • This is especially painful for developers, as:
    longer build times = longer feedback loops = less productivity
    
  • Do the linting elsewhere - eg. git hooks or CI stages - instead of slowing down the build with a linter.

Example: package.json: pre-commit linting via husky git hooks + eslint

{
    "scripts": {
        "lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'"
    },
    "husky": {
        "hooks": {
            "pre-commit": "yarn lint"
        }
    }
}

3. Diagnose tsc

  • Use tsc -diagnostics to get insight into the tsc compile step
  • Use tsc --listFiles to see what files tsc is using for the compile step
  • If there are extra files that aren’t required for the build, tweak the files/include/exclude properties in tsconfig.json to see if you can exclude these files, as:
Fewer files = less code to transpile = shorter build times

Example: tsconfig.json: Include all source files but exclude all tests (ie. *.spec.ts) (reference: official documentation)

{
    "include": [
        "src/**/*"
    ],
    "exclude": [
        "node_modules",
        "**/*.spec.ts"
    ]
}

See more:

4. Try other TypeScript loaders

  • Try switching to other TypeScript loaders to see if you can get faster build times.
  • My colleague swapped out awesome-typescript-loader with ts-loader for our project, and that alone halved the build time!
  • Don’t forget to look into the configuration settings the loader that you’re using to squeeze more time savings out from it.

Example: Configuration for awesome-typescript-loader

{
    "useCache": true,
    "forceIsolatedModules": true,
    "transpileOnly": true
}

See more:

5. Use Babel to transpile your entire project

  • Since Babel 7, Babel is able to natively transpile TypeScript into JavaScript.
  • You can experiment with a Babel-first approach to building your project (instead of tsc as the usual default for TypeScript projects)
  • To do this, just remove your existing TypeScript loader and configure babel-loader to read your .ts/.tsx files.

Example: webpack.config.js: babel-loader accepting .tsx files (reference: react-scripts’s webpack.config.js)

{
    module: {
        rules: [
            {
              test: /\.(js|mjs|jsx|ts|tsx)$/,
              include: paths.appSrc,
              loader: require.resolve('babel-loader'),
            }
        ]
    }
}
  • Caveat: Babel won’t typecheck your code, so it’s prudent to ‘typecheck’ the project.

Example: package.json: typecheck script

{
    "scripts": {
        "typecheck": "tsc --noEmit"
    }
}

See more:

Footnote

While understanding the full build process may be daunting for greenhorns, keep experimenting with different methods to speed up build times, all whilst staying curious as to how these different techniques work. Happy grokking! ⛏