Typescript: Typescript pulls entire MUI library - super slow type checking

Created on 20 Jun 2018  ·  12Comments  ·  Source: microsoft/TypeScript


TypeScript Version: 2.9.2


Search Terms:
MUI slow typescript
TSC compiles all MUI files

Code

In a react project, I use the UI library MUI (1.0).
In total, I'm doing around 15 imports of this library, always in the following way:
import CircularProgress from '@material-ui/core/CircularProgress/CircularProgress';

tsconfig.json

{
  "compilerOptions": {
    "baseUrl": "./src",
    "outDir": "build/dist",
    "target": "es5",
    "lib": ["es6", "es7", "dom"],
    "sourceMap": true,
    "allowJs": false,
    "jsx": "react",
    "esModuleInterop": true,
    "skipLibCheck": true,
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "rootDir": "./src",
    "noEmitOnError": false,
    "isolatedModules": true,
    "strictPropertyInitialization": false,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "noErrorTruncation": true,
    "noImplicitReturns": true,
    "noImplicitAny": true,
    "noImplicitThis": true,
    "strictNullChecks": true,
    "diagnostics": true,
    "suppressImplicitAnyIndexErrors": true,
    "noUnusedLocals": true
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "dist",
    "build",
    "node_modules",
    "src/**/__tests__"
  ],
  "defaultSeverity": "warning"
}

Expected behavior:
TS picks up only the type definitions it needs from that library. (around 20 files, as I counted)
Code compiles in 3-6 seconds, if I remove MUI (with lots of errors, certainly)
image

Actual behavior:
TS pulls the entire MUI library, with over 600.000 types
Compilation (type checking) usually takes >1min
image
tsc --extendedDiagnostics --listFiles --noEmit
image

and it goes on...

I would expect this to happen if I was importing from the core modules, which exports all types, but I am most definitely not.

Related Issues:
No :( I found other cases of slow compilation, but not of this sort.

Bug Fixed High Priority

Most helpful comment

import withStyles from '@material-ui/core/styles/withStyles';

points at withStyles.d.ts, which contains

import { ConsistentWith, Overwrite } from '..';

that .. is a reference to the top-level index.d.ts in @material-ui/core that imports _everything_, which would likely be why the file count goes up so much with so few imports; I wouldn't be surprised if that root import shows up in a few other places in material-ui, too, since they stashed some util types in the root index.d.ts.

BUT! The the inclusion of all those files is likely not itself what's making your build so slow (yes, it's more work than it should need to do, but not 50s of work, more like 1s) - somewhere where you're actually using @material-ui (eg, a tag), you're triggering some kind of catastropic worst-case typechecking scenario, since if you have just a file with those imports that does nothing real:

import * as React from "react";

import createStyles from '@material-ui/core/styles/createStyles';
import createMuiTheme from '@material-ui/core/styles/createMuiTheme';
import withStyles from '@material-ui/core/styles/withStyles';

import Button from '@material-ui/core/Button';
import CircularProgress from '@material-ui/core/CircularProgress';
import Typography from '@material-ui/core/Typography/Typography';
import Hidden from '@material-ui/core/Hidden';
import Card from '@material-ui/core/Card';

import Grid from '@material-ui/core/Grid';
import TextField from '@material-ui/core/TextField';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import CardContent from '@material-ui/core/CardContent';

import Checkbox from '@material-ui/core/Checkbox';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import ListItem from '@material-ui/core/ListItem';
import Snackbar from '@material-ui/core/Snackbar';
import IconButton from '@material-ui/core/IconButton';

import Paper from '@material-ui/core/Paper';
import Dialog from '@material-ui/core/Dialog';
import DialogContent from '@material-ui/core/DialogContent';
import DialogActions from '@material-ui/core/DialogActions';
import ExpansionPanel from '@material-ui/core/ExpansionPanel';

import ExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary';
import ExpansionPanelDetails from '@material-ui/core/ExpansionPanelDetails';
import Tooltip from '@material-ui/core/Tooltip';

