Skip to content

Conversation

@max-moser
Copy link
Contributor

@max-moser max-moser commented Mar 1, 2025

Information (updated 2025-03-28)

This PR is the frontend cousin of #384 (which similarly enabled uv for python).

Enabling pnpm

Note: This feature requires flask-webpackext v2.1.0, and a recent (global) installation of the CLI command pnpm (10+) ⚠️

Similar to uv, pnpm can be enabled in .invenio (which is the "public" configuration file that is intended to be shared between developers via version control).
Unlike uv, there are (currently [1]) no artifacts in the project directory that would indicate whether npm or pnpm should be used and thus the fallback is simply npm (i.e. pnpm has to be explicitly configured).

Configuration in .invenio:

[cli]
flavour = RDM
logfile = /logs/invenio-cli.log
javascript_package_manager = pnpm

[1] this may change once the "reusable frontend lock file" logic gets merged as:

  • package.lock -> npm
  • pnpm-lock.yaml -> pnpm

Enabling rspack

Note: This feature requires invenio-assets v4.1.0 (or v3.2.0 for InvenioRDM v12) ⚠️

invenio.cfg:

# somewhere in the file...
WEBPACKEXT_PROJECT = "invenio_assets.webpack:rspack_project"

Like any other configuration item, it could alternatively be specified as an env var with prefix (INVENIO_WEBPACKEXT_PROJECT="invenio_assets.webpack:rspack_project"), but this is out of scope for here – iykyk.

Why aren't pnpm and rspack both configured in invenio.cfg?

While it may seem strange that rspack uses a different configuration mechanism (invenio.cfg) than pnpm (.invenio), the reason here is simple:

  1. The frontend build project was already previously configurable via a configuration item (old default: WEBPACKEXT_PROJECT = "invenio_assets.webpack:project") that could for instance be configured via invenio.cfg.
  2. The pnpm switch did not exist previously, and both invenio-cli as well as invenio (the application) have to agree on which JS package manager is used (and invenio-cli does not parse invenio.cfg itself).

What's with react-invenio-forms and pnpm?

The link-dist script in Invenio-y JS packages is geared towards npm link and thus obviously won't work nicely for pnpm.
(Also, requiring these nonstandard script entries means that only these Invenio-y JS packages are compatible.)
This should likely be reworked in these JS packages, but that's a bit too much effort for now.

For now, we've decided to simply write the pnpm logic to perform basically the same steps as npm would, except for the actual linking step (which only requires a single step with pnpm).
For those interested, I recommend searching the comments mentioning prepostlink-dist and others.

More context (for historical reasons)

Second part of #383 – support for pnpm and rspack

This PR won't work as standalone, it still requires changes to core Invenio packages.
Either inveniosoftware/invenio-assets#176
Or inveniosoftware/invenio-assets#172, inveniosoftware/flask-webpackext#26, inveniosoftware/pywebpack#47
Depending on the choice, some tweaks need to be performed in this PR here.

Also, npm is still hard-coded in React-Invenio-Forms which needs to be addressed.
Edit: This has been resolved, see above.

@max-moser max-moser force-pushed the mm/pnpm-and-rspack branch from c6ff314 to 187dfa2 Compare March 1, 2025 00:22
response = run_interactive(
op, env={"PIPENV_VERBOSITY": "-1"}, log_file=log_file
op,
env={"PIPENV_VERBOSITY": "-1", **js_pkg_man.env_overrides()},
Copy link
Contributor Author

Choose a reason for hiding this comment

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

here we tell invenio about the JS package manager that we want to use, via environment variables

Comment on lines +89 to +97
ops = [py_pkg_man.run_command("invenio", "collect", "--verbose")]

if force:
ops.append(pkg_man.run_command("invenio", "webpack", "clean", "create"))
ops.append(pkg_man.run_command("invenio", "webpack", "install"))
ops.append(py_pkg_man.run_command("invenio", "webpack", "clean", "create"))
ops.append(py_pkg_man.run_command("invenio", "webpack", "install"))
else:
ops.append(pkg_man.run_command("invenio", "webpack", "create"))
ops.append(py_pkg_man.run_command("invenio", "webpack", "create"))
ops.append(self._statics)
ops.append(pkg_man.run_command("invenio", "webpack", "build"))
ops.append(py_pkg_man.run_command("invenio", "webpack", "build"))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

there is still a good amount of optimization potential by calling the invenio command only once and thus saving all the redundant application initializations which eat up a lot of time.
one way to move forward is to implement a single larger command (e.g. in invenio-app-rdm) that performs all the steps currently implemented here, based on the provided CLI args.
@ntarocco has pointed out to me that something very much like that has already been done in Invenio-App-ILS

Copy link
Contributor

Choose a reason for hiding this comment

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

an option would be to use a rpc-server implementation. a WIP would be here for invenio-cli combined with PR from invenio-app

@max-moser max-moser force-pushed the mm/pnpm-and-rspack branch 4 times, most recently from 62a7f3a to 0ee5d67 Compare March 6, 2025 15:33
Comment on lines +360 to +362
AssetsFunction(_prelink_dist, "Executing prelink-dist script..."),
AssetsFunction(_link_package_single_step, "Linking module to assets..."),
AssetsFunction(_postlink_dist, "Executing postlink-dist script..."),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

3 is better than 1!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

as discussed, we're basically executing the same scripts with pnpm as we did with npm, except for the part where the actual linking happens (which is more sane with pnpm.

since we don't have preprelink-dist, postprelink-dist, prepostlink-dist and postpostlink-dist scripts defined in our packages i think we should be executing the same set of scripts as before here.

# This is geared towards Invenio JS packages...
# But so are all the other steps
status_code = assets_pkg.link(
str(module_pkg.package_json_path.parent / "dist")
Copy link
Contributor Author

Choose a reason for hiding this comment

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

the fact that we're linking against the "dist" directory and not using the scripts requires some knowledge about the target package... but so does executing the link-dist script, which is not exactly a standard AFAIK 😅

class AssetsFunction:
"""Function to run an assets command with `assets_pkg` and `module_pkg`."""

function: Callable[[NPMPackage, NPMPackage], ProcessResponse]
Copy link
Contributor Author

@max-moser max-moser Mar 6, 2025

Choose a reason for hiding this comment

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

the dataclass wants to have some type annotation, but Callable should do the trick already.
i have no strong attachment to this type hint otherwise.

@max-moser max-moser marked this pull request as ready for review March 27, 2025 14:14
@max-moser max-moser force-pushed the mm/pnpm-and-rspack branch from 0ee5d67 to 64964fe Compare March 28, 2025 08:58
utnapischtim and others added 3 commits March 28, 2025 22:26
* bump pynpm dependency for the PNPMPackage
* tell invenio about which JS package manager is actually selected
  currently (npm or pnpm), via the new `WEBPACKEXT_NPM_PKG_CLS` config
* also, use the module_pkg to execute the install command in the target
  path (rather than the instance's path, which made a difference in the
  case of pnpm)
* as discussed, we implement the `pnpm link` to basically do the same
  thing as the current `npm link` procedure, to not require any changes
  in JS packages
@max-moser max-moser force-pushed the mm/pnpm-and-rspack branch from 64964fe to 0a695af Compare March 28, 2025 21:29
@max-moser max-moser changed the title Enable PNPM and rspack Enable PNPM ~~(and rspack)~~ Mar 28, 2025
@max-moser max-moser changed the title Enable PNPM ~~(and rspack)~~ Enable PNPM (rspack is part of Invenio-Assets) Mar 28, 2025
@max-moser
Copy link
Contributor Author

Once again (like with the PRs for Flask-WebpackExt & Invenio-Assets), we've discussed this feature and its implementation during the InvenioRDM community workshop 2025 etc. so the lack of official approval shouldn't indicate my rebellion here.

@max-moser max-moser merged commit 72626c5 into inveniosoftware:master Mar 28, 2025
2 checks passed
@max-moser max-moser deleted the mm/pnpm-and-rspack branch March 28, 2025 22:09
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.

3 participants