rollup-plugin-typescript2 icon indicating copy to clipboard operation
rollup-plugin-typescript2 copied to clipboard

Compilation very slow with TS v3.4

Open Kerumen opened this issue 5 years ago • 27 comments

What happens and why it is wrong

Once I upgraded TS to v3.4.2, the compilation time is very slow. With TS v3.3 my project built in ~20s and with TS v3.4 it takes ~5mn.

I tried with clean: true, I tried to add typescript: require('typescript'), I tried to upgrade rollup and all the related plugins.. Each time, same result the compilation takes a lot of time.

Note: when I run tsc -p tsconfig.prod.json directly, it takes less than 10 seconds to output the dist.

Environment

Versions

  • typescript: v3.4.2
  • rollup: v1.6.0
  • rollup-plugin-typescript2: v0.19.2

rollup.config.js

  {
    input: 'src/index.ts',
    output: [
      { file: pkg.main, format: 'cjs' },
      { file: pkg.module, format: 'es' },
    ],
    plugins: [
      external({ includeDependencies: true }),
      resolve(),
      typescript({
        tsconfig: './tsconfig.prod.json',
        rollupCommonJSResolveHack: true,
      }),
      commonjs(),
      filesize(),
    ],
  }

tsconfig.json

tsconfig.json
{
  "compilerOptions": {
    "module": "esnext",
    "target": "es5",
    "jsx": "react",
    "esModuleInterop": true,
    "lib": ["dom", "es2017"],
    "moduleResolution": "node",
    "rootDir": "src",
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "suppressImplicitAnyIndexErrors": true,
    "noUnusedLocals": false,
    "downlevelIteration": true
  },
  "include": ["src/**/*", "types/**/*"]
}
tsconfig.prod.json
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./dist",
    "noUnusedLocals": true,
    "sourceMap": true,
    "declaration": true
  },
  "exclude": ["src/doc", "**/stories.tsx", "**/test.tsx", "**/fixture.ts"]
}

package.json

    "rollup": "^1.6.0",
    "rollup-plugin-commonjs": "^9.2.1",
    "rollup-plugin-filesize": "^6.0.1",
    "rollup-plugin-node-resolve": "^4.0.1",
    "rollup-plugin-peer-deps-external": "^2.2.0",
    "rollup-plugin-typescript2": "^0.19.2",
    "typescript": "^3.4.2"

plugin output with verbosity 3

