Skip to content

fix: log4js-node/log4js-node#968#1023

Closed
aellerton wants to merge 2 commits intolog4js-node:masterfrom
aellerton:webpack-968
Closed

fix: log4js-node/log4js-node#968#1023
aellerton wants to merge 2 commits intolog4js-node:masterfrom
aellerton:webpack-968

Conversation

@aellerton
Copy link
Copy Markdown

@aellerton aellerton commented May 27, 2020

This addresses #968 by allowing certain require's to run only in node, not in the browser.

All tests pass as before. However, I didn't add new tests specifically for this, which I
acknowledge isn't great, but I'm not sure how to write tests for "this works when
building with webpack" beyond adding a whole webpack project to the tests, and
grepping output. There might be a great way, but I'm not sure what it is.

I also found it useful to add this in the package.json of the project using log4js,
which I'm adding as a note here only in case it is useful for others facing this problem.

"browser": {
  "fs": false,
  "cluster": false
},

The initial PR build failed on Windows for unknown reasons; hopefully another build attempt will resolve that.

ellers added 2 commits May 27, 2020 14:53
Improve dynamic require for webpack.

You may also need this in the `package.json` of the project using
log4js:

```
"browser": {
  "fs": false,
  "cluster": false
},
```
Minor comment to clarify, and also kick off another build.
@aellerton aellerton closed this Jun 18, 2020
@aellerton aellerton reopened this Jun 18, 2020
Copy link
Copy Markdown

@Download Download left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took the liberty to review your code, even though I'm not in any way affiliated with this project :)
Hope it's helpful.

Comment thread lib/appenders/index.js
typeof process !== 'undefined' &&
process.versions != null &&
process.versions.node != null;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a nitpick, but why check against null?
I would expect:

const isNode = typeof process !== 'undefined' && process.versions && process.versions.node

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call. I should have seen this.

Comment thread lib/appenders/index.js
coreAppenders.set('fileSync', require('./fileSync'));
coreAppenders.set('file', isNode ? require('./file') : {});
coreAppenders.set('dateFile', isNode ? require('./dateFile') : {});
coreAppenders.set('fileSync', isNode ? require('./fileSync'): {});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether there is a better way to do this...

There is a field in package.json called browser that might be better suited for this use case.
The way it works is this: You specify which file(s) to use instead of the default one(s), when running on the browser.
For example, we could make a new file called core-appenders.js and place the lines creating the coreAppenders map and populating it with the core appenders in that file. We could then make a second file called core-appenders-browser.js and place the equivalent code for the browser in that file. Then, in package.json we would write:

{
  "browser": {
    "./lib/appenders/core-appenders.js": "./lib/appenders/core-appenders-browser.js"
  }
}

Then, Browserify, Webpack and Rollup et all will know to replace the code in core-appenders.js with the code in core-appenders-browser.js when building the browser version.

An example where this is used is the popular logging package debug:
https://github.com/visionmedia/debug/blob/4.2.0/package.json#L55

There are two forms for the browser field:

  • Object with node file names as keys and browser filenames as values
  • File name of entry point to use instead of the one listed in the main field.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hadn't realised this - nicely spotted, and clearly explained! Only thing that comes to mind is a possible ordering issue, or that there would be code duplication and one of those files (node or browser) could get left behind. I'm not sure i that's a higher price or the runtime cost; given the runtime cost is (as far as I can see) once off, I think it might be better to leave it as-is. More thought required!

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An important thing to understand about this line of code:

coreAppenders.set('file', isNode ? require('./file') : {});

Even though the isNode check will prevent the file appender from being added to the coreAppenders map on the browser, it actually still gets bundled into the browser bundle. The reason is that, even though Webpack is pretty clever, it's not actually smart enough to figure out that isNode will always be false on browsers. Basically what Webpack does is find all required files in a static analysis phase and make sure each and every single file that might be required at runtime gets packaged into the bundle.

Using the browser field to inform Webpack and other bundlers about the fact that the file appender is not used on browsers is the accepted/standard way to do this.

there would be code duplication

That depends entirely on how you structure things. Make sure you place only the code that differs between Node and browsers in separate files and then use the browser field to map the browser versions of those files. No code needs to be duplicated.

@aellerton
Copy link
Copy Markdown
Author

I took the liberty to review your code, even though I'm not in any way affiliated with this project :)
Hope it's helpful.

So happy to get your code review! Thanks for your time!

@jrebmann
Copy link
Copy Markdown

jrebmann commented Sep 8, 2020

I had the problem starting my vue project in the browser due to a dependency on a package that itself has a dependency on log4js.
I've tested this bugfix in my project and can confirm that it works.

But on compiling I get 2 warnings. Maybe it would be fine solve them as well:
image

@beorn
Copy link
Copy Markdown

beorn commented Nov 3, 2020

Any update on this? :-|

@aellerton
Copy link
Copy Markdown
Author

Yeah sorry, I've had a series of release deadlines that have stopped me from tackling this.

I had a look recently and noted that the core logic that routes log messages - a kind of root logger, if you will - is built around nodejs cluster API (https://nodejs.org/api/cluster.html) which, of course, isn't a thing in the browser.

That had me thinking that the approach of substituting files when building for the browse - which @Download rightly points out - may be adequate but not a very elegant solution. It'd be preferable to change the root logger idea into one which is browser or node, and that root logger requires all the bits it needs.

But naturally this is bigger than it looks and that takes me back to just doing the simplest solution to let webpack work.

Anyone have views and thoughts on best approach?

@sunfeng90
Copy link
Copy Markdown

Don't solve this in this version ?

@lamweili
Copy link
Copy Markdown
Contributor

Don't solve this in this version ?

This wasn't merged. You might want to see #1050 for possible solutions (which sadly no one ever got back on).

@aellerton
Copy link
Copy Markdown
Author

Superseded by #1374

@aellerton aellerton closed this Mar 7, 2023
@lamweili lamweili added this to the 6.8.1 milestone Mar 7, 2023
@lamweili lamweili added bug Something isn't working enhancement New feature or request and removed bug Something isn't working labels Mar 7, 2023
@lamweili lamweili modified the milestone: 6.9.0 Mar 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants