Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(fix): declaration maps should have correct sources #221

Merged
merged 1 commit into from
Oct 2, 2020

Conversation

agilgur5
Copy link
Collaborator

@agilgur5 agilgur5 commented Mar 29, 2020

  • change declarationDir default to be Rollup's output destination
    instead of cwd

    • previously, it was set to cwd if useTsconfigDeclarationDir wasn't
      true, however, declarations aren't output to cwd, but to Rollup's
      output destination, so this was incorrect
  • also change the one line in the docs that says it'll be
    process.cwd(); every other reference says it'll be the output dest

Fixes #204 and downstream jaredpalmer/tsdx#479 . Better solution to downstream jaredpalmer/tsdx#488

Couldn't change get-options-overrides because the options hook only gets InputOptions; it's not till generateBundle that we get access to OutputOptions.

RE: multiple output dirs: Rollup will call generateBundle for each output as far as I understand. InputOptions is passed to rollup which generates a bundle object, and bundle.write is called with each OutputOptions -- it's a two step+ process. I think that's also why the type is OutputOptions and not OutputOptions[] (though the code doesn't use Rollup's Plugin interface; but that also defines it as generateBundle with just OutputOptions).

Would be great to add tests to ensure the declaration maps are correct now, but there doesn't seem to be any test set-up 😕 #135 seems to partially address that but was never completed.
Can see jaredpalmer/tsdx#488 for how I tested sources there

@ezolenko
Copy link
Owner

ezolenko commented Apr 8, 2020

Sorry for ignoring this for a while -- this breaks something -- if you build the plugin itself with this change, it drops types into dist\node_modules\.cache\rollup-plugin-typescript2\placeholder instead of dist like rollup config says.

To test do npm build (check changes in git) and then do npm build-self (check git again and you'll see lots of files moved).

@agilgur5
Copy link
Collaborator Author

agilgur5 commented Sep 30, 2020

So I had to learn a lot about Rollup plugins and lifecycle to write this PR. Then without further guidance here had to do a lot of learning of this codebase and the TS API. As a result, it took me a while to understand how to fix this.

Debugging the PR

it drops types into dist\node_modules\.cache\rollup-plugin-typescript2\placeholder instead of dist like rollup config says.

I figured out why this was happening relatively quickly, that's because outDir is set to ${cacheRoot}/placeholder, and by default declarationDir is equivalent to outDir. That's on this line:

outDir: `${cacheRoot}/placeholder`, // need an outdir that is different from source or tsconfig parsing trips up. https://github.com/Microsoft/TypeScript/issues/24715

I added some logging during output that displays this as well. While sources is correct now, the entry was output to the wrong place, ${cacheRoot}/placeholder:

entry name:  /Users/agilgur5/Desktop/GitHub/rollup-plugin-typescript2/node_modules/.cache/rollup-plugin-typescript2/placeholder/partial.d.ts.map
dtsmap entry text:  {"version":3,"file":"partial.d.ts","sourceRoot":"","sources":["../../../../src/partial.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,MAAM,OAAO,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;CAAG,CAAC"}

That can't be changed to Rollup's output.dir for the same reason declarationDir can't be; per my opening comment "it's not till generateBundle that we get access to OutputOptions."

Current PR doesn't work

In the current PR, the changes apparently have no effect on the output because they change declarationDir during generateBundle, but the declarations were already created during transform:

declarations[key] = { type: result.dts, map: result.dtsmap };

Trying different solutions

Between March - June-ish, I came back to this a few times to add more logging and understand this as well as to try to somehow set declarationDir properly, but failed a lot because this isn't possible basically.

The LanguageServer, which has the tsconfig declarationDir setting, is created during options:

servicesHost = new LanguageServiceHost(parsedConfig, pluginOptions.transformers, pluginOptions.cwd);

I thought to lazily initialize this, but that's not possible, it's needed in the next plugin lifecycle steps, especially transform.

It can't be done in generateBundle where I was trying in the current PR -- it would have to be done in or before transform -- but OutputOptions like output.dir aren't passed until generateBundle. That causes quite a dilemma.

But Rollup is designed that way intentionally, any output transformations should be left until generateBundle.

Solution

Basically the only option is to transform the declaration maps' sources to the correct relative path to output.dir during generateBundle. I didn't want to resort to doing so as it's one more transform and seemingly in the wrong lifecycle step, but that seems to be how it's designed. It's also a bit expensive performance-wise as each declaration map JSON has to be parsed and then stringified, and sometimes the full source (in this case declaration source) is inside those, making that more perf-heavy.

I checked @wessberg/rollup-plugin-ts to see if it was handled similarly there, and it indeed seems to be (it also bundles declarations, so the logic is a bit different, but still relevant):

map = JSON.parse(text) as SourceMap;
map.file = options.declarationPaths.fileName;

So I'm going to rework this PR to have a similar approach and transform sources during generateBundle. Should hopefully have that done soon.

Other issues

But TSDX is having a lot of other issues with rollup-plugin-typescript2, such as bugs with emitless/type-only imports (jaredpalmer/tsdx#725) and composite projects (jaredpalmer/tsdx#828), among others (jaredpalmer/tsdx#796)

src/get-options-overrides.ts Outdated Show resolved Hide resolved
Comment on lines +368 to +369
// don't mutate the entry because generateBundle gets called multiple times
let entryText = entry.text
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this took me a few hours to debug and was by far the most time-consuming piece 😕 I originally changed entry.text itself which then got changed on top of itself for each output...

Ideally I think generateBundle should have some caching so this isn't repeated per output. I could do that with a cache key inside of declarations{}, but there's a good question as to what that cache key should be (in this case, I think the declarationDir variable is the only thing that is subject to change, but that sounds brittle if more stuff gets added).

src/index.ts Outdated Show resolved Hide resolved
- previously, declarationDir was set to cwd if useTsconfigDeclarationDir
  wasn't true, however, declarations aren't output to cwd, but to
  Rollup's output destination, so this was incorrect
  - instead, don't set declarationDir, which defaults it to outDir,
    which is currently set to a placeholder
    - previously, it rewrote declarations to output to Rollup's dest
      from cwd, now rewrite from outDir placeholder instead
  - and add a rewrite of sources to match relative path from Rollup's
    output dest instead of outDir placeholder

- also change the one line in the docs that says it'll be
  `process.cwd()`; every other reference says it'll be the output dest
@agilgur5
Copy link
Collaborator Author

agilgur5 commented Sep 30, 2020

@ezolenko this should be good to go now -- if you run npm run build && npm run build-self it will change the declaration maps' sources to be correct now, and the files should all still be in the right places.

As I wrote in my opening comment, a test set-up like #135 would be great to have; could add the test I have in jaredpalmer/tsdx#488 here then.

@ezolenko
Copy link
Owner

ezolenko commented Oct 2, 2020

@agilgur5 looks good now. The only problem I see is sources in type maps are in windows format if I build it on windows: "..\\src\\context.ts". Any idea if this will confuse existing tooling?

nvm, fixed it

@ezolenko ezolenko merged commit ee33209 into ezolenko:master Oct 2, 2020
@agilgur5
Copy link
Collaborator Author

agilgur5 commented Oct 2, 2020

Ah, I don't run on a Windows machine, but if that's not normal behavior (wouldn't know), then could use path.normalize

@ezolenko
Copy link
Owner

ezolenko commented Oct 2, 2020

@agilgur5 Ok, PR is in master, could you doublecheck and I'll do a release

@agilgur5
Copy link
Collaborator Author

agilgur5 commented Oct 2, 2020

Looks like you added normalize in front of the relative call so looks correct to me.

I saw you added normalize in front of the emitFile fileName mapping to however -- that didn't have normalize in a previous version, I only changed the path, not how it was mutated: ec0568b#diff-f41e9d04a45c83f3b6f6e630f10117feL368 . I don't know if it should be normalized, but that is different from what it was before.

On install + build + build-self, the package-lock.json auto-updates to the new version and the cjs.js.map and es.js.map get updated for some reason (not possible to read the diff to understand since it's a one-liner). Not sure what that means. Otherwise, don't see any weird anomalies.

@agilgur5
Copy link
Collaborator Author

agilgur5 commented Oct 9, 2020

@ezolenko any update on the above or a release?

@agilgur5
Copy link
Collaborator Author

@ezolenko you merged some of my other PRs, but didn't comment on the above and there still hasn't been a release 😕

@ezolenko
Copy link
Owner

Sorry, was distracted.

When you run npm install it will pull patch updated of deps and I that might affect source maps a bit (maybe line number changed because of comments or something).

I'll do a release later today.

@agilgur5
Copy link
Collaborator Author

What about this part?

I saw you added normalize in front of the emitFile fileName mapping to however -- that didn't have normalize in a previous version, I only changed the path, not how it was mutated: ec0568b#diff-f41e9d04a45c83f3b6f6e630f10117feL368 . I don't know if it should be normalized, but that is different from what it was before.

@ezolenko
Copy link
Owner

Re normalize for emit file, seems to have no effects either way, rollup handles it fine, but might affect downstream plugins that want to modify maps. Normalize is more correct in principle though, so I guess we should keep it and see if problems show up.

@agilgur5
Copy link
Collaborator Author

Ok, yea I read in some Rollup issues (can't find which one it was) that it allows whichever internally, which means plugins have to handle and do the normalization. rollup/rollup#2952 suggests this is particularly relevant for resolveId

agilgur5 added a commit to agilgur5/react-signature-canvas that referenced this pull request Apr 20, 2022
- fancy source maps for declarations

- apparently I left these out of `ts-library-base` so they didn't get
  copied here either
  - but most of my tsconfig there was copied too, so I suspect I left
    it out either because of @wessberg/rollup-plugin-ts's bugs with it
    or because TSDX previously had bugs with it
    - c.f. ezolenko/rollup-plugin-typescript2#221
      and the worse downstream version I had written first:
      jaredpalmer/tsdx#488

- Unfortunately I did encounter a small error with declaration maps when
  using rpts2 as a configPlugin, due to an unexpected edge case in code
  I wrote myself in the above PR
  - wrote up an issue for it and will probably PR it myself too:
    ezolenko/rollup-plugin-typescript2#310
  - as a workaround, I wrote a small `tsconfig.rollup.json` to be used
    with rpts2 as a configPlugin that disables `declarationMap`
    - and also adds some optimizations over my base tsconfig
    - took me a bit to figure out how to use options with configPlugins,
      as that was one of the reasons I didn't use @rollup/plugin-babel
      as the configPlugin
      - I still can't get it to read my `babel.config.js` even with
        options as it has no option for this (it auto-detects it) :/
agilgur5 added a commit to agilgur5/react-signature-canvas that referenced this pull request Apr 20, 2022
- fancy source maps for declarations

- apparently I left these out of `ts-library-base` so they didn't get
  copied here either
  - but most of my tsconfig there was copied too, so I suspect I left
    it out either because of @wessberg/rollup-plugin-ts's bugs with it
    or because TSDX previously had bugs with it
    - c.f. ezolenko/rollup-plugin-typescript2#221
      and the worse downstream version I had written first:
      jaredpalmer/tsdx#488

- Unfortunately I did encounter a small error with declaration maps when
  using rpts2 as a configPlugin, due to an unexpected edge case in code
  I wrote myself in the above PR
  - wrote up an issue for it and will probably PR it myself too:
    ezolenko/rollup-plugin-typescript2#310
  - as a workaround, I wrote a small `tsconfig.rollup.json` to be used
    with rpts2 as a configPlugin that disables `declarationMap`
    - and also adds some optimizations over my base tsconfig
    - took me a bit to figure out how to use options with configPlugins,
      as that was one of the reasons I didn't use @rollup/plugin-babel
      as the configPlugin
      - I still can't get it to read my `babel.config.js` even with
        options as it has no option for this (it auto-detects it) :/
@agilgur5 agilgur5 added the kind: bug Something isn't working properly label May 7, 2022
Repository owner locked as resolved and limited conversation to collaborators May 7, 2022
@agilgur5 agilgur5 added the topic: OS separators Path normalization between OSes. Windows = '\', POSIX = '/'. Rollup resolve = native, TS = POSIX label Jun 25, 2022
@agilgur5 agilgur5 deleted the fix-declaration-map-sources branch July 2, 2023 21:28
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
kind: bug Something isn't working properly topic: OS separators Path normalization between OSes. Windows = '\', POSIX = '/'. Rollup resolve = native, TS = POSIX
Projects
None yet
Development

Successfully merging this pull request may close these issues.

declaration maps (*.d.ts.map) have incorrect relative paths in sources unless declarationDir is set
2 participants