Output
rpt2: typescript version: 3.4.2
rpt2: tslib version: 1.9.3
rpt2: rollup-plugin-typescript2 version: 0.19.2
rpt2: plugin options:
{
    "tsconfig": "./tsconfig.prod.json",
    "rollupCommonJSResolveHack": true,
    "clean": true,
    "verbosity": 3,
    "typescript": "version 3.4.2",
    "check": true,
    "cacheRoot": "/Users/yannpringault/git/PayFit/components/.rpt2_cache",
    "include": [
        "*.ts+(|x)",
        "**/*.ts+(|x)"
    ],
    "exclude": [
        "*.d.ts",
        "**/*.d.ts"
    ],
    "abortOnError": true,
    "useTsconfigDeclarationDir": false,
    "tsconfigOverride": {},
    "transformers": [],
    "tsconfigDefaults": {},
    "objectHashIgnoreUnknownHack": false
}
rpt2: rollup config:
{
    "chunkGroupingSize": 5000,
    "experimentalCacheExpiry": 10,
    "inlineDynamicImports": false,
    "input": "src/index.ts",
    "perf": false,
    "plugins": [
        {
            "name": "peer-deps-external"
        },
        {
            "name": "node-resolve"
        },
        {
            "name": "rpt2"
        },
        {
            "name": "commonjs"
        },
        {
            "name": "filesize"
        }
    ]
}
rpt2: built-in options overrides: {
    "noEmitHelpers": false,
    "importHelpers": true,
    "noResolve": false,
    "noEmit": false,
    "inlineSourceMap": false,
    "outDir": "/Users/yannpringault/git/PayFit/components/.rpt2_cache/placeholder",
    "moduleResolution": 2,
    "allowNonTsExtensions": true,
    "declarationDir": "/Users/yannpringault/git/PayFit/components"
}
rpt2: parsed tsconfig: {
    "options": {
        "module": 6,
        "target": 1,
        "jsx": 2,
        "esModuleInterop": true,
        "lib": [
            "lib.dom.d.ts",
            "lib.es2017.d.ts"
        ],
        "moduleResolution": 2,
        "rootDir": "/Users/yannpringault/git/PayFit/components/src",
        "forceConsistentCasingInFileNames": true,
        "noImplicitReturns": true,
        "noImplicitThis": true,
        "noImplicitAny": true,
        "strictNullChecks": true,
        "suppressImplicitAnyIndexErrors": true,
        "noUnusedLocals": true,
        "downlevelIteration": true,
        "outDir": "/Users/yannpringault/git/PayFit/components/.rpt2_cache/placeholder",
        "sourceMap": true,
        "declaration": true,
        "configFilePath": "/Users/yannpringault/git/PayFit/components/./tsconfig.prod.json",
        "noEmitHelpers": false,
        "importHelpers": true,
        "noResolve": false,
        "noEmit": false,
        "inlineSourceMap": false,
        "allowNonTsExtensions": true,
        "declarationDir": "/Users/yannpringault/git/PayFit/components"
    },
    "fileNames": [
        "/Users/yannpringault/git/PayFit/components/src/index.ts",
        "/Users/yannpringault/git/PayFit/components/src/components/index.ts",
        "/Users/yannpringault/git/PayFit/components/src/components/Alert/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Alert/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Avatar/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Avatar/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/AvatarGroup/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/AvatarGroup/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Badge/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Badge/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Button/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Button/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Checkbox/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Checkbox/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/CheckboxGroup/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/CheckboxGroup/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/DatePicker/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/DatePicker/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/DatePicker/Popin/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Dropdown/MenuContext.ts",
        "/Users/yannpringault/git/PayFit/components/src/components/Dropdown/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Dropdown/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Dropdown/DropdownItem/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Dropdown/DropdownItem/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Field/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Field/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Icon/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Icon/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Input/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Input/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Layout/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Legend/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Legend/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Loader/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Loader/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/ProgressBar/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/ProgressBar/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/ProgressCircle/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/ProgressCircle/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/RadioGroup/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/RadioGroup/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Select/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Select/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Steps/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Steps/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Table/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Table/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Table/components/Body.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Table/components/Cell.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Table/components/Footer.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Table/components/Header.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Table/components/HeaderCell.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Table/components/HeaderRow.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Table/components/Limit.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Table/components/Row.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/TableGroup/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/TableGroup/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Tag/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Tag/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Text/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Toggle/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Toggle/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Tooltip/index.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/Tooltip/style.tsx",
        "/Users/yannpringault/git/PayFit/components/src/components/_helpers/colors.test.ts",
        "/Users/yannpringault/git/PayFit/components/src/components/_helpers/colors.ts",
        "/Users/yannpringault/git/PayFit/components/src/components/_helpers/react.ts",
        "/Users/yannpringault/git/PayFit/components/src/components/_helpers/string.test.ts",
        "/Users/yannpringault/git/PayFit/components/src/components/_helpers/string.ts",
        "/Users/yannpringault/git/PayFit/components/src/primitives/_helpers.tsx",
        "/Users/yannpringault/git/PayFit/components/src/primitives/box.tsx",
        "/Users/yannpringault/git/PayFit/components/src/primitives/text.tsx",
        "/Users/yannpringault/git/PayFit/components/src/utils/index.ts",
        "/Users/yannpringault/git/PayFit/components/src/utils/colors/index.ts",
        "/Users/yannpringault/git/PayFit/components/src/utils/shadows/index.ts",
        "/Users/yannpringault/git/PayFit/components/src/utils/shadows/test.ts",
        "/Users/yannpringault/git/PayFit/components/src/utils/zIndex/index.ts",
        "/Users/yannpringault/git/PayFit/components/types/index.d.ts",
        "/Users/yannpringault/git/PayFit/components/types/modules.d.ts"
    ],
    "typeAcquisition": {
        "enable": false,
        "include": [],
        "exclude": []
    },
    "raw": {
        "extends": "./tsconfig.json",
        "compilerOptions": {
            "outDir": "./dist",
            "noUnusedLocals": true,
            "sourceMap": true,
            "declaration": true
        },
        "exclude": [
            "src/doc",
            "**/stories.tsx",
            "**/test.tsx",
            "**/fixture.ts"
        ],
        "compileOnSave": false,
        "include": [
            "src/**/*",
            "types/**/*"
        ]
    },
    "errors": [],
    "wildcardDirectories": {
        "/users/yannpringault/git/payfit/components/src": 1,
        "/users/yannpringault/git/payfit/components/types": 1
    },
    "compileOnSave": false,
    "configFileSpecs": {
        "includeSpecs": [
            "src/**/*",
            "types/**/*"
        ],
        "excludeSpecs": [
            "src/doc",
            "**/stories.tsx",
            "**/test.tsx",
            "**/fixture.ts"
        ],
        "validatedIncludeSpecs": [
            "src/**/*",
            "types/**/*"
        ],
        "validatedExcludeSpecs": [
            "src/doc",
            "**/stories.tsx",
            "**/test.tsx",
            "**/fixture.ts"
        ],
        "wildcardDirectories": {
            "/users/yannpringault/git/payfit/components/src": 1,
            "/users/yannpringault/git/payfit/components/types": 1
        }
    }
}
rpt2: included:
'[
    "*.ts+(|x)",
    "**/*.ts+(|x)"
]'
rpt2: excluded:
'[
    "*.d.ts",
    "**/*.d.ts"
]'

