Experimental DX improvements #2629
Replies: 6 comments 6 replies
-
I appreciate the step-by-step to help understand what's happening and what you were able to get working. I'm in agreement with this direction. It sounds like you found an approach that is close to fully working with where things are right now is that right, but still more to figure out? Would the ultimate goal be to finish completely converting to TS? I'm not sure if that was the original intention when the piece-meal introduction of TS started a few years ago before my time, but I gathered from comments that the mixed JS/TS setup that evolved wasn't quite as clean as hoped. |
Beta Was this translation helpful? Give feedback.
-
I think we may be able to split change of splitting I think that this approach might be a little hard to get working while we still have modules being implemented in JS. I'm not entirely sure how lerna handles this, but you can set up turbo (or gradle) to understand that the test script in package x requires the build in package y to have completed. That might allow us to have the minimal set of builds get completed to run the various scripts in a reliable way. If we did make it to a TS-only repo, I'm pretty confident that project references can help us manage the dependency tree, and |
Beta Was this translation helpful? Give feedback.
-
Thanks heaps for your comments @twelch and @mfedderly. Answering inline below:
What I'm suggesting isn't so much to convert completely to TS. It's more to avoid generating JS in dist/ unless we need to. Is there a way to develop - edit, add features, bug fix, and test - without having to generate all the stuff in dist/ with
It's actually come together pretty smoothly (surprised Pikachu face). I can fix a bug, add and run tests, and commit - all without having to run build or generate anything in dist/. Then to prepare a release, the generated code in dist/ looks pretty much identical to the current setup. All the .js, .cjs, .d.ts and .d.cts files are the same (except for the expected changes where importing sweepline-intersections and rbush). The .map files differ so I will double check them.
It did seem to be required. From the TS docs it's much the same as what we used to have (node16) except it's more forgiving of relative imports. Which is what I believe the TS runtime falls back to via
Fairly sure nothing in this approach blocks mixing in JS modules. For example, turf-bbox is TS and happily consumes meta (JS) and helpers (TS) under the new setup. Agree a consistent language across the codebase would be nice. Moving everything to TS first isn't a pre-requisite though.
Happy to take it in a couple of stages, though I don't believe we're really changing the build system. A release is still generated using tsup and the code produced seems to be equivalent. All we're changing is to not generate a bunch of release related artefacts just to develop and run unit tests.
This is a key point - I don't think people have to run pnpm build. With this new setup, if I edit turf-meta/index.js and then run the tests in turf-bbox/ they pick up my change in meta without having to build anything. As a next step I'll push my branch so you can all take a look and have a play with it. Clone the repo, npm install, change some TS or JS, and run the tests. See how far you can get without having to run |
Beta Was this translation helpful? Give feedback.
-
Here's the branch: https://github.com/smallsaucepan/turf/tree/experimental-dx Try:
This should run the tests without building or generating any JS. Ignore warnings about "Invalid 'main' field in ..." for now. Add a console.log() call to transformRotate() in turf-transform-rotate/index.js. Immediately run the turf-ellipse tests again, and you should see your new message logged multiple times. You can also run That should be enough to get you started. Have a play around and let me know how you go. |
Beta Was this translation helpful? Give feedback.
-
Wondering if anyone has had a chance to have a play with this? FWIW I've been dog-fooding this approach with recent converting to typescript PRs, and it's worked fine. |
Beta Was this translation helpful? Give feedback.
-
Ok I've got a few observations already here. I really want to cache the The first is that our nx.json file has The second is that you can execute any task in the repo and specifically include its dependencies with a command like so:
If we're willing to use that style of command or wrap it with some syntax sugar, we can probably get away with not modifying the repo very much and we get partial (but correct) builds. |
Beta Was this translation helpful? Give feedback.
-
Currently
pnpm install
installs the required packages from npm (thank you) but then also starts generating esm and commonjs Javascript for the whole project (uhh ... thanks?) This takes 10 - 15 minutes on my laptop.And it occurs every time you run install. When working on a bug for example, installing or upgrading a dependency to try it out triggers a full rebuild of the whole project. I can cancel it once I see the package is installed, but that doesn't feel right.
Which leads to the question, if Turf is (basically) a TS project, do we need to generate JS at all unless we're preparing a release?
And then thinking more broadly, can we improve the developer experience (DX) of working on Turf? Make it quicker, less wasteful, and more clear what's going on. Spent some time looking at this and below is a summary of the process. Choosing to document it here as while largely (I think) successful, it is a departure from the way we're currently doing things and will require discussion.
Goals are broadly:
Stop building JS so often
According to NPM scripts prepare runs in a couple of circumstances, including after install. We can split the above into:
Running
npm install
installs husky commit hooks, but doesn't run the build target until we're clearly about to publish a release.Get unit tests to pass without having to build JS
Right out of the gate NX has the lerna test target depend on build, so remove that dependency:
With the above done it's possible to run
pnpm run test
in turf-helpers without building (no JS in the dist/ directory), as helpers depends on no other turf packages.Running the same in turf-along fails though because along depends on @turf/bearing, etc. This currently works because while the along code is being loaded from turf-along/index.ts all the local dependencies are loaded from generated JS e.g. turf-bearing/dist/esm/index.js. So a lot of our testing is being run against a mixture of TS and JS. Not the worst thing in the world, though I hadn't realised this.
To instead allow turf-along/index.ts to import turf-bearing/index.ts directly, we can add the below to tsconfig.shared.json:
This wasn't quite working though. The solution seemed to be
By and large package unit tests now work without having to generate JS. This will have an impact on the generated JS that we publish and would need to be investigated for backwards compatibility.
Get type tests to pass
types.ts tests fail though because tsc is still running with the old module and moduleResolution values, and can't see the paths added to tsconfig.shared.json. This is because tsc can't mix tsconfig file options and command line options so they are all configured on the command line. The cleanest solution seemed to be to bite the bullet and add a tsconfig.testTypes.json file to each package,
and then change
to
Most type tests work now, with a few exceptions.
Reversing some export related workarounds
Remaining type tests that were failing were related to current re-export workarounds in some packages that imported older third party libraries with weird types e.g.
Removing these (sweepline-intersections and rbush) and simply importing the third party library directly allowed all type tests to pass.
@turf/turf
@turf/turf being an exceptional package - aggregating all the micro-functions and providing a minified bundle - required special treatment.
My thinking here (and happy to hear other points of view) is that for most development work @turf/turf doesn't need to be built. If someone is fixing a bug in @turf/along they can code, test and commit using TS only.
In other words, only build and run last-checks - which tests the aggregation and minification - when we're doing a release (and probably for CI runs too if we want to be on the safe side).
Summary
A fair read to be sure, though what this covers reflects where Turf probably could be as a developer friendly project. And depending on your opinion, it might also be a more sensible project setup - split steps to be more in line with npm life cycles and don't spend time generating things until we absolutely need to.
Welcome thoughts, criticisms, or questions 😅
Beta Was this translation helpful? Give feedback.
All reactions