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

Add support for generating TypeScript declarations, and named pipelines #3613

Merged
merged 26 commits into from
Oct 11, 2019

Conversation

devongovett
Copy link
Member

This adds support for generating TypeScript declaration files as a library target, along with the beginnings of named pipeline support. This allows the same input file to be sent through multiple different pipelines to produce different outputs (a .js file and a .d.ts file in this case). A pipeline parameter has been added to dependencies, asset requests, and config requests to support this in core. Related: #3477.

Eventually, resolvers should be able to return pipeline names parsed from import specifiers, so you could reference pipelines from code. For now, the pipeline is set on entries based on the target name (e.g. types from package.json). So, you can have a package.json like this:

{
  "name": "my-package",
  "main": "dist/index.js",
  "types": "dist/index.d.ts"
}

And a .parcelrc like this (actually, this is in the default config):

{
  "transforms": {
    "types:*.{ts,tsx}": "@parcel/transformer-typescript-types",
  }
}

Parcel will resolve the targets in package.json, and apply the appropriate pipeline based on the target name. If no named pipeline is found for that target (e.g. no main pipeline), then it will fall back to the non-named pipeline that matches.

In terms of actually generating TS declarations, we use the TypeScript compiler and a custom TypeScript transformer to do that. TypeScript normally generates separate .d.ts file for each file that you import in your code, but if you specify the outFile option it will generate a "bundle" file instead with all modules inlined. Unfortunately, this still includes all types, not only ones that are exported by the package.

So, we have a custom TS transformer which uses the AST to tree shake and flatten these modules into one top-level .d.ts file containing only exported types. It works in three passes, similar to the JS tree shaking implementation: first collecting information about the imported, exported, and local declarations in each module, then propagating exports from the entry module through to the children and marking used nodes, and finally removing unused nodes and flattening into the top-level scope, renaming declarations as needed.

@parcel-benchmark
Copy link

parcel-benchmark commented Oct 7, 2019

Benchmark Results

packages/benchmarks/kitchen-sink

Timings

Description Time Difference
Cold 10.38s -541.00ms 🚀
Cached 8.25s -582.00ms 🚀

Cold Bundles

Bundle Size Difference Time Difference
dist/legacy/parcel.ff215454.webp 102.94kb +0.00b 204.00ms -22.00ms 🚀
dist/modern/parcel.76ee4591.webp 102.94kb +0.00b 204.00ms -21.00ms 🚀
dist/modern/index.js 794.00b +0.00b 471.00ms -28.00ms 🚀
dist/legacy/index.js 252.00b +0.00b 473.00ms -29.00ms 🚀

Cached Bundles

Bundle Size Difference Time Difference
dist/modern/index.js 794.00b +0.00b 12.00ms -1.00ms 🚀
dist/legacy/index.js 252.00b +0.00b 15.00ms -2.00ms 🚀
dist/legacy/index.css 29.00b +0.00b 11.00ms -1.00ms 🚀
dist/modern/index.css 29.00b +0.00b 10.00ms -1.00ms 🚀

packages/benchmarks/react-hn

Timings

Description Time Difference
Cold 14.76s -32.00ms
Cached FAILED -0.00ms

Cold Bundles

No bundle changes detected.

Cached Bundles

No bundles found, this is probably a failed build...

Click here to view a detailed benchmark overview.

Copy link
Contributor

@wbinnssmith wbinnssmith left a comment

Choose a reason for hiding this comment

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

Looks great to me. Would be interested to hear from @jamiebuilds on the named pipeline work.

packages/core/core/src/Dependency.js Outdated Show resolved Hide resolved
@@ -0,0 +1,23 @@
// @flow strict-local
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this only for packaging type definitions? Maybe the name of the file could include "types"?

Copy link
Member Author

Choose a reason for hiding this comment

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

I guess I could work for any TS... but we could go more specific... It's not even really just TS, all it is needed for is inserting the source mapping url, which the raw packager doesn't do.

@@ -1,6 +1,7 @@
{
"bundler": "@parcel/bundler-default",
"transforms": {
"types:*.{ts,tsx}": ["@parcel/transformer-typescript-types"],
Copy link
Member

Choose a reason for hiding this comment

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

Is this supposed to be the syntax for named pipelines?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants