Skip to content

Commit cf55e8a

Browse files
arbrandesclaude
andcommitted
feat: support npm workspaces for local development
Add workspaces configuration, turbo.json for build orchestration, and workspace-aware scripts for developing with local frontend apps and frontend-base. Also, since npm skips bin-linking for workspace packages during install, do it when frontend-base is built. Part of openedx/frontend-base#184 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 7dfd7d4 commit cf55e8a

6 files changed

Lines changed: 970 additions & 901 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ npm-debug.log
33
coverage
44
module.config.js
55
dist/
6+
packages/
67
/*.tgz
8+
/.turbo
79

810
### i18n ###
911
src/i18n/transifex_input.json

Makefile

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
TURBO = TURBO_TELEMETRY_DISABLED=1 turbo --dangerously-disable-package-manager-check
2+
3+
.PHONY: bin-link build-packages clean-packages clean dev-packages
4+
5+
# NPM doesn't bin-link workspace packages during install, so it must be done manually.
6+
bin-link:
7+
[ -f packages/frontend-base/package.json ] && npm rebuild --ignore-scripts @openedx/frontend-base || true
8+
9+
build-packages:
10+
$(TURBO) run build
11+
$(MAKE) bin-link
12+
13+
clean-packages:
14+
$(TURBO) run clean
15+
16+
dev-packages:
17+
$(TURBO) run watch:build dev:site
18+
19+
dev-site: bin-link
20+
npm run dev
21+
22+
clean:
23+
rm -rf dist

README.rst

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,77 @@ created when copying this template above.
5252
The dev server is running at `http://apps.local.openedx.io:8080 <http://apps.local.openedx.io:8080>`_
5353
or whatever port you setup.
5454

55+
Local Development with Workspaces
56+
==================================
57+
58+
This repository supports `npm workspaces`_ to enable local development of
59+
frontend apps (e.g., ``frontend-app-authn``, ``frontend-app-learner-dashboard``)
60+
and ``frontend-base`` itself, all running together in the context of a site.
61+
62+
The ``packages/`` directory (gitignored) holds local checkouts of packages being
63+
developed. These act as development-only overrides of the npm-published
64+
versions.
65+
66+
Since symlinks cause module resolution failures (Node.js resolves to the real
67+
path, breaking hoisted dependency resolution), local checkouts should either be
68+
made directly under ``packages/`` or made available via bind mounts (or volume
69+
mounts, if running under Docker). For example, if the checkouts are siblings
70+
of this repository::
71+
72+
mkdir -p packages/{frontend-base,frontend-app-authn,frontend-app-learner-dashboard}
73+
cd packages
74+
for i in *; do sudo mount --bind ../../${i} ${i}; done
75+
cd ..
76+
npm install
77+
78+
`bindfs`_ can be used instead of ``sudo mount --bind`` to avoid requiring root
79+
privileges.
80+
81+
.. _bindfs: https://bindfs.org/
82+
.. _npm workspaces: https://docs.npmjs.com/cli/using-npm/workspaces
83+
84+
Version Placeholders
85+
--------------------
86+
87+
The ``@openedx/`` packages use `semantic-release`_ and carry a placeholder
88+
version of ``0.0.0-dev`` in their ``package.json`` until they are published.
89+
Because npm resolves peer dependencies strictly, a workspace checkout at
90+
``0.0.0-dev`` will not satisfy a requirement like ``^1.0.0``. To work
91+
around this, each ``@openedx/`` dependency in the site's ``package.json``
92+
includes ``|| 0.0.0-dev`` — for example,
93+
``"@openedx/frontend-base": "^1.0.0 || 0.0.0-dev"``. If you add a new
94+
``@openedx/`` package that will be checked out as a workspace, make sure to
95+
include the same ``|| 0.0.0-dev`` suffix.
96+
97+
.. _semantic-release: https://github.com/semantic-release/semantic-release
98+
99+
Why Turborepo
100+
-------------
101+
102+
Workspace packages must be built in dependency order — for example,
103+
``frontend-base`` before apps that depend on it — but npm is not smart enough
104+
to do this on its own. `Turborepo`_ handles this automatically via
105+
``dependsOn: ["^build"]`` in ``turbo.json``, building the dependency graph and
106+
running tasks in the correct topological order.
107+
108+
It also enables watch mode without race conditions: the ``clean`` target is
109+
decoupled from ``build`` so that watch rebuilds overwrite in place without
110+
wiping ``dist/``.
111+
112+
Note that Turborepo collects anonymous telemetry by default. To disable it, set
113+
``TURBO_TELEMETRY_DISABLED=1`` in your environment.
114+
115+
.. _Turborepo: https://turbo.build/
116+
117+
Workspace Scripts
118+
-----------------
119+
120+
- ``npm run build:packages`` — Build all workspace packages in dependency order.
121+
- ``npm run clean:packages`` — Run the ``clean`` script in each workspace package.
122+
- ``npm run dev:packages`` — Watch-build all workspace packages and start the
123+
dev server, so that changes to any local dependency are picked up
124+
automatically.
125+
55126
Internationalization
56127
====================
57128

0 commit comments

Comments
 (0)