{"action":"created","issue":{"url":"https://api.github.com/repos/ipfs/js-ipfs/issues/429","repository_url":"https://api.github.com/repos/ipfs/js-ipfs","labels_url":"https://api.github.com/repos/ipfs/js-ipfs/issues/429/labels{/name}","comments_url":"https://api.github.com/repos/ipfs/js-ipfs/issues/429/comments","events_url":"https://api.github.com/repos/ipfs/js-ipfs/issues/429/events","html_url":"https://github.com/ipfs/js-ipfs/issues/429","id":172322987,"number":429,"title":"Distributing JavaScript","user":{"login":"dignifiedquire","id":790842,"avatar_url":"https://avatars.githubusercontent.com/u/790842?v=3","gravatar_id":"","url":"https://api.github.com/users/dignifiedquire","html_url":"https://github.com/dignifiedquire","followers_url":"https://api.github.com/users/dignifiedquire/followers","following_url":"https://api.github.com/users/dignifiedquire/following{/other_user}","gists_url":"https://api.github.com/users/dignifiedquire/gists{/gist_id}","starred_url":"https://api.github.com/users/dignifiedquire/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dignifiedquire/subscriptions","organizations_url":"https://api.github.com/users/dignifiedquire/orgs","repos_url":"https://api.github.com/users/dignifiedquire/repos","events_url":"https://api.github.com/users/dignifiedquire/events{/privacy}","received_events_url":"https://api.github.com/users/dignifiedquire/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/ipfs/js-ipfs/labels/discussion","name":"discussion","color":"fbca04"},{"url":"https://api.github.com/repos/ipfs/js-ipfs/labels/enhancement","name":"enhancement","color":"84b6eb"},{"url":"https://api.github.com/repos/ipfs/js-ipfs/labels/milestone%204","name":"milestone 4","color":"c2e0c6"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":7,"created_at":"2016-08-21T14:15:24Z","updated_at":"2016-10-20T14:44:13Z","closed_at":null,"body":"JS IPFS is a large collection of modules that aim to implement IPFS in Node.js and the browser. As such the distributions of these modules has a specific set of constraints.\r\n\r\nOur current setup is not bad, and does generate bundles usable in Node.js and the browser, but there are some pain points that need work.\r\n\r\n### Current Pain Points\r\n\r\n1. Bundles are quite large\r\n2. Lots of dependencies are duplicated, for example `readable-stream` is included 12 times in the current `js-ipfs` browser bundle.\r\n3. Developers have to know very domain specific configurations to\r\n   be able to use browserify or webpack.\r\n4. We break browserify and webpack compat without knowing about it\r\n   until we get a bug report.\r\n\r\n### Optimization Goals\r\n\r\n1. Bundle Size\r\n2. Ease of use for developers embedding the library (i.e. Orbit)\r\n3. Ease of use for contributors\r\n\r\n### Module Formats\r\n\r\nThere are two different module formats for JavaScript modules in main use today.\r\n\r\n1. CommonJS\r\n  - `var dep = require('dependency')`\r\n  - Only native format in Node.js at the moment.\r\n2. ES2015 Modules\r\n  - `import dep from 'dependency'`\r\n  - You can read about it in detail in this article: http://www.2ality.com/2014/09/es6-modules-final.html\r\n\r\nThe current code base uses CommonJS.\r\n\r\n### Available Tooling\r\n\r\nThe tooling landscape is quite large today, with things developing and changing quite rapidly. The for us currently relevant tooling is listed below.\r\n\r\n#### Module Bundlers\r\n\r\nA module bundler can take in many JavaScript files and generate a bundle, which is usable in the browser.\r\n\r\n1. [Webpack] (CommonJS, ES2015)\r\n2. [jspm] (CommonJS, ES2015)\r\n3. [Closure Compiler] (CommonJS, ES2015)\r\n4. [Rollup] (CommonJS, ES2015)\r\n5. [Browserify] (CommonJS)\r\n6. [Babel] (CommonJS, ES2015)\r\n\r\n#### ES2015 Transpilers\r\n\r\nTranspilers can transform code written with ES2015 features and output code that is usable in ES5 (and lower) environments.\r\n\r\n1. [Babel]\r\n2. [Typescript]\r\n3. [Closure Compiler]\r\n\r\nA good comparision of the differences in size and runtime can be found in [The cost of transpiling ES2015 in 2016](https://github.com/samccone/The-cost-of-transpiling-es2015-in-2016).\r\n\r\n## Proposal\r\n\r\nGiven the set of constraints mentioned above, the following is a list of steps I suggest to improve and solve our current pain points.\r\n\r\n#### 1. Improve build artifacts\r\n\r\nSimilar to what PouchDB does, the end result for Node.js and the browser should be a single file.\r\n\r\nIf there are differences between Node.js and browser, modules use two different entry points\r\n\r\n- `src/index.js` - Original source for node.js\r\n- `src/index-browser.js` - Original source the browser\r\n\r\nFor the builds we target the same places as currently\r\n\r\n- `dist/index.js` ES5 code for the browser\r\n- `lib/index.js` - ES5 code for node.js\r\n\r\nbut `lib/index.js` will be a single file, fully transformed rather than still many files such that treeshaking and processing of things like webpack loaders already happend and this is runnable through in node.js directly.\r\n\r\nTo make tooling aware of what is avaliable, the following should fields should be in `package.json`\r\n\r\n```json\r\n\"main\": \"./lib/index.js\",\r\n\"jsnext:main\": \"./src/index.js\",\r\n\"browser\": {\r\n  \"./lib/index.js\": \"./dist/index.js\"\r\n},\r\n\"jspm\": {\r\n  \"main\": \"dist/index.js\"\r\n}\r\n```\r\n\r\n##### Benefits\r\n\r\n- Fully compatabile out of the box, with default configuaration with\r\n  - browserify\r\n  - webpack\r\n  - jspm\r\n  - rollup\r\n\r\n##### Drawbacks\r\n\r\n- Transpiled code in `lib/index.js` is a bit harder to read as it\r\n  is now a single large file.\r\n\r\n#### 2. Test webpack & browserify in CI\r\n\r\n1. Build with the default configurations for browserify and webpack.\r\n2. Run the full test suite against these versions.\r\n\r\n##### Benefits\r\n\r\n- We can be sure that our builds are usable by other developers.\r\n\r\n##### Drawbacks\r\n\r\n- CI run time increases.\r\n\r\n#### 3. Move to ES2015 Modules\r\n\r\n- Using tools like [cjs-to-es6](https://github.com/nolanlawson/cjs-to-es6) this is pretty straight forward for our own modules.\r\n- For dependencies that do not yet publish a build which uses ES2015\r\n- Enable tree shaking in our webpack build.\r\n\r\n#### Benefits\r\n\r\n- Smaller module size, due to the availability of statically analyzable dependencies and so allowing us to use tree shaking\r\n\r\n#### Drawbacks\r\n\r\n- Not runnable in Node.js directly anymore until they integrate ES2015 modules or you use something like [`babel-register`](https://www.npmjs.com/package/babel-register).\r\n\r\n#### 4. Carefully audit the dependency tree\r\n\r\n- Look at all of them\r\n- Migrate where needed and large enough benefits are clear to ES2105 modules\r\n- Major culprits that we know about\r\n  - all shims for Node.js functionality in the browser\r\n  - forge\r\n  - web-crypto -> browserify-crypto\r\n  - readable-stream and all users of it\r\n\r\n##### Benefits\r\n\r\n- Only include what we absolutly need\r\n- Improves tree shaking if we can use dependencies that use ES2015 modules.\r\n\r\n##### Drawbacks\r\n\r\n- Takes time\r\n\r\n### Resources\r\n\r\n#### Blog Posts\r\n\r\n- https://nolanlawson.com/2016/08/15/the-cost-of-small-modules/\r\n- https://pouchdb.com/2016/01/13/pouchdb-5.2.0-a-better-build-system-with-rollup.html\r\n- https://pouchdb.com/2016/06/06/introducing-pouchdb-custom-builds.html\r\n- https://github.com/samccone/The-cost-of-transpiling-es2015-in-2016\r\n- http://www.2ality.com/2015/12/webpack-tree-shaking.html\r\n\r\n#### Issues on IPFS\r\n\r\n- https://github.com/ipfs/js-ipfs/issues/398\r\n- https://github.com/ipfs/js-ipfs-api/issues/353\r\n\r\n[Webpack{1|2}]: http://webpack.github.io/\r\n[jspm]: http://jspm.io/\r\n[Closure Compiler]: https://developers.google.com/closure/compiler/\r\n[Rollup]: http://rollupjs.org/\r\n[Browserify]: http://browserify.org/\r\n[babel]: http://babeljs.io/\r\n[Typescript]: http://www.typescriptlang.org/"},"comment":{"url":"https://api.github.com/repos/ipfs/js-ipfs/issues/comments/255126610","html_url":"https://github.com/ipfs/js-ipfs/issues/429#issuecomment-255126610","issue_url":"https://api.github.com/repos/ipfs/js-ipfs/issues/429","id":255126610,"user":{"login":"pelle","id":8680,"avatar_url":"https://avatars.githubusercontent.com/u/8680?v=3","gravatar_id":"","url":"https://api.github.com/users/pelle","html_url":"https://github.com/pelle","followers_url":"https://api.github.com/users/pelle/followers","following_url":"https://api.github.com/users/pelle/following{/other_user}","gists_url":"https://api.github.com/users/pelle/gists{/gist_id}","starred_url":"https://api.github.com/users/pelle/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pelle/subscriptions","organizations_url":"https://api.github.com/users/pelle/orgs","repos_url":"https://api.github.com/users/pelle/repos","events_url":"https://api.github.com/users/pelle/events{/privacy}","received_events_url":"https://api.github.com/users/pelle/received_events","type":"User","site_admin":false},"created_at":"2016-10-20T14:44:13Z","updated_at":"2016-10-20T14:44:13Z","body":"@dignifiedquire I would like to recommend that you continue transpiring it. The most important browsers that would need it are mobile browsers. You could create 2 different versions though.\r\n\r\nSince before Devcon2 I've been busy working on other things, but I'm going to start reviewing this again to see if we can start using the ipfs-js libraries in our browser/RN code for uPort.\r\n\r\nThe largest problem unless there have been many changes since I last looked at it, is the node first approach. I would really recommend using browser http abstractions as the core, such as `fetch` or `XHR` that are built into the browser. There are node implementations of then. `fetch` in particular is a modern promise based way of doing http.\r\n\r\nRemember that for node it doesn't matter that you're pulling in a few extra dependencies. But for the browser it does."}}
{"actor":{"display_login":"pelle"}}