import Popover, { PopoverActions } from '@material-ui/core/Popover';
import { WithStyles, StyledComponentProps } from '@material-ui/core/styles';
import { GridSpacing, GridJustification, GridSize } from '@material-ui/core/Grid';
import { ButtonProps } from '@material-ui/core/Button';

void createStyles, createMuiTheme, withStyles, Button, CircularProgress, Typography, Hidden, Card, Grid, TextField,
    AppBar, Toolbar, CardContent, Checkbox, FormControlLabel, ListItem, Snackbar, IconButton, Paper, Dialog, DialogContent,
    DialogActions, ExpansionPanel, ExpansionPanelSummary, ExpansionPanelDetails, Tooltip, Popover, React;

declare var x: PopoverActions;
declare var y: WithStyles;
declare var z: StyledComponentProps;
declare var a: GridSpacing;
declare var b: GridJustification;
declare var c: GridSize;
declare var d: ButtonProps;

void x,y,z,a,b,c,d;

the project compiles in around a second. That bears out in the type count, too -
image
That's nowheres near the more concerning 600k types you report. So while @material-ui likely participates in the types which are causing this problem, it alone is not the problem. Could you share a more detailed repro?

My intuition is to look around the code where you use withStyles, since that has a relatively complex type itself (and so is more likely to interact poorly with something else complex and create a explosion like this); but that's just a gut feeling and without knowing more, the problem could be almost anywhere.

All 12 comments

It's possible that the package, or one of the packages it depends on, has a type declaration that is causing this slowness.

If you look at issue 24435, you'll see that it's possible to get check times of 497.42s or more. Sometimes never terminating, or running out of memory (I have this problem regularly).

It may be that the type is too complicated, or that the way it is written could be simplified.

I'm not 100% sure it's the cause of your problems but it may be worth investigating.

Thank you, that gives me a couple ideas how to try and debug this. I'll do it soon and report my findings here

@weswigham can you take a look at the library and see what is causing the perf issues?

@rpmonteiro do you have a list of the material-ui components you use? CircularProgress alone doesn't seem to significantly impact build times at all.

here are the imports being used, both for types, and components:

type imports

import { PopoverActions } from '@material-ui/core/Popover';
import { WithStyles, StyledComponentProps } from '@material-ui/core/styles';
import { GridSpacing, GridJustification, GridSize } from '@material-ui/core/Grid';
import { ButtonProps } from '@material-ui/core/Button';

component/method imports

import createStyles from '@material-ui/core/styles/createStyles';
import createMuiTheme from '@material-ui/core/styles/createMuiTheme';
import withStyles from '@material-ui/core/styles/withStyles';

import Button from '@material-ui/core/Button';
import CircularProgress from '@material-ui/core/CircularProgress';
import Typography from '@material-ui/core/Typography/Typography';
import Hidden from '@material-ui/core/Hidden';
import Card from '@material-ui/core/Card';

import Grid from '@material-ui/core/Grid';
import TextField from '@material-ui/core/TextField';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import CardContent from '@material-ui/core/CardContent';

import Checkbox from '@material-ui/core/Checkbox';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import ListItem from '@material-ui/core/ListItem';
import Snackbar from '@material-ui/core/Snackbar';
import IconButton from '@material-ui/core/IconButton';

import Paper from '@material-ui/core/Paper';
import Dialog from '@material-ui/core/Dialog';
import DialogContent from '@material-ui/core/DialogContent';
import DialogActions from '@material-ui/core/DialogActions';
import ExpansionPanel from '@material-ui/core/ExpansionPanel';

import ExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary';
import ExpansionPanelDetails from '@material-ui/core/ExpansionPanelDetails';
import Tooltip from '@material-ui/core/Tooltip';
import withStyles from '@material-ui/core/styles/withStyles';

points at withStyles.d.ts, which contains

import { ConsistentWith, Overwrite } from '..';

that .. is a reference to the top-level index.d.ts in @material-ui/core that imports _everything_, which would likely be why the file count goes up so much with so few imports; I wouldn't be surprised if that root import shows up in a few other places in material-ui, too, since they stashed some util types in the root index.d.ts.

