{"action":"closed","number":3421,"pull_request":{"url":"https://api.github.com/repos/jashkenas/backbone/pulls/3421","id":26440842,"html_url":"https://github.com/jashkenas/backbone/pull/3421","diff_url":"https://github.com/jashkenas/backbone/pull/3421.diff","patch_url":"https://github.com/jashkenas/backbone/pull/3421.patch","issue_url":"https://api.github.com/repos/jashkenas/backbone/issues/3421","number":3421,"state":"closed","locked":false,"title":"Make jquery in commonjs a standard dependency","user":{"login":"dgbeck","id":1483694,"avatar_url":"https://avatars.githubusercontent.com/u/1483694?v=3","gravatar_id":"","url":"https://api.github.com/users/dgbeck","html_url":"https://github.com/dgbeck","followers_url":"https://api.github.com/users/dgbeck/followers","following_url":"https://api.github.com/users/dgbeck/following{/other_user}","gists_url":"https://api.github.com/users/dgbeck/gists{/gist_id}","starred_url":"https://api.github.com/users/dgbeck/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dgbeck/subscriptions","organizations_url":"https://api.github.com/users/dgbeck/orgs","repos_url":"https://api.github.com/users/dgbeck/repos","events_url":"https://api.github.com/users/dgbeck/events{/privacy}","received_events_url":"https://api.github.com/users/dgbeck/received_events","type":"User","site_admin":false},"body":"## Context\r\n\r\nLooks like this all started back in #2862, which added a UMD wrapper in which jquery was omitted as a dependency when a commonjs environment was detected, based on the reasoning that commonjs is for the server side and jquery is not needed on the server side. In this first iteration of the UMD, `Backbone.$` was left undefined in the commonjs environment. However, commonjs was becoming increasingly common on the client side thanks to tools like browserify, Web Pack, component, cartero, et. al. #2862 was then merged so that backbone could be used with jquery in commonjs environments, which added a `require( 'jquery' )` but wrapped it in a try / catch. However, this \"light dependency\" approach \"broke\" browserify, as discussed in #2997, since browserify would fail if jquery was not present. As a result of this issue the [require + try / catch was removed](https://github.com/jashkenas/backbone/commit/f1479e62eb74a2dd85fdf2e20d9c907c5757313e) altogether, and it was made a requirement to explicitly set `Backbone.$` in all commonjs environments.\r\n\r\n```\r\nvar Backbone = require('backbone');\r\nBackbone.$ = require('jquery');\r\n```\r\n\r\nUnfortunately, we've seen this solution also has its share of problems:\r\n\r\n* the requirement of setting `Backbone.$ = require('jquery')` is not intuitive and most people miss it, which is a constant source of friction (see #3038 and #3240).\r\n* that pattern can not be used in Firefox plugins (see #3156).\r\n* there are issues when a third party module requires jquery to be set on `Backbone.$` (see #3291). Under the current paradigm, eventhough the module needs jquery to be available at `Backbone.$`, potentially even at load time, the responsibly for putting it there falls on the application developer, not the module author. The module author has no way of guaranteeing what the application developer is going to put there when, and the application developer is burdened by what is really an internal concern of the module.\r\n\r\n## Proposed solution\r\n\r\nThe proposed solution in this PR is to go with the straight forward solution of treating jquery as a standard dependency (as it is in AMD environments). What follows is a break down of how this solution would play out with the various use cases.\r\n\r\n### On the server side (node)\r\n\r\n#### For people using jquery\r\nEverything just works.\r\n\r\n#### For people who do not need a DOM library\r\njquery will install and will load when the node application starts up, as soon as backbone is `require`d, eventhough it is not needed. However both the disk space it consumes and the time it takes to load are too small to have any consequential impact.\r\n\r\n#### For people who want to use a DOM library other than jquery\r\nSame as above case, except that `Backbone.$` will need to be set to the alternate DOM library during startup. (Assuming node_modules has been [deduped](https://docs.npmjs.com/cli/dedupe), the backbone module is shared accross the entire application and thus setting `Backbone.$` at application startup is sufficient to ensure that the alternate DOM library is always used by backbone.)\r\n\r\n### On the client side\r\n\r\n#### For people using jquery\r\nThis is the most common case, I think. Using this approach, everything just works for this case as expected. (Note that `npm dedupe` still needs to be run to make sure that only one copy of jquery will be floating around.)\r\n\r\n#### For people who want to use a DOM library other than jquery\r\nThis is the group of people who would be inconvenienced by this approach. Luckily the inconvenience is pretty minimal. They need to either\r\n\r\na) Explicitly set `Backbone.$` to the DOM library of their choice whenever a page is loaded, and then configure the build tool to ignore the jquery dependency (so that jquery is not dead weight in their js bundle). With browserify, the `exclude` option can be used to have `require('jquery')` return `undefined`:\r\n\r\n```\r\nbrowserify main.js --exclude jquery > bundle.js\r\n```\r\n\r\nWith Web Pack,\r\n\r\n```\r\n{\r\n    plugins: [\r\n        new webpack.IgnorePlugin(/^jquery$/)\r\n    ]\r\n}\r\n```\r\n\r\nb) configure their build tool to \"alias\" jquery for another library. With browserify, this can be done with aliasify,\r\n\r\n```\r\nnpm install --save aliasify\r\n```\r\n\r\nAdd an \"aliasify\" section to the application's `package.json`:\r\n\r\n```\r\n{\r\n    \"aliasify\": {\r\n        aliases: {\r\n            \"jquery\": \"zepto\"\r\n        }\r\n    }\r\n}\r\n```\r\n\r\nUsing WebPack, the [resolve.alias](http://webpack.github.io/docs/configuration.html#resolve-alias) configuration option can be used:\r\n\r\n```\r\n{\r\n    context: __dirname + \"/app\",\r\n    entry: \"./entry\",\r\n    output: {\r\n        path: __dirname + \"/dist\",\r\n        filename: \"bundle.js\"\r\n    }\r\n    resolve : {\r\n    \talias : {\r\n\t\t\t\"jquery\": \"zepto\"\r\n\t\t}\r\n\t}\r\n}\r\n```\r\n\r\n#### For people who want to use a DOM library with backbone and jquery in other places\r\n\r\nJust set `Backbone.$` explicitly to the library of their choosing.\r\n\r\n## Comparison with try / catch\r\n\r\nAnother solution worth considering is to go back to #2862 which wraps the `require( 'jquery' )` in a try / catch. This solution would also address most of the problems with the current approach. However,\r\n\r\n1. I don't see a significant upside over the standard dependency approach.\r\n2. #2997 would again be a problem, which we know for sure, since we have been there before.\r\n2. The lack of clarity as to what is actually supposed to be at `Backbone.$` presents a problem for module and meta framework authors. I agree with @akre54's [comment](https://github.com/jashkenas/backbone/issues/2997#issuecomment-67651342):\r\n\r\n> Marionette should be using the same jQuery as Backbone and the same jQuery as your app. It becomes an absolute mess when your view's $el property has a different $.fn than the rest of your app\r\n\r\nBut where is the global jquery object? External modules and meta frameworks can not assume `Backbone.$` is jquery and interact with it as such if there is no firm stance taken. What is `Backbone.$` supposed to be in the baseline case? Is it jquery? Is it zepto? What the heck is it?\r\n\r\nIf backbone has a standard dependency on jquery then it is clear - the baseline case is that `Backbone.$` === the global jquery object.","created_at":"2014-12-22T06:24:53Z","updated_at":"2015-03-20T16:42:44Z","closed_at":"2015-03-20T16:42:44Z","merged_at":null,"merge_commit_sha":"9f566da52fb556dcd09098e4a42e042ce06f88cb","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/jashkenas/backbone/pulls/3421/commits","review_comments_url":"https://api.github.com/repos/jashkenas/backbone/pulls/3421/comments","review_comment_url":"https://api.github.com/repos/jashkenas/backbone/pulls/comments{/number}","comments_url":"https://api.github.com/repos/jashkenas/backbone/issues/3421/comments","statuses_url":"https://api.github.com/repos/jashkenas/backbone/statuses/df5a215399759b9c646e4fc839bee9da30a60043","head":{"label":"dgbeck:jquery-commonjs-dep","ref":"jquery-commonjs-dep","sha":"df5a215399759b9c646e4fc839bee9da30a60043","user":{"login":"dgbeck","id":1483694,"avatar_url":"https://avatars.githubusercontent.com/u/1483694?v=3","gravatar_id":"","url":"https://api.github.com/users/dgbeck","html_url":"https://github.com/dgbeck","followers_url":"https://api.github.com/users/dgbeck/followers","following_url":"https://api.github.com/users/dgbeck/following{/other_user}","gists_url":"https://api.github.com/users/dgbeck/gists{/gist_id}","starred_url":"https://api.github.com/users/dgbeck/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dgbeck/subscriptions","organizations_url":"https://api.github.com/users/dgbeck/orgs","repos_url":"https://api.github.com/users/dgbeck/repos","events_url":"https://api.github.com/users/dgbeck/events{/privacy}","received_events_url":"https://api.github.com/users/dgbeck/received_events","type":"User","site_admin":false},"repo":{"id":7347787,"name":"backbone","full_name":"dgbeck/backbone","owner":{"login":"dgbeck","id":1483694,"avatar_url":"https://avatars.githubusercontent.com/u/1483694?v=3","gravatar_id":"","url":"https://api.github.com/users/dgbeck","html_url":"https://github.com/dgbeck","followers_url":"https://api.github.com/users/dgbeck/followers","following_url":"https://api.github.com/users/dgbeck/following{/other_user}","gists_url":"https://api.github.com/users/dgbeck/gists{/gist_id}","starred_url":"https://api.github.com/users/dgbeck/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dgbeck/subscriptions","organizations_url":"https://api.github.com/users/dgbeck/orgs","repos_url":"https://api.github.com/users/dgbeck/repos","events_url":"https://api.github.com/users/dgbeck/events{/privacy}","received_events_url":"https://api.github.com/users/dgbeck/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/dgbeck/backbone","description":"Give your JS App some Backbone with Models, Views, Collections, and Events","fork":true,"url":"https://api.github.com/repos/dgbeck/backbone","forks_url":"https://api.github.com/repos/dgbeck/backbone/forks","keys_url":"https://api.github.com/repos/dgbeck/backbone/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dgbeck/backbone/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dgbeck/backbone/teams","hooks_url":"https://api.github.com/repos/dgbeck/backbone/hooks","issue_events_url":"https://api.github.com/repos/dgbeck/backbone/issues/events{/number}","events_url":"https://api.github.com/repos/dgbeck/backbone/events","assignees_url":"https://api.github.com/repos/dgbeck/backbone/assignees{/user}","branches_url":"https://api.github.com/repos/dgbeck/backbone/branches{/branch}","tags_url":"https://api.github.com/repos/dgbeck/backbone/tags","blobs_url":"https://api.github.com/repos/dgbeck/backbone/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dgbeck/backbone/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dgbeck/backbone/git/refs{/sha}","trees_url":"https://api.github.com/repos/dgbeck/backbone/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dgbeck/backbone/statuses/{sha}","languages_url":"https://api.github.com/repos/dgbeck/backbone/languages","stargazers_url":"https://api.github.com/repos/dgbeck/backbone/stargazers","contributors_url":"https://api.github.com/repos/dgbeck/backbone/contributors","subscribers_url":"https://api.github.com/repos/dgbeck/backbone/subscribers","subscription_url":"https://api.github.com/repos/dgbeck/backbone/subscription","commits_url":"https://api.github.com/repos/dgbeck/backbone/commits{/sha}","git_commits_url":"https://api.github.com/repos/dgbeck/backbone/git/commits{/sha}","comments_url":"https://api.github.com/repos/dgbeck/backbone/comments{/number}","issue_comment_url":"https://api.github.com/repos/dgbeck/backbone/issues/comments{/number}","contents_url":"https://api.github.com/repos/dgbeck/backbone/contents/{+path}","compare_url":"https://api.github.com/repos/dgbeck/backbone/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dgbeck/backbone/merges","archive_url":"https://api.github.com/repos/dgbeck/backbone/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dgbeck/backbone/downloads","issues_url":"https://api.github.com/repos/dgbeck/backbone/issues{/number}","pulls_url":"https://api.github.com/repos/dgbeck/backbone/pulls{/number}","milestones_url":"https://api.github.com/repos/dgbeck/backbone/milestones{/number}","notifications_url":"https://api.github.com/repos/dgbeck/backbone/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dgbeck/backbone/labels{/name}","releases_url":"https://api.github.com/repos/dgbeck/backbone/releases{/id}","created_at":"2012-12-28T00:10:30Z","updated_at":"2013-01-13T20:39:43Z","pushed_at":"2015-02-25T04:22:15Z","git_url":"git://github.com/dgbeck/backbone.git","ssh_url":"git@github.com:dgbeck/backbone.git","clone_url":"https://github.com/dgbeck/backbone.git","svn_url":"https://github.com/dgbeck/backbone","homepage":"http://backbonejs.org","size":24777,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"jashkenas:master","ref":"master","sha":"29244e4175c06ae16fc17f51450769cc40788c6f","user":{"login":"jashkenas","id":4732,"avatar_url":"https://avatars.githubusercontent.com/u/4732?v=3","gravatar_id":"","url":"https://api.github.com/users/jashkenas","html_url":"https://github.com/jashkenas","followers_url":"https://api.github.com/users/jashkenas/followers","following_url":"https://api.github.com/users/jashkenas/following{/other_user}","gists_url":"https://api.github.com/users/jashkenas/gists{/gist_id}","starred_url":"https://api.github.com/users/jashkenas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jashkenas/subscriptions","organizations_url":"https://api.github.com/users/jashkenas/orgs","repos_url":"https://api.github.com/users/jashkenas/repos","events_url":"https://api.github.com/users/jashkenas/events{/privacy}","received_events_url":"https://api.github.com/users/jashkenas/received_events","type":"User","site_admin":false},"repo":{"id":952189,"name":"backbone","full_name":"jashkenas/backbone","owner":{"login":"jashkenas","id":4732,"avatar_url":"https://avatars.githubusercontent.com/u/4732?v=3","gravatar_id":"","url":"https://api.github.com/users/jashkenas","html_url":"https://github.com/jashkenas","followers_url":"https://api.github.com/users/jashkenas/followers","following_url":"https://api.github.com/users/jashkenas/following{/other_user}","gists_url":"https://api.github.com/users/jashkenas/gists{/gist_id}","starred_url":"https://api.github.com/users/jashkenas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jashkenas/subscriptions","organizations_url":"https://api.github.com/users/jashkenas/orgs","repos_url":"https://api.github.com/users/jashkenas/repos","events_url":"https://api.github.com/users/jashkenas/events{/privacy}","received_events_url":"https://api.github.com/users/jashkenas/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jashkenas/backbone","description":"Give your JS App some Backbone with Models, Views, Collections, and Events","fork":false,"url":"https://api.github.com/repos/jashkenas/backbone","forks_url":"https://api.github.com/repos/jashkenas/backbone/forks","keys_url":"https://api.github.com/repos/jashkenas/backbone/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jashkenas/backbone/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jashkenas/backbone/teams","hooks_url":"https://api.github.com/repos/jashkenas/backbone/hooks","issue_events_url":"https://api.github.com/repos/jashkenas/backbone/issues/events{/number}","events_url":"https://api.github.com/repos/jashkenas/backbone/events","assignees_url":"https://api.github.com/repos/jashkenas/backbone/assignees{/user}","branches_url":"https://api.github.com/repos/jashkenas/backbone/branches{/branch}","tags_url":"https://api.github.com/repos/jashkenas/backbone/tags","blobs_url":"https://api.github.com/repos/jashkenas/backbone/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jashkenas/backbone/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jashkenas/backbone/git/refs{/sha}","trees_url":"https://api.github.com/repos/jashkenas/backbone/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jashkenas/backbone/statuses/{sha}","languages_url":"https://api.github.com/repos/jashkenas/backbone/languages","stargazers_url":"https://api.github.com/repos/jashkenas/backbone/stargazers","contributors_url":"https://api.github.com/repos/jashkenas/backbone/contributors","subscribers_url":"https://api.github.com/repos/jashkenas/backbone/subscribers","subscription_url":"https://api.github.com/repos/jashkenas/backbone/subscription","commits_url":"https://api.github.com/repos/jashkenas/backbone/commits{/sha}","git_commits_url":"https://api.github.com/repos/jashkenas/backbone/git/commits{/sha}","comments_url":"https://api.github.com/repos/jashkenas/backbone/comments{/number}","issue_comment_url":"https://api.github.com/repos/jashkenas/backbone/issues/comments{/number}","contents_url":"https://api.github.com/repos/jashkenas/backbone/contents/{+path}","compare_url":"https://api.github.com/repos/jashkenas/backbone/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jashkenas/backbone/merges","archive_url":"https://api.github.com/repos/jashkenas/backbone/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jashkenas/backbone/downloads","issues_url":"https://api.github.com/repos/jashkenas/backbone/issues{/number}","pulls_url":"https://api.github.com/repos/jashkenas/backbone/pulls{/number}","milestones_url":"https://api.github.com/repos/jashkenas/backbone/milestones{/number}","notifications_url":"https://api.github.com/repos/jashkenas/backbone/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jashkenas/backbone/labels{/name}","releases_url":"https://api.github.com/repos/jashkenas/backbone/releases{/id}","created_at":"2010-09-30T19:41:28Z","updated_at":"2015-03-20T16:10:09Z","pushed_at":"2015-03-20T15:51:27Z","git_url":"git://github.com/jashkenas/backbone.git","ssh_url":"git@github.com:jashkenas/backbone.git","clone_url":"https://github.com/jashkenas/backbone.git","svn_url":"https://github.com/jashkenas/backbone","homepage":"http://backbonejs.org","size":46689,"stargazers_count":21106,"watchers_count":21106,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":4731,"mirror_url":null,"open_issues_count":33,"forks":4731,"open_issues":33,"watchers":21106,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/jashkenas/backbone/pulls/3421"},"html":{"href":"https://github.com/jashkenas/backbone/pull/3421"},"issue":{"href":"https://api.github.com/repos/jashkenas/backbone/issues/3421"},"comments":{"href":"https://api.github.com/repos/jashkenas/backbone/issues/3421/comments"},"review_comments":{"href":"https://api.github.com/repos/jashkenas/backbone/pulls/3421/comments"},"review_comment":{"href":"https://api.github.com/repos/jashkenas/backbone/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/jashkenas/backbone/pulls/3421/commits"},"statuses":{"href":"https://api.github.com/repos/jashkenas/backbone/statuses/df5a215399759b9c646e4fc839bee9da30a60043"}},"merged":false,"mergeable":false,"mergeable_state":"dirty","merged_by":null,"comments":13,"review_comments":2,"commits":2,"additions":5,"deletions":3,"changed_files":2}}