Parcel: Typescript project reference

Created on 2 Aug 2018  路  22Comments  路  Source: parcel-bundler/parcel

馃檵 feature request

With typescript 3.0.0 there's now something called "Project reference". It basically links multiple ts packages together in mono-repository. And build them in order in a single tsc call.

https://www.typescriptlang.org/docs/handbook/project-references.html

Faster build time, cool and all. But it requires a custom flag to tsc : tsc -b

馃 Expected Behavior

Parcel detects that there's project reference activated and pass -b flag

馃槸 Current Behavior

-b flag isn't passed. Therefore dependencies are not built. Leading to

Cannot resolve dependency "my-dependency"

馃拋 Possible Solution

If the tsconfig.json contains references field, add -b flag
As a workaround, we can manually call tsc -w -b on another terminal. But then that's the equivalent of not using parcel

馃敠 Context

Simply setting up a project with "Project references".

馃捇 Examples

WIP

Feature TypeScript

Most helpful comment

Sure, I鈥檇 be happy to. I鈥檓 happy for us to also look into implementing project references. We may end up with a TypeScript specific resolver at some point to handle this and other TS specific stuff (e.g. paths, baseUrl) in the future. In the mean time, hopefully one of these workarounds works for you.

All 22 comments

Well parcel isn't even running typescript 3 yet, perhaps we should start with simply upgrading to 3 first

Isn't it?

I used other typescript 3 features with parcel today (spread operator with tupples). Worked perfectly.

Interesting.

That's pretty cool, parcel localRequires it so it just uses whatever the user has installed. Means ts 3 doesn't have that many changes that would break parcel's implementation. We currently test against typescript 2.9.

It's mainly a thing of running ts 3 in the tests to make sure everything still works, I'll create a PR in a bit

According to typescript documentation, the only breaking change is unknown now being a reserved keyword

https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md

In the mean time, I'll try to make a fork that adds that -b flag and see what happens.

Awesome, thanks for looking that up.
I had just ran all tests against 3.0 and seems to be all good :)

Update PR: #1840

Tried adding build: true in TypeScriptAsset.js on a parcel fork.

Doesn't seems to do anything. I expected as much considering it seems we _must_ use tsc cli to pass that flag.

Maybe it's something on typescript side. Like supporting a build to compilerOptions (weird it's not there)

https://github.com/Microsoft/TypeScript/issues/25613

It seems voluntary on TS side that --build flag can't be set using compilerOptions. I wonder what we can do here

Well that's a pity, although I'm not sure if this would be able to work inside parcel at all as parcel compiles one file at a time and gives typescript very little information.

Yeah, I realized that. Maybe we can have a middle ground.
Where typescript would list module dependencies and parcel add them to the build list. Or maybe just parse the references object.

I don't know. But this would be quite cool if this was supported by parcel. We wouldn't need to have one watcher per package.

Edit: I came across collectDependecies method in Asset class which can be overridden.
Somehow it should be possible to add the baseUrl/index.tsx? of each reference as dependency.

But I wonder how parcel would handle going outside of the current package boundaries.

From Ryan Cavanaugh as an answer to "How to compile projets references with transpileModule api ?"

If you want to read the references from the tsconfig to walk the dependency graph and build upstream projects, you can call ts.createSolutionBuilder and then call getBuildGraph to get a representation of the dependency tree you can traverse.

Would this be ok to do that in parcel ?

Probably better to contribute this to parcel-plugin-typescript as that's a more complete and advanced version of ts than parcel's internal implementation.

Does Parcel still not support typescript project references, i.e. composite projects?

I read the docs above but I don鈥檛 think I really understand what this feature is or what we鈥檇 need to do in Parcel to enable it. Can someone summarize?

Parcel 2 is using more TypeScript internals than Parcel 1 but still uses transpileModule to compile files independently (with a plugin - we compile with Babel by default now).

@devongovett basically inside tsconfig.json you define which monorepo packages your typescript package depends on. Then your editor and Typescript compiler can lint and compile your package while resolving its monorepo dependencies. E.g. I may have this tsconfig.settings.json in my workspace root:

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es2015",
    "lib": ["es2015"],
    "moduleResolution": "node",

    "rootDir": ".",
    "baseUrl": "./packages",
    "paths": {
      "@org/*": ["./*/src"]
    },

    "composite": true,
     ....
}

and then have a folder structure like:

- packages/react-app
- packages/serverless-backend
- packages/common

Where packages/react-app has a package.json like:

{
  "name": "@org/react-app",
  "dependencies": {
    "@org/common": "^1.0.0"
  }
}

and a tsconfig.json like:

{
  "extends": "../../tsconfig.settings.json",
  "compilerOptions": {
    "outDir": "dist",
    "rootDir": "src"
  },
  "include": ["src"],
  "references": [
    { "path": "../common" },
  ]
}

now inside e.g. packages/react-app/src/index.tsx I can do import { someUtility } from '@org/common and this Typescript reference will be picked up from the scope of @org/react-app (the typings will work and tsc -b will know how to compile it even though @org/common is not yet compiled)

I鈥檓 probably missing something, but does this not already work via normal node_modules resolution with something like Yarn workspaces?

@devongovett no because that would require you to first build the dependency packages; Typescript project references understand source references

Hmm, a bundler like Parcel would build the dependency packages on demand. You can use the source field in package.json to reference your source files and Parcel will use it over e.g. main.

@devongovett how would my editor pick that up though? I'm using vscode. Intellisense understands typescript project references, but wouldn't be aware of Parcel

Combine them? I鈥檇 like to convince TS to support source as well.

Another solution I鈥檝e found is to create an index.ts in each package that re-exports src. Then TS will fall back from main/types during development.

@devongovett hmm ok, I'll give this a try and create an open source boilerplate with Parcel + Typescript References + Yarn workspaces + Lerna + React.js + Serverless Framework. Let me know if you'd be open to providing feedback along the way

Sure, I鈥檇 be happy to. I鈥檓 happy for us to also look into implementing project references. We may end up with a TypeScript specific resolver at some point to handle this and other TS specific stuff (e.g. paths, baseUrl) in the future. In the mean time, hopefully one of these workarounds works for you.

@devongovett My team uses project references. It works something like this:

without project references = when we import something, typescript does the usual flow (import, read source, check types, compile source)

with project references = when we import something, typescript does nothing, just imports signatures from d.ts file of the referenced project and uses already compiled js

Would be really cool to see parcel supporting it.

Was this page helpful?
0 / 5 - 0 ratings