g0t4 / webpack-stats-graph

Generate a graph to visualize modules and bundles from webpack via stats.json
MIT License
32 stars 18 forks source link

issue with webpack 4 following this pluralsight course of yours! #4

Open cantacuzene opened 6 years ago

cantacuzene commented 6 years ago

Hello there ! I just started to watch your webpack course on pluralsight and came upon a little error running webpack-stats-graph with a webpack 4 generated json.

the issue is :

       graphId: d.moduleId.toString(),
                            ^

TypeError: Cannot read property 'toString' of null
    at issuers.m.reasons.map.d (/usr/local/lib/node_modules/webpack-stats-graph/index.js:329:29)
    at Array.map (<anonymous>)
    at parseModule (/usr/local/lib/node_modules/webpack-stats-graph/index.js:327:8)
    at Array.map (<anonymous>)
    at modulesByChunks.forEach.p (/usr/local/lib/node_modules/webpack-stats-graph/index.js:410:8)
    at Array.forEach (<anonymous>)
    at buildGraph (/usr/local/lib/node_modules/webpack-stats-graph/index.js:405:19)
    at Object.<anonymous> (/usr/local/lib/node_modules/webpack-stats-graph/index.js:126:15)
    at Module._compile (module.js:649:30)
    at Object.Module._extensions..js (module.js:660:10)

the issue is caused by the map on the reason object. It seems the moduleId can be null now.

a quick and dirty patch could be to check for null when mapping on line 348 of the index.js:

      .map(d => ({
        // again make sure to use string for id:
        graphId: d.moduleId !== null && d.moduleId !== undefined? d.moduleId.toString():"",
        type: d.type,
      })),

but I guess might be better ways to do this . here is the content of my statfile:


{
  "errors": [],
  "warnings": [
    "configuration\nThe 'mode' option has not been set. Set 'mode' option to 'development' or 'production' to enable defaults for this environment. "
  ],
  "version": "4.1.1",
  "hash": "3015f48d8a587d325813",
  "time": 100,
  "builtAt": 1521127314535,
  "publicPath": "",
  "outputPath": "/Users/mp/optimizing-web-apps-webpack/app/dist",
  "assetsByChunkName": {
    "main": "app.bundle.js"
  },
  "assets": [
    {
      "name": "app.bundle.js",
      "size": 1110,
      "chunks": [
        0
      ],
      "chunkNames": [
        "main"
      ],
      "emitted": true
    }
  ],
  "filteredAssets": 0,
  "entrypoints": {
    "main": {
      "chunks": [
        0
      ],
      "assets": [
        "app.bundle.js"
      ]
    }
  },
  "chunks": [
    {
      "id": 0,
      "rendered": true,
      "initial": true,
      "entry": true,
      "size": 961,
      "names": [
        "main"
      ],
      "files": [
        "app.bundle.js"
      ],
      "hash": "b62316bcb1454f1555e5",
      "siblings": [],
      "parents": [],
      "children": [],
      "modules": [
        {
          "id": 0,
          "identifier": "/Users/mp/optimizing-web-apps-webpack/app/klondike/scoring.js",
          "name": "./app/klondike/scoring.js",
          "index": 1,
          "index2": 0,
          "size": 867,
          "cacheable": true,
          "built": true,
          "optional": false,
          "prefetched": false,
          "chunks": [
            0
          ],
          "issuer": "/Users/mp/optimizing-web-apps-webpack/app/app.js",
          "issuerId": 1,
          "issuerName": "./app/app.js",
          "issuerPath": [
            {
              "id": 1,
              "identifier": "/Users/mp/optimizing-web-apps-webpack/app/app.js",
              "name": "./app/app.js"
            }
          ],
          "failed": false,
          "errors": 0,
          "warnings": 0,
          "assets": [],
          "reasons": [
            {
              "moduleId": 1,
              "moduleIdentifier": "/Users/mp/optimizing-web-apps-webpack/app/app.js",
              "module": "./app/app.js",
              "moduleName": "./app/app.js",
              "type": "harmony side effect evaluation",
              "userRequest": "./klondike/scoring.js",
              "loc": "1:0-31"
            }
          ],
          "usedExports": false,
          "providedExports": null,
          "optimizationBailout": [
            "ModuleConcatenation bailout: Module is not an ECMAScript module"
          ],
          "depth": 1,
          "source": "angular.module(\"klondike.scoring\", [])\n  .service(\"scoring\", [function Scoring() {\n    \"use strict\";\n\n    this.score = 0;\n\n    this.newGame = function () {\n      this.score = 0;\n    };\n    this.tableauCardTurnedUp = function () {\n      this.score += 5;\n    };\n    this.dropped = function (source, destionation) {\n      this.score += scoreForMoving(source, destionation) || 0;\n    };\n    this.wasteRecycled = function () {\n      this.score = Math.max(this.score - 100, 0);\n    };\n\n    function scoreForMoving(source, destionation) {\n      if (destionation.name === \"TableauPile\") {\n        if (source.name === \"FoundationPile\") {\n          return -15;\n        }\n        return 5;\n      }\n      if (destionation.name === \"FoundationPile\") {\n        if (source.name === \"TableauPile\" || source.name === \"WastePile\") {\n          return 10;\n        }\n      }\n    }\n  }]);\n"
        },
        {
          "id": 1,
          "identifier": "/Users/mp/optimizing-web-apps-webpack/app/app.js",
          "name": "./app/app.js",
          "index": 0,
          "index2": 1,
          "size": 94,
          "cacheable": true,
          "built": true,
          "optional": false,
          "prefetched": false,
          "chunks": [
            0
          ],
          "issuer": null,
          "issuerId": null,
          "issuerName": null,
          "issuerPath": null,
          "failed": false,
          "errors": 0,
          "warnings": 0,
          "assets": [],
          "reasons": [
            {
              "moduleId": "",
              "moduleIdentifier": null,
              "module": null,
              "moduleName": null,
              "type": "single entry",
              "userRequest": "/Users/mp/optimizing-web-apps-webpack/app/app.js",
              "loc": "main"
            }
          ],
          "usedExports": true,
          "providedExports": [],
          "optimizationBailout": [
            "ModuleConcatenation bailout: Module is an entry point"
          ],
          "depth": 0,
          "source": "import \"./klondike/scoring.js\";\n\n  angular.module(\"solitaire\", [\"klondike\", \"ngDraggable\"]);\n\n"
        }
      ],
      "filteredModules": 0,
      "origins": [
        {
          "module": "",
          "moduleIdentifier": "",
          "moduleName": "",
          "loc": "main",
          "request": "/Users/mp/optimizing-web-apps-webpack/app/app.js",
          "reasons": []
        }
      ]
    }
  ],
  "modules": [
    {
      "id": 0,
      "identifier": "/Users/mp/optimizing-web-apps-webpack/app/klondike/scoring.js",
      "name": "./app/klondike/scoring.js",
      "index": 1,
      "index2": 0,
      "size": 867,
      "cacheable": true,
      "built": true,
      "optional": false,
      "prefetched": false,
      "chunks": [
        0
      ],
      "issuer": "/Users/mp/optimizing-web-apps-webpack/app/app.js",
      "issuerId": 1,
      "issuerName": "./app/app.js",
      "issuerPath": [
        {
          "id": 1,
          "identifier": "/Users/mp/optimizing-web-apps-webpack/app/app.js",
          "name": "./app/app.js"
        }
      ],
      "failed": false,
      "errors": 0,
      "warnings": 0,
      "assets": [],
      "reasons": [
        {
          "moduleId": 1,
          "moduleIdentifier": "/Users/mp/optimizing-web-apps-webpack/app/app.js",
          "module": "./app/app.js",
          "moduleName": "./app/app.js",
          "type": "harmony side effect evaluation",
          "userRequest": "./klondike/scoring.js",
          "loc": "1:0-31"
        }
      ],
      "usedExports": false,
      "providedExports": null,
      "optimizationBailout": [
        "ModuleConcatenation bailout: Module is not an ECMAScript module"
      ],
      "depth": 1,
      "source": "angular.module(\"klondike.scoring\", [])\n  .service(\"scoring\", [function Scoring() {\n    \"use strict\";\n\n    this.score = 0;\n\n    this.newGame = function () {\n      this.score = 0;\n    };\n    this.tableauCardTurnedUp = function () {\n      this.score += 5;\n    };\n    this.dropped = function (source, destionation) {\n      this.score += scoreForMoving(source, destionation) || 0;\n    };\n    this.wasteRecycled = function () {\n      this.score = Math.max(this.score - 100, 0);\n    };\n\n    function scoreForMoving(source, destionation) {\n      if (destionation.name === \"TableauPile\") {\n        if (source.name === \"FoundationPile\") {\n          return -15;\n        }\n        return 5;\n      }\n      if (destionation.name === \"FoundationPile\") {\n        if (source.name === \"TableauPile\" || source.name === \"WastePile\") {\n          return 10;\n        }\n      }\n    }\n  }]);\n"
    },
    {
      "id": 1,
      "identifier": "/Users/mp/optimizing-web-apps-webpack/app/app.js",
      "name": "./app/app.js",
      "index": 0,
      "index2": 1,
      "size": 94,
      "cacheable": true,
      "built": true,
      "optional": false,
      "prefetched": false,
      "chunks": [
        0
      ],
      "issuer": null,
      "issuerId": null,
      "issuerName": null,
      "issuerPath": null,
      "failed": false,
      "errors": 0,
      "warnings": 0,
      "assets": [],
      "reasons": [
        {
          "moduleId": "",
          "moduleIdentifier": null,
          "module": null,
          "moduleName": null,
          "type": "single entry",
          "userRequest": "/Users/mp/optimizing-web-apps-webpack/app/app.js",
          "loc": "main"
        }
      ],
      "usedExports": true,
      "providedExports": [],
      "optimizationBailout": [
        "ModuleConcatenation bailout: Module is an entry point"
      ],
      "depth": 0,
      "source": "import \"./klondike/scoring.js\";\n\n  angular.module(\"solitaire\", [\"klondike\", \"ngDraggable\"]);\n\n"
    }
  ],
  "filteredModules": 0,
  "children": []
}
ghost commented 6 years ago

It seems nullable moduleId & moduleIdentifier in reason object are logical as app/app.js is the root module. Just curious whether changing the root to index.html would help to fix this...

g0t4 commented 6 years ago

Hey, thanks for sharing this fix. I'm glad you're digging into the example.

dvancuyk commented 6 years ago

I had this issue as well. I solved it by manually editing the installed webpack-stats-graph/index.js file, line 325 from: issuers: m.reasons .map(d => ({ graphId: (d.moduleId).toString(), type: d.type, })), To:

issuers: m.reasons .filter(d => d.moduleId) .map(d => ({ graphId: (d.moduleId).toString(), type: d.type, })),

Essentially I am just filtering out any nodes that don't have a moduleId associated with it.

Previously, I had just the moduleId to an empty string if it was null, but that gave me a line into my app.js in the rendering. This way makes it look like it does in the video.

cantacuzene commented 6 years ago

it sounds way better than my quick & dirty empty string :)

g0t4 commented 6 years ago

Have you all had any other trouble with webpack v4?

On Tue, Mar 20, 2018 at 5:59 PM, Hugo Cantacuzene notifications@github.com wrote:

it sounds way better than my quick & dirty empty string :)

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/g0t4/webpack-stats-graph/issues/4#issuecomment-374771591, or mute the thread https://github.com/notifications/unsubscribe-auth/AAK_3a_2PVSQQc0BOK0EbCzKPg3Oh6Kpks5tgXurgaJpZM4SsZWi .

cantacuzene commented 6 years ago

I just found my way around the webpack doc a little sooner than expected.

But again it was nothing the doc could not fix! That was a great course BTW!

Spidermain50 commented 6 years ago

@dvancuyk your solution did not work for me for some reason. I replaced the code on line 325 with your code and still getting that error when I run webpack-stats-graph.

@cantacuzene does updating to webpack 4 fix this issue?

cantacuzene commented 6 years ago

the issue is triggered by the webpack 4 upgrade. You should not have anyissues with webpack 3 stats files

johannao76 commented 6 years ago

@Spidermain50 : Check where the index.js file is being loaded from. I was having the same issue and the cause was that the file was being loaded from my local npm roaming directory.

@g0t4 : I am still unable to get the tool to work after applying the workarounds above, i get a new error

graphId: chunk.id,
               ^

TypeError: Cannot read property 'id' of undefined at parseClusterDetailsFromOneChunk (C:\Users\Johanna\AppData\Roaming\npm\node_modules\webpack-stats-graph\index.js:662:20) at parseClusterDetails (C:\Users\Johanna\AppData\Roaming\npm\node_modules\webpack-stats-graph\index.js:634:12) at modulesByChunks.forEach.p (C:\Users\Johanna\AppData\Roaming\npm\node_modules\webpack-stats-graph\index.js:414:28) at Array.forEach (<anonymous>) at buildGraph (C:\Users\Johanna\AppData\Roaming\npm\node_modules\webpack-stats-graph\index.js:406:19) at Object.<anonymous> (C:\Users\Johanna\AppData\Roaming\npm\node_modules\webpack-stats-graph\index.js:126:15) at Module._compile (module.js:652:30) at Object.Module._extensions..js (module.js:663:10) at Module.load (module.js:565:32) at tryModuleLoad (module.js:505:12)

Simply adding null check here results in further errors.

HACHIMIam commented 6 years ago

@johannao76 i have the same issue did you figure a way to solve it

nschulzke commented 6 years ago

I ran into this error and used the filter solution listed above (mine is slightly different--the one above will not show dependencies for those items that depend on module 0, because 0 does not evaluate to true). Take a look at my pull request to see the solution.

gitMonks commented 6 years ago

@dvancuyk Thanks a lot. This fixed it.

mhamri commented 6 years ago

@dvancuyk your solution is omitting the link between the modules like this: image

but @cantacuzene solution is perfect image

if anyone come for a solution here, follow the code that @cantacuzene put, but modify line 327

image

AlexJeffcott commented 6 years ago

@johannao76 @HACHIMIam @g0t4 I have fixed the original issue and the emergent issue. Edit the index.js, as talked about above as per the below:

For the original error, add the following under line 325 (as per the answer above and the open PR): .filter(d => d.moduleId !== null)

For the 'chunk.id' error, change line around 412 from: const clusterDetails = parseClusterDetails(chunkIds.map(c => stats.chunks[c])); to: const clusterDetails = parseClusterDetails(chunkIds.filter(id => stats.chunks[id]));

pks90 commented 6 years ago

@johannao76 , stats.json should not have any special characters and these special characters may sweep in as any warning thrown by webpack. In my case it was the missing --mode production from the npx webpack app/app.js --output app/dist/app.bundle.js --json > stats.json and hence there was a warning being thrown in the output json which was then being transferred to stats.json.

When I did npx webpack app/app.js --output app/dist/app.bundle.js --mode production --json > stats.json , it worked.

Violet-Bora-Lee commented 5 years ago

FYI, i made stats.json file with below command but it has same issues. npx webpack app/app.js --output app/dist/app.bundle.js --mode development --json > stats.json

I made img file with @AlexLexo 's solution.

voroninp commented 4 years ago

@g0t4 Hello from 2020 =) I am also watching your Pluralsight course.

Is there any reason why this PR is still not merged?

camiloxs commented 3 years ago

My workaround using webpack 4.44.2

  1. Add manually this PR
  2. Run (note --mode none) npx webpack app/app.js --output app/dist/app.bundle.js --mode none --json > stats.json