-
-
Notifications
You must be signed in to change notification settings - Fork 109
[change] Reduce library size #392 #425
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
7b1d3ca to
5236b0e
Compare
nemesifier
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main problem I see is that now yarn build produces multiple files, which doesn't make it easy for us to drop the resulting work in OpenWISP. Is this on purpose?
Yes, there are several reasons for this approach:
The contenthash in filenames will optimize CDN cache management when using cdn (if we are using cdn). Integration Considerations:
let me know your thoughts! |
nemesifier
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@codesankalp what do you think about the following?
- a result set providing the current output: all separate files
- a result set providing the library + echarts
- a result set providing the library + echarts + leaflet
Can you add basic explanation about the above?
68ed674 to
17ffba3
Compare
|
New Buid Sizes:
|
e43988e to
5355c03
Compare
0c99ec8 to
b4bbfa9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have the following problem:
yarn install
yarn install v1.22.22
[1/4] Resolving packages...
[2/4] Fetching packages...
error Error: https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.3.tgz: Request failed "404 Not Found"
at ResponseError.ExtendableBuiltin (/usr/share/yarn/lib/cli.js:696:66)
at new ResponseError (/usr/share/yarn/lib/cli.js:802:124)
at Request.<anonymous> (/usr/share/yarn/lib/cli.js:66750:16)
at Request.emit (node:events:519:28)
at module.exports.Request.onRequestResponse (/usr/share/yarn/lib/cli.js:142287:10)
at ClientRequest.emit (node:events:519:28)
at HTTPParser.parserOnIncomingClient (node:_http_client:716:27)
at HTTPParser.parserOnHeadersComplete (node:_http_common:117:17)
at TLSSocket.socketOnData (node:_http_client:558:22)
at TLSSocket.emit (node:events:519:28)
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
I see the following line in yarn.lock:
debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.4.1:
version "4.4.2"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.2.tgz#96b480a7fe47cc04fe57f0bf56e058dba2a001fa"
integrity sha512-IQeXCZhGRpFiLI3MYlCGLjNssUBiE8G21RMyNH35KFsxIvhrMeh5jXuG82woDZrYX9pgqHs+GF5js2Ducn4y4A==
dependencies:
ms "^2.1.3"
The URL https://registry.yarnpkg.com/debug/-/debug-4.4.2.tgz#96b480a7fe47cc04fe57f0bf56e058dba2a001fa returns 404.
I am not sure why the CI build is not complaining about this, but it feels wrong to me to reference a 404 URL in yarn.lock, what do you think?
b4bbfa9 to
4d026ce
Compare
nemesifier
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did some changes to the README.
The save on the complete bundle is only ~300KB.
In OpenWISP dashboard we need to load the complete bundle, so reducing 300KB is good but I wonder if we really need 1.3 MB to show geographic and indoor maps.
Is there a way to reduce the imports of echarts so that we only import exactly what we use and let the javascript pruning tools do the work of removing all the JS code that we don't use?
bc058f2 to
e6c4b28
Compare
ba20b6c to
85097e8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@webpack-plugins/inject-leaflet-loader.js`:
- Around line 195-199: The inline-script regex is too restrictive (only allows
an optional type attribute) and misses scripts with other attrs (defer, nonce,
etc.), causing the loader not to be injected; update the matching logic around
the scriptRegex variable to match any <script ...> tag with arbitrary attributes
but no src attribute (e.g. capture attributes with
/<script\b([^>]*?)>\s*([\s\S]*?)\s*<\/script>/i and then ensure you only treat
tags without a src attribute as inline), preserve the full attributes string
when reinserting the modified script, and apply the same change to the other
occurrence around lines 216-219 so all inline scripts are detected and updated
correctly.
- Around line 204-214: The current logic detects module scripts via
scriptTypeMatch/scriptType but still wraps everything in an initMap function
when creating newScript, which breaks module semantics; modify the code around
scriptTypeMatch/scriptType and the newScript construction so that if scriptType
=== "module" you do not wrap originalScript in the initMap function (instead
inject loaderSnippet alongside originalScript or apply a module-compatible
injection), otherwise continue to wrap as before; update references to
loaderSnippet, originalScript and newScript accordingly and ensure module
scripts are emitted unchanged in scope.
♻️ Duplicate comments (1)
webpack-plugins/inject-leaflet-loader.js (1)
137-139: Rename shadowing variable to satisfy Biome lint.
constructorshadows the global identifier and tripslint/suspicious/noShadowRestrictedNames. This was already flagged earlier.🔧 Suggested fix
- const HtmlWebpackPlugin = compiler.options.plugins - .map((plugin) => plugin.constructor) - .find((constructor) => constructor && constructor.name === "HtmlWebpackPlugin"); + const HtmlWebpackPlugin = compiler.options.plugins + .map((plugin) => plugin.constructor) + .find((pluginCtor) => pluginCtor && pluginCtor.name === "HtmlWebpackPlugin");
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
webpack-plugins/inject-leaflet-loader.js
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,ts,css,scss,json}
📄 CodeRabbit inference engine (AGENTS.md)
Format code using
openwisp-qa-formatcommand with Python virtualenv enabled andyarn lint:fix(runs eslint --fix and prettier via lint-staged)
Files:
webpack-plugins/inject-leaflet-loader.js
🧠 Learnings (4)
📓 Common learnings
Learnt from: codesankalp
Repo: openwisp/netjsongraph.js PR: 425
File: src/js/netjsongraph.render.js:1-26
Timestamp: 2026-01-20T16:51:06.213Z
Learning: In the netjsongraph.js project, imports from `echarts/lib/chart/*/install`, `echarts/lib/component/*/install`, and `echarts/lib/renderer/install*` paths produce better tree-shaking results than the public entry points (`echarts/charts`, `echarts/components`, `echarts/renderers`) in their webpack configuration. The project maintainer has tested both approaches and confirmed the `/lib/*/install` pattern yields smaller bundles.
📚 Learning: 2026-01-20T16:51:06.213Z
Learnt from: codesankalp
Repo: openwisp/netjsongraph.js PR: 425
File: src/js/netjsongraph.render.js:1-26
Timestamp: 2026-01-20T16:51:06.213Z
Learning: In the netjsongraph.js project, imports from `echarts/lib/chart/*/install`, `echarts/lib/component/*/install`, and `echarts/lib/renderer/install*` paths produce better tree-shaking results than the public entry points (`echarts/charts`, `echarts/components`, `echarts/renderers`) in their webpack configuration. The project maintainer has tested both approaches and confirmed the `/lib/*/install` pattern yields smaller bundles.
Applied to files:
webpack-plugins/inject-leaflet-loader.js
📚 Learning: 2026-01-04T08:00:40.936Z
Learnt from: dee077
Repo: openwisp/netjsongraph.js PR: 417
File: src/js/netjsongraph.util.js:1302-1341
Timestamp: 2026-01-04T08:00:40.936Z
Learning: In the netjsongraph.js codebase, the `== null` pattern is intentionally used to check for both null and undefined values in a single comparison, which is a well-established JavaScript idiom and should not be flagged for replacement with strict equality checks.
Applied to files:
webpack-plugins/inject-leaflet-loader.js
📚 Learning: 2026-01-20T00:42:32.369Z
Learnt from: dee077
Repo: openwisp/netjsongraph.js PR: 417
File: src/js/netjsongraph.core.js:132-145
Timestamp: 2026-01-20T00:42:32.369Z
Learning: In the netjsongraph.js codebase, node IDs are guaranteed not to contain the "~" character, so using "source~target" as a composite key for links in nodeLinkIndex will not collide with node ID keys.
Applied to files:
webpack-plugins/inject-leaflet-loader.js
🧬 Code graph analysis (1)
webpack-plugins/inject-leaflet-loader.js (1)
webpack.config.js (2)
InjectLeafletLoaderPlugin(10-10)HtmlWebpackPlugin(5-5)
🪛 Biome (2.1.2)
webpack-plugins/inject-leaflet-loader.js
[error] 139-139: Do not shadow the global "constructor" property.
Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.
(lint/suspicious/noShadowRestrictedNames)
🔇 Additional comments (2)
webpack-plugins/inject-leaflet-loader.js (2)
6-19: LGTM: constructor config is clear and scoped.
isEchartsOnlygating plus an explicitmapExampleslist keeps the plugin’s scope predictable.
22-128: LGTM: loader snippet covers Leaflet + plugin sequencing cleanly.The onload/error handling and plugin gating look solid for the echarts-only case.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
85097e8 to
0ad4fe2
Compare
0ad4fe2 to
ac84bae
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
index.html (1)
1-278:⚠️ Potential issue | 🟡 MinorFix Prettier formatting issues to pass CI.
The CI pipeline is failing because this file has code style issues detected by Prettier. Run
prettier --write index.htmloryarn lint:fixto automatically fix the formatting..github/workflows/ci.yml (1)
123-126:⚠️ Potential issue | 🟡 MinorCoveralls may receive multiple coverage reports from matrix builds.
The Coveralls step runs for all three matrix entries (
dev,prod,echarts-only), but only thedevbuild runs unit tests and generates coverage data. Theprodandecharts-onlybuilds will submit empty or incomplete coverage reports.Consider restricting Coveralls to only the
devbuild:🔧 Suggested fix
- name: Coveralls + if: matrix.build-type == 'dev' uses: coverallsapp/github-action@master with: github-token: ${{ secrets.GITHUB_TOKEN }}src/js/netjsongraph.core.js (1)
80-179:⚠️ Potential issue | 🟠 Major
async render()has noawaitstatements, causing immediate Promise resolution without waiting for readiness.The function is marked async but contains no top‑level
await, so it returns a resolved Promise immediately. Tests and future callers thatawait render()expect the function to wait forpaginatedDataParseandonReadycompletion, but the Promise resolves before these operations finish, breaking the async contract. Either addawaitto the parse chain or removeasyncto match actual behavior.🛠️ Possible fix: await parse chain and return completion Promise
async render() { const [JSONParam, ...resParam] = this.JSONParam; this.config.onRender.call(this); // Ensure applyUrlFragmentState runs only after onReady has completed, // as onReady may perform asynchronous operations const onReadyDone = new Promise((resolve) => { this.event.once("onReady", async () => { try { await this.config.onReady.call(this); } catch (error) { console.error("onReady callback failed:", error); } resolve(); }); }); this.event.once("onLoad", this.config.onLoad.bind(this)); this.event.once("applyUrlFragmentState", async () => { try { await onReadyDone; } catch (e) { console.error("onReady failed:", e); } this.utils.applyUrlFragmentState.call(this, this); }); - this.utils.paginatedDataParse + await this.utils.paginatedDataParse .call(this, JSONParam) .then((JSONData) => { if (this.utils.isNetJSON(JSONData)) { this.type = "netjson"; } else if (this.utils.isGeoJSON(JSONData)) { // Treat GeoJSON as a first-class citizen by converting it once // to NetJSON shape while keeping the original for polygon rendering. this.type = "geojson"; // Preserve the original GeoJSON so that non-point geometries (e.g. Polygons) // can still be rendered as filled shapes via a separate Leaflet layer later // in the rendering pipeline, while the converted NetJSON shape is used for // clustering and ECharts overlays. this.originalGeoJSON = this.utils.fastDeepCopy(JSONData); JSONData = this.utils.geojsonToNetjson(JSONData); } else { throw new Error("Invalid data format!"); } if (this.utils.isNetJSON(JSONData)) { if (JSONData.nodes.length > this.config.maxPointsFetched) { this.hasMoreData = true; } JSONData.nodes.splice( this.config.maxPointsFetched - 1, JSONData.nodes.length - this.config.maxPointsFetched, ); const nodeSet = new Set(); // Build a lookup map (this.nodeLinkIndex) for quick access to node or link data. // Uses node IDs as keys for nodes and "source~target" as keys for links. // This avoids repeated traversal when restoring state from URL fragments. this.nodeLinkIndex = {}; JSONData.nodes.forEach((node) => { nodeSet.add(node.id); this.nodeLinkIndex[node.id] = node; }); JSONData.links = JSONData.links.filter((link) => { if (nodeSet.has(link.source) && nodeSet.has(link.target)) { const key = `${link.source}~${link.target}`; this.nodeLinkIndex[key] = link; return true; } if (!nodeSet.has(link.source)) { console.warn(`Node ${link.source} does not exist!`); } else { console.warn(`Node ${link.target} does not exist!`); } return false; }); } this.config.prepareData.call(this, JSONData); this.data = JSONData; if (this.config.dealDataByWorker) { this.utils.dealDataByWorker.call( this, JSONData, this.config.dealDataByWorker, ); } else { this.data = JSONData; this.utils.render(); } }) .catch((error) => { console.error(error); }); if (resParam.length) { const renderArray = function _renderArray() { resParam.map((file) => this.utils.JSONDataUpdate.call(this, file, false)); }; this.JSONParam = [JSONParam]; this.event.once("renderArray", renderArray.bind(this)); } }
🤖 Fix all issues with AI agents
In @.github/workflows/ci.yml:
- Around line 51-57: Add an explicit permissions block to the GitHub Actions job
named "build" to restrict the GITHUB_TOKEN to only the scopes required for
running tests and collecting coverage; under the build job (where
matrix.build-type is defined) add a permissions section that at minimum sets
contents: read and packages: read and optionally checks: write and actions: read
(adjust to your CI needs) so the workflow no longer inherits broad default token
permissions.
🧹 Nitpick comments (2)
src/js/echarts-leaflet/LeafletCoordSys.js (1)
153-155: Redundant Leaflet availability check.The check
typeof L === "undefined"at line 153 is now redundant. SinceLis assigned fromgetLeaflet()at line 12, and lines 13-15 throw if Leaflet is unavailable,Lis guaranteed to be defined when this callback executes.♻️ Optional cleanup
ecModel.eachComponent("leaflet", (leafletModel) => { const viewportRoot = api.getZr().painter.getViewportRoot(); - if (typeof L === "undefined") { - throw new Error("Leaflet api is not loaded"); - } if (leafletCoordSys) { throw new Error("Only one leaflet component can exist"); }webpack-plugins/inject-leaflet-loader.js (1)
35-37: Hardcoded CDN URLs with SRI hashes may become stale.The Leaflet version (1.8.0) and integrity hashes are hardcoded. If the project's Leaflet dependency is updated, these values won't automatically sync. Consider documenting this dependency or extracting the version to a shared constant.
Also applies to: 42-44
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
lib/css/assets/leaflet-measure.pngis excluded by!**/*.pngpublic/assets/images/floorplan.pngis excluded by!**/*.pngyarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (25)
.github/workflows/ci.ymlREADME.mdindex.htmlpackage.jsonpublic/assets/data/airplaneRouteMap.jsonpublic/assets/data/netjsongraph-graphGL.jsonpublic/example_templates/netjsongraph-graphGL.htmlpublic/example_templates/netjsonmap-animation.htmlpublic/example_templates/netjsonmap-indoormap.htmlsrc/js/echarts-leaflet/LeafletCoordSys.jssrc/js/echarts-leaflet/LeafletModel.jssrc/js/echarts-leaflet/LeafletView.jssrc/js/echarts-leaflet/index.jssrc/js/leaflet-loader.jssrc/js/netjsongraph.clients.jssrc/js/netjsongraph.config.jssrc/js/netjsongraph.core.jssrc/js/netjsongraph.geojson.jssrc/js/netjsongraph.jssrc/js/netjsongraph.render.jstest/browser.test.utils.jstest/netjsongraph.duplicateNodes.test.jstest/netjsongraph.render.test.jswebpack-plugins/inject-leaflet-loader.jswebpack.config.js
💤 Files with no reviewable changes (4)
- test/browser.test.utils.js
- public/assets/data/airplaneRouteMap.json
- public/example_templates/netjsongraph-graphGL.html
- public/example_templates/netjsonmap-animation.html
🚧 Files skipped from review as they are similar to previous changes (8)
- src/js/netjsongraph.geojson.js
- src/js/netjsongraph.clients.js
- public/example_templates/netjsonmap-indoormap.html
- src/js/leaflet-loader.js
- package.json
- src/js/netjsongraph.js
- src/js/echarts-leaflet/LeafletView.js
- README.md
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,ts,css,scss,json}
📄 CodeRabbit inference engine (AGENTS.md)
Format code using
openwisp-qa-formatcommand with Python virtualenv enabled andyarn lint:fix(runs eslint --fix and prettier via lint-staged)
Files:
src/js/netjsongraph.core.jssrc/js/netjsongraph.config.jssrc/js/echarts-leaflet/LeafletModel.jswebpack.config.jstest/netjsongraph.duplicateNodes.test.jstest/netjsongraph.render.test.jssrc/js/echarts-leaflet/LeafletCoordSys.jswebpack-plugins/inject-leaflet-loader.jssrc/js/netjsongraph.render.jssrc/js/echarts-leaflet/index.js
src/**/*.js
📄 CodeRabbit inference engine (AGENTS.md)
Husky pre-commit hooks automatically run lint-staged to format JavaScript files in
src/**/*.jswith prettier
Files:
src/js/netjsongraph.core.jssrc/js/netjsongraph.config.jssrc/js/echarts-leaflet/LeafletModel.jssrc/js/echarts-leaflet/LeafletCoordSys.jssrc/js/netjsongraph.render.jssrc/js/echarts-leaflet/index.js
**/*.test.{js,ts}
📄 CodeRabbit inference engine (AGENTS.md)
Write unit tests using Jest with jsdom and run with
yarn test
Files:
test/netjsongraph.duplicateNodes.test.jstest/netjsongraph.render.test.js
🧠 Learnings (11)
📓 Common learnings
Learnt from: codesankalp
Repo: openwisp/netjsongraph.js PR: 425
File: src/js/netjsongraph.render.js:1-26
Timestamp: 2026-01-20T16:51:06.213Z
Learning: In the netjsongraph.js project, imports from `echarts/lib/chart/*/install`, `echarts/lib/component/*/install`, and `echarts/lib/renderer/install*` paths produce better tree-shaking results than the public entry points (`echarts/charts`, `echarts/components`, `echarts/renderers`) in their webpack configuration. The project maintainer has tested both approaches and confirmed the `/lib/*/install` pattern yields smaller bundles.
📚 Learning: 2026-01-20T00:56:36.062Z
Learnt from: dee077
Repo: openwisp/netjsongraph.js PR: 417
File: src/js/netjsongraph.core.js:132-145
Timestamp: 2026-01-20T00:56:36.062Z
Learning: In the netjsongraph.js codebase, the data model does not support parallel links (multiple links between the same source and target). Ensure nodeLinkIndex is keyed by a single 'source~target' pair and that adding a link does not overwrite existing links for that pair. If parallel links are ever required, the data model must be changed (e.g., allow an array of links per 'source~target' key) rather than storing only one link.
Applied to files:
src/js/netjsongraph.core.jssrc/js/netjsongraph.config.jstest/netjsongraph.duplicateNodes.test.jstest/netjsongraph.render.test.jssrc/js/netjsongraph.render.js
📚 Learning: 2026-01-20T16:50:56.414Z
Learnt from: codesankalp
Repo: openwisp/netjsongraph.js PR: 425
File: src/js/netjsongraph.render.js:1-26
Timestamp: 2026-01-20T16:50:56.414Z
Learning: In netjsongraph.js, prefer importing from echarts/lib/chart/*/install, echarts/lib/component/*/install, and echarts/lib/renderer/install* rather than the public entry points (echarts/charts, echarts/components, echarts/renderers) to improve tree-shaking and reduce bundle size. Apply this pattern across JS files in src (update imports accordingly) and verify by comparing bundle sizes between the install-path imports and the public-entry imports.
Applied to files:
src/js/netjsongraph.core.jssrc/js/netjsongraph.config.jssrc/js/echarts-leaflet/LeafletModel.jssrc/js/echarts-leaflet/LeafletCoordSys.jssrc/js/netjsongraph.render.jssrc/js/echarts-leaflet/index.js
📚 Learning: 2026-01-22T22:37:11.271Z
Learnt from: CR
Repo: openwisp/netjsongraph.js PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-22T22:37:11.271Z
Learning: Run QA checks using `./run-qa-checks` before committing code
Applied to files:
.github/workflows/ci.yml
📚 Learning: 2026-01-22T22:37:11.271Z
Learnt from: CR
Repo: openwisp/netjsongraph.js PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-22T22:37:11.271Z
Learning: Applies to test/netjsongraph.browser.test.js : Write browser tests in test/netjsongraph.browser.test.js using Chrome/ChromeDriver and run with `yarn test test/netjsongraph.browser.test.js`
Applied to files:
.github/workflows/ci.ymltest/netjsongraph.duplicateNodes.test.jstest/netjsongraph.render.test.js
📚 Learning: 2026-01-22T22:37:11.271Z
Learnt from: CR
Repo: openwisp/netjsongraph.js PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-22T22:37:11.271Z
Learning: Applies to **/*.test.{js,ts} : Write unit tests using Jest with jsdom and run with `yarn test`
Applied to files:
.github/workflows/ci.yml
📚 Learning: 2026-01-20T16:51:06.213Z
Learnt from: codesankalp
Repo: openwisp/netjsongraph.js PR: 425
File: src/js/netjsongraph.render.js:1-26
Timestamp: 2026-01-20T16:51:06.213Z
Learning: In the netjsongraph.js project, imports from `echarts/lib/chart/*/install`, `echarts/lib/component/*/install`, and `echarts/lib/renderer/install*` paths produce better tree-shaking results than the public entry points (`echarts/charts`, `echarts/components`, `echarts/renderers`) in their webpack configuration. The project maintainer has tested both approaches and confirmed the `/lib/*/install` pattern yields smaller bundles.
Applied to files:
webpack.config.jstest/netjsongraph.duplicateNodes.test.jstest/netjsongraph.render.test.jswebpack-plugins/inject-leaflet-loader.js
📚 Learning: 2026-01-04T08:00:40.936Z
Learnt from: dee077
Repo: openwisp/netjsongraph.js PR: 417
File: src/js/netjsongraph.util.js:1302-1341
Timestamp: 2026-01-04T08:00:40.936Z
Learning: In the netjsongraph.js codebase, the `== null` pattern is intentionally used to check for both null and undefined values in a single comparison, which is a well-established JavaScript idiom and should not be flagged for replacement with strict equality checks.
Applied to files:
test/netjsongraph.duplicateNodes.test.jswebpack-plugins/inject-leaflet-loader.jssrc/js/netjsongraph.render.js
📚 Learning: 2026-01-27T19:09:23.929Z
Learnt from: nemesifier
Repo: openwisp/netjsongraph.js PR: 473
File: src/js/netjsongraph.render.js:433-468
Timestamp: 2026-01-27T19:09:23.929Z
Learning: In the netjsongraph.js project, when implementing wheel zoom propagation from the graph container to the canvas: ECharts intercepts wheel events directly on the canvas with preventDefault(), so those events don't bubble to the container. A wheel listener on the container only catches events that occur outside the canvas (in the empty container space), making checks for e.target === canvas unnecessary since canvas events never reach the container listener.
Applied to files:
src/js/echarts-leaflet/LeafletCoordSys.jssrc/js/netjsongraph.render.js
📚 Learning: 2026-01-20T00:42:32.369Z
Learnt from: dee077
Repo: openwisp/netjsongraph.js PR: 417
File: src/js/netjsongraph.core.js:132-145
Timestamp: 2026-01-20T00:42:32.369Z
Learning: In the netjsongraph.js codebase, node IDs are guaranteed not to contain the "~" character, so using "source~target" as a composite key for links in nodeLinkIndex will not collide with node ID keys.
Applied to files:
webpack-plugins/inject-leaflet-loader.js
📚 Learning: 2026-01-30T08:31:13.746Z
Learnt from: Dhruv-ub
Repo: openwisp/netjsongraph.js PR: 474
File: src/js/netjsongraph.render.js:347-351
Timestamp: 2026-01-30T08:31:13.746Z
Learning: In src/js/netjsongraph.render.js, treat showMapLabelsAtZoom = 0 as the explicit 'disabled' state (not a valid threshold). Do not rely on generic falsy checks for this flag. Update logic to distinguish between undefined/null (not set), 0 (disabled), and >0 (enabled at a given zoom). For example, use explicit checks such as: if (showMapLabelsAtZoom === 0) { /* labels hidden */ } else if (typeof showMapLabelsAtZoom === 'number' && showMapLabelsAtZoom > 0) { /* show labels at/above this zoom */ } else { /* default behavior or undefined */ }. If needed, document this convention or normalize input (e.g., set undefined to a sensible default) to avoid ambiguity in future reviews.
Applied to files:
src/js/netjsongraph.render.js
🧬 Code graph analysis (5)
src/js/netjsongraph.config.js (4)
src/js/leaflet-loader.js (2)
L(12-12)getLeaflet(14-38)src/js/echarts-leaflet/LeafletCoordSys.js (1)
L(12-12)src/js/echarts-leaflet/index.js (1)
L(11-11)src/js/netjsongraph.geojson.js (2)
L(136-136)L(140-140)
test/netjsongraph.render.test.js (2)
src/js/netjsongraph.geojson.js (1)
map(142-142)test/netjsongraph.duplicateNodes.test.js (1)
NetJSONGraphRender(2-2)
webpack-plugins/inject-leaflet-loader.js (1)
webpack.config.js (2)
InjectLeafletLoaderPlugin(10-10)HtmlWebpackPlugin(5-5)
src/js/netjsongraph.render.js (5)
src/js/leaflet-loader.js (2)
L(12-12)getLeaflet(14-38)src/js/echarts-leaflet/LeafletCoordSys.js (1)
L(12-12)src/js/echarts-leaflet/index.js (1)
L(11-11)src/js/netjsongraph.config.js (1)
L(370-370)src/js/netjsongraph.geojson.js (2)
L(136-136)L(140-140)
src/js/echarts-leaflet/index.js (5)
src/js/leaflet-loader.js (2)
L(12-12)getLeaflet(14-38)src/js/echarts-leaflet/LeafletCoordSys.js (1)
L(12-12)src/js/netjsongraph.config.js (1)
L(370-370)src/js/echarts-leaflet/LeafletModel.js (1)
extendLeafletModel(6-50)src/js/echarts-leaflet/LeafletView.js (1)
extendLeafletView(6-122)
🪛 Biome (2.3.13)
webpack-plugins/inject-leaflet-loader.js
[error] 139-139: Do not shadow the global "constructor" property.
Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.
(lint/suspicious/noShadowRestrictedNames)
🪛 GitHub Actions: netjsongraph.js CI BUILD
index.html
[warning] 1-1: Code style issues found in index.html. Run Prettier with --write to fix.
[error] 1-1: CI process failed with exit code 1 due to formatting check failure. Prettier formatting check did not pass. Run 'prettier --write' to fix code style issues in this file.
🪛 GitHub Check: CodeQL
.github/workflows/ci.yml
[warning] 52-128: Workflow does not contain permissions
Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {{contents: read}}
🔇 Additional comments (19)
src/js/echarts-leaflet/LeafletModel.js (1)
1-50: LGTM!The refactor to import
extendComponentModeldirectly fromecharts/coreand remove theechartsparameter is clean and aligns with the PR's modular import strategy. The component definition logic remains unchanged.src/js/echarts-leaflet/LeafletCoordSys.js (1)
11-15: LGTM!The dynamic Leaflet loading via
getLeaflet()with proper error handling and destructuring is well-implemented. This enables the ECharts-only build variant to work without bundling Leaflet.src/js/netjsongraph.config.js (1)
366-378: LGTM!The lazy getter pattern for
crsis the right approach since Leaflet may not be available at module load time. Returningnullwhen Leaflet is unavailable allows the ECharts-only build to function correctly.src/js/echarts-leaflet/index.js (1)
10-21: LGTM!The graceful early return when Leaflet is unavailable (line 12-16) enables the library to function in graph-only mode without errors. The registration flow is clean and properly chains the model/view extensions before coordinate system registration.
src/js/netjsongraph.render.js (6)
1-26: LGTM!The modular ECharts imports using the
echarts/lib/*/installpattern align with the project's established approach for optimal tree-shaking. Based on learnings, this pattern yields smaller bundles than the public entry points in this project's webpack configuration.
83-92: Tooltip formatter correctly simplified.The formatter now only handles
graphandlinescomponent subtypes, removing the deadgraphGLbranches that were flagged in previous reviews.
206-211: Graph series simplified to use only "graph" type.The series type is now always
"graph"with a default"force"layout, removing the unnecessary graphGL complexity. This aligns with the PR objective to reduce library size by removing unused features.
515-519: LGTM!The dynamic Leaflet loading with proper error handling ensures map rendering fails gracefully with a clear error message when Leaflet is unavailable.
733-741: Cluster click handling correctly uses "scatter" type.The check for cluster clicks now uses
params.componentSubType === "scatter", which aligns with the simplified map series type at line 327.
871-871: Export surface narrowed to default-only.Removing the named exports for
echartsandLis appropriate since consumers should use the library's public API rather than accessing internal dependencies directly.test/netjsongraph.render.test.js (3)
1-3: LGTM! Import updates align with the new module structure.The imports correctly reflect the module restructuring where
NetJSONGraphRenderis now a default export andL(Leaflet) is imported separately rather than being re-exported from the render module.
477-481: LGTM! Async test pattern is correct.The test properly awaits the now-asynchronous
render()call and asserts on the expected error behavior.
707-715: LGTM! Prototype isolation prevents test pollution.Snapshotting and restoring
NetJSONGraphRender.prototypebetween tests is good practice since thesetUpfunction modifies the prototype chain viaObject.setPrototypeOf.test/netjsongraph.duplicateNodes.test.js (1)
2-2: LGTM! Import correctly accesses the default export.The
require(...).defaultpattern properly retrieves the default export from the restructured module, consistent with the import pattern in other test files.webpack.config.js (5)
61-65: LGTM! Build type detection enables dual-build strategy.The function-based configuration cleanly supports both full and echarts-only builds via the
BUILD_TYPEenvironment variable, enabling the size reduction objectives of this PR.
84-88: LGTM! Leaflet externalization reduces echarts-only bundle size.Externalizing Leaflet as
Lfor echarts-only builds allows consumers to load Leaflet separately or via the dynamic loader, supporting the selective loading objective.
169-171: LGTM! DefinePlugin enables conditional Leaflet bundling.
BUNDLE_LEAFLETallows source code to conditionally include/exclude Leaflet-related code paths based on build type, supporting dead code elimination.
172-204: LGTM! Compression plugins configured for optimal delivery.Gzip and Brotli compression with aggressive settings (level 9 / quality 11) will significantly reduce transfer sizes for production builds. The threshold of 1024 bytes appropriately skips small files.
93-93: CSS and polyfills are safe withsideEffects: falsein this codebase.CSS files in
src/css/are handled as static assets (copied via webpack's CopyPlugin, lines 155-156) and processed through webpack's CSS loader rules (lines 107-108), not imported as ES6 modules. No side-effectful bare imports were found in the source code. ThesideEffects: falsesetting is intentional and explicitly declared inpackage.json(line 6), consistent with the project's careful tree-shaking optimization strategy (includingusedExports: true,providedExports: true,concatenateModules: true, etc.).Likely an incorrect or invalid review comment.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/ci.yml (1)
26-28:⚠️ Potential issue | 🟡 MinorDeprecated
set-outputcommand usage.The
::set-outputcommand is deprecated and will eventually be removed. This affects both theqa-checksjob (line 28) andbuildjob (line 69).🔧 Suggested fix
- name: Get yarn cache directory path id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" + run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUTApply the same fix to line 69 in the
buildjob.
🧹 Nitpick comments (2)
webpack-plugins/inject-leaflet-loader.js (1)
35-44: Hardcoded Leaflet version may drift from bundled version.The CDN URLs reference Leaflet 1.8.0, which should match the version specified in
package.json. If the bundled version changes, these URLs won't automatically update.Consider extracting the Leaflet version to a shared constant or reading it from package.json during build to ensure consistency:
// At build time, could inject version from package.json const LEAFLET_VERSION = "1.8.0"; const LEAFLET_CDN_BASE = `https://unpkg.com/leaflet@${LEAFLET_VERSION}/dist`;webpack.config.js (1)
70-78: Consider extracting filename logic for clarity.The nested ternary operators for
filenameare functional but reduce readability. A helper function or object lookup could make the intent clearer.♻️ Optional refactor for readability
const getOutputFilename = (isProduction, isEchartsOnly) => { const prefix = isEchartsOnly ? "netjsongraph.echarts" : "netjsongraph"; const hash = isProduction ? ".[contenthash:8]" : ""; const suffix = isProduction ? ".min.js" : ".js"; return `${prefix}${hash}${suffix}`; }; // Then in config: filename: getOutputFilename(isProduction, isEchartsOnly),
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
.github/workflows/ci.ymlindex.htmlwebpack-plugins/inject-leaflet-loader.jswebpack.config.js
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,ts,css,scss,json}
📄 CodeRabbit inference engine (AGENTS.md)
Format code using
openwisp-qa-formatcommand with Python virtualenv enabled andyarn lint:fix(runs eslint --fix and prettier via lint-staged)
Files:
webpack.config.jswebpack-plugins/inject-leaflet-loader.js
🧠 Learnings (7)
📓 Common learnings
Learnt from: codesankalp
Repo: openwisp/netjsongraph.js PR: 425
File: src/js/netjsongraph.render.js:1-26
Timestamp: 2026-01-20T16:51:06.213Z
Learning: In the netjsongraph.js project, imports from `echarts/lib/chart/*/install`, `echarts/lib/component/*/install`, and `echarts/lib/renderer/install*` paths produce better tree-shaking results than the public entry points (`echarts/charts`, `echarts/components`, `echarts/renderers`) in their webpack configuration. The project maintainer has tested both approaches and confirmed the `/lib/*/install` pattern yields smaller bundles.
📚 Learning: 2026-01-20T16:51:06.213Z
Learnt from: codesankalp
Repo: openwisp/netjsongraph.js PR: 425
File: src/js/netjsongraph.render.js:1-26
Timestamp: 2026-01-20T16:51:06.213Z
Learning: In the netjsongraph.js project, imports from `echarts/lib/chart/*/install`, `echarts/lib/component/*/install`, and `echarts/lib/renderer/install*` paths produce better tree-shaking results than the public entry points (`echarts/charts`, `echarts/components`, `echarts/renderers`) in their webpack configuration. The project maintainer has tested both approaches and confirmed the `/lib/*/install` pattern yields smaller bundles.
Applied to files:
webpack.config.jswebpack-plugins/inject-leaflet-loader.js
📚 Learning: 2026-01-04T08:00:40.936Z
Learnt from: dee077
Repo: openwisp/netjsongraph.js PR: 417
File: src/js/netjsongraph.util.js:1302-1341
Timestamp: 2026-01-04T08:00:40.936Z
Learning: In the netjsongraph.js codebase, the `== null` pattern is intentionally used to check for both null and undefined values in a single comparison, which is a well-established JavaScript idiom and should not be flagged for replacement with strict equality checks.
Applied to files:
webpack-plugins/inject-leaflet-loader.js
📚 Learning: 2026-01-20T00:42:32.369Z
Learnt from: dee077
Repo: openwisp/netjsongraph.js PR: 417
File: src/js/netjsongraph.core.js:132-145
Timestamp: 2026-01-20T00:42:32.369Z
Learning: In the netjsongraph.js codebase, node IDs are guaranteed not to contain the "~" character, so using "source~target" as a composite key for links in nodeLinkIndex will not collide with node ID keys.
Applied to files:
webpack-plugins/inject-leaflet-loader.js
📚 Learning: 2026-01-22T22:37:11.271Z
Learnt from: CR
Repo: openwisp/netjsongraph.js PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-22T22:37:11.271Z
Learning: Run QA checks using `./run-qa-checks` before committing code
Applied to files:
.github/workflows/ci.yml
📚 Learning: 2026-01-22T22:37:11.271Z
Learnt from: CR
Repo: openwisp/netjsongraph.js PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-22T22:37:11.271Z
Learning: Applies to test/netjsongraph.browser.test.js : Write browser tests in test/netjsongraph.browser.test.js using Chrome/ChromeDriver and run with `yarn test test/netjsongraph.browser.test.js`
Applied to files:
.github/workflows/ci.yml
📚 Learning: 2026-01-22T22:37:11.271Z
Learnt from: CR
Repo: openwisp/netjsongraph.js PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-22T22:37:11.271Z
Learning: Applies to **/*.test.{js,ts} : Write unit tests using Jest with jsdom and run with `yarn test`
Applied to files:
.github/workflows/ci.yml
🪛 Biome (2.3.13)
webpack-plugins/inject-leaflet-loader.js
[error] 139-139: Do not shadow the global "constructor" property.
Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.
(lint/suspicious/noShadowRestrictedNames)
🪛 GitHub Check: CodeQL
.github/workflows/ci.yml
[warning] 52-129: Workflow does not contain permissions
Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {{contents: read}}
🔇 Additional comments (7)
index.html (1)
1-277: LGTM!The removal of demo cards for
netjsongraph-graphGL.htmlandnetjsonmap-animation.htmlaligns with the PR objective to remove unused examples and reduce library size. The minor whitespace adjustments are acceptable..github/workflows/ci.yml (1)
83-98: Well-structured matrix strategy for multi-variant CI.The conditional build and server steps correctly route to the appropriate build commands based on
matrix.build-type. Thefail-fast: falsesetting ensures all build variants complete even if one fails, which is good for comprehensive testing.webpack-plugins/inject-leaflet-loader.js (1)
5-20: LGTM on plugin structure and map examples list.The plugin correctly initializes with configurable options and maintains a clear list of Leaflet-dependent examples. The early return in
apply()when!isEchartsOnlyis a clean way to skip processing for full builds.webpack.config.js (4)
22-59: Aggressive Terser options are well-configured for size reduction.The compression settings with 3 passes, dead code elimination, and various optimization flags align with the PR objective to reduce library size. The
pure_getters: trueandtoplevel: trueoptions enable deep optimizations.
169-171: Good use of DefinePlugin for conditional Leaflet bundling.The
BUNDLE_LEAFLETcompile-time constant enables dead code elimination for Leaflet-related code paths in echarts-only builds, supporting the PR's selective loading objective.
172-204: Compression plugins are well-configured.Both gzip and Brotli compression are set up with appropriate thresholds (1024 bytes) and quality levels. Brotli quality 11 is maximum but acceptable for production builds where build time is less critical than output size.
89-103: No action required —sideEffects: falseis correctly configured.ECharts and zrender both properly declare their side effects in their package.json files, which means webpack respects those declarations even with the global
sideEffects: falsesetting. This allows safe tree-shaking while preserving modules with implicit side effects. Leaflet is already externalized in the webpack configuration (lines 84-88), so it is not bundled and not affected by this setting.The configuration is sound and follows webpack best practices for maximizing bundle efficiency while respecting module side effects.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
ac84bae to
364cf21
Compare
Signed-off-by: Sankalp <[email protected]>
Signed-off-by: Sankalp <[email protected]>
Should maintain consistent return type (undefined instead of null)
- `InjectLeafletLoaderPlugin` assumes specific HTML structure that may break - Uses regex to remove/replace script tags which is fragile
a2d6125 to
2caff6c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/js/echarts-leaflet/index.js (1)
41-41:⚠️ Potential issue | 🟡 MinorRemove unused default export to fix pipeline failure.
The CI pipeline reports:
Knip: Unused export 'default' found in src/js/echarts-leaflet/index.js. SinceregisterLeafletSystemis only imported and used as a named export in the codebase, this default export is redundant.🔧 Suggested fix
registerLeafletSystem.version = "1.0.0"; - -export default registerLeafletSystem;package.json (1)
57-93:⚠️ Potential issue | 🟡 MinorRemove unused
acorndependency from devDependencies.
acorn(line 61) is not referenced anywhere in the codebase. Remove it or add a Knip ignore rule if intentionally retained.
zrender(line 93) is included in jesttransformIgnorePatterns, indicating it may be intentionally configured for proper module resolution despite being a transitive dependency of echarts. Verify with the team before removing.
🤖 Fix all issues with AI agents
In `@src/js/netjsongraph.js`:
- Around line 73-77: registerLeafletSystem currently never returns a value so
the guard lock is set even when registration failed; change
registerLeafletSystem to return true after successfully registering the Leaflet
system and return false when Leaflet is unavailable, then update the caller that
checks isLeafletRegistered so it only assigns isLeafletRegistered = true when
registerLeafletSystem() returns true (the code path just before the existing
init(this.graph.el, ...) call); ensure the boolean return is used to allow
future retries if registration initially failed.
🧹 Nitpick comments (1)
src/js/echarts-leaflet/LeafletCoordSys.js (1)
153-155: Redundant Leaflet availability check — already guarded at function entry.The check
if (typeof L === "undefined")at line 153 is now unreachable. IfgetLeaflet()returnedundefined, line 14 would have already thrown. Consider removing this dead code.♻️ Suggested fix
ecModel.eachComponent("leaflet", (leafletModel) => { const viewportRoot = api.getZr().painter.getViewportRoot(); - if (typeof L === "undefined") { - throw new Error("Leaflet api is not loaded"); - } if (leafletCoordSys) { throw new Error("Only one leaflet component can exist"); }
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
lib/css/assets/leaflet-measure.pngis excluded by!**/*.pngpublic/assets/images/floorplan.pngis excluded by!**/*.pngyarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (25)
.github/workflows/ci.ymlREADME.mdindex.htmlpackage.jsonpublic/assets/data/airplaneRouteMap.jsonpublic/assets/data/netjsongraph-graphGL.jsonpublic/example_templates/netjsongraph-graphGL.htmlpublic/example_templates/netjsonmap-animation.htmlpublic/example_templates/netjsonmap-indoormap.htmlsrc/js/echarts-leaflet/LeafletCoordSys.jssrc/js/echarts-leaflet/LeafletModel.jssrc/js/echarts-leaflet/LeafletView.jssrc/js/echarts-leaflet/index.jssrc/js/leaflet-loader.jssrc/js/netjsongraph.clients.jssrc/js/netjsongraph.config.jssrc/js/netjsongraph.core.jssrc/js/netjsongraph.geojson.jssrc/js/netjsongraph.jssrc/js/netjsongraph.render.jstest/browser.test.utils.jstest/netjsongraph.duplicateNodes.test.jstest/netjsongraph.render.test.jswebpack-plugins/inject-leaflet-loader.jswebpack.config.js
💤 Files with no reviewable changes (4)
- test/browser.test.utils.js
- public/example_templates/netjsongraph-graphGL.html
- public/example_templates/netjsonmap-animation.html
- public/assets/data/airplaneRouteMap.json
🚧 Files skipped from review as they are similar to previous changes (6)
- src/js/netjsongraph.geojson.js
- src/js/leaflet-loader.js
- src/js/netjsongraph.clients.js
- README.md
- public/example_templates/netjsonmap-indoormap.html
- index.html
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,ts,css,scss,json}
📄 CodeRabbit inference engine (AGENTS.md)
Format code using
openwisp-qa-formatcommand with Python virtualenv enabled andyarn lint:fix(runs eslint --fix and prettier via lint-staged)
Files:
webpack.config.jssrc/js/netjsongraph.render.jssrc/js/netjsongraph.config.jssrc/js/echarts-leaflet/LeafletModel.jssrc/js/echarts-leaflet/LeafletCoordSys.jswebpack-plugins/inject-leaflet-loader.jssrc/js/echarts-leaflet/index.jssrc/js/netjsongraph.jssrc/js/netjsongraph.core.jstest/netjsongraph.render.test.jssrc/js/echarts-leaflet/LeafletView.jstest/netjsongraph.duplicateNodes.test.jspackage.json
src/**/*.js
📄 CodeRabbit inference engine (AGENTS.md)
Husky pre-commit hooks automatically run lint-staged to format JavaScript files in
src/**/*.jswith prettier
Files:
src/js/netjsongraph.render.jssrc/js/netjsongraph.config.jssrc/js/echarts-leaflet/LeafletModel.jssrc/js/echarts-leaflet/LeafletCoordSys.jssrc/js/echarts-leaflet/index.jssrc/js/netjsongraph.jssrc/js/netjsongraph.core.jssrc/js/echarts-leaflet/LeafletView.js
**/*.test.{js,ts}
📄 CodeRabbit inference engine (AGENTS.md)
Write unit tests using Jest with jsdom and run with
yarn test
Files:
test/netjsongraph.render.test.jstest/netjsongraph.duplicateNodes.test.js
🧠 Learnings (11)
📓 Common learnings
Learnt from: codesankalp
Repo: openwisp/netjsongraph.js PR: 425
File: src/js/netjsongraph.render.js:1-26
Timestamp: 2026-01-20T16:51:06.213Z
Learning: In the netjsongraph.js project, imports from `echarts/lib/chart/*/install`, `echarts/lib/component/*/install`, and `echarts/lib/renderer/install*` paths produce better tree-shaking results than the public entry points (`echarts/charts`, `echarts/components`, `echarts/renderers`) in their webpack configuration. The project maintainer has tested both approaches and confirmed the `/lib/*/install` pattern yields smaller bundles.
📚 Learning: 2026-01-20T16:51:06.213Z
Learnt from: codesankalp
Repo: openwisp/netjsongraph.js PR: 425
File: src/js/netjsongraph.render.js:1-26
Timestamp: 2026-01-20T16:51:06.213Z
Learning: In the netjsongraph.js project, imports from `echarts/lib/chart/*/install`, `echarts/lib/component/*/install`, and `echarts/lib/renderer/install*` paths produce better tree-shaking results than the public entry points (`echarts/charts`, `echarts/components`, `echarts/renderers`) in their webpack configuration. The project maintainer has tested both approaches and confirmed the `/lib/*/install` pattern yields smaller bundles.
Applied to files:
webpack.config.jswebpack-plugins/inject-leaflet-loader.jstest/netjsongraph.render.test.jstest/netjsongraph.duplicateNodes.test.jspackage.json
📚 Learning: 2026-01-20T16:50:56.414Z
Learnt from: codesankalp
Repo: openwisp/netjsongraph.js PR: 425
File: src/js/netjsongraph.render.js:1-26
Timestamp: 2026-01-20T16:50:56.414Z
Learning: In netjsongraph.js, prefer importing from echarts/lib/chart/*/install, echarts/lib/component/*/install, and echarts/lib/renderer/install* rather than the public entry points (echarts/charts, echarts/components, echarts/renderers) to improve tree-shaking and reduce bundle size. Apply this pattern across JS files in src (update imports accordingly) and verify by comparing bundle sizes between the install-path imports and the public-entry imports.
Applied to files:
src/js/netjsongraph.render.jssrc/js/netjsongraph.config.jssrc/js/echarts-leaflet/LeafletModel.jssrc/js/echarts-leaflet/LeafletCoordSys.jssrc/js/echarts-leaflet/index.jssrc/js/netjsongraph.jssrc/js/netjsongraph.core.jssrc/js/echarts-leaflet/LeafletView.js
📚 Learning: 2026-01-04T08:00:40.936Z
Learnt from: dee077
Repo: openwisp/netjsongraph.js PR: 417
File: src/js/netjsongraph.util.js:1302-1341
Timestamp: 2026-01-04T08:00:40.936Z
Learning: In the netjsongraph.js codebase, the `== null` pattern is intentionally used to check for both null and undefined values in a single comparison, which is a well-established JavaScript idiom and should not be flagged for replacement with strict equality checks.
Applied to files:
src/js/netjsongraph.render.jswebpack-plugins/inject-leaflet-loader.jstest/netjsongraph.duplicateNodes.test.js
📚 Learning: 2026-01-27T19:09:23.929Z
Learnt from: nemesifier
Repo: openwisp/netjsongraph.js PR: 473
File: src/js/netjsongraph.render.js:433-468
Timestamp: 2026-01-27T19:09:23.929Z
Learning: In the netjsongraph.js project, when implementing wheel zoom propagation from the graph container to the canvas: ECharts intercepts wheel events directly on the canvas with preventDefault(), so those events don't bubble to the container. A wheel listener on the container only catches events that occur outside the canvas (in the empty container space), making checks for e.target === canvas unnecessary since canvas events never reach the container listener.
Applied to files:
src/js/netjsongraph.render.jssrc/js/echarts-leaflet/LeafletCoordSys.jssrc/js/netjsongraph.js
📚 Learning: 2026-01-20T00:56:36.062Z
Learnt from: dee077
Repo: openwisp/netjsongraph.js PR: 417
File: src/js/netjsongraph.core.js:132-145
Timestamp: 2026-01-20T00:56:36.062Z
Learning: In the netjsongraph.js codebase, the data model does not support parallel links (multiple links between the same source and target). Ensure nodeLinkIndex is keyed by a single 'source~target' pair and that adding a link does not overwrite existing links for that pair. If parallel links are ever required, the data model must be changed (e.g., allow an array of links per 'source~target' key) rather than storing only one link.
Applied to files:
src/js/netjsongraph.render.jssrc/js/netjsongraph.config.jssrc/js/netjsongraph.core.jstest/netjsongraph.render.test.jstest/netjsongraph.duplicateNodes.test.js
📚 Learning: 2026-01-30T08:31:13.746Z
Learnt from: Dhruv-ub
Repo: openwisp/netjsongraph.js PR: 474
File: src/js/netjsongraph.render.js:347-351
Timestamp: 2026-01-30T08:31:13.746Z
Learning: In src/js/netjsongraph.render.js, treat showMapLabelsAtZoom = 0 as the explicit 'disabled' state (not a valid threshold). Do not rely on generic falsy checks for this flag. Update logic to distinguish between undefined/null (not set), 0 (disabled), and >0 (enabled at a given zoom). For example, use explicit checks such as: if (showMapLabelsAtZoom === 0) { /* labels hidden */ } else if (typeof showMapLabelsAtZoom === 'number' && showMapLabelsAtZoom > 0) { /* show labels at/above this zoom */ } else { /* default behavior or undefined */ }. If needed, document this convention or normalize input (e.g., set undefined to a sensible default) to avoid ambiguity in future reviews.
Applied to files:
src/js/netjsongraph.render.js
📚 Learning: 2026-01-22T22:37:11.271Z
Learnt from: CR
Repo: openwisp/netjsongraph.js PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-22T22:37:11.271Z
Learning: Run QA checks using `./run-qa-checks` before committing code
Applied to files:
.github/workflows/ci.yml
📚 Learning: 2026-01-22T22:37:11.271Z
Learnt from: CR
Repo: openwisp/netjsongraph.js PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-22T22:37:11.271Z
Learning: Applies to test/netjsongraph.browser.test.js : Write browser tests in test/netjsongraph.browser.test.js using Chrome/ChromeDriver and run with `yarn test test/netjsongraph.browser.test.js`
Applied to files:
.github/workflows/ci.ymltest/netjsongraph.render.test.jstest/netjsongraph.duplicateNodes.test.jspackage.json
📚 Learning: 2026-01-22T22:37:11.271Z
Learnt from: CR
Repo: openwisp/netjsongraph.js PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-22T22:37:11.271Z
Learning: Applies to **/*.test.{js,ts} : Write unit tests using Jest with jsdom and run with `yarn test`
Applied to files:
.github/workflows/ci.ymlpackage.json
📚 Learning: 2026-01-20T00:42:32.369Z
Learnt from: dee077
Repo: openwisp/netjsongraph.js PR: 417
File: src/js/netjsongraph.core.js:132-145
Timestamp: 2026-01-20T00:42:32.369Z
Learning: In the netjsongraph.js codebase, node IDs are guaranteed not to contain the "~" character, so using "source~target" as a composite key for links in nodeLinkIndex will not collide with node ID keys.
Applied to files:
webpack-plugins/inject-leaflet-loader.js
🧬 Code graph analysis (6)
src/js/netjsongraph.render.js (3)
src/js/leaflet-loader.js (2)
L(12-12)getLeaflet(14-38)src/js/echarts-leaflet/LeafletCoordSys.js (1)
L(12-12)src/js/netjsongraph.geojson.js (2)
L(136-136)L(140-140)
src/js/netjsongraph.config.js (4)
src/js/leaflet-loader.js (2)
L(12-12)getLeaflet(14-38)src/js/echarts-leaflet/LeafletCoordSys.js (1)
L(12-12)src/js/echarts-leaflet/index.js (1)
L(11-11)src/js/netjsongraph.geojson.js (2)
L(136-136)L(140-140)
src/js/echarts-leaflet/LeafletCoordSys.js (2)
src/js/leaflet-loader.js (2)
L(12-12)getLeaflet(14-38)src/js/echarts-leaflet/index.js (1)
L(11-11)
webpack-plugins/inject-leaflet-loader.js (1)
webpack.config.js (2)
InjectLeafletLoaderPlugin(10-10)HtmlWebpackPlugin(5-5)
src/js/netjsongraph.js (1)
src/js/echarts-leaflet/index.js (1)
registerLeafletSystem(10-37)
src/js/echarts-leaflet/LeafletView.js (1)
src/js/echarts-leaflet/LeafletCoordSys.js (3)
mapOffset(126-126)mapOffset(132-132)api(113-113)
🪛 Biome (2.3.13)
webpack-plugins/inject-leaflet-loader.js
[error] 142-142: Do not shadow the global "constructor" property.
Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.
(lint/suspicious/noShadowRestrictedNames)
🪛 GitHub Actions: netjsongraph.js CI BUILD
src/js/echarts-leaflet/index.js
[error] 1-1: Knip: Unused export 'default' found in src/js/echarts-leaflet/index.js.
package.json
[error] 1-1: Knip: Unused dependency 'zrender' detected in package.json.
[error] 1-1: Knip: Unused devDependency 'acorn' detected in package.json.
🪛 GitHub Check: CodeQL
.github/workflows/ci.yml
[warning] 52-129: Workflow does not contain permissions
Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {{contents: read}}
🔇 Additional comments (9)
src/js/netjsongraph.core.js (1)
80-80: Theasynckeyword doesn't make render() awaitable for completion.The method is marked
asyncbut doesn'tawaitthepaginatedDataParsepromise chain (lines 105-171). Callers whoawait render()will resolve immediately rather than when rendering actually completes.If the intent is to let callers wait for full render completion, consider returning and awaiting the promise:
🔧 Suggested approach
async render() { const [JSONParam, ...resParam] = this.JSONParam; // ... setup code ... - this.utils.paginatedDataParse + await this.utils.paginatedDataParse .call(this, JSONParam) .then((JSONData) => { // ... }) .catch((error) => { console.error(error); }); // ... }Alternatively, if the current fire-and-forget behavior is intentional, consider documenting this or removing
asyncto avoid misleading callers.src/js/echarts-leaflet/LeafletModel.js (1)
1-17: LGTM!Clean refactor removing the
echartsparameter in favor of direct import fromecharts/core. This aligns well with the modular architecture introduced by this PR.src/js/echarts-leaflet/LeafletView.js (1)
1-7: LGTM!The refactor to import
extendComponentViewandgetInstanceByDomdirectly fromecharts/coreis correct. Removing theechartsandLparameters simplifies the API while maintaining functionality through the model'sgetLeaflet()method.src/js/echarts-leaflet/LeafletCoordSys.js (1)
11-25: LGTM on the runtime Leaflet loading pattern.The destructuring of Leaflet components (
Layer,DomUtil,Projection, etc.) from the dynamically loaded instance is a clean approach that enables the echarts-only build while maintaining full functionality when Leaflet is available.src/js/echarts-leaflet/index.js (1)
10-21: LGTM on the graceful Leaflet handling.The early return when Leaflet is unavailable (lines 12-16) cleanly enables graph-only rendering without throwing errors, while still registering the coordinate system when Leaflet is present.
src/js/netjsongraph.config.js (1)
366-378: LGTM on the dynamic CRS resolution.The getter-based
crsproperty elegantly defers Leaflet loading until actually needed, returningnullwhen Leaflet is unavailable. This supports the echarts-only build while maintaining full functionality for map rendering.src/js/netjsongraph.render.js (3)
1-26: LGTM on the modular ECharts imports.The
echarts/lib/*/installimport pattern aligns with project learnings confirming this approach produces better tree-shaking results than the public entry points. Theuse()registration covers all required components for both graph and map rendering.Based on learnings: "In netjsongraph.js, prefer importing from echarts/lib/chart//install, echarts/lib/component//install, and echarts/lib/renderer/install* rather than the public entry points."
515-519: LGTM on the runtime Leaflet loading in mapRender.Clean error handling when Leaflet is unavailable, with targeted destructuring of only the needed Leaflet utilities (
circleMarker,latLngBounds). This pattern is consistent with other files in the PR.
206-207: LGTM on the series type updates.The changes from
graphGLtograph(line 206) and toscatter(line 327) correctly reflect the removal of echarts-gl dependency, aligning with the PR's goal of reducing library size.Also applies to: 327-327
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
- Update CI to use matrix strategy for 'dev' (unit+browser), 'prod' (browser), and 'echarts-only' (browser) builds. - Remove unsafe Terser optimizations to ensure stability. - Fix 'InjectLeafletLoaderPlugin' regex to prevent accidental removal of plugin scripts. - Use 'http-server' via npx in CI for serving production builds. Signed-off-by: Sankalp <[email protected]>
2caff6c to
1670b7b
Compare
I tried and leaflet plugins was working for me. can you please tell where it was breaking for you? I am testing echarts only build like this: Also, I have added separate CI matrix to test both complete and echarts only build where we are running browser tests. |
| "ignore": ["examples/**", "lib/js/**", "public/**", "scripts/**"], | ||
| "ignoreBinaries": ["wait-on"] | ||
| "ignoreBinaries": ["wait-on"], | ||
| "ignoreDependencies": ["leaflet"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is optional now.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
index.html (1)
123-131:⚠️ Potential issue | 🟡 MinorMake mobile cards truly full-width by sizing the card container.
width: 100%on the<a>alone won’t necessarily expand the.cardsflex item, so the mobile layout may still hug content width. Consider setting the card width in the media query.Proposed tweak
`@media` (max-width: 768px) { main { flex-direction: column; align-items: center; } + .cards { + width: 100%; + max-width: 100%; + } + .cards a { width: 100%; } }.github/workflows/ci.yml (1)
26-29:⚠️ Potential issue | 🟡 MinorUpdate deprecated
set-outputcommand.The
::set-outputcommand is deprecated. Use$GITHUB_OUTPUTenvironment file instead.🔧 Suggested fix
- name: Get yarn cache directory path id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" + run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUTAlso applies to line 69.
🤖 Fix all issues with AI agents
In `@package.json`:
- Around line 5-6: The package.json "main" entry points to a non-existent
index.js; fix by either adding a top-level index.js that re-exports the
library's public API (matching what built bundles export) or update the "main"
field to the actual build output (e.g., "dist/netjsongraph.js" or the production
filename pattern). Modify package.json "main" to the chosen bundle or create an
index.js that imports/exports from the build output (ensure symbols exported by
your library remain identical), and update any build/publish scripts if needed
so the referenced file exists after npm publish.
In `@webpack.config.js`:
- Around line 89-103: The optimization config sets sideEffects: false which
disables webpack's side-effects-based tree-shaking; change sideEffects to true
inside the optimization object (where usedExports, providedExports,
concatenateModules, etc. are set) so webpack will respect the package.json
"sideEffects" flags and drop unused modules—update the optimization.sideEffects
property from false to true and re-run the build to validate minification via
getMinimizers still behaves as expected.
🧹 Nitpick comments (1)
webpack-plugins/inject-leaflet-loader.js (1)
38-46: Consider extracting CDN version to a constant or reading from package.json.The Leaflet version
1.8.0is hardcoded in the CDN URLs. If the version inpackage.jsonis updated, these URLs would become stale. Consider extracting the version to a constant at the top of the file or reading it from package.json.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
.github/workflows/ci.ymlindex.htmlknip.jsonpackage.jsonsrc/js/echarts-leaflet/index.jssrc/js/leaflet-loader.jssrc/js/netjsongraph.jswebpack-plugins/inject-leaflet-loader.jswebpack.config.js
🚧 Files skipped from review as they are similar to previous changes (2)
- src/js/leaflet-loader.js
- src/js/netjsongraph.js
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{js,ts,css,scss,json}
📄 CodeRabbit inference engine (AGENTS.md)
Format code using
openwisp-qa-formatcommand with Python virtualenv enabled andyarn lint:fix(runs eslint --fix and prettier via lint-staged)
Files:
webpack.config.jsknip.jsonwebpack-plugins/inject-leaflet-loader.jssrc/js/echarts-leaflet/index.jspackage.json
src/**/*.js
📄 CodeRabbit inference engine (AGENTS.md)
Husky pre-commit hooks automatically run lint-staged to format JavaScript files in
src/**/*.jswith prettier
Files:
src/js/echarts-leaflet/index.js
🧠 Learnings (8)
📓 Common learnings
Learnt from: codesankalp
Repo: openwisp/netjsongraph.js PR: 425
File: src/js/netjsongraph.render.js:1-26
Timestamp: 2026-01-20T16:51:06.213Z
Learning: In the netjsongraph.js project, imports from `echarts/lib/chart/*/install`, `echarts/lib/component/*/install`, and `echarts/lib/renderer/install*` paths produce better tree-shaking results than the public entry points (`echarts/charts`, `echarts/components`, `echarts/renderers`) in their webpack configuration. The project maintainer has tested both approaches and confirmed the `/lib/*/install` pattern yields smaller bundles.
📚 Learning: 2026-01-20T16:51:06.213Z
Learnt from: codesankalp
Repo: openwisp/netjsongraph.js PR: 425
File: src/js/netjsongraph.render.js:1-26
Timestamp: 2026-01-20T16:51:06.213Z
Learning: In the netjsongraph.js project, imports from `echarts/lib/chart/*/install`, `echarts/lib/component/*/install`, and `echarts/lib/renderer/install*` paths produce better tree-shaking results than the public entry points (`echarts/charts`, `echarts/components`, `echarts/renderers`) in their webpack configuration. The project maintainer has tested both approaches and confirmed the `/lib/*/install` pattern yields smaller bundles.
Applied to files:
webpack.config.jswebpack-plugins/inject-leaflet-loader.jspackage.json
📚 Learning: 2026-01-04T08:00:40.936Z
Learnt from: dee077
Repo: openwisp/netjsongraph.js PR: 417
File: src/js/netjsongraph.util.js:1302-1341
Timestamp: 2026-01-04T08:00:40.936Z
Learning: In the netjsongraph.js codebase, the `== null` pattern is intentionally used to check for both null and undefined values in a single comparison, which is a well-established JavaScript idiom and should not be flagged for replacement with strict equality checks.
Applied to files:
webpack-plugins/inject-leaflet-loader.js
📚 Learning: 2026-01-20T00:42:32.369Z
Learnt from: dee077
Repo: openwisp/netjsongraph.js PR: 417
File: src/js/netjsongraph.core.js:132-145
Timestamp: 2026-01-20T00:42:32.369Z
Learning: In the netjsongraph.js codebase, node IDs are guaranteed not to contain the "~" character, so using "source~target" as a composite key for links in nodeLinkIndex will not collide with node ID keys.
Applied to files:
webpack-plugins/inject-leaflet-loader.js
📚 Learning: 2026-01-20T16:50:56.414Z
Learnt from: codesankalp
Repo: openwisp/netjsongraph.js PR: 425
File: src/js/netjsongraph.render.js:1-26
Timestamp: 2026-01-20T16:50:56.414Z
Learning: In netjsongraph.js, prefer importing from echarts/lib/chart/*/install, echarts/lib/component/*/install, and echarts/lib/renderer/install* rather than the public entry points (echarts/charts, echarts/components, echarts/renderers) to improve tree-shaking and reduce bundle size. Apply this pattern across JS files in src (update imports accordingly) and verify by comparing bundle sizes between the install-path imports and the public-entry imports.
Applied to files:
src/js/echarts-leaflet/index.js
📚 Learning: 2026-01-22T22:37:11.271Z
Learnt from: CR
Repo: openwisp/netjsongraph.js PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-22T22:37:11.271Z
Learning: Applies to test/netjsongraph.browser.test.js : Write browser tests in test/netjsongraph.browser.test.js using Chrome/ChromeDriver and run with `yarn test test/netjsongraph.browser.test.js`
Applied to files:
package.json.github/workflows/ci.yml
📚 Learning: 2026-01-22T22:37:11.271Z
Learnt from: CR
Repo: openwisp/netjsongraph.js PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-22T22:37:11.271Z
Learning: Applies to **/*.test.{js,ts} : Write unit tests using Jest with jsdom and run with `yarn test`
Applied to files:
package.json.github/workflows/ci.yml
📚 Learning: 2026-01-22T22:37:11.271Z
Learnt from: CR
Repo: openwisp/netjsongraph.js PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-22T22:37:11.271Z
Learning: Run QA checks using `./run-qa-checks` before committing code
Applied to files:
.github/workflows/ci.yml
🧬 Code graph analysis (2)
webpack.config.js (2)
test/netjsongraph.duplicateNodes.test.js (1)
require(1-1)test/netjsonWorker.test.js (1)
require(1-1)
src/js/echarts-leaflet/index.js (5)
src/js/leaflet-loader.js (2)
L(12-12)getLeaflet(14-38)src/js/netjsongraph.config.js (1)
L(370-370)src/js/echarts-leaflet/LeafletCoordSys.js (1)
L(12-12)src/js/echarts-leaflet/LeafletModel.js (1)
extendLeafletModel(6-50)src/js/echarts-leaflet/LeafletView.js (1)
extendLeafletView(6-122)
🪛 Biome (2.3.13)
webpack-plugins/inject-leaflet-loader.js
[error] 142-142: Do not shadow the global "constructor" property.
Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.
(lint/suspicious/noShadowRestrictedNames)
🪛 GitHub Check: CodeQL
.github/workflows/ci.yml
[warning] 52-129: Workflow does not contain permissions
Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {{contents: read}}
🔇 Additional comments (11)
index.html (1)
245-249: The "Nodes expand or fold" demo ships correctly.The
netjsongraph-nodeExpand.htmlfile exists at the referenced path (./examples/netjsongraph-nodeExpand.html), so the link will not 404. No changes needed.knip.json (1)
5-6: LGTM!The
ignoreDependenciesaddition forleafletis appropriate since it's now an optional peer dependency that's dynamically loaded at runtime. This prevents knip from incorrectly flagging it as unused..github/workflows/ci.yml (1)
119-121: LGTM!Browser tests running unconditionally across all matrix build types (
dev,prod,echarts-only) ensures the echarts-only build is properly exercised by CI, addressing the review concern about detecting future breakage.src/js/echarts-leaflet/index.js (2)
10-16: LGTM!The early return pattern with
getLeaflet(true)(suppressing errors) gracefully enables graph-only rendering when Leaflet is unavailable. This aligns well with the echarts-only build strategy.
1-5: LGTM!The imports are correctly structured. The
echarts/coreimport forregisterCoordinateSystemandregisterActionis appropriate since these are core registration APIs, not chart/component/renderer modules where the/lib/*/installpattern applies for tree-shaking. Based on learnings, the/lib/*/installpattern is specifically for chart, component, and renderer imports.webpack-plugins/inject-leaflet-loader.js (1)
57-127: LGTM!The plugin loading logic with
waitForLeafletpolling (5-second timeout) and coordinatedonload/onerrorhandlers ensures robust initialization. The error handlers appropriately prevent blocking initialization if a plugin fails to load.package.json (2)
89-99: LGTM!The dependency structure is now correct:
leafletindevDependenciesfor development/buildingleafletas optionalpeerDependencyfor consumers who need map features- Core
dependenciesreduced to onlyechartsandkdbushThis ensures echarts-only consumers won't install Leaflet by default while preserving full build capability.
6-6:sideEffects: falseis correctly configured and safe to use.The concern about import-time side effects breaking module registration is unfounded. The
registerLeafletSystem()function is imported but not called at module load time—it's explicitly invoked only wheninitializeECharts()runs during construction. The echarts registrations (registerCoordinateSystem,registerAction) occur inside the function body, not on import. No CSS imports or other import-time side effects exist that would be affected by tree-shaking.webpack.config.js (3)
61-88: LGTM!The build configuration cleanly handles both build variants:
isEchartsOnlyflag derived fromBUILD_TYPEenvironment variable- Conditional filenames with contenthash for production caching
- Leaflet externalized as
"L"for echarts-only builds, aligning with CDN loading
22-59: LGTM!The TerserPlugin configuration with aggressive compression options (3 passes, dead code elimination, unused removal) should produce well-optimized production bundles. The
hoist_vars: falsesetting is appropriate as hoisting variables can cause issues in some scenarios.
169-171: LGTM!The
DefinePlugincorrectly setsBUNDLE_LEAFLETtotruefor full builds andfalsefor echarts-only builds, aligning with the conditional logic insrc/js/leaflet-loader.js(lines 22-24) that decides whether torequire("leaflet")or usewindow.L.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
| "main": "index.js", | ||
| "sideEffects": false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify index.js exists and check its contents
if [ -f "index.js" ]; then
echo "index.js exists:"
cat index.js
else
echo "WARNING: index.js does not exist at package root"
echo "Searching for potential entry points:"
fd -t f 'index.js' --max-depth 2
fiRepository: openwisp/netjsongraph.js
Length of output: 154
🏁 Script executed:
#!/bin/bash
# List files at package root
echo "=== Package root contents ==="
ls -la | grep -E '^-'
echo ""
echo "=== Directory structure (top level) ==="
ls -la | head -20
echo ""
echo "=== Search for all index files ==="
fd -t f 'index\.' --max-depth 3
echo ""
echo "=== Check if there's a dist or build directory ==="
ls -la | grep -E '^d' | grep -v '^\.'Repository: openwisp/netjsongraph.js
Length of output: 3683
🏁 Script executed:
#!/bin/bash
# Check lib directory
echo "=== Contents of lib/ ==="
find lib -type f -name '*.js' -o -name '*.ts' | head -20
echo ""
echo "=== Contents of src/ ==="
find src -type f -name '*.js' -o -name '*.ts' | head -20
echo ""
echo "=== Current package.json main field ==="
grep -A 2 '"main"' package.json
echo ""
echo "=== package.json excerpt (lines 1-20) ==="
head -20 package.jsonRepository: openwisp/netjsongraph.js
Length of output: 1556
🏁 Script executed:
#!/bin/bash
# Check webpack.config.js for output configuration
echo "=== webpack.config.js output config ==="
grep -A 10 "output:" webpack.config.js
echo ""
echo "=== Check if there's any dist or build directory already ==="
ls -la | grep -E '^d' | awk '{print $NF}'Repository: openwisp/netjsongraph.js
Length of output: 765
The main entry point does not exist and must be fixed before publishing.
The package.json points to "main": "index.js", but this file does not exist at the package root. npm consumers will fail to import this package. The webpack configuration outputs to dist/ with filenames like netjsongraph.js (dev) or netjsongraph.[contenthash:8].min.js (production).
Either create an index.js entry point that re-exports the library's public API, or update the main field to point to the correct build output location (e.g., dist/netjsongraph.js for production builds).
🤖 Prompt for AI Agents
In `@package.json` around lines 5 - 6, The package.json "main" entry points to a
non-existent index.js; fix by either adding a top-level index.js that re-exports
the library's public API (matching what built bundles export) or update the
"main" field to the actual build output (e.g., "dist/netjsongraph.js" or the
production filename pattern). Modify package.json "main" to the chosen bundle or
create an index.js that imports/exports from the build output (ensure symbols
exported by your library remain identical), and update any build/publish scripts
if needed so the referenced file exists after npm publish.
| optimization: { | ||
| minimize: isProduction, | ||
| minimizer: getMinimizers(isProduction), | ||
| usedExports: true, | ||
| sideEffects: false, | ||
| providedExports: true, | ||
| concatenateModules: true, | ||
| flagIncludedChunks: true, | ||
| mangleExports: true, | ||
| removeAvailableModules: true, | ||
| removeEmptyChunks: true, | ||
| mergeDuplicateChunks: true, | ||
| innerGraph: true, | ||
| moduleIds: "deterministic", | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
webpack optimization.sideEffects true false meaning documentation
💡 Result:
In webpack, optimization.sideEffects controls whether webpack will drop entire modules/files during tree shaking when it believes importing them isn’t needed (because the import has “no side effects”). This works together with the "sideEffects" field in a package’s package.json (and module.rules[].sideEffects). [1]
-
optimization.sideEffects: true(default)
webpack will use side-effects information and can also analyze code to mark some modules as side‑effect‑free, allowing it to skip those modules when their exports aren’t used. [1] -
optimization.sideEffects: false
Disables this optimization: webpack will not try to skip modules based on side-effects detection/flags (so it’s less aggressive about pruning). [1] -
optimization.sideEffects: "flag"
webpack will only use the manual flags (package.json"sideEffects"andrule.sideEffects) and will not analyze source code for side effects. This is the default behavior in non‑production builds. [1]
Related (often confused) concept: the "sideEffects" field in a package’s package.json is the hint you (as a library/package author) provide:
"sideEffects": falsemeans “all files in this package are side‑effect‑free,” enabling webpack to drop unused files/imports (but this can be wrong for things like CSS/polyfills). [2]
Sources: webpack optimization config (optimization.sideEffects) [1], webpack tree-shaking guide (package.json "sideEffects") [2].
Change sideEffects: false to sideEffects: true to enable tree-shaking optimization.
In webpack's optimization.sideEffects, setting it to false disables tree-shaking: webpack will not skip modules based on side-effects detection. Setting it to true (the default) enables webpack to use side-effects information and analyze code to drop unused modules. Given the other aggressive optimizations in this config (usedExports: true, providedExports: true), this should be true to properly leverage the "sideEffects" field from package.json.
🔧 Suggested fix
optimization: {
minimize: isProduction,
minimizer: getMinimizers(isProduction),
usedExports: true,
- sideEffects: false,
+ sideEffects: true,
providedExports: true,📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| optimization: { | |
| minimize: isProduction, | |
| minimizer: getMinimizers(isProduction), | |
| usedExports: true, | |
| sideEffects: false, | |
| providedExports: true, | |
| concatenateModules: true, | |
| flagIncludedChunks: true, | |
| mangleExports: true, | |
| removeAvailableModules: true, | |
| removeEmptyChunks: true, | |
| mergeDuplicateChunks: true, | |
| innerGraph: true, | |
| moduleIds: "deterministic", | |
| }, | |
| optimization: { | |
| minimize: isProduction, | |
| minimizer: getMinimizers(isProduction), | |
| usedExports: true, | |
| sideEffects: true, | |
| providedExports: true, | |
| concatenateModules: true, | |
| flagIncludedChunks: true, | |
| mangleExports: true, | |
| removeAvailableModules: true, | |
| removeEmptyChunks: true, | |
| mergeDuplicateChunks: true, | |
| innerGraph: true, | |
| moduleIds: "deterministic", | |
| }, |
🤖 Prompt for AI Agents
In `@webpack.config.js` around lines 89 - 103, The optimization config sets
sideEffects: false which disables webpack's side-effects-based tree-shaking;
change sideEffects to true inside the optimization object (where usedExports,
providedExports, concatenateModules, etc. are set) so webpack will respect the
package.json "sideEffects" flags and drop unused modules—update the
optimization.sideEffects property from false to true and re-run the build to
validate minification via getMinimizers still behaves as expected.
Checklist
Reference to Existing Issue
Closes #392
Description of Changes
Use chunk splitting, dynamic loading and removed unused examples to reduce library size.
#425 (comment)