Skip to content

fix(cli): omit heavy devDependencies for local plugins to reduce node_modules size - #203

Open
singhlovepreet9 wants to merge 2 commits into
strapi:mainfrom
singhlovepreet9:fix-local-plugin-size-22946
Open

singhlovepreet9 wants to merge 2 commits into
strapi:mainfrom
singhlovepreet9:fix-local-plugin-size-22946

Conversation

@singhlovepreet9

Copy link
Copy Markdown

Fixes strapi/strapi#22946

This PR modifies the sdk-plugin so that when it runs inside a Strapi project (isStrapiProject is true), it completely omits heavy devDependencies like @types/react, react-dom, styled-components, typescript, @strapi/design-system, @strapi/icons etc.

These packages are already available in the root of the monorepo workspace for a Strapi project, so they do not need to be duplicated in the local plugin's devDependencies.

This significantly reduces the size of a local plugin's node_modules (from ~300+MB to a few KB if the user runs npm install inside the plugin directory), and stops high server memory consumption during builds caused by duplicated module resolution.

@changeset-bot

changeset-bot Bot commented Jul 12, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: de7b316

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Jul 12, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4f7bb033-5c04-4eb9-9955-12d03c0259f5

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sonarqubecloud

Copy link
Copy Markdown

@singhlovepreet9
singhlovepreet9 marked this pull request as ready for review July 14, 2026 10:46
@unrevised6419

Copy link
Copy Markdown
Contributor

The problem this targets is real (a ~300 MB nested node_modules is nasty), but I don't think dropping the devDependencies is the right fix — I used to think the same thing and it turned out to be wrong for a few concrete reasons.

devDependencies + peerDependencies is one unit, not redundancy

For anything a plugin's own source imports, there are exactly two valid ways to declare it:

  1. dependencies — the plugin owns and ships the dependency; or
  2. peerDependencies + devDependencies — the host provides it at runtime (peer), and the plugin installs it locally so it can typecheck, lint and bundle (dev).

A devDependencies-only entry is the broken case: a consumer installing the plugin never gets devDeps, so nothing imported from source may live there alone. That's exactly why the template lists react, react-dom, styled-components, @strapi/design-system etc. twice — it's the correct pattern, not duplication to be cleaned up.

This PR removes the other half of the pair. A peerDependencies-only entry declares a contract with nothing installed to satisfy it locally, so strapi-plugin build and tsc inside the plugin can only resolve those imports by walking outside the package boundary — which is precisely what a package manifest exists to avoid.

Some packages end up declared nowhere at all

Worse than the split above: typescript, @strapi/typescript-utils, @types/react and @types/react-dom have no peerDependencies counterpart, so after this change they appear in no dependency field. The generated plugin still ships "test:ts:front": "run -T tsc -p admin/tsconfig.json" and a tsconfig that needs the React types, with nothing in the manifest that would ever install them. That's not a leaner manifest, it's an incomplete one.

The "they're already available in the root of the monorepo workspace" premise doesn't hold

A project generated by create-strapi is not a workspace, and src/plugins/* is not a workspace package — there is no hoisting contract to lean on. Some of these packages (react, react-dom, react-router-dom, styled-components, and typescript/@types/* in a TS project) do happen to be direct deps of a generated project, but others — @strapi/design-system, @strapi/icons, react-intl, @strapi/typescript-utils — are not; they resolve only because npm flattens them into the root node_modules as transitive deps of @strapi/admin. Consequences:

  • the version the plugin builds against is whatever the root or @strapi/admin happened to hoist, not the range the plugin still declares in peerDependencies;
  • it breaks under pnpm and Yarn PnP, which deliberately don't expose undeclared transitive deps;
  • it breaks the moment the plugin is moved out of src/plugins to be published — the documented graduation path for a local plugin, and the one case where a correct manifest matters most.

So the generated plugin would build "by accident" on npm, and not at all on stricter installers.

The size comes from the install, not from the manifest

sdk-plugin init doesn't run an install. The duplication appears when someone runs npm install inside src/plugins/my-plugin, where a non-workspace nested package necessarily duplicates its whole tree. Fixes that address that without weakening the manifest:

  • register the local plugin from the root — "my-plugin": "file:src/plugins/my-plugin" in the project's package.json, or declare src/plugins/* as a workspace — so a single root install covers it and no nested node_modules is ever created;
  • have init print that guidance (or add the file: entry itself) when isStrapiProject is true, instead of emitting a manifest that only resolves through hoisting luck.

That keeps the plugin self-contained and publishable while still giving the user the small install they're after.

Smaller notes

  • fix_test.patch looks like it was committed by accident.
  • The new test (should NOT put admin runtime deps in devDependencies for local plugins) locks in the inverted invariant, so it would make the correct behaviour look like a regression later.
  • This overlaps fix: omit @strapi devDependencies for local plugins #202 almost entirely — probably worth keeping only one.

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.

Strapi 5 local plugins : size has significantly increased

2 participants