2

I'm trying to create an npm package that could be used by web apps or other node modules.

If I were to only support browsers, I would just assign to window window.myExport = myExport; (unless there's a more modern way I'm not aware of?).

If I were to only support node modules, I would just use export, module.exports = myExport; (again, if there's a better way I'm not aware of, please let me know).

But I want to support both. Currently, what I'm doing is

var window, module;
if (window)
    window.myExport = myExport;
if (module)
    module.exports = myExport;

This looks very ugly, but works so far. What's a better approach? This is very lightweight node module, so I don't want to bring in some builder like webpack or something unless un-avoidable. I am already using babel though to create an es5 compatible version of my code, so if babel can solve this issue for me, that would work.

junvar
  • 11,151
  • 2
  • 30
  • 46

1 Answers1

3

If someone is already using npm to manage their dependencies than it is logical to assume that they will be using something like webpack or browserify that will allow them to import/require the module. It would be unusual for someone to download a library from NPM and manually include it in their page. I would also consider it a gross violation for an npm library to add itself to the window object. This could cause all sorts of issues especially if different versions of your library are included on the same page.

The real question is ES module exports or commonJS exports. Of which I currently favor CommonJS because ES modules are not natively implemented in nodejs yet so you have to use babel to easily import them.

Deadron
  • 5,135
  • 1
  • 16
  • 27
  • I'm not so sure about it being a gross violation. Providing an option that can be plugged directly into the browser is beneficial but shouldn't be mixed with a module option like the asker suggests. Not everything is a SPA with module resolution. – Clint Mar 05 '18 at 19:39
  • the web app I was hoping to integrate with doesn't use webpack or browserify. In fact, this would be the first npm module it imports. Other imports, such as jquery, are done through bower and directly injected onto window. I don't have as much freedom to modify the webapp as I do with my node module, which is why I'm interested in my options. – junvar Mar 05 '18 at 19:56
  • You can always add the module to the window in your project's code. I strongly recommend not allowing the module to add itself to the window automatically. Npm modules are designed specifically to be imported/required. What happens if code on the page outside your project uses this dependency since it was added to the window? You have now created an implicit dependency on an npm module that is not explicitly declared on the page. If that is your use case it is better to not use npm at all and add the script into your page. – Deadron Mar 05 '18 at 20:16
  • "The real question is ES module exports or commonJS exports", If i stick with `module.export = ...`, how would I be able to use this in a web app? Would I need webpack or browserify, or can commonJS exports be imported via browser's es6 import statements? Maybe my npm package can do both `module.exports = myExport; export default bsv;`? – junvar Mar 05 '18 at 21:18
  • The simple answer is no. Browsers do not have native support for modules. This is why you must use something like webpack or babelify to resolve your modules inside your npm project. I think you are making your npm usage too complicated. One option might be to publish multiple versions of your script with one made to be included in the browser as is while another is to be a npm package. Keep in mind Npm is not positioned as a solution to manage browser resources. This is more the domain of bower. – Deadron Mar 06 '18 at 01:34
  • 1
    The comment about no native browser support is now out of date. Refer to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules for more details. – Deadron Jul 10 '20 at 18:54