`failed to transpile` `tslib.es6.js` after update to `v0.30.0`
See original GitHub issueWhat happens and why it is wrong
failed to transpile '[...]/node_modules/tslib/tslib.es6.js'
rollup-plugin-typescript2
v0.29.0 works fine, v0.30.0 introduces this error.
The setup is a bit complex because it happened as part of Rollpkg. It happens when tsconfig target: es5
(so tslib
is needed). I was alerted to it from this issue. Rollpkg v0.5.0
has the bug, v0.5.1
fixes it by downgrading rollup-plugin-typescript2
to v0.29.0.
I’m using TypeScript v4.2.3
.
Issue Analytics
- State:
- Created 3 years ago
- Comments:7 (3 by maintainers)
Top Results From Across the Web
Developers - Fails to transpile tslib.es6.js - - Bountysource
rollup-plugin-typescript2 v0.29.0 works fine, v0.30.0 introduces this error. The setup is a bit complex because it happened as part of Rollpkg.
Read more >Project dependencies - D2iQ Help Center
Vendor Name Version License Id github.com/blang/semver v4 v4.0.0 MIT github.com/go-openapi spec v0.19.3 Apache-2.0 github.com/google go-cmp v0.5.4 ...
Read more >JavaScript Packages - Raspberry Connect
First get an updated package list by entering the following command in to terminal if this has not been done today sudo apt...
Read more >Open Source Used In Firepower 7.0.0 - Cisco
In your requests please include the following reference number 78EE117C99- ... 1.19 vault-plugin-secrets-azure v0.5.2-0.20190814210135-54b8afbc42ae.
Read more >rollup-plugin-typescript2 - bytemeta
`failed to transpile` `tslib.es6.js` after update to `v0.30.0`. yaldram ... Syntactically incorrect JS output with `declare const` globals -- due to Rollup ...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
So, I took a look at this issue and this was a doozy to figure out, but eventually got to the root cause
initial investigation
This took a decent bit more time & effort to investigate as this is not a minimal reproduction – in general, a minimal repro makes it significantly easier to investigate any issue. Given that most maintainers are volunteers with severely limited time, making it as easy possible for them to investigate should be the goal. The permalinks that you gave (and which are still available!) are still helpful that being said.
It so happens that I solo-maintained TSDX for ~1.5 years (that’s how I originally became a contributor here), so reading through
rollpkg
’s code was measuredly simpler, as they have somewhat similar layouts.Sidebar: TSDX comparison flaws
(Also your TSDX comparison is flawed, as TSDX actually uses both TypeScript (via rpt2) and Babel (basically: ts -> esnext -> preset-env), and, again, that’s how I found myself here.
Otherwise, the comparison is more or less accurate. See https://github.com/jaredpalmer/tsdx/issues/634 and https://github.com/jaredpalmer/tsdx/issues/635 as the two main RFCs I was pushing to get out of the configuration and compatibility hell.
size-limit
was (partly) intentional though, given the various trade-offs I analyzed. One was that there’s no reason that stats should be tied to the build or slow it down).Anyway, there were two things that stood out to me initially:
tslib
, which, well, shouldn’t be transpiled in the first place, for a number of reasonsnode_modules
and should be anexternal
0.30.0
@rollup/pluginutils
to v4, which included https://github.com/rollup/plugins/pull/517pluginutils
is responsible for filtering, i.e.include
andexclude
in most Rollup plugins’ options.process.cwd()
that was added in front of any glob patterns given to itinclude
d without changing the default settings. So this change ended up unintentionally solving lots of monorepo issues. And also caused this issue, as it means things likenode_modules
can also beinclude
d by default.external
s, and because rpt2’s defaultinclude
only has TS files, which are not often present and not meant to beimport
’d fromnode_modules
You can probably see where I’m going from here, but therein lies the problem.
root cause analysis
rollpkg
’stsconfig
setsallowJs: true
and sets rpt2’sinclude
to also process JS files.Notably, what’s missing is a changed
exclude
. rpt2’s docs do point out that you probably want to addnode_modules
to yourexclude
if you’re settingallowJs
andinclude
ing JS files.(Your
external
configuration is also a bit problematic in that it’ll miss submodule deps, similar to https://github.com/stevenbenisek/rollup-plugin-auto-external/issues/16. I personally userollup-plugin-node-externals
, which doesn’t have this issue)So, with that, the problem becomes a lot more straightforward.
HashLink.jsx
gets processed by rpt2 (logged on this line) and it returns this code at the top of the file:Note, of course, the presence of
tslib
.So when rpt2 gives this ESM code to Rollup, it parses it and tries to resolve, and if configured to do so, transform, all the imports. Given the lack of
tslib
in your deps, this means thatrollpkg
doesn’t add it to yourexternal
s list, meaning thattslib
ends up getting processed by your Rollup plugins. And, given the lack ofexclude
, that means rpt2 tries processingtslib
.So the solution therein is to add
tslib
to your deps. You probably also want to addnode_modules
torollpkg
’s rpt2’s plugin optionsexclude
. The specific glob that worked for me during testing wasexclude: ['**/node_modules/**/*']
.what about the lacking error though?
I dug a bit more to really understand this though, in particular as the lack of syntactic or semantic errors is still pretty strange. This is where things start to get complicated… especially as we get into the lacking TS Compiler docs 😕
The
failed to transpile
error message means that rpt2 hit what it currently considers a fatal error somewhere. This results in TS skipping emit of files.Normally, this is caused either by a compiler option error (i.e.
tsconfig
configuration issue) or a syntactic or semantic error (i.e. type-checking issue). The fact that neither was printed out in this case is strange, and often indicative of a bug.I did some logging and that did not make things any less confusing, unfortunately…
emitSkipped
and no files, butid
clearly exists:no semantic or syntactic errors (which is to be expected, given that this is compiled
tslib
helper code):snapshot exists and is correct (matches the exact source code of
tslib.es6.js
):So that’s odd. I’ve never seen
emitSkipped
in a scenario like this (and I don’t think ezolenko has either).figuring out
emitSkipped
So I decided to look into
emitSkipped
in more detail.Unfortunately, as usual, the TS Compiler API Docs don’t elaborate in any way on this. It’s just used in 2 examples there, and that’s what most TS Compiler integrations base their implementation on, including rpt2. Based on that example, I didn’t see anything strange about rpt2’s usage (which I’ve already read through dozens of times too).
So I did some more searching about
emitSkipped
. I stumbled upon this issue ints-node
: https://github.com/TypeStrong/ts-node/issues/693 . That happened to get some explanatory comments on it literally yesterday. Per that comment, it turns out this arootDir
issue.From the TSConfig Reference on
rootDir
:So, it turns out (basically through reverse-engineering as the TS Compiler Docs don’t remotely go into this), that a compiled file will have
emitSkipped
set when that file is outside of therootDir
.And indeed,
rollpkg
(similarly to TSDX), sets a defaultrootDir
of./src
../node_modules/tslib/tslib.es6.js
is clearly outside of./src
and so outside of yourrootDir
and hence its emit gets skipped.But normally a
rootDir
issue will throw a compiler options error (c.f. https://github.com/jaredpalmer/tsdx/issues/638#issue-586338455), such as:But it doesn’t here.
Well that’s because TS doesn’t know what all the files are ahead-of-time.
tsc
only reads thetsconfig
include
and bases it off that. But with Rollup and plugins, your files get transformed along the way. In this case, thetslib
import was added during compilation (wasn’t there before) and then the lack ofexternal
and pluginexclude
meant thattslib
got passed to rpt2. So the compiler, at run-time, is given a file outside ofrootDir
that it didn’t know about beforehand. There’s no compiler options error as this is after parsing the compiler opts and not expected based on thetsconfig.json
. So the compiler just returns an empty file withemitSkipped
… which apparently can indicate that there’s a previously undetectedrootDir
issue that isn’t documented in the TS Compiler API docs.Root cause found.
next steps
For @rafgraph , the next steps are fairly straightforward, add
tslib
to deps inreact-router-hash-link
, and, ideally,exclude: ['**/node_modules/**/*']
inrollpkg
when it configures rpt2’s plugin options. Could also addtslib
manually toexternal
s inrollpkg
. (maybe modify the TSDX comparison section too 😉 )For rpt2, the next steps are more opaque. This is the only time this issue has occurred too, so it’s pretty rare.
ts-node
addressed this in an intriguing way in https://github.com/TypeStrong/ts-node/pull/1629 which implements https://github.com/TypeStrong/ts-node/issues/1345. Basically, whenemitSkipped
,ts-node
will switch to the simplertranspileModule
API, which just does TS -> JS with no type-checking (i.e. similar to Babel andisolatedModules
).I’m not sure if that is ideal behavior for rpt2 though, which does not have as general a use-case as
ts-node
. rpt2 is only meant to compile projects (not arbitrary code, which is one ofts-node
’s capabilities and purposes) and so should respecttsconfig.json
as much as possible within the constraints of Rollup semantics.This does hit a Rollup boundary, but I think in this case, throwing a
rootDir
compiler options error would be the most accurate behavior and is closest to whattsc
would do, which we try to follow to aim for the “principle of least surprise”.I pasted the text of the
rootDir
error above, which we could copy+paste, but ideally, we should pull that from the TS API somewhere, which would also make it more resilient to error code / error message changes.The one caveat is that given that
emitSkipped
is mostly undocumented, it’s difficult to tell if there are other scenarios whereemitSkipped
would be hit but there are no syntactic or semantic errors. The only other one I’ve heard of so far (have not confirmed) is when TS skips emit instead of overwriting an existing file, which is usually only hit ifallowJs
and nooutDir
. (I also checked the TS source code references toemitSkipped
and that did not help my understanding much… there’s only a dozen or so references in the source though (not including tests etc), that being said).So what we could do is, if
emitSkipped
and no diagnostics, check theid
of the file currently being processed (i.e. its path) against therootDir
, which we have access to. If it’s not withinrootDir
, we could conclude that it is indeed arootDir
issue, and throw therootDir
error. Basically re-implementing some simple TS logic. Otherwise, we leave it as justfailed to transpile
, as it would therefore be an unknown error (as in, if it is none of syntactic, semantic, orrootDir
error).Low priority given the rarity of the issue and that this change just improves DX (it’s not a bugfix in that sense, more a feature), but, that being said, it should be fairly simple to implement.
Surprising that there are no other errors, just
failed to transpile
. Usually there are typescript errors (semantic or diagnostic) printed before that, which caused typescript language service to not emit output .