Kerumen avatar Apr 09 '19 09:04 Kerumen

I'm having the same issue. Went from 24s to 345s when bumping TS from 3.3.4000 to 3.4.3

deini avatar Apr 11 '19 14:04 deini

I tried to reproduce and at first I saw a slowdown, but using clean: true and going back and forth between typescript versions several times, I don't see the difference on clean build now...

Could you set clean: true, update rtp2 to latest (0.20.1 or master) and time a build several times in a row on ts 3.3 and ts 3.4?

ezolenko avatar Apr 11 '19 18:04 ezolenko

@ezolenko Sorry for the late reply!

I put clean: true and upgraded rtp2 to 0.20.1. Here are the results:

TS 3.3.3333

build -> 18s
tsc   -> 14.39s

TS 3.3.4000

build -> 17.3s
tsc   -> 14.39s

TS 3.4.1

build -> 5m 25.1s
tsc   -> 21.26s

TS 3.4.3

build -> 5m 52.7s
tsc   -> 21.57s

Additionally there is this issue on the TS repo which seems related but I have @types/styled-components pinned to v4.1.4 so it doesn't cover my case.

Let me know if you need more infos.


For fun I also tried the latest 3.5 build:

TS 3.5.0-dev.20190413

build -> 1m 23.5s
tsc   -> 18.84s

Kerumen avatar Apr 15 '19 14:04 Kerumen

