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

Improve how Typescript compiles across the monorepo #1085

Merged
merged 10 commits into from
Aug 10, 2021

Conversation

JaapRood
Copy link
Contributor

@JaapRood JaapRood commented Aug 5, 2021

Why

Optic is structured as a monorepo, with multiple interdependent packages individually published and built in one repo. However, making changes across Typescript packages has been very painful so far, basically sourcing from every package being compiled in isolation by a separate Typescript instance.

Generically, when working on package A, that depends on B, which depends on C, making a change in one of the dependencies doesn't automatically propagate up to package A: you have to manually make sure everything is compiled in the right order.

Often, to make sure things are done correctly, you end up rebuilding everything, which is super slow. And even then you have to reload the VSC window, or restart the Typescript language server.

What

In essence, we're connecting the isolated packages and making the Typescript compiler aware of dependencies living locally and are compilable as well.

It should enable :

  • Compiling all Typescript from the project root
  • Watching and compiling all the Typescript from the project root
  • Compiling a single package with all it's dependencies auto-compiling when necessary
  • Support TypeScript tooling across packages (e.g. Go to definition, refactor, etc.)
  • Allow for source maps debugging across all packages
  • Shared configurations and setup to consolidate setup.
  • making ui-v2 webpack-dev-server automatically recompile when one of the dependencies changes (might not work out through a lack of support: Need support for Typescript Project references facebook/create-react-app#6799)

It manages to do this through:

It adds a task:

  • workspaces:watch, to watch the source of all Typescript and WASM targets and recompile them automatically.

Additional todos:

  • Reconsider building from root with one TSC instance for workspaces:build (possibly more efficient): not necessary. As all Typescript packages are now connected, even building them one by one causes incremental builds, only recompiling what's necessary.

Validation

  • CI passes
  • All tasks around compiling packages work in various states

@JaapRood JaapRood requested a review from devdoshi as a code owner August 5, 2021 14:58
@JaapRood JaapRood requested a review from niclim August 5, 2021 14:58
@github-actions github-actions bot added the chore label Aug 5, 2021
Copy link
Contributor

@niclim niclim left a comment

Choose a reason for hiding this comment

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

🎉

Comment on lines +112 to +127
workspaces:watch:
desc: Watch source files and build as they change
deps: [workspaces:watch:typescript]
cmds:
- echo "Watching ended"

workspaces:watch:typescript:
desc: Watch all the source of Typescripts workspaces and automatically recompile (with a single watcher)
cmds:
- yarn tsc -b --watch

workspaces:watch:wasm:
desc: Watch the source of WASM targets and automatically recompile
cmds:
- yarn wsrun --parallel --exclude-missing ws:watch-wasm

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@notnmeyer this is the best way I could imagine doing watchers with Taskfile. Do you see any problems with this / know of a better way?

Copy link
Member

Choose a reason for hiding this comment

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

sorry, been out. this looks fine to me though. i dont think its a better solution in this case, but taskfile also supports fingerprinting source files and watching a task too,

https://github.com/go-task/task/blob/master/docs/usage.md#watch-tasks
https://github.com/go-task/task/blob/master/docs/usage.md#by-fingerprinting-locally-generated-files-and-their-sources

@JaapRood
Copy link
Contributor Author

JaapRood commented Aug 6, 2021

I've added watching of all the assets, except for optic-engine-native, where changes to the underlying Rust code don't trigger any recompiles up the chain (and aren't necessary for the Javascript).

Cargo doesn't have any watching abilities, and while the cargo-watch exists, the preferred method is to run your development binaries through cargo run instead of compiling and calling the binary manually. The latter would actually be the preferred and simplest way to make sure optic-engine-native always runs against a up-to-date binary in development, and prevents us from having to watch the optic-engine Rust code twice (already happens for optic-engine-wasm).

However, that would touch the production code path for spawning optic-engine-native, so that's better done in a separate PR with separate review and testing.

Comment on lines +3 to +36
// We provide a mock for the webpack compiler, so we don't have to reimplement all the watching and can
// leverage the existing plugin.

let beforeCompileHook;
let thisCompilationHook;

const compiler = {
options: {
mode: 'development',
},

watchMode: true,

hooks: {
beforeCompile: {
tapPromise(pluginName, hook) {
beforeCompileHook = hook;
},
},
thisCompilation: {
tap(pluginName, hook) {
thisCompilationHook = hook;
},
},
},
};

let wasmPack = createWasmPackPlugin();

wasmPack.apply(compiler);

beforeCompileHook().catch((err) => {
throw err;
});
Copy link
Contributor Author

@JaapRood JaapRood Aug 6, 2021

Choose a reason for hiding this comment

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

How hacky is this? Pretty hacky! But given how incredibly small the integration between the wasm-pack watcher and webpack is, there being no alternatives and the complexity of forking / writing it ourselves being more complicated than this, I say it's worth it (for now, at least).

@JaapRood JaapRood requested a review from niclim August 6, 2021 10:55
@niclim
Copy link
Contributor

niclim commented Aug 9, 2021

Seems reasonable - watching on optic-engine-native would be nice, but this solves a large painpoint with the current TS compilations

@JaapRood
Copy link
Contributor Author

Developed against this for two days, all seems to working smoothly, passing CI as well. Lets get this out to develop!

@JaapRood JaapRood merged commit bba68be into develop Aug 10, 2021
@JaapRood JaapRood deleted the chore/monorepo-typescript branch August 10, 2021 08:47
@JaapRood
Copy link
Contributor Author

@LouManglass these changes are definitely an added risk for the next release train. Perhaps we should get a side channel build out there to verify it's all functional?

@LouManglass
Copy link
Contributor

@LouManglass these changes are definitely an added risk for the next release train. Perhaps we should get a side channel build out there to verify it's all functional?

Yeah, I'll check that today. Better to find out sooner.

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

Successfully merging this pull request may close these issues.

None yet

4 participants