{"action":"created","issue":{"url":"https://api.github.com/repos/substack/node-browserify/issues/1151","labels_url":"https://api.github.com/repos/substack/node-browserify/issues/1151/labels{/name}","comments_url":"https://api.github.com/repos/substack/node-browserify/issues/1151/comments","events_url":"https://api.github.com/repos/substack/node-browserify/issues/1151/events","html_url":"https://github.com/substack/node-browserify/pull/1151","id":60138698,"number":1151,"title":"Make browserify recognize its own bundles","user":{"login":"jmm","id":129203,"avatar_url":"https://avatars.githubusercontent.com/u/129203?v=3","gravatar_id":"","url":"https://api.github.com/users/jmm","html_url":"https://github.com/jmm","followers_url":"https://api.github.com/users/jmm/followers","following_url":"https://api.github.com/users/jmm/following{/other_user}","gists_url":"https://api.github.com/users/jmm/gists{/gist_id}","starred_url":"https://api.github.com/users/jmm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jmm/subscriptions","organizations_url":"https://api.github.com/users/jmm/orgs","repos_url":"https://api.github.com/users/jmm/repos","events_url":"https://api.github.com/users/jmm/events{/privacy}","received_events_url":"https://api.github.com/users/jmm/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":11,"created_at":"2015-03-06T18:21:33Z","updated_at":"2015-03-09T13:56:35Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/substack/node-browserify/pulls/1151","html_url":"https://github.com/substack/node-browserify/pull/1151","diff_url":"https://github.com/substack/node-browserify/pull/1151.diff","patch_url":"https://github.com/substack/node-browserify/pull/1151.patch"},"body":"# Summary\r\n\r\n* It's a pain in the neck to use a browserify bundle in a subsequent bundling operation.\r\n\r\n* Wouldn't it be nice if you could just `require()` a browserify bundle in another bundle?\r\n\r\n* Pragma: prepend on output, detect on input\r\n\r\n* [Demo](https://github.com/jmm/browserify-pragma-demo)\r\n\r\nI think this is pretty light-weight and useful, but it seems like the kind of thing I should get some thumbs up on before going ahead with.\r\n\r\nThis involves changes to browserify and several dependencies, so the branch this points to is just a placeholder. The real commits are here:\r\n\r\n* https://github.com/substack/node-browserify/compare/9.0.3...jmm:pragma\r\n* https://github.com/substack/browser-pack/compare/4.0.1...jmm:pragma\r\n* https://github.com/substack/module-deps/compare/3.7.2...jmm:pragma\r\n\r\nTests pass except for one on browserify that I think will be remedied easily enough.\r\n\r\nMy anecdotal testing suggests this would have a negligible impact on performance, but I welcome suggestions on how it should be tested.\r\n\r\n# Details\r\n\r\nCurrently it's kind of a pain in the neck to bundle a browserify bundle A in a new browserify bundle B, e.g.:\r\n\r\n```js\r\nbrowserify('./entry.js')\r\n```\r\n\r\n`entry.js`\r\n```js\r\n// bundle-a is a browserify bundle\r\nrequire('./bundle-a');\r\n```\r\n\r\nIf you just do that it's highly prone to failure. There are at least 2 failure modes:\r\n\r\n1. Bundle operation B errors out because it attempts to resolve paths in `require()` calls in bundle A and doesn't find them. It's unnecessary and undesirable to even do this because bundle A already contains all of the files referenced by `require()` calls that it needs to contain.\r\n\r\n2. Bundle operation B resolves paths from `require()` calls in bundle A to files that don't have anything to do with anything and includes them in the bundle even though they're not referenced by anything.\r\n\r\nI've seen confusion about how to consume a bundle in a subsequent bundling operation a number of times here and on stackoverflow<sup><a href=\"#footnote-1\">1</a></sup>. Generally it can be cured by:\r\n\r\n1. Setting `noParse` for bundle A in the bundle B operation; or\r\n2. Running the standalone bundle through derequire; or\r\n3. Minifying the bundle\r\n\r\nBut each of those approaches requires that you and / or consumers of the module keep track of which modules are browserify bundles and / or modify them or do extra work to use them, instead of being able to just require them like any other module.\r\n\r\nAnd to boot, `noParse` currently suffers from path mis-matching issues that are affecting a lot of things in browserify right now (e.g. it's sensitive to including / omitting file extension for one thing).\r\n\r\nAnd a lot of users don't even know about doing those things. Neither the `noParse` documentation nor the notes about derequire even mention that use case. Also, standalone bundles used to be processed through derequire on creation and that was discontinued. I don't think it's obvious, especially to users used to the former behavior, that it won't work to:\r\n\r\n# just `require()` a browserify bundle in another bundle.\r\n\r\nWouldn't it be nice if you could do that, without breaking anything else? I think there might be a way. This PR is a proof of concept of a method for doing that.\r\n\r\nIn a nutshell, when bundling:\r\n\r\n* On output, prepend a pragma kind of thing, similar to the ECMAScript `use strict` directive. The current format I'm testing is: `({\"compiler\": \"browserify\", \"version\": \"1.23.456\"});`\r\n\r\n* On input check the beginning of each bundled file for the pragma. When found, `noParse` the file. Probably omit transforms as well (but that could be an option).\r\n\r\nI'm guessing that the pragma format(s) I'm testing wouldnt wouldn't break one bundle in a million in the wild, but if that doesn't seem safe enough then a (bit) longer, more arbitrary value could be added, like `b1c2247fb27f6c8ffb66871b1cfbd30e`, which I expect would reduce the likelihood of breakage to one in a trillion.\r\n\r\nThese are the ideas I've iterated through for the format of the pragma (chronological order):\r\n\r\n* `\"BROWSERIFIED\";` (or with `'`)\r\n* `\"BROWSERIFIED@1.2.3\";` (or with `'`)\r\n* `\"compiler:browserify@1.2.3\";` (or with `'`)\r\n* `'{\"compiler\": \"browserify\", \"version\": \"1.23.456\"}';`\r\n* `({\"compiler\": \"browserify\", \"version\": \"1.23.456\"});` (current)\r\n* More compact possible alternative: `({\"browserify\": \"1.23.456\"});`\r\n\r\nAnother option could be to apply special handling by file extension(s), like `.bify.js`, `.browserify.js`, or `.browserified.js`, but I favor the pragma approach if it's one or the other.\r\n\r\nThoughts?\r\n\r\n<a id=\"footnote-1\">1.</a>\r\n* http://stackoverflow.com/q/28266540/1034448\r\n* http://stackoverflow.com/q/28078425/1034448\r\n* https://github.com/substack/node-browserify/issues/374\r\n"},"comment":{"url":"https://api.github.com/repos/substack/node-browserify/issues/comments/77857297","html_url":"https://github.com/substack/node-browserify/pull/1151#issuecomment-77857297","issue_url":"https://api.github.com/repos/substack/node-browserify/issues/1151","id":77857297,"user":{"login":"calvinmetcalf","id":1128607,"avatar_url":"https://avatars.githubusercontent.com/u/1128607?v=3","gravatar_id":"","url":"https://api.github.com/users/calvinmetcalf","html_url":"https://github.com/calvinmetcalf","followers_url":"https://api.github.com/users/calvinmetcalf/followers","following_url":"https://api.github.com/users/calvinmetcalf/following{/other_user}","gists_url":"https://api.github.com/users/calvinmetcalf/gists{/gist_id}","starred_url":"https://api.github.com/users/calvinmetcalf/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/calvinmetcalf/subscriptions","organizations_url":"https://api.github.com/users/calvinmetcalf/orgs","repos_url":"https://api.github.com/users/calvinmetcalf/repos","events_url":"https://api.github.com/users/calvinmetcalf/events{/privacy}","received_events_url":"https://api.github.com/users/calvinmetcalf/received_events","type":"User","site_admin":false},"created_at":"2015-03-09T13:56:34Z","updated_at":"2015-03-09T13:56:34Z","body":"@jmm  we could go one farther actually and since detective is finding all of the requires detective could also change the function name as it finds it and then in the latter step when browserify wraps in in the `function (require, exports, module){}` it could use the modified name for require.  This would likely be the most performant version possible but would have some issues with people not wanting their code mangled like that."}}