Skip to content

Commit 7762d62

Browse files
Re-organize and upgrade NPM dependencies (#5021)
### Motivation There are several problems with the existing dependency management via npm.json and npm.py. **No control over importmap key** Example: Newer Three.js versions come with three.module.js which points to three.core.js. We can declare both files as a dependency, but they use the same key "three" in the importmap. A similar problem came up in #4163. **"Manual" code modifications needed** If a file like three.module.js references `./three.core.js`, we have to replace the relative link because the file three.core.js isn't found at this relative URL. Similarly there is an import of `../utils/BufferGeometryUtils.js` in Three.js' GLTFLoader which we need to replace with `BufferGeometryUtils`. These corrections happen in npm.py. **Complex dependencies hard or impossible to integrate** There is an extra script at scripts/codemirror/bundle.bash to integrate CodeMirror. And we wanted to integrate ajv-formats for `ui.json_editor` (https://cdn.jsdelivr.net/npm/[email protected]/+esm), but it includes references to e.g. "/npm/[email protected]/+esm" which don't work in a local NiceGUI app (see #4749). ### Implementation For this PR I decided to move modules with dependencies into separate directories (e.g. nicegui/elements/scene/) instead of holding all dependencies in one giant lib/ directory. This includes codemirror, scene, aggrid, joystick, json_editor, plotly, echarts, leaflet and mermaid. Each of these subdirectories contains an independent package.json, bundler configuration (rollup or vite), src/ directory with an index.js, a Git-ignored node-modules/ directory, and a generated dist/ directory with the resulting (sometimes chunked) bundle. This way we can configure the build individually for each UI element and don't have to find a one-fits-all solution. Furthermore, we can rely on standard NPM tools without the need for our own custom JSON format and Python scripts for downloading and extracting packages. Now the build process is 1. `npm install` and 2. `npm run build`. For registering the module in NiceGUI, I introduced a new `esm` parameter when subclassing an `Element`, e.g.: ```py class JsonEditor(Element, component='json_editor.js', esm={'nicegui-json-editor': 'dist'}): ... ``` This defines an entry to the importmap named "nicegui-json-editor" pointing to the relative directory dist/. This replaces the definition of individual `dependencies=[...]`, which we will probably deprecate. ### Progress The PR is still work in progress. The change has quite some implications that still need to be implemented. - [x] I chose a meaningful title that completes the sentence: "If applied, this PR will..." - [x] The implementation is complete. - [x] remove deprecated parameters from `Element.__init_subclass__` - [x] create custom package.jsons per UI element - [x] create package.json for NiceGUI's core dependencies (Vue, Quasar, Tailwind) - [x] remove npm.json/npm.py - [x] update examples for custom components (number_checker, signature_pad) - [x] update gitattributes - [x] generate DEPENDENCIES.md? - [x] what about minification and maps? - [x] Pytests are not necessary. - [x] Documentation has been updated.
1 parent 1536d95 commit 7762d62

File tree

677 files changed

+143227
-404024
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

677 files changed

+143227
-404024
lines changed

.gitattributes

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
nicegui/elements/tailwind.py linguist-generated
22
nicegui/elements/tailwind_types/** linguist-generated
3-
nicegui/elements/lib/** linguist-vendored
4-
nicegui/scripts/codemirror/*.json linguist-vendored
5-
nicegui/scripts/codemirror/node_modules linguist-vendored
3+
nicegui/elements/*/dist/** linguist-vendored
64
nicegui/static/es-module-shims.js linguist-vendored
75
nicegui/static/fonts/** linguist-vendored
86
nicegui/static/fonts.css linguist-vendored
@@ -16,3 +14,4 @@ website/** linguist-documentation
1614
website/static/fuse.js@* linguist-vendored
1715
examples/** linguist-documentation
1816
examples/fullcalendar/lib/** linguist-vendored
17+
**/package-lock.json linguist-vendored

.gitignore

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
__pycache__/
22
*.egg-info/
33
.*.swp
4-
dist
54
/test.py
65
*.pickle
76
screenshots/
@@ -12,4 +11,3 @@ venv
1211
.DS_Store
1312
.env
1413
node_modules/
15-
package-lock.json

.pre-commit-config.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
default_language_version:
22
python: python3.9
33
default_install_hook_types: [pre-commit, pre-push]
4-
default_stages: [commit]
4+
default_stages: [pre-commit]
55

66
repos:
77
- repo: https://github.com/astral-sh/ruff-pre-commit
@@ -15,7 +15,6 @@ repos:
1515
- id: trailing-whitespace
1616
exclude: &exclusions |
1717
(?x)^(
18-
nicegui/elements/lib/.*|
1918
nicegui/static/es-module-shims\.js|
2019
nicegui/static/fonts/.*|
2120
nicegui/static/fonts\.css|
@@ -25,7 +24,8 @@ repos:
2524
nicegui/static/tailwindcss\..*|
2625
nicegui/static/vue\..*|
2726
website/static/fuse\.js\@.*|
28-
examples/fullcalendar/lib/.*
27+
examples/fullcalendar/lib/.*|
28+
.*\.js\.map
2929
)$
3030
- id: end-of-file-fixer
3131
exclude: *exclusions

CONTRIBUTING.md

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -228,28 +228,27 @@ The title should match the example folder name when [snake case converted](https
228228

229229
## Node dependencies
230230

231-
We use [npm.json](https://github.com/zauberzeug/nicegui/blob/main/npm.json) to pin the versions of the node dependencies.
231+
We use package.json files to pin the versions of node dependencies.
232+
There is a `package.json` file in the root directory for core dependencies
233+
and additional `package.json` files in `nicegui/elements/.../` directories for individual UI elements.
232234
They are usually updated by the maintainers during major releases.
233235

234236
To update or add new dependencies, we follow these steps:
235237

236238
1. Use `npm` or other derivative tools, modify the `package.json` file with new versions or add dependencies.
237-
- We **never** modify the version in `package.json` or `npm.json` directly, since there may be conflicts between versions.
238-
- `npx npm-check-updates -u --target semver` is a good starting point for updating dependencies.
239239
2. Run `npm install` to install the new dependencies.
240240
Any conflicts in installation will be caught at this moment.
241-
3. Run `pin_versions.py` to update the `npm.json` file.
242-
4. Run `npm.py` to download dependencies into the `nicegui/static/` and `nicegui/elements/lib/` directories.
243-
5. Remember to commit `package.json` in addition to the new dependencies and `DEPENDENCIES.md`, such that Dependabot can catch outdated dependencies with security issues.
241+
3. Run `npm run build` to copy the dependencies into the `nicegui/static/` directory or
242+
to bundle the dependencies in the `nicegui/elements/.../` directories.
244243

245-
Apart from updating Node libraries, the following tools are used to update other resources:
244+
The following tools are used to update other resources:
246245

247-
- scripts/codemirror/bundle.bash for managing the CodeMirror dependency
248246
- fetch_google_fonts.py for fetching the Google Fonts
249247
- fetch_languages.py to update the list of supported languages in language.py
250248
- fetch_milestone.py to prepare the release notes for a given milestone
251249
- fetch_sponsors.py to update the list of sponsors on the website and in the README.md file
252250
- fetch_tailwind.py to update NiceGUI's Tailwind API
251+
- summarize_dependencies.py to update the dependencies in the DEPENDENCIES.md file
253252

254253
## Pull requests
255254

DEPENDENCIES.md

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
# Included Web Dependencies
22

3-
- vue: 3.4.38 ([MIT](https://opensource.org/licenses/MIT))
4-
- quasar: 2.16.9 ([MIT](https://opensource.org/licenses/MIT))
5-
- tailwindcss: 3.4.10 ([MIT](https://opensource.org/licenses/MIT))
6-
- socket.io: 4.7.5 ([MIT](https://opensource.org/licenses/MIT))
7-
- es-module-shims: 1.10.0 ([MIT](https://opensource.org/licenses/MIT))
8-
- aggrid: 32.1.0 ([MIT](https://opensource.org/licenses/MIT))
9-
- codemirror: 6.0.1 ([MIT](https://opensource.org/licenses/MIT))
10-
- echarts: 5.5.1 ([Apache-2.0](https://opensource.org/licenses/Apache-2.0))
11-
- echarts-gl: 2.0.9 ([BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause))
12-
- leaflet: 1.9.4 ([BSD-2-Clause](https://opensource.org/licenses/BSD-2-Clause))
13-
- leaflet-draw: 1.0.4 ([MIT](https://opensource.org/licenses/MIT))
14-
- mermaid: 11.0.2 ([MIT](https://opensource.org/licenses/MIT))
15-
- nipplejs: 0.10.2 ([MIT](https://opensource.org/licenses/MIT))
16-
- plotly: 2.35.0 ([MIT](https://opensource.org/licenses/MIT))
17-
- three: 0.168.0 ([MIT](https://opensource.org/licenses/MIT))
18-
- tween: 25.0.0 ([MIT](https://opensource.org/licenses/MIT))
19-
- vanilla-jsoneditor: 0.23.8 ([ISC](https://opensource.org/licenses/ISC))
3+
- es-module-shims: 2.6.2 ([MIT](https://opensource.org/licenses/MIT))
4+
- quasar: 2.18.2 ([MIT](https://opensource.org/licenses/MIT))
5+
- socket.io: 4.8.1 ([MIT](https://opensource.org/licenses/MIT))
6+
- tailwindcss: 3.4.17 ([MIT](https://opensource.org/licenses/MIT))
7+
- vue: 3.5.18 ([MIT](https://opensource.org/licenses/MIT))
8+
- ag-grid-community: ^34.1.1 ([MIT](https://opensource.org/licenses/MIT))
9+
- codemirror: ^6.0.2 ([MIT](https://opensource.org/licenses/MIT))
10+
- @codemirror/language-data: ^6.5.1 ([MIT](https://opensource.org/licenses/MIT))
11+
- @codemirror/theme-one-dark: ^6.1.3 ([MIT](https://opensource.org/licenses/MIT))
12+
- @uiw/codemirror-themes-all: ^4.24.2 ([MIT](https://opensource.org/licenses/MIT))
13+
- @babel/runtime: ^7.28.2 ([MIT](https://opensource.org/licenses/MIT))
14+
- echarts: ^6.0.0 ([Apache-2.0](https://opensource.org/licenses/Apache-2.0))
15+
- echarts-gl: ^2.0.9 ([BSD 3-Clause](https://opensource.org/licenses/BSD-3-Clause))
16+
- nipplejs: ^0.10.2 ([MIT](https://opensource.org/licenses/MIT))
17+
- vanilla-jsoneditor: ^3.8.0 ([ISC](https://opensource.org/licenses/ISC))
18+
- leaflet: ^1.9.4 ([BSD-2-Clause](https://opensource.org/licenses/BSD-2-Clause))
19+
- leaflet-draw: ^1.0.4 ([MIT](https://opensource.org/licenses/MIT))
20+
- mermaid: ^11.9.0 ([MIT](https://opensource.org/licenses/MIT))
21+
- plotly.js: ^3.1.0 ([MIT](https://opensource.org/licenses/MIT))
22+
- three: ^0.179.1 ([MIT](https://opensource.org/licenses/MIT))
23+
- @tweenjs/tween.js: ^25.0.0 ([MIT](https://opensource.org/licenses/MIT))

examples/editable_ag_grid/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ async def delete_selected():
3535
aggrid = ui.aggrid({
3636
'columnDefs': columns,
3737
'rowData': rows,
38-
'rowSelection': 'multiple',
38+
'rowSelection': {'mode': 'multiRow'},
3939
'stopEditingWhenCellsLoseFocus': True,
4040
}).on('cellValueChanged', handle_cell_value_change)
4141

examples/local_file_picker/local_file_picker.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def __init__(self, directory: str, *,
3131
self.add_drives_toggle()
3232
self.grid = ui.aggrid({
3333
'columnDefs': [{'field': 'name', 'headerName': 'File'}],
34-
'rowSelection': 'multiple' if multiple else 'single',
34+
'rowSelection': {'mode': 'multiRow' if multiple else 'singleRow'},
3535
}, html_columns=[0]).classes('w-96').on('cellDoubleClicked', self.handle_double_click)
3636
with ui.row().classes('w-full justify-end'):
3737
ui.button('Cancel', on_click=self.close).props('outline')

examples/node_module_integration/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ We chose this package to demonstrate a very simple node module which has a depen
66
namely the [is-number](https://www.npmjs.com/package/is-number) package.
77
Using NPM, we can easily install both packages and bundle them into a single file which can be used in the app.
88
The package.json file defines the is-odd dependency and some dev dependencies for bundling the node module,
9-
the webpack.config.js file specifies the entry point for the node module,
9+
the rollup.config.mjs file configures the bundling process,
10+
the src/index.mjs file is the entry point for the node module,
1011
and number_checker.js as well as number_checker.py define a new UI element to be used in the NiceGUI app main.py.
1112

1213
1. First, install all third-party node modules (assuming you have NPM installed):
@@ -23,6 +24,8 @@ and number_checker.js as well as number_checker.py define a new UI element to be
2324
npm run build
2425
```
2526

27+
This will create a dist directory containing the is-odd module.
28+
2629
3. Finally, you can run the app as usual:
2730

2831
```bash
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
function e(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}
2+
/*!
3+
* is-number <https://github.com/jonschlinkert/is-number>
4+
*
5+
* Copyright (c) 2014-2018, Jon Schlinkert.
6+
* Released under the MIT License.
7+
*/var r,t,n,u;function o(){return t?r:(t=1,r=function(e){var r=+e;return r-r===0&&(r===e||"string"==typeof e&&(0!==r||""!==e.trim()))})}
8+
/*!
9+
* is-odd <https://github.com/jonschlinkert/is-odd>
10+
*
11+
* Copyright (c) 2015-2017, Jon Schlinkert.
12+
* Released under the MIT License.
13+
*/var a=function(){if(u)return n;u=1;const e=o();return n=function(r){const t=Math.abs(r);if(!e(t))throw new TypeError("expected a number");if(!Number.isInteger(t))throw new Error("expected an integer");if(!Number.isSafeInteger(t))throw new Error("value exceeds maximum safe integer");return t%2==1}}(),i=e(a);export{i as default};

examples/node_module_integration/number_checker.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1+
import isOdd from "is-odd";
2+
13
export default {
2-
async mounted() {
3-
await import("is-odd");
4-
},
54
methods: {
65
isOdd(number) {
76
return isOdd(number);

0 commit comments

Comments
 (0)