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

Typescript project reference #1839

Open
rrousselGit opened this issue Aug 2, 2018 · 22 comments
Open

Typescript project reference #1839

rrousselGit opened this issue Aug 2, 2018 · 22 comments

Comments

@rrousselGit
Copy link

rrousselGit commented Aug 2, 2018

🙋 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

@DeMoorJasper
Copy link
Member

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

@rrousselGit
Copy link
Author

Isn't it?

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

Interesting.

@DeMoorJasper
Copy link
Member

DeMoorJasper commented Aug 2, 2018

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

@rrousselGit
Copy link
Author

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.

@DeMoorJasper
Copy link
Member

DeMoorJasper commented Aug 2, 2018

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

Update PR: #1840

@rrousselGit
Copy link
Author

rrousselGit commented Aug 2, 2018

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)

@rrousselGit
Copy link
Author

microsoft/TypeScript#25613

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

@DeMoorJasper
Copy link
Member

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.

@rrousselGit
Copy link
Author

rrousselGit commented Aug 2, 2018

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.

@rrousselGit
Copy link
Author

rrousselGit commented Aug 3, 2018

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 ?

@DeMoorJasper
Copy link
Member

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.

@tommedema
Copy link

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

@devongovett
Copy link
Member

I read the docs above but I don’t think I really understand what this feature is or what we’d 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).

@tommedema
Copy link

tommedema commented Nov 27, 2019

@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)

@devongovett
Copy link
Member

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

@tommedema
Copy link

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

@devongovett
Copy link
Member

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.

@tommedema
Copy link

tommedema commented Nov 27, 2019

@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

@devongovett
Copy link
Member

Combine them? I’d like to convince TS to support source as well.

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

@tommedema
Copy link

@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

@devongovett
Copy link
Member

Sure, I’d be happy to. I’m 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.

@miraage
Copy link

miraage commented Apr 18, 2020

@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.

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

No branches or pull requests

5 participants