46

I want to ask if it is possible (and generally a good idea) to use npm to handle front-end dependencies (Backbone, jQuery).

I have found that Backbone, jQuery and so on are all available through npm but I would have to set another extraction point (the default is node_modules) or symlink or something else...

Has somebody done this before?

Is it possible?

What do I have to change in package.json?

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
dev.pus
  • 7,919
  • 13
  • 37
  • 51

5 Answers5

18

+1 for using Browserify. We use it here at diy.org and love it. The best introduction and reasoning behind Browserify can be found in the Browserify Handbook. Topics like CommonJS & AMD solutions, build pipelines and testing are covered there.

The main reason Browserify works so well is it transparently works w/ NPM. As long as a module can be required it can be Browserified (though not all modules are made to work in the browser).

Basics:

npm install jquery-browserify

main.js

var $ = require('jquery-browserify');
$("img[attr$='png']").hide();

Then run:

browserify main.js > bundle.js

Then include bundle.js in your HTML doc and the code in main.js will execute.

Derek Reynolds
  • 3,473
  • 3
  • 25
  • 34
17

Short answer: sort of.

It is largely up to the module author to support this, but it isn't common. Socket.io is an example of such a supporting module, as demonstrated on their landing page. There are other solutions however. These are the two I actually know anything about:

  • http://ender.no.de/ - Ender JS, self-described NPM analogue for client modules. A bit too involved for my tastes.
  • https://github.com/substack/node-browserify - Browserify, a utility that will walk your dependencies and allow you to output a single script by emulating the node.js module pattern. You can use a jake|cake|rake|make build script to spit out your application.js, and even automate it if you want to get fancy. I used this briefly, but decided it was a bit clunky, and became annoying to debug. Also, not all dual-environment npm modules like to be run through browserify.

Personally, I am currently opting for using RequireJS ( http://requirejs.org/ ) and manually managing my modules, similar to how Mozilla does with their BrowserQuest sample application ( https://github.com/mozilla/BrowserQuest ). Note that this comes with the challenge of having to potentially shim modules like backbone or underscore which removed support for AMD style module loaders. You can find an example of what is involved in shimming here: http://tbranyen.com/post/amdrequirejs-shim-plugin-for-loading-incompatible-javascript

Really it seems like it is going to hurt no matter what, which is why native module support is such a hot topic.

Steve McGuire
  • 1,467
  • 12
  • 8
  • Hi, thank you for the quick answer! I already use requirejs in my application, even I am not really common with it. However I dismissed a bit how you use RequireJs for the node_modules. Do you install a package via npm and than add the path (node_modules/jquery/index) to main.js or have I missed something? – dev.pus Jul 07 '12 at 05:38
  • Unfortunately, it wouldn't even directly use node_modules. Instead, you would keep a separate lib folder with your client dependencies/shims. I have an example here as well (start with application.js): https://github.com/steveorsomethin/umlol/tree/master/client – Steve McGuire Jul 07 '12 at 05:41
  • Ok that is nearly the same way I handle the deps currently. However thank you for your help. Now I know that there is no client-package manager :) – dev.pus Jul 07 '12 at 05:44
  • No problem :) Also, ender COULD still serve your needs, since it strives to be npm compatible. You would just have to make the investment and see if it fits. – Steve McGuire Jul 07 '12 at 05:48
  • btw. backbone now has support for AMD. – Legends Jan 03 '17 at 22:04
5

Our team maintains a tool called Lineman for building front-end projects. The tool is node-based, so a project relies on a lot of npm modules that operate server-side to build your assets, but out-of-the-box it expects to find your client-side dependencies in copied and committed to vendor/js.

However, a bunch of folks (myself included) have tried integrating with browserify, and we've run into a lot of complexity and problems, ranging from (a) npm modules being maintained by a third party which are either out of date or add unwanted changes, to (b) actual libraries that start failing when loaded traditionally whenever a top-level function named require is even defined, due to AMD/Require.js baggage.

My short-term recommendation is to hold off and stick with good ol' fashioned script concatenation until the dust settles. Until you have problems big enough or complex enough to warrant it, I suspect you'll spend more time debugging and remediating your build than you otherwise would. And I think most of us agree the best use of your time is focusing on your application code, not its build tools.

Justin Searls
  • 4,789
  • 4
  • 45
  • 56
  • 1
    Hi Justin. I don't like that this is the best answer, but it still is. I just finished up a project that did use a front-end module system (`brunch`), but we still didn't try to load our dependencies out of a package manager, let alone `npm`, which is (as is appropriate) full of node-specific code. – Sean McMillan Jul 02 '14 at 19:38
3

You might want to take a look at http://jspm.io/ which is a browser package manager. Has nice ES6 support too.

Brian Di Palma
  • 7,043
  • 3
  • 19
  • 15
1

I personally use webmake for my small projects. It is an alternative to browserify in the way it brings npm dependencies into your browser, and it's apparently lighter.

I didn't have the opportunity to compare in details browserify and webmake, but I noticed webmake doesn't work well with modules internally using global variables such as socket.io (which is full of bloat anyway IMO).

I would be cautious about RequireJS, which has been recommended above. Because it is an AMD loader, your browser will load your JS files asynchronously. It will induces more exchanges between your client and server and may degrade the UX of people browsing from mobile networks / under bad WiFi. Moreover, if you succeed to keep your JS code simple and tiny, asynchronous loading is absolutely not needed !

vcarel
  • 1,787
  • 1
  • 16
  • 23