That issue you found (https://github.com/Microsoft/TypeScript/issues/30663) and the fact that 3.5-dev became 5 times faster for you makes me think they did something with LanguageService API. This is the API rpt2 uses as part of compilation and what typecheckers in IDEs are using (that's why WebStorm times out etc).

Your project might be using affected type structures elsewhere, that's why pinning styled-components doesn't help. And that's why I don't see a big slowdown when building rpt2 itself for example.

I guess we'll wait for final 3.5 release.

ezolenko avatar Apr 23 '19 22:04 ezolenko

btw, try building with check: false option

ezolenko avatar Apr 23 '19 22:04 ezolenko

Has anyone confirmed if this is this fixed with 3.5 release?

tomasro27 avatar Jun 21 '19 02:06 tomasro27

@tomasro27 Not for me, nor with 6 (3.6.0-dev.20190621). Seems < 3.3 is still the fastest.

bradc1105 avatar Jun 21 '19 14:06 bradc1105

It looks like 3.5 is a little bit faster but it could still be better

LiamMartens avatar Jul 17 '19 11:07 LiamMartens

Is there any update on this? Seem like its still blocked by TS?

donifer avatar Jul 23 '19 21:07 donifer

Yeah, I don't think anything can be done from this end. Anybody is welcome to try though :)

ezolenko avatar Jul 24 '19 16:07 ezolenko

+1 3.5.3 is also very slow for us

fobdy avatar Aug 15 '19 15:08 fobdy

check: false is working great.

But the problem is that it doesn't give any compilation error (if you use vscode, it'll prompt the errors 😄).

At least I can do check: false when I'm working on CSS (in JS). 👍

ritwickdey avatar Aug 28 '19 06:08 ritwickdey

@ezolenko do you know what exact typescript api call causes the build to slow down? :)

ZainlessBrombie avatar Mar 10 '20 12:03 ZainlessBrombie

@ZainlessBrombie no, everything I know is in this thread. Typescript issue that is linked is probably related, but not direct cause (because they say it should be fixed in 3.5+, and apparently it isn't).

If you have slow builds in your project, check if ts 3.3 is actually faster if possible, maybe the problem is not typescript, but something else.

ezolenko avatar Mar 10 '20 16:03 ezolenko

Alright thanks. If I get around to it this might be a wall I'm willing to bash my head against so to speak :)

Edit: This problem only occurs for files that import styled components as it seems Also, Typescript documentation is terrible

ZainlessBrombie avatar Mar 10 '20 17:03 ZainlessBrombie

Profiling typescript reveals the source of the problem to be these extremely large unions that styled components has. The only place to fix this is typescript, unless there is a way to get typescript to cache module resolution (which it should).

ZainlessBrombie avatar Mar 10 '20 21:03 ZainlessBrombie

I'm actually not using module resolution cache in nodeModuleNameResolver call here: https://github.com/ezolenko/rollup-plugin-typescript2/blob/b7c7389dcdf168715669520128ca656d6e940111/src/index.ts#L148

Not sure if that makes ts use default one or not use one at all.

ezolenko avatar Mar 10 '20 23:03 ezolenko

Yes I saw that TODO :) Unfortunately debugging the module resolution cache when used shows that it caches rebass but not styled components for some reason. It passes an internal cache for those...

ZainlessBrombie avatar Mar 11 '20 06:03 ZainlessBrombie

I am currently in the process of migrating my C# codebase of my library to TypeScript and I'm using Rollup for bundling. (I had a custom C# > Haxe > JavaScript toolchain before). Unfortunately I am suffering also quite a lot on the compilation speed of my new TypeScript codebase which makes development quite hard.

If possible I am happy to provide some profiling reports if it is possible to generate them.

Here some insights to my project:

Usually I'm using ttypescript to do to some AST transformation. Lines of Code: ~50000

rollup -c rollup.config.ts: ~9-10sec rollup -c rollup.config.ts -w (initial compile): ~9-10sec rollup -c rollup.config.ts -w (adding 1 alert in 1 TS file): ~20sec rollup -c rollup.config.ts -w (removing alert again): ~20sec

tsc --version: 3.8.3 tsc --project tsconfig.json: ~6-7sec tsc --project tsconfig.json -w (initial compile): ~6-7sec tsc --project tsconfig.json -w (adding 1 alert in 1 TS file): ~0.1-0.2sec tsc --project tsconfig.json -w (removing alert again): ~0.1-0.2sec