BUT! The the inclusion of all those files is likely not itself what's making your build so slow (yes, it's more work than it should need to do, but not 50s of work, more like 1s) - somewhere where you're actually using @material-ui (eg, a tag), you're triggering some kind of catastropic worst-case typechecking scenario, since if you have just a file with those imports that does nothing real:

import * as React from "react";

import createStyles from '@material-ui/core/styles/createStyles';
import createMuiTheme from '@material-ui/core/styles/createMuiTheme';
import withStyles from '@material-ui/core/styles/withStyles';

import Button from '@material-ui/core/Button';
import CircularProgress from '@material-ui/core/CircularProgress';
import Typography from '@material-ui/core/Typography/Typography';
import Hidden from '@material-ui/core/Hidden';
import Card from '@material-ui/core/Card';

import Grid from '@material-ui/core/Grid';
import TextField from '@material-ui/core/TextField';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import CardContent from '@material-ui/core/CardContent';

import Checkbox from '@material-ui/core/Checkbox';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import ListItem from '@material-ui/core/ListItem';
import Snackbar from '@material-ui/core/Snackbar';
import IconButton from '@material-ui/core/IconButton';

import Paper from '@material-ui/core/Paper';
import Dialog from '@material-ui/core/Dialog';
import DialogContent from '@material-ui/core/DialogContent';
import DialogActions from '@material-ui/core/DialogActions';
import ExpansionPanel from '@material-ui/core/ExpansionPanel';

import ExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary';
import ExpansionPanelDetails from '@material-ui/core/ExpansionPanelDetails';
import Tooltip from '@material-ui/core/Tooltip';

import Popover, { PopoverActions } from '@material-ui/core/Popover';
import { WithStyles, StyledComponentProps } from '@material-ui/core/styles';
import { GridSpacing, GridJustification, GridSize } from '@material-ui/core/Grid';
import { ButtonProps } from '@material-ui/core/Button';

void createStyles, createMuiTheme, withStyles, Button, CircularProgress, Typography, Hidden, Card, Grid, TextField,
    AppBar, Toolbar, CardContent, Checkbox, FormControlLabel, ListItem, Snackbar, IconButton, Paper, Dialog, DialogContent,
    DialogActions, ExpansionPanel, ExpansionPanelSummary, ExpansionPanelDetails, Tooltip, Popover, React;

declare var x: PopoverActions;
declare var y: WithStyles;
declare var z: StyledComponentProps;
declare var a: GridSpacing;
declare var b: GridJustification;
declare var c: GridSize;
declare var d: ButtonProps;

void x,y,z,a,b,c,d;

the project compiles in around a second. That bears out in the type count, too -
image
That's nowheres near the more concerning 600k types you report. So while @material-ui likely participates in the types which are causing this problem, it alone is not the problem. Could you share a more detailed repro?

My intuition is to look around the code where you use withStyles, since that has a relatively complex type itself (and so is more likely to interact poorly with something else complex and create a explosion like this); but that's just a gut feeling and without knowing more, the problem could be almost anywhere.

Thank you for your comprehensive reply!! I'm going to do as you suggest, and report my findings ASAP. Thanks again

Ok, I already made a significant discovery.

There are 81 imports of the Grid component in the app.

import Grid from '@material-ui/core/Grid/Grid';

Also tried changing the import to the following, but with the same results:

import Grid from '@material-ui/core/Grid';

Results of commenting all those Grid imports out:
Before
image
After
image

And after commenting out all imports from that library:
image

Alright... I think Grid is a generic component (iirc); what do your usages of Grid look like?

Like the following:
image

Sometimes there are more complex layouts with 3 or 4 nested Grid components

We found a similar repro from Developer Community (slow checking with MUI, seems to use Grid a lot as well) and will be investigating from that one - almost certainly the root cause is the same. Thanks for the help so far!

Amazing! The entire team and I are very happy with the once again blazing fast performance. Thank you, guys!!

Was this page helpful?
0 / 5 - 0 ratings