Skip to content
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

Refactored deprecation message for default format #207

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

mbrowne
Copy link

@mbrowne mbrowne commented Jul 19, 2019

Fixes #190

Copy link
Contributor

@dougwilson dougwilson left a comment

Choose a reason for hiding this comment

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

The thing that is deprecated is the morgan.default property, not just using a format string that happens to be the same format...

This would falsy give the message if the user gave their own string that is the same as the default level, which is definitely not deprecated (and is the only method to use that format in a non deprecated way).

@dougwilson dougwilson added the pr label Jul 19, 2019
@mbrowne
Copy link
Author

mbrowne commented Jul 19, 2019

Ah, sorry I missed that...does my latest commit work? It's not checking for the case where no format is passed, but that already has its own deprecation message (undefined format: specify a format), so I figured that was fine.

@mbrowne
Copy link
Author

mbrowne commented Aug 14, 2019

I think my latest changes should work? Can this be merged? Thank you

@dougwilson
Copy link
Contributor

Thank you, sorry I didn't see your previous message. It looks like there is no warning displayed on the usage of the deprecated property though? For example the following should produce a deprecated warning so folks know it will stop working in the next release:

app.use(morgan(`ACCESS ${morgan.default}`))

@mbrowne
Copy link
Author

mbrowne commented Aug 14, 2019

It shows the deprecation warning if you do: morgan('default'), which I thought was the standard way of doing it.

If morgan.default still needs to work, then unfortunately that defeats the whole purpose of this PR. esm assumes that module.exports.default is the default export of an ES6 module, which is why it's accessing it as soon as you import the module. The only way to solve it as far as I can tell is to ensure that module.exports.default no longer points to the default format function.

@dougwilson
Copy link
Contributor

So the idea is to remove the module.exports.default property, so the deprecation warning is to let folks know to not use it since it's going to be removed.

Are you saying we shouldn't remove that property?

@mbrowne
Copy link
Author

mbrowne commented Aug 14, 2019

Actually I just thought of a solution that I think preserves the current behavior...in my initial testing it seems to work fine. It's a change to the exports at the top of the file:

Object.defineProperty(module.exports, '__esModule', { value: true })
module.exports.default = morgan
module.exports.compile = compile
module.exports.format = format
module.exports.token = token

morgan.compile = compile
morgan.format = format
morgan.token = token

Can you think of any compatibility issues with this approach? If not, I can do some more testing and update the PR.

@dougwilson
Copy link
Contributor

I'm not familiar with that property, so no idea what it's effects would be.

@mbrowne
Copy link
Author

mbrowne commented Aug 14, 2019

We then see that we're setting the __esModule property of exports to true. This simply tells any system that imports this file that it just imported a module. If this option is off, some module resolution systems will assume that this file would put an object in the global scope and will execute it without trying to get any of its exports directly.

(from https://www.codementor.io/elliotaplant/understanding-javascript-module-resolution-systems-with-dinosaurs-il2oqro6e)

I'm guessing that as long as this solution works in native node.js and also with bundlers like webpack and rollup, that it should be fine? If all of those work, I can't think of a scenario where it would fail, unless older versions of node use a very different module resolution algorithm. I can test it with node 6 just in case.

@dougwilson
Copy link
Contributor

dougwilson commented Aug 14, 2019

This module supports down to Node.js 0.8

@mbrowne
Copy link
Author

mbrowne commented Aug 14, 2019

P.S. The __esModule property is automatically set to true by Babel and other tools when they're transpiling ES6 modules to CommonJS modules. So if you intend to use import/export syntax in the source code for any future version of this module, __esModule will be set to true anyhow.

@dougwilson
Copy link
Contributor

So from reading through Babel issues, etc. the __esModule === true is when the module is a ECMAScript module and not a CommonJS module. This is a CommonJS module, though. I'm trying to look at what issues this could case, but just at a high level, setting the __esModule to true doesn't seem correct, as this is, in fact, a Common JS module.

From my limited searching it would seem that setting __esModule to true, as your proposal is, would make folks who are using import morgan from "morgan" end up with morgan being a string and not the expected middleware function.

This is because when __esModule is not set, the Babel load will make module.exports the default export (which is how Common JS modules work), but when it is true, then the property with the name of default is treated as the default export.

@mbrowne
Copy link
Author

mbrowne commented Aug 16, 2019

After further investigation, I found that my proposed solution doesn't work the way I thought it would. (I think the only way that would work correctly is if it were a module imported by another module that had been transpiled from ES6, but obviously node users who aren't using any module bundler need to be able to require morgan directly.)

So this brings it back to a choice: either don't address this issue at all, or accept the fact that the deprecation warning would only show up with standard usage, i.e. morgan('default'). Any version of the code that keeps morgan.default pointing to the format function would not prevent the erroneous warning when using the esm module. In other words, if morgan(morgan.default) absolutely still needs to work as it did in previous versions and also show the deprecation warning, then the ESM issue can't be fixed.

The good news is that this library seems to work fine as-is with native modules support using node --experimental-modules; the issue only happens specifically with the 3rd party esm module. Since esm is a stopgap solution that will eventually become irrelevant once node finalizes native modules support, it would be understandable if you choose not to merge this PR.

@dougwilson
Copy link
Contributor

And just to clarify here: we are sure this is not just some kind of esm bug?

@mbrowne
Copy link
Author

mbrowne commented Aug 16, 2019

Originally I didn't think it was an esm bug, but after looking into this I'm wondering if maybe it is...maybe it wouldn't happen if esm checked for that __esModule flag. It seems like it's treating morgan as an ES module even though it's not.

@mbrowne
Copy link
Author

mbrowne commented Aug 16, 2019

Looks like someone reported this same issue in the esm repo:
standard-things/esm#812

@dougwilson
Copy link
Contributor

Thank you for the research you have put into this, it is really appreciated. Perhaps the best solution overall here is just to set some time aside this weekend and I will push out a 2.0 of morgan which will drop the .default export finally, which I think may be the best all-around solution. I'm not saying to close this PR per se; let me see what happens this weekend re: 2.0.

@yordis
Copy link

yordis commented Oct 17, 2019

@dougwilson any updates on finally removing default key after 5 years that key 😭

@Arnoldmn
Copy link

app.use(morgan('tiny')); this code the magic for me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Deprecation warning when using import
4 participants