Modernize Djblets JavaScript setup.
Review Request #14646 — Created Oct. 23, 2025 and updated
This change makes a bunch of changes to modernize our JavaScript build
process across our products:Support npm workspaces
In order to better support development across our many repos and
packages, this dramatically improves the way we handle npm workspaces.We used to have a
djblets/package.jsonfile which defines our JavaScript
dependencies, and then a symbolic link from the repo root to make that
also available fornpm install. This change removes the symbolic link,
and adds a new top-levelpackage.jsonwhich defines workspaces as
djbletsand.npm-workspaces/*. This allows creating symbolic links
in the workspaces directory in order to bring in development copies of
spina, ink, beanbag-eslint-plugin, or whatever other JS dependencies one
desires.Depending on the package, this may require having a shared parent
directory and a symbolic link from../node_modulesto
./node_modules, since some things like to resolve to absolute paths
and then crawl up the directory tree (looking at you,tsc).Update and consolidate JS dependencies.
The actual dependencies listed in
djblets/package.jsonhave been
simplified, using the new@beanbag/js-buildkitmetapackage to ensure
build-time dependencies. We also no longer have an explicit dependency
on spina and backbone versions, preferring instead to just inherit
whichever versions we're getting from ink.Use modern invocation for static media builder utilities.
We were hard-coding the locations for
babel,lessc,rollup, and
uglifyjsbased onnode_modules/.bin. Because of the vagaries of npm
we can't necessarily assume that there's anode_modulesin the current
directory, or that things will be in.bin. I've changed these to use
npm exec ...instead, allowing npm to locate the binary and invoke it.Use terser instead of uglifyjs (opt-in).
UglifyJS lacks support for a lot of ES6+ features, and its cousin
UglifyES is unmaintained. I've changed our pipeline configuration to use
Terser instead, which is a fork of these which is actively maintained
and supports newer JS. The actual dependency for this will live in
@beanbag/frontend-buildkit.Some of our upstream dependencies already depend on terser, so this
reduces our dependency footprint as well.I was hoping we would be able to get sourcemaps for the fully-compressed
JS with this, but unfortunately the way that django-pipeline does
compressors won't allow for that.Use modern pipeline setup for static media during tests.
Unit tests had their own pipeline configuration for some reason, which
didn't even include any of the rollup files. This has been replaced with
a call to the samebuild_pipeline_settingsthat we use everywhere
else.Pulled in backbone types.
I'm working on upstreaming our changes and improvements to the type
definitions for Backbone, but in the meantime we can't just reference
the file fromnode_modulesthe way we did before. This has been copied
into the Djblets tree for the time being.Updated to ESLint 9.
With the newer
@beanbag/eslint-pluginbundled in
@beanbag/js-buildkit, we now use ESLint 9.Simplify browserslist.
I've changed the browserslist config to exist inside the top-level
package.json and just specifybaseline widely available. This mirrors
what we have in Review Board (though RB also has that in our shareable
babel config).
- Set up Djblets into an environment that used npm workspaces to include
Djblets, Review Board, @beanbag/frontend-buildkit, @beanbag/js-buildkit,
@beanbag/jasmine-suites, and @beanbag/eslint-plugin. - Ran unit tests.
- Ran eslint.
- Built static media.
- Built the rbintegrations extension to verify that static media
building still worked for that.
| Summary | ID |
|---|---|
| nqrtxwxorzwwvlnlzqmtnpuouvxxmzww |
| Description | From | Last Updated |
|---|---|---|
|
"djblets" -> "Djblets" in the summary/description/testing. Also, the node_modules and some other references in the description should probably be code … |
|
|
|
This is targeting 5.x, but has breaking changes. Notably the npm_dependencies changes would break Review Board 7.0. Those would need … |
|
|
|
I'd like to keep r as explicit for all file operations, so it's always clear. I don't like the usage … |
|
|
|
5.3. |
|
|
|
In others, we list NotRequired below required. |
|
|
|
5.3. |
|
|
|
Blank line before return. |
|
|
|
Can we quote the path? |
|
|
|
Some people have a node_modules in $HOME. What's the risk of impact here? It may also be worth adding comments … |
|
|
|
This file should have a module docstring and a Version Added. |
|
- Description:
-
This change makes a bunch of changes to modernize our JavaScript build
process across our products: Support npm workspaces
In order to better support development across our many repos and
packages, this dramatically improves the way we handle npm workspaces. We used to have a djblets/package.json file which defines our JavaScript
dependencies, and then a symbolic link from the repo root to make that also available for npm install. This change removes the symbolic link,and adds a new top-level package.jsonwhich defines workspaces asdjbletsand.npm-workspaces/*. This allows creating symbolic linksin the workspaces directory in order to bring in development copies of spina, ink, beanbag-eslint-plugin, or whatever other JS dependencies one desires. Depending on the package, this may require having a shared parent
directory and a symbolic link from ../node_modules to ./node_modules, since some things like to resolve to absolute paths and then crawl up the directory tree (looking at you, tsc).Update and consolidate JS dependencies.
The actual dependencies listed in djblets/package.json have been
simplified, using the new @beanbag/js-buildkitmetapackage to ensurebuild-time dependencies. We also no longer have an explicit dependency on spina and backbone versions, preferring instead to just inherit whichever versions we're getting from ink. ~ Remove
npm_dependenciesandbuild-npm-dependencies.py~ Remove
npm_dependenciesandbuild-npm-deps.pyIt used to be that all our JS dependencies were specified inside
djblets/dependencies.pyand then we would write out apackage.jsonfile on demand. A while back we inverted that so that package.jsonwasthe authoritative list, and we would auto-generate python code back into dependencies.py. However, none of that stuff was actually consumedanywhere other than from within Review Board (which does the same thing). I've removed the
build-npm-deps.pyscript and the associated blockinside djblets/dependencies.py.Use modern invocation for static media builder utilities.
We were hard-coding the locations for
babel,lessc,rollup, anduglifyjsbased onnode_modules/.bin. Because of the vagaries of npmwe can't necessarily assume that there's a node_modulesin the currentdirectory, or that things will be in .bin. I've changed these to usenpm exec ...instead, allowing npm to locate the binary and invoke it.Use terser instead of uglifyjs.
UglifyJS lacks support for a lot of ES6+ features, and its cousin
UglifyES is unmaintained. I've changed our pipeline configuration to use Terser instead, which is a fork of these which is actively maintained and supports newer JS. The actual dependency for this will live in @beanbag/frontend-buildkit. Some of our upstream dependencies already depend on terser, so this
reduces our dependency footprint as well. I was hoping we would be able to get sourcemaps for the fully-compressed
JS with this, but unfortunately the way that django-pipeline does compressors won't allow for that. Use modern pipeline setup for static media during tests.
Unit tests had their own pipeline configuration for some reason, which
didn't even include any of the rollup files. This has been replaced with a call to the same build_pipeline_settingsthat we use everywhereelse. Pulled in backbone types.
I'm working on upstreaming our changes and improvements to the type
definitions for Backbone, but in the meantime we can't just reference the file from node_modules the way we did before. This has been copied into the djblets tree for the time being. Updated to ESLint 9.
With the newer
@beanbag/eslint-pluginbundled in@beanbag/js-buildkit, we now use ESLint 9. - Commits:
-
Summary ID nqrtxwxorzwwvlnlzqmtnpuouvxxmzww nqrtxwxorzwwvlnlzqmtnpuouvxxmzww
Checks run (2 succeeded)
- Change Summary:
-
- Update eslint config for new plugin.
- Add a script entry so we can do
npm run lint. - Fix json syntax in djblets/package.json.
- Commits:
-
Summary ID nqrtxwxorzwwvlnlzqmtnpuouvxxmzww nqrtxwxorzwwvlnlzqmtnpuouvxxmzww
Checks run (2 succeeded)
- Change Summary:
-
Simplify browserslist (similar to what I've done in the RB codebase).
- Description:
-
This change makes a bunch of changes to modernize our JavaScript build
process across our products: Support npm workspaces
In order to better support development across our many repos and
packages, this dramatically improves the way we handle npm workspaces. We used to have a djblets/package.json file which defines our JavaScript
dependencies, and then a symbolic link from the repo root to make that also available for npm install. This change removes the symbolic link,and adds a new top-level package.jsonwhich defines workspaces asdjbletsand.npm-workspaces/*. This allows creating symbolic linksin the workspaces directory in order to bring in development copies of spina, ink, beanbag-eslint-plugin, or whatever other JS dependencies one desires. Depending on the package, this may require having a shared parent
directory and a symbolic link from ../node_modules to ./node_modules, since some things like to resolve to absolute paths and then crawl up the directory tree (looking at you, tsc).Update and consolidate JS dependencies.
The actual dependencies listed in djblets/package.json have been
simplified, using the new @beanbag/js-buildkitmetapackage to ensurebuild-time dependencies. We also no longer have an explicit dependency on spina and backbone versions, preferring instead to just inherit whichever versions we're getting from ink. Remove
npm_dependenciesandbuild-npm-deps.pyIt used to be that all our JS dependencies were specified inside
djblets/dependencies.pyand then we would write out apackage.jsonfile on demand. A while back we inverted that so that package.jsonwasthe authoritative list, and we would auto-generate python code back into dependencies.py. However, none of that stuff was actually consumedanywhere other than from within Review Board (which does the same thing). I've removed the
build-npm-deps.pyscript and the associated blockinside djblets/dependencies.py.Use modern invocation for static media builder utilities.
We were hard-coding the locations for
babel,lessc,rollup, anduglifyjsbased onnode_modules/.bin. Because of the vagaries of npmwe can't necessarily assume that there's a node_modulesin the currentdirectory, or that things will be in .bin. I've changed these to usenpm exec ...instead, allowing npm to locate the binary and invoke it.Use terser instead of uglifyjs.
UglifyJS lacks support for a lot of ES6+ features, and its cousin
UglifyES is unmaintained. I've changed our pipeline configuration to use Terser instead, which is a fork of these which is actively maintained and supports newer JS. The actual dependency for this will live in @beanbag/frontend-buildkit. Some of our upstream dependencies already depend on terser, so this
reduces our dependency footprint as well. I was hoping we would be able to get sourcemaps for the fully-compressed
JS with this, but unfortunately the way that django-pipeline does compressors won't allow for that. Use modern pipeline setup for static media during tests.
Unit tests had their own pipeline configuration for some reason, which
didn't even include any of the rollup files. This has been replaced with a call to the same build_pipeline_settingsthat we use everywhereelse. Pulled in backbone types.
I'm working on upstreaming our changes and improvements to the type
definitions for Backbone, but in the meantime we can't just reference the file from node_modules the way we did before. This has been copied into the djblets tree for the time being. Updated to ESLint 9.
With the newer
@beanbag/eslint-pluginbundled in@beanbag/js-buildkit, we now use ESLint 9.+ + + + Simplify browserslist.
+ + I've changed the browserslist config to exist inside the top-level
+ package.json and just specify baseline widely available. This mirrors+ what we have in Review Board (though RB also has that in our shareable + babel config). - Commits:
-
Summary ID nqrtxwxorzwwvlnlzqmtnpuouvxxmzww nqrtxwxorzwwvlnlzqmtnpuouvxxmzww - Diff:
-
Revision 4 (+2086 -716)
Checks run (2 succeeded)
-
-
"djblets" -> "Djblets" in the summary/description/testing.
Also, the
node_modulesand some other references in the description should probably be code literals. -
This is targeting 5.x, but has breaking changes. Notably the
npm_dependencieschanges would break Review Board 7.0. Those would need to be moved to a 6.0. -
I'd like to keep
ras explicit for all file operations, so it's always clear. I don't like the usage of the default for something as important as file I/O. -
-
-
-
-
-
Some people have a
node_modulesin$HOME. What's the risk of impact here?It may also be worth adding comments above this code block to state what's going on and the implications.
-
- Summary:
-
Modernize djblets JavaScript setup.Modernize Djblets JavaScript setup.
- Description:
-
This change makes a bunch of changes to modernize our JavaScript build
process across our products: Support npm workspaces
In order to better support development across our many repos and
packages, this dramatically improves the way we handle npm workspaces. ~ We used to have a djblets/package.json file which defines our JavaScript
~ We used to have a
djblets/package.jsonfile which defines our JavaScriptdependencies, and then a symbolic link from the repo root to make that also available for npm install. This change removes the symbolic link,and adds a new top-level package.jsonwhich defines workspaces asdjbletsand.npm-workspaces/*. This allows creating symbolic linksin the workspaces directory in order to bring in development copies of spina, ink, beanbag-eslint-plugin, or whatever other JS dependencies one desires. Depending on the package, this may require having a shared parent
~ directory and a symbolic link from ../node_modules to ./node_modules, ~ since some things like to resolve to absolute paths and then crawl up ~ the directory tree (looking at you, tsc).~ directory and a symbolic link from ../node_modulesto~ ./node_modules, since some things like to resolve to absolute paths~ and then crawl up the directory tree (looking at you, tsc).Update and consolidate JS dependencies.
~ The actual dependencies listed in djblets/package.json have been
~ The actual dependencies listed in
djblets/package.jsonhave beensimplified, using the new @beanbag/js-buildkitmetapackage to ensurebuild-time dependencies. We also no longer have an explicit dependency on spina and backbone versions, preferring instead to just inherit whichever versions we're getting from ink. Remove
npm_dependenciesandbuild-npm-deps.pyIt used to be that all our JS dependencies were specified inside
djblets/dependencies.pyand then we would write out apackage.jsonfile on demand. A while back we inverted that so that package.jsonwasthe authoritative list, and we would auto-generate python code back into dependencies.py. However, none of that stuff was actually consumedanywhere other than from within Review Board (which does the same thing). I've removed the
build-npm-deps.pyscript and the associated blockinside djblets/dependencies.py.Use modern invocation for static media builder utilities.
We were hard-coding the locations for
babel,lessc,rollup, anduglifyjsbased onnode_modules/.bin. Because of the vagaries of npmwe can't necessarily assume that there's a node_modulesin the currentdirectory, or that things will be in .bin. I've changed these to usenpm exec ...instead, allowing npm to locate the binary and invoke it.Use terser instead of uglifyjs.
UglifyJS lacks support for a lot of ES6+ features, and its cousin
UglifyES is unmaintained. I've changed our pipeline configuration to use Terser instead, which is a fork of these which is actively maintained and supports newer JS. The actual dependency for this will live in @beanbag/frontend-buildkit. Some of our upstream dependencies already depend on terser, so this
reduces our dependency footprint as well. I was hoping we would be able to get sourcemaps for the fully-compressed
JS with this, but unfortunately the way that django-pipeline does compressors won't allow for that. Use modern pipeline setup for static media during tests.
Unit tests had their own pipeline configuration for some reason, which
didn't even include any of the rollup files. This has been replaced with a call to the same build_pipeline_settingsthat we use everywhereelse. Pulled in backbone types.
I'm working on upstreaming our changes and improvements to the type
definitions for Backbone, but in the meantime we can't just reference ~ the file from node_modules the way we did before. This has been copied ~ into the djblets tree for the time being. ~ the file from node_modulesthe way we did before. This has been copied~ into the Djblets tree for the time being. Updated to ESLint 9.
With the newer
@beanbag/eslint-pluginbundled in@beanbag/js-buildkit, we now use ESLint 9.Simplify browserslist.
I've changed the browserslist config to exist inside the top-level
package.json and just specify baseline widely available. This mirrorswhat we have in Review Board (though RB also has that in our shareable babel config). - Testing Done:
-
~ - Set up djblets into an environment that used npm workspaces to include
djblets, reviewboard, @beanbag/frontend-buildkit, @beanbag/js-buildkit,
@beanbag/jasmine-suites, and @beanbag/eslint-plugin.
~ - Set up Djblets into an environment that used npm workspaces to include
Djblets, Review Board, @beanbag/frontend-buildkit, @beanbag/js-buildkit,
@beanbag/jasmine-suites, and @beanbag/eslint-plugin.
- Ran unit tests.
- Ran eslint.
- Built static media.
- Built the rbintegrations extension to verify that static media
building still worked for that.
- Set up djblets into an environment that used npm workspaces to include
- Commits:
-
Summary ID nqrtxwxorzwwvlnlzqmtnpuouvxxmzww nqrtxwxorzwwvlnlzqmtnpuouvxxmzww - Diff:
-
Revision 5 (+2110 -716)
Checks run (2 succeeded)
- Change Summary:
-
- Add build-npm-deps back in and fix it up a bit.
- Make terser opt-in with a deprecation warning if it's not opted into.
- Description:
-
This change makes a bunch of changes to modernize our JavaScript build
process across our products: Support npm workspaces
In order to better support development across our many repos and
packages, this dramatically improves the way we handle npm workspaces. We used to have a
djblets/package.jsonfile which defines our JavaScriptdependencies, and then a symbolic link from the repo root to make that also available for npm install. This change removes the symbolic link,and adds a new top-level package.jsonwhich defines workspaces asdjbletsand.npm-workspaces/*. This allows creating symbolic linksin the workspaces directory in order to bring in development copies of spina, ink, beanbag-eslint-plugin, or whatever other JS dependencies one desires. Depending on the package, this may require having a shared parent
directory and a symbolic link from ../node_modulesto./node_modules, since some things like to resolve to absolute pathsand then crawl up the directory tree (looking at you, tsc).Update and consolidate JS dependencies.
The actual dependencies listed in
djblets/package.jsonhave beensimplified, using the new @beanbag/js-buildkitmetapackage to ensurebuild-time dependencies. We also no longer have an explicit dependency on spina and backbone versions, preferring instead to just inherit whichever versions we're getting from ink. - Remove
npm_dependenciesandbuild-npm-deps.py- - It used to be that all our JS dependencies were specified inside
- djblets/dependencies.pyand then we would write out apackage.json- file on demand. A while back we inverted that so that package.jsonwas- the authoritative list, and we would auto-generate python code back into - dependencies.py. However, none of that stuff was actually consumed- anywhere other than from within Review Board (which does the same - thing). - - I've removed the
build-npm-deps.pyscript and the associated block- inside djblets/dependencies.py.- - - Use modern invocation for static media builder utilities.
We were hard-coding the locations for
babel,lessc,rollup, anduglifyjsbased onnode_modules/.bin. Because of the vagaries of npmwe can't necessarily assume that there's a node_modulesin the currentdirectory, or that things will be in .bin. I've changed these to usenpm exec ...instead, allowing npm to locate the binary and invoke it.~ Use terser instead of uglifyjs.
~ Use terser instead of uglifyjs (opt-in).
UglifyJS lacks support for a lot of ES6+ features, and its cousin
UglifyES is unmaintained. I've changed our pipeline configuration to use Terser instead, which is a fork of these which is actively maintained and supports newer JS. The actual dependency for this will live in @beanbag/frontend-buildkit. Some of our upstream dependencies already depend on terser, so this
reduces our dependency footprint as well. I was hoping we would be able to get sourcemaps for the fully-compressed
JS with this, but unfortunately the way that django-pipeline does compressors won't allow for that. Use modern pipeline setup for static media during tests.
Unit tests had their own pipeline configuration for some reason, which
didn't even include any of the rollup files. This has been replaced with a call to the same build_pipeline_settingsthat we use everywhereelse. Pulled in backbone types.
I'm working on upstreaming our changes and improvements to the type
definitions for Backbone, but in the meantime we can't just reference the file from node_modulesthe way we did before. This has been copiedinto the Djblets tree for the time being. Updated to ESLint 9.
With the newer
@beanbag/eslint-pluginbundled in@beanbag/js-buildkit, we now use ESLint 9.Simplify browserslist.
I've changed the browserslist config to exist inside the top-level
package.json and just specify baseline widely available. This mirrorswhat we have in Review Board (though RB also has that in our shareable babel config). - Commits:
-
Summary ID nqrtxwxorzwwvlnlzqmtnpuouvxxmzww nqrtxwxorzwwvlnlzqmtnpuouvxxmzww - Diff:
-
Revision 6 (+2306 -468)