Move prosemirror-view to peerDependencies #28

Closed
ocavue wants to merge 1 commit from ocavue/rm-view-dep into master
ocavue commented 2026-03-07 04:56:53 +01:00 (Migrated from github.com)

Currently, prosemirror-view depends on prosemirror-state, and prosemirror-state also depends on prosemirror-view. This causes a circular dependency.

CleanShot 2026-03-07 at 14 58 15@2x

⬆️ Image from https://npmgraph.js.org/?q=prosemirror-view@1.41.6

prosemirror-state doesn't actually need prosemirror-view for runtime JS (see prosemirror-state/dist/index.js); it only needs prosemirror-view for some types (see prosemirror-state/dist/index.d.ts).

This situation is mostly okay but still has subtle differences. For example, if I want to use prosemirror-state and prosemirror-model to apply some updates on the Node.js server side, npm would still install prosemirror-view in the node_modules, although I don't need it at all.

This PR improves it by moving prosemirror-view from dependencies to peerDependencies. peerDependencies is still needed so that TypeScript can find the required type during development for type checking.

I also tweaked the source TypeScript code a bit by using import type {...} from "..." instead of import {type ...} from "...". This adds an extra assurance that we don't import prosemirror-view in the runtime JS code, even if verbatimModuleSyntax is enabled.

TypeScript 5.0 introduces a new option called --verbatimModuleSyntax to simplify the situation. The rules are much simpler - any imports or exports without a type modifier are left around. Anything that uses the type modifier is dropped entirely.

// Erased away entirely.
import type { A } from "a";
// Rewritten to 'import { b } from "bcd";'
import { b, type c, type d } from "bcd";
// Rewritten to 'import {} from "xyz";'
import { type xyz } from "xyz";
Currently, `prosemirror-view` depends on `prosemirror-state`, and `prosemirror-state` also depends on `prosemirror-view`. This causes a circular dependency. <img width="1688" height="366" alt="CleanShot 2026-03-07 at 14 58 15@2x" src="https://github.com/user-attachments/assets/3ade84bd-f35a-4231-ae02-05b8587cd88e" /> > ⬆️ Image from https://npmgraph.js.org/?q=prosemirror-view@1.41.6 `prosemirror-state` doesn't actually need `prosemirror-view` for runtime JS (see [prosemirror-state/dist/index.js](https://unpkg.com/prosemirror-state@1.4.4/dist/index.js)); it only needs `prosemirror-view` for some types (see [prosemirror-state/dist/index.d.ts](https://unpkg.com/prosemirror-state@1.4.4/dist/index.d.ts)). This situation is mostly okay but still has subtle differences. For example, if I want to use `prosemirror-state` and `prosemirror-model` to apply some updates on the Node.js server side, `npm` would still install `prosemirror-view` in the `node_modules`, although I don't need it at all. This PR improves it by moving `prosemirror-view` from `dependencies` to `peerDependencies`. `peerDependencies` is still needed so that TypeScript can find the required type during development for type checking. I also tweaked the source TypeScript code a bit by using `import type {...} from "..."` instead of `import {type ...} from "..."`. This adds an extra assurance that we don't import `prosemirror-view` in the runtime JS code, even if [`verbatimModuleSyntax`](https://www.typescriptlang.org/tsconfig/#verbatimModuleSyntax) is enabled. > TypeScript 5.0 introduces a new option called `--verbatimModuleSyntax` to simplify the situation. The rules are much simpler - any imports or exports without a `type` modifier are left around. Anything that uses the `type` modifier is dropped entirely. > > ```ts > // Erased away entirely. > import type { A } from "a"; > // Rewritten to 'import { b } from "bcd";' > import { b, type c, type d } from "bcd"; > // Rewritten to 'import {} from "xyz";' > import { type xyz } from "xyz"; > ```
marijnh commented 2026-03-07 09:24:41 +01:00 (Migrated from github.com)

My experience with peerDependencies is that different packaging tools (and different versions of packaging tools) handle it in weird, unreliable ways. Installing an extra package in a situation where you don't really need it doesn't seem like a big enough problem to open that can of worms again. And also, when you're using TypeScript in the depending package, you'll really want prosemirror-view installed or TypeScript will fail to typecheck the prosemirror-state declaration files.

As such, I don't think this is a good idea.

My experience with `peerDependencies` is that different packaging tools (and different versions of packaging tools) handle it in weird, unreliable ways. Installing an extra package in a situation where you don't really need it doesn't seem like a big enough problem to open that can of worms again. And also, when you're using TypeScript in the depending package, you'll really want prosemirror-view installed or TypeScript will fail to typecheck the prosemirror-state declaration files. As such, I don't think this is a good idea.
ocavue commented 2026-03-07 09:39:48 +01:00 (Migrated from github.com)

different packaging tools (and different versions of packaging tools) handle it in weird, unreliable ways.

That's true, and that's why I added peerDependenciesMeta so that it can be truly a peer dependency. See the following npm docs as an example. All other modern package managers (i.e., excluding Yarn v1) are using the same behavior now, AFAIK.

In npm versions 3 through 6, peerDependencies were not automatically installed, and would raise a warning if an invalid version of the peer dependency was found in the tree. As of npm v7, peerDependencies are installed by default.


that can of worms

o(≧▽≦)o


As such, I don't think this is a good idea.

Fair enough. It's a little embarrassing that we have a circular dependency here, but I can live with it. Thanks for your fast reply! Going to close this.

> different packaging tools (and different versions of packaging tools) handle it in weird, unreliable ways. That's true, and that's why I added `peerDependenciesMeta` so that it can be _truly_ a peer dependency. See the following [npm docs](https://docs.npmjs.com/cli/v11/configuring-npm/package-json#peerdependencies) as an example. All other modern package managers (i.e., excluding Yarn v1) are using the same behavior now, AFAIK. > In `npm` versions 3 through 6, `peerDependencies` were not automatically installed, and would raise a warning if an invalid version of the peer dependency was found in the tree. As of `npm` v7, `peerDependencies` are installed by default. --- > that can of worms o(≧▽≦)o --- > As such, I don't think this is a good idea. Fair enough. It's a little embarrassing that we have a circular dependency here, but I can live with it. Thanks for your fast reply! Going to close this.

Pull request closed

Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
prosemirror/prosemirror-state!28
No description provided.