ttsc --version: 3.8.3 ttsc --project tsconfig.json: ~7-8sec ttsc --project tsconfig.json -w (initial compile): ~6-7sec ttsc --project tsconfig.json -w (adding 1 alert in 1 TS file): ~0.1-0.2sec ttsc --project tsconfig.json -w (removing alert again): ~0.1-0.2sec

Incremental builds are active in the tsconfig.

It seems to me quite unusual that an incremental/watch build would take twice as much than a full build.

Things seem to go crazy in my environment when ti comes to testing. I hooked up rollup with karma and this typescript plugin. As you might know: each test suite gets its own bundle, which means the numbers of above pile up. Memory grows to >2GB over time; even after minutes the test run does not actually start. This happens on each single npm run test.

Once it reaches the "Generating bundle for..." area on the test generation I see ridiculous high numbers: File01.test.ts containing 1 simple test of a parser class takes 15secs File02.test.ts containing 11 XML parsing tests needs 2.5minutes File03.test.ts did not even complete after 5 minutes.

I have no clue where this issue might be caused and if it is really due to the typescript module of rollup but this seemed to be the most likely issue I'm related to.

As my repo is quite large and complicated I did not share more details on configs. If anybody can guide me how to collect them, I'm happy to provide logs/profiling results etc. I will try to setup a new simple independent repository reflecting my overall project situation, but I cannot promise that the issue will persist.

Danielku15 avatar Apr 05 '20 20:04 Danielku15

@Danielku15 Your main problem is that you are migrating from C# and not from C++ :)

This plugin is not explicitly using typescript's own incremental builds (this didn't exist when it started).

You could try @rollup/plugin-typescript, they use a different approach I think and might give you different numbers.

Another option is to do typescript compilation out of rollup chain (as a prebuild step in npm or something) and feed resulting js to rollup instead. Watch build would be interesting, although I think you can start tsc and rollup in watch mode and if project is configured correctly it will just work.

ezolenko avatar Apr 06 '20 18:04 ezolenko

Your main problem is that you are migrating from C# and not from C++

Off-Topic: I am not sure if I would like to migrate a C++ framework/library to TypeScript. Depending on the use of macros and templates (which C++ devs tend to love) things might go wild during migration 😅 Luckily my C# codebase was always tailored to a style that allows cross compilation to other languages so the result is quite acceptable from a code structure. I just need to figure out a bit better how to organize the modules to reduce some overhead. 😊

This plugin is not explicitly using typescript's own incremental builds (this didn't exist when it started).

This is interesting, is this plugin having some own custom "incremental" build strategy? This could explain why a full-clean build might be taking longer than an source change when using watch. The typescript compilation is more or less stable, it is unfortunate that this plugin cannot utilize the incremental updates yet, but I think the time spent in the type script compiler is stable. But the time spend in rollup seems to be varying. Only this explains to me that a clean build is faster than a code change with watch-mode.

You could try @rollup/plugin-typescript ...

Thanks for the hint I will give it a try to see if it improves.

Another option is to do typescript compilation out of rollup chain

I had such a setup at the very beginning but dropped it half way to have "watch" builds during development. I will give it again a shot if I can hook up a pipeline with the two tools "watching" independently. 👍

Update 1: I was able to setup my whole compile and test environment now with invoking tsc chained with rollup. I needed to make my own rollup plugin to resolve the tsconfig paths correctly but after that it was working fine.

Clean compilation: 9secs, Watch compilation: 0.5-1secs and tests via Karma + Rollup are also running (compilation there takes a bit longer as it generates a bundle for each test suite).

Danielku15 avatar Apr 06 '20 20:04 Danielku15

I tried to reproduce and at first I saw a slowdown, but using clean: true and going back and forth between typescript versions several times, I don't see the difference on clean build now...

