hawtio icon indicating copy to clipboard operation
hawtio copied to clipboard

Console doesn't work after linking from local hawtio-next instance

Open mmelko opened this issue 2 years ago • 1 comments

After cloning latest main from hawtio-next , linking with yarn link ../../hawtio-next/packages/hawtio and rebuilding everything following exception is in javascript console:

Uncaught (in promise) TypeError: Cannot set properties of undefined (setting 'html')
    at k (193.aaebc9e3.chunk.js:1492:1025)
    at 807 (193.aaebc9e3.chunk.js:1497:89)
    at t (main.366cd516.js:1:243)
    at 57811 (193.aaebc9e3.chunk.js:430:9049)
    at t (main.366cd516.js:1:243)
    at 53078 (193.aaebc9e3.chunk.js:1487:164006)
    at t (main.366cd516.js:1:243)
    at 76938 (193.aaebc9e3.chunk.js:1497:386)
    at t (main.366cd516.js:1:243)
    at 97194 (193.aaebc9e3.chunk.js:1286:18887)
    ```

mmelko avatar Mar 22 '24 14:03 mmelko

I had the same problem. @tadayosi found that you have to remove 'html' from this array: https://github.com/hawtio/hawtio/blob/4.x/console/craco.config.js#L42

I have no idea why, but it works ;)

grgrzybek avatar Mar 22 '24 14:03 grgrzybek

This issue has been automatically marked as stale due to a year of inactivity. It will be closed if no further activity occurs within 14 days. If you think that’s incorrect or the issue should never stale, please simply write any comment. Thanks for your contributions!

github-actions[bot] avatar Mar 30 '25 01:03 github-actions[bot]

OH YES. After chatting for a while with ChatGPT I learned how to analyze webpack bundles. Generally (skipping code splitting):

webpack bundles concatenate javascript modules

By "javascript module" I mean single file, like ./node_modules/@patternfly/react-table/dist/esm/components/Table/CollapseColumn.js

While JavaScript itself has two kinds of modules:

  • ESM with import xxx from "yyy" and import("xxx")
  • CJS (Node.js, aka CommonJS) with require("xxx")

Webpack is mostly used to generate IIFE kind of modules - see output.iife option. Even if ESM works with current browsers, CJS does not.

So webpack generated code is roughly:

module definitions:

const __webpack_modules__ = ({
  "../node_modules/module1/index.js": (__webpack_module__, __webpack_exports__, __webpack_require__) => {
    // module code
  },
...
  "./src/index.ts": ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
    // module code
  },
...
})

and module usage:

__webpack_require__.e("webpack_sharing_consume_default_react_react")
...
__webpack_require__.e("src_bootstrap_tsx")
...
__webpack_require__(/*! ./cjs/react-dom.development.js */ "./node_modules/react-dom/cjs/react-dom.development.js")
...

(__webpack_require__.e() is chunk loading function for dynamic import() statements).

Now - in order to have consistent "JavaScipt application" we should ensure that we have no duplicated code.

I had this issue (discussed with ChatGPT), where React component <NavLink> form react-router was claimed to be rendered outside of <BrowserRouter> (even if code didn't show that).

The problem was that the react-router package was loaded differently:

  • by webpack itself - using __webpack_require__(/*! react-router */ "../../node_modules/react-router/dist/development/index.jsdist/development/chunk-D4RADZKF.mjs")
  • by webpack transforming external CJS package - using __webpack_require__(/*! react-router */ "../../node_modules/react-router/dist/development/index.js")

This is what helped (webpack.config.js):

resolve: {
  alias: {
    // because this app built with webpack used:
    //  - "../../node_modules/react-router/dist/development/index.js"
    // and @showcase/hawtio-react built with tsup used require("react-router") turned into:
    //  - "../../node_modules/react-router/dist/development/chunk-D4RADZKF.mjs"
    "react-router": path.resolve(__dirname, "../../node_modules/react-router")
  }
},

OK - back to this issue. @tadayosi suggested removing "html" from MonacoWebpackPlugin.languages - yes, it works, but we don't know why it works without "html" and we don't know why it breaks with "html" :)

So I simply analyzed the webpack-generated bundles in https://github.com/hawtio/hawtio/tree/4.x/console and I found:

  !*** ../../hawtio-next/node_modules/monaco-editor/esm/vs/base/browser/defaultWorkerFactory.js ***!
  !*** ./node_modules/monaco-editor/esm/vs/base/browser/defaultWorkerFactory.js ***!

(hint - edit the bundle in VIM and use :v/\*\*\* .*node_modules.* \*\*\*!$/d - this will roughly show you individual modules in the bundle)

And I have no idea how I found it, but the problem is here:

$ yarn link ../../hawtio-next/packages/hawtio

This line should make dev life easier - it creates a symlink from hawtio/console to hawtio-next/packages/hawtio, so the NPM package doesn't have to be downloaded from NPM.

There must be some issue with yarn portal protocol, because somehow the resolution escapes current tree and includes tree of the linked package - we don't want that!

This is the addition to package.json after yarn link (absolute location):

"resolutions": {
  "@hawtio/react": "portal:/data/sources/github.com/hawtio/hawtio-next/packages/hawtio"
}

and I found that if you change portal to file (symlink will be gone and package will be copied instead) the problem with monaco is gone! and in --mode development the size of vendors-node_modules_hawtio_react_dist_index_js.chunk.js is changed from 34MB to 23MB.

And hawtio just works.

Now I'll check if there are other duplications (not related to yarn link).

grgrzybek avatar May 16 '25 10:05 grgrzybek

Also chatgpt suggests:

Add this in both host and remote Webpack configs:

resolve: {
  symlinks: false,
}

    Prevents Yarn workspace symlinks from confusing Webpack into thinking @hawtio/react is two different packages (thus breaking singleton logic).

grgrzybek avatar Jun 03 '25 08:06 grgrzybek

@mmelko @tadayosi @phantomjinx I just checked ChatGPT suggestion about resolve.symlinks and it works! so no need to change portal: to file:, it's enough to have:

resolve: {
  extensions: ['.ts', '.tsx', '.js', '.jsx'],
  symlinks: false
},

in your webpack.config.js

grgrzybek avatar Jun 05 '25 09:06 grgrzybek