Skip to content

Conversation

@cprecioso
Copy link
Member

@cprecioso cprecioso commented Sep 15, 2025

🎉 It's here! 🎉

This PR enables npm workspaces in the users' projects, pulling the dependencies from each folder's node_modules to a the common top-level node_modules (when possible, for most packages). This was in general easier than expected, and looks like it will be mostly transparent for our users. npm will adapt to whether the .wasp/{out,build} folders exist or not and fold them into the general dependency resolution.

  • Added workspaces to starters
  • Added workspaces to example projects
  • The compiler checks that package.json#workspaces exists and has the correct value
  • There was some complex logic in NpmDependencies to deduplicate dependencies between the user package and the framework packages. npm now takes care of this, so we don't need it.
  • This change does not require users to do anything different. The current https://wasp.sh/docs/project/dependencies docs are still the way to do, we're just now intelligent about it. No changes to docs.

Extra fixes that I had to do:

  • Update Wasp App Runner because of the behaviour of npx in workspaces (actually done in Correctly set dir to serve in wasp-app-runner #3168)
  • Ensure the node_modules folder is always created inside Docker (even if empty) so the instruction copying it doesn't fail.
  • I had to change the names of the generated packages. npm needs every package in a workspace to have a different name. The server and web-app packages have the same name whether output to .wasp/out or .wasp/build, so I made the generation change the name based on if it's dev or build: @wasp.sh/generated-{server,client}-{build,dev}. I added an issue to improve this here Unsplit .wasp/build and .wasp/out #3163

Left over:

  • Adding the SDK folder as a workspace too. Currently it is not necessary because we run the install and build ourselves anyways, and it is fully a dependency so the dependencies are correctly shared. Still, we should upgrade it to a workspace so we can remove the ugly file:.wasp/out/sdk dependency.
    • Currently a overly-zealous resolution makes an incompatible resolution for @types/react that would make the workspace installation fail. We should review when we Migrate to React 19 #2482.

Steps / Criteria

Copied from #3130

  • Check Wasp behaves correctly with package.json#workspaces
  • Edit the starter package.json's to have the workspaces key
  • Check that dependencies are correctly shared
  • Test that dependency checking logic inside waspc still works correctly
  • Add a check for workspaces in the compiler
  • Adapt wasp deps command not needed
  • Add a migration guide and documentation

@cprecioso cprecioso self-assigned this Sep 15, 2025
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Sep 17, 2025

Deploying wasp-docs-on-main with  Cloudflare Pages  Cloudflare Pages

Latest commit: b15f1fb
Status: ✅  Deploy successful!
Preview URL: https://e4623771.wasp-docs-on-main.pages.dev
Branch Preview URL: https://cprecioso-npm-workspaces.wasp-docs-on-main.pages.dev

View logs

@cprecioso cprecioso force-pushed the cprecioso/npm-workspaces branch from b2c82e8 to e267c5b Compare September 18, 2025 14:03
Copy link
Member Author

Choose a reason for hiding this comment

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

This file is just stuff extracted from TsConfig.hs that I also wanted to use in PackageJson.hs.

getOppositePackageJsonDepedencyKey :: PackageRequirement -> Maybe String
getOppositePackageJsonDepedencyKey = \case
getOppositePackageJsonDependencyKey :: PackageRequirement -> Maybe String
getOppositePackageJsonDependencyKey = \case
Copy link
Member Author

Choose a reason for hiding this comment

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

Just fixing a typo

-getOppositePackageJsonDepedencyKey
+getOppositePackageJsonDependencyKey
                           ^ here

@cprecioso cprecioso marked this pull request as ready for review September 18, 2025 16:38
@cprecioso cprecioso changed the title Move to npm workspaces Turn the user project and the generated packages into an npm workspace Sep 18, 2025
@cprecioso cprecioso changed the title Turn the user project and the generated packages into an npm workspace Enable npm workspace for user project and the generated code Sep 18, 2025
validateDevelopmentDependencies :: P.PackageJson -> [GeneratorError]
validateDevelopmentDependencies packageJson =
concat $
concat
Copy link
Member Author

Choose a reason for hiding this comment

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

Fixing a linter warning

@cprecioso
Copy link
Member Author

@sodic ready for re-review

  • Undid the validator refactor and made an smaller change for validation
  • When defining the globs, convert from StrongPath to regular String earlier to simplify code
  • Turned PackageJson.workspaces into a Set as it fits better how I'm checking it
  • Updated main and solved conflicts

Copy link
Contributor

@sodic sodic left a comment

Choose a reason for hiding this comment

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

All good!

I left a few comments with suggested changes on the messages. Please consider them.
I don't want to dwell on this for too long since we're refactoring it soon.

You don't need to ping me again before merging :)

Comment on lines 75 to 80
[ "Wasp requires \"workspaces\" to include",
showSet NW.workspaceGlobs,
"but is missing",
showSet $ NW.workspaceGlobs `S.difference` definedWorkspaces,
"in package.json."
]
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
[ "Wasp requires \"workspaces\" to include",
showSet NW.workspaceGlobs,
"but is missing",
showSet $ NW.workspaceGlobs `S.difference` definedWorkspaces,
"in package.json."
]
[ "Wasp requires package.json \"workspaces\" to include",
showSet NW.workspaceGlobs,
", but",
showSet $ NW.workspaceGlobs `S.difference` definedWorkspaces,
"is missing."
]

This sounds a little more natural. But the entire message might leave users confused (because of the arrays surrounding the output).

image

I recommend saying:

- Wasp requires package.json "workspaces" to include: ".wasp/build", ".wasp/out". You are missing: ".wasp/build".

dependencies :: !DependenciesMap,
devDependencies :: !DependenciesMap
devDependencies :: !DependenciesMap,
workspaces :: !(Maybe (Set String))
Copy link
Contributor

@sodic sodic Oct 28, 2025

Choose a reason for hiding this comment

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

How come we went with a set here?

This structure should mirror how the file works, not how we want it to work. So I believe this should be an array. If we need the set, we should introduce it in the processing.

Comment on lines 85 to 88
[ "Wasp requires \"workspaces\" to be present with the value",
showSet NW.workspaceGlobs,
"in package.json."
]
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
[ "Wasp requires \"workspaces\" to be present with the value",
showSet NW.workspaceGlobs,
"in package.json."
]
[ "Wasp requires package.json \"workspaces\" to be present and include values:",
showSet NW.workspaceGlobs, -- we do a comma separated list without the brackets.
]

Slighly more correct and readable I think.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, do we want to allow them to have extra workspaces? Perhaps it's simpler keeping it airtight for now: You must have this and only this.

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 initially went for not allowing it, but Miho asked me to allow it.

@cprecioso cprecioso merged commit ce81a90 into main Oct 28, 2025
24 checks passed
@cprecioso cprecioso deleted the cprecioso/npm-workspaces branch October 28, 2025 14:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Share dependencies through an npm workspace

6 participants