Could you set clean: true, update rtp2 to latest (0.20.1 or master) and time a build several times in a row on ts 3.3 and ts 3.4?

Where do I have to add this? rollup.config or tsconfig?

vinayaksh42 avatar Aug 18 '21 06:08 vinayaksh42

The bitter truth now is that you should use esbuild plugin instead of this one. And if you want a type checking you just need to run tsc -noEmit directly as an additional step.

fobdy avatar Aug 18 '21 07:08 fobdy

The bitter truth now is that you should use esbuild plugin instead of this one. And if you want a type checking you just need to run tsc -noEmit directly as an additional step.

Thanks for the help, esbuild seems to be working way faster than typescript2 plugin. I am unable to produce the .d.ts files using esbuild. Here is my config

const esConfig = {
    ...baseConfig,
    input: 'src/entry.esm.ts',
    external,
    output: {
      file: 'dist/vue2testrepo.esm.js',
      format: 'esm',
      exports: 'named',
    },
    plugins: [
      replace(baseConfig.plugins.replace),
      ...baseConfig.plugins.preVue,
      vue(baseConfig.plugins.vue),
      ...baseConfig.plugins.postVue,
      esbuild({
        minify: false,
        sourceMap: true,
        target: "es2017"
      }),
      babel({
        ...baseConfig.plugins.babel,
        presets: [
          [
            '@babel/preset-env',
            {
              ...babelPresetEnvConfig,
              targets: esbrowserslist,
            },
          ],
        ],
      }),
    ],
  };

vinayaksh42 avatar Aug 18 '21 12:08 vinayaksh42

Yep, sorry, for producing d.ts you should run tsc directly in an extra step with the emitDeclarationOnly option enabled (in this case you don't need noEmit anymore since it will also check types). Or you can use Vite where everything should work out of the box.

P.S. There is Vue 2 plugin for Vite.

fobdy avatar Aug 18 '21 12:08 fobdy

The bitter truth now is that you should use esbuild plugin instead of this one.

It's important to note that even though esbuild is dope you will sacrifice some rather essential TypeScript features. Like for one, const enums are not supported plus a couple of other caveats. Another rather important feature that is lacking if one would choose to adopt the esbuild plugin into their stack will be the inability to elegantly handle TypeScript paths{} (remap imports).

As per issue 70, rollup-plugin-esbuild requires you lean on @rollup/plugin-alias for handling remaps which is far from ideal. This becomes rather problematic in large projects that take advantage of import remaps because @rollup/plugin-alias is slow, verbose and requires you to explicitly define the entries and thus those speed gains made with esbuild are quickly taken away.

If you decide to choose the official @rollup/typescript plugin then be rest assured at some point you will run into issues and find yourself trying to debug something that will be directly related to that plugin. Given the rather incorrigible nature some official rollup plugin maintainers happen to retain - when (and trust me, it is a matter of when) you find yourself scouring previous issues of the official plugins repository in an attempt to fix whatever the problem you've encountered might be or even if you wish to submit a PR it will be met with red-tape and fatigue. Essentially, the juice is really not worth the squeeze on that one imo.

There is also tszip maintained by ctjlewis which might be a solution for some as it is using a tsc to rollup compile approach and can be customized depending on your time and needs.

The fact remains that ts2 is clearly the breadwinner in the nexus of Rollup and TS support. It is not the fastest solution but it is the most stable and well maintained (side note: thanks ezolenko). There are some things you can do to help negate that, like those mentioned in previous comments here and while I am not sure if applicable maybe assumeChangesOnlyAffectDirectDependencies option within tsconfig.json could help?

Wishing everyone good karma, heath and happiness!

panoply avatar Nov 21 '21 02:11 panoply

For anyone else coming to this issue after finding rollup builds were intolerably (25 minutes for a large project) our solution after some investigation was rather simple. Setting declaration: false in tsconfig.json resulted in builds going down to under a minute. We now generate typings separately using tsc which only takes about 10s.

cookejames avatar Jan 26 '22 11:01 cookejames

upstream issue

Hi folks, just doing some housekeeping in the issues. I'm going to close this one out as it's gone quite stale (no comments in 9 months) and as far as I can tell, there really isn't anything we can do on this front since the slowdown is within TypeScript itself and not this plugin. rpt2 also does not specify a specific version of TS and is compatible with many versions (we only specify a minimum TS version).

This issue with TS v3.4 was also reproduced by other tools in TS ecosystem, e.g. https://github.com/s-panferov/awesome-typescript-loader/issues/633 . So it's not specific to this plugin either (or even Rollup) in that sense.

rpt2 internal nuances

I've made a handful of optimizations here and there since I joined on to help maintain rpt2, but most of those have been cache or watch mode related. The CPU-bound nature of compilation and type-checking still remains and those are primarily just calls to the TS Compiler API, so there isn't much speed-up to be had there. The rpt2 codebase is relatively small too, with the source at a bit over ~1k LoC, so very generically speaking, there isn't too much overhead in the codebase itself.

We use the LanguageService API that IDEs use, and if I had to guess, this is slower than tsc because it's a file-oriented API as opposed to a whole Program-oriented API. tsc is also faster as a single tool that encompasses the whole build, whereas rpt2 is just a single plugin in a Rollup build (and multiple plugins may perform parsing, as well as Rollup itself).

Rollup also processes the code graph on a file-by-file basis, so file-oriented APIs are somewhat necessary for us to use. If we offload type-checking to another thread, as #113 suggests, then it might be possible to operate a bit differently in that case. But that has its own caveats, as if we don't error out on type-check errors, that can cause the output JS to be problematic and cause Rollup to error out confusingly instead of a nice type error. Plus, the history of Webpack threading has shown that moving type-checking into a separate thread is not always a performance improvement and can sometimes negatively impact performance instead (it also uses more memory, since Node worker_threads are quite primitive with sharing memory, so they're almost like separate processes). This likely depends heavily on the size and structure of your project, as well as the complexity of your types. I'll do a deep dive with Webpack plugin issue references in that issue later, but that's the gist of it.

tuning

Overall, I don't think there's anything we can do to address this issue specifically. There may be other optimizations to be had in other issues, but this one itself is generic, caused by upstream TS itself, and doesn't really have a course of action we can take. That being said, please feel free to continue recommending specific optimizations and the performance characteristics of different configurations, as those can be helpful / useful, especially to other users!

Off the top of my head, a few configurations that can change performance characteristics are:

rpt2 options:

  • check: false disables type-checking
  • clean: true disables rpt2's caching. this may slow down some projects and speed up others, it depends. I imagine turning caching off may speed up compilation of smaller projects, where the I/O of a filesystem cache may not be worthwhile, whereas the default caching is probably better for larger projects. This has not been thoroughly benchmarked though.
  • exclude can be used to optimize filtering of files
  • transformers in that less transformations = better perf
  • useTsconfigDeclarationDir may improve perf as it skips Rollup's emit APIs and instead writes directly to the FS. It may also improve perf if you have multiple Rollup outputs.

Rollup options:

  • sourcemap: false disables source maps
  • potentially others that I can't think of off the top of my head

tsconfig options:

  • emitDeclarationOnly: true is supported as of 0.33.0 / #366, if you want to use Babel, esbuild, swc etc as transpiler and rpt2 as type-checker + declaration emitter. As others have mentioned above, note the caveats of not being able to use const enum etc with this configuration
  • declaration: false + declarationMap: false disables declarations and declaration maps
  • some other diagnostic and type-checking strictness options may also change performance, but it's not clear how
  • See also the official TS Performance docs

agilgur5 avatar Sep 05 '22 20:09 agilgur5