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

Advice required for working with npm packages that break Hem conventions #73

Open
louismrose opened this issue Jul 26, 2013 · 3 comments

Comments

@louismrose
Copy link

Hi,

Firstly, thank-you for Hem: a fantastic tool that significantly simplifies my workflow!

I'm having a little bit of trouble understanding how I can use Hem with npm packages that don't have an index.js file. For example, I'm trying to use Hem to allow my application to require files from the codemirror npm package. I see that codemirror has the following package.json:

{
  "name": "codemirror",
  "version": "3.14.1",
  "main": "lib/codemirror.js",
  "directories": {
    "lib": "./lib"
  }
  ...
}

I have a number of questions related to this:

  1. When I try to require('codemirror'), Hem can't find the module and I receive module 'codemirror' not found. This makes sense as there is no index.js file (and I see that Hem's stitch.eco looks for the path of an index file). Instead, I see that a require('codemirror/lib/codemirror') does work. Is there any workaround for this so that I can use require('codemirror')?
  2. lib/codemirror.js exports a global variable onto window, rather than onto module.exports, like this: window.CodeMirror = (function() { ... I see that Hem expects the CommonJS style, and so won't pick up this variable. I can change lib/codemirror.js to store the variable on module.exports, but I'd prefer not to change code that I don't own. Is there any workaround for this?
  3. The codemirror npm package includes a number of additional JS files that I'd like to include, but they rely on the presence of the CodeMirror variable. I can issue a separate require statement for each: require('codemirror/lib/codemirror') then a require('codemirror/modes/javascript/javascript'). However, this fails because codemirror/modes/javascript/javascript assumes that it will be able to access the CodeMirror global variable, and I believe that Hem might be requiring files into a "sandboxed" environment where there is no access to other variables. The following doesn't work either: CodeMirror = require('codemirror/lib/codemirror') followed by a require('codemirror/modes/javascript/javascript'). Any ideas?
  4. The codemirror npm package includes a number of CSS files that I'd like to include in my application. Is there any support for this in Hem?

I'm using Spine as my application framework, and would prefer to use the npm dependencies rather than plain-old javascript files (i.e. Hem libs) if possible.

If needed and of interest to the Hem developers, I would be happy to work on a patch to support any of the features above (though I would require a little help in designing solutions).

Thank-you in advance for answers or hints towards solving any of these questions.

Best,
Louis.

@cengebretson
Copy link
Member

Hi Louis,

Thanks for the questions and input, definitely appreciated. I'll try my best to answer the questions you posted.

  1. This is a known issue, right now the way Hem determines npm modules to load is fairly simple and it doesn't completely model itself after how the node require process works. I think this should be a fairly easy thing to fix in a future version of hem but as of right now you will probably have to stick with require('codemirror/lib/codemirror') if you don't want to modify the codemirror package structure.

  2. This one is a bit trickier. I took a brief look at the codemirror project and it doesn't appear to be a true node module, in that it doesn't use module.exports and uses a reference to window instead. Off the top of my head I can't really think of an easy way to transform npm modules that don't use the commonjs standard to something that uses modules.export; that is for the most part up to the module author. That said, I think the module as its written can still be used, you just end up with CodeMirror as window/global space variable when used on the browser.

  3. I think if you try the following it should work...

    require('codemirror/lib/codemirror')  
    require('codemirror/modes/javascript/javascript')
    

    The first require should set window.CodeMirror correctly, and from that point on CodeMirror will exist as a global variable which every module should have access to using window.CodeMirror or even CodeMirror.

  4. This is might be hard to pull off, in that node modules are meant for node/server applications, not necessarily for the web. So there really isn't a standard way to know where to look for css files. One approach would be to scan all the folders in a module and include all CSS but this seems pretty fragile. I think in this case something like bower or component might be a better approach as they are geared more towards web projects. Component looks very interesting in that it already supports the commonjs approach so it would be fairly easy to incorporate.

I am currently working on a refactor of hem and one of the main areas I wanted to focus on was improving the module/dependency handling. I'd like to keep the ability of using npm modules, but at the some time was hoping to open the door to using bower/component as well. Its my gut feeling that the web related javascript modules are a better fit in those vs trying to make them npm modules.

@louismrose
Copy link
Author

Hi Chris,

Thanks so much for taking the time to reply, and providing such a detailed and helpful response!

As our app is increasingly dependent on front-end Javascript modules rather than Node modules, we might be better served by switching to Bower or Component as you suggested.

This past week, I've been investigating Yeoman (Bower + Grunt + RequireJS), and this combination has solved all of the issues I list above. However, I must say that putting all of these components together has taken a lot of effort (I'd say around 8 hours so far), and has made me appreciate even more how much utility we were getting from Hem with very little effort! I think it might be time for us to switch to Yeoman for the flexibility, but I will certainly miss the simplicity that Hem provides.

Keep up the good work, and I shall be looking out for Bower / Component support in Hem, so that we can switch back to a simpler world!

Cheers,
Louis.

@cengebretson
Copy link
Member

Hi Louis,

Again I appreciate the feedback. I really do like the idea of something that should take minutes to setup (vs hours) and hopefully I can get hem to that point. I think it should be doable, especially if simple conventions are followed.

Really it should be a matter of simply putting the files in the correct location and they are automagically used/compiled. I understand that doesn't work for everyone or for every application, in those cases something like yeoman is a great tool, but for simple web applications I think hem can have a home.

But it would be great to get some more feedback once the refactored hem is ready for serious use, I'll update this issue once its further along.

thanks!

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

No branches or pull requests

2 participants