{"id":19091362,"url":"https://github.com/andrei-cacio/es-modules","last_synced_at":"2025-11-12T14:31:17.074Z","repository":{"id":72353980,"uuid":"90521031","full_name":"andrei-cacio/es-modules","owner":"andrei-cacio","description":"JavaScript modules overview","archived":false,"fork":false,"pushed_at":"2017-11-06T20:59:08.000Z","size":25,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-22T07:27:50.282Z","etag":null,"topics":["commonjs","es-module","javascript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andrei-cacio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-05-07T09:09:49.000Z","updated_at":"2017-07-11T07:57:14.000Z","dependencies_parsed_at":null,"dependency_job_id":"d6f7767a-2503-4296-96ca-19743a31f136","html_url":"https://github.com/andrei-cacio/es-modules","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/andrei-cacio/es-modules","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrei-cacio%2Fes-modules","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrei-cacio%2Fes-modules/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrei-cacio%2Fes-modules/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrei-cacio%2Fes-modules/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andrei-cacio","download_url":"https://codeload.github.com/andrei-cacio/es-modules/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrei-cacio%2Fes-modules/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":284050888,"owners_count":26939118,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-12T02:00:06.336Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["commonjs","es-module","javascript"],"created_at":"2024-11-09T03:13:13.346Z","updated_at":"2025-11-12T14:31:17.055Z","avatar_url":"https://github.com/andrei-cacio.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Anatomy of ES Modules\nAn overview of modules in javascript. \n\n## Contents\n\n### Pre-transpilers/tooling era\n- [module pattern](https://github.com/andrei-cacio/es-modules#module-pattern11)\n- [Commonjs](https://github.com/andrei-cacio/es-modules#commonjs)\n- AMD\n\n### Post-transpilers/tooling era\n- `import`/`export`\n- `import()`\n- `System.import()`\n\n### ES Modules native\n- `import` support in the browser [[1]](https://github.com/andrei-cacio/es-modules#references)\n\n\n## [Module pattern](./modules/module-pattern)[[11]](https://github.com/andrei-cacio/es-modules#references) \n\n```javascript\n// counter.js\nconst counterModule = (() =\u003e {\n    let counter = 0;\n    const increaseCounter = () =\u003e counter++;\n    const decreaseCounter = () =\u003e counter--;\n    const resetCounter = () =\u003e counter = 0;\n\n    return {\n        increaseCounter,\n        decreaseCounter,\n        resetCounter,\n        get counter() {\n            return counter;\n        }\n    };\n})();\n```\n\n```javascript\n// index.js\ncounterModule.increaseCounter();\ncounterModule.decreaseCounter();\n\nconsole.log(counterModule.counter); // 0\n```\n\n## [Commonjs](./modules/common-js)\n### Implementations:\n- nodejs\n- browserify (for browser usage)\n- webpack\n\n### Syntax\n- `require()` function\n- the `module` object\n\n### Main characteristics:\n#### Modules are executed once\n- once a module is required, it is parsed and kept in memory\n\n#### Required data is passed by value/reference\n- variables are passed by value\n```javascript\n// module.js\nconst a = 2;\n\nmodule.exports = { a };\n```\n\n```javascript\n// index.js\nconst a = require('./module').a;\n```\n\n#### Synchronous parsing \n- all **required** dependencies are loaded synchronous\n- async implementations for better browser support: \n    - `require.ensure()` [(webpack code splitting)](https://webpack.github.io/docs/code-splitting.html)\n\n#### Dynamic module structure\n- all dependencies injected using `require()` are handled at runtime.\n \n```javascript\n//module.js\nconsole.log('module1 required');\n```\n\n```javascript\n//module2.js\nconsole.log('module2 required');\n```\n\n```javascript\n//module3.js\nconsole.log('module3 required');\n```\n\n\n```javascript\n//index.js\nsetTimeout(() =\u003e require('./module2'), 3000);\n\nif (false) {\n    require('./module3');\n}\n\nrequire('./module');\n```\n\n#### Cyclic dependencies support\n[Example from Nodejs docs](./modules/common-js/cyclic-deps)[[7]](https://github.com/andrei-cacio/es-modules#references)\n\n#### Counter example\n```javascript\n// counter.js\nlet counter = 0;\nconst increaseCounter = () =\u003e counter++;\nconst decreaseCounter = () =\u003e counter--;\nconst resetCounter = () =\u003e counter = 0;\n\nmodule.exports = {\n    increaseCounter,\n    decreaseCounter,\n    resetCounter,\n    get counter() {\n        return counter;\n    }\n};\n```\n```javascript\n// index.js\nconst counter = require('./counter');\n\nfunction main() {\n    counterModule.increaseCounter();\n    counterModule.decreaseCounter();\n}\n\nmodule.exports = main;\n```\n\n## ES Modules\n### Implementations\n- webpack + babel\n- rollup\n\n### Syntax\n#### import[[5]](https://github.com/andrei-cacio/es-modules#references)\n```javascript\nimport defaultMember from \"module-name\";\nimport * as name from \"module-name\";\nimport { member } from \"module-name\";\nimport { member as alias } from \"module-name\";\nimport { member1 , member2 } from \"module-name\";\nimport { member1 , member2 as alias2 , [...] } from \"module-name\";\nimport defaultMember, { member [ , [...] ] } from \"module-name\";\nimport defaultMember, * as name from \"module-name\"\nimport \"module-name\";\n```\n### export[[6]](https://github.com/andrei-cacio/es-modules#references)\n```javascript\nexport { name1, name2, …, nameN };\nexport { variable1 as name1, variable2 as name2, …, nameN };\nexport let name1, name2, …, nameN; // also var\nexport let name1 = …, name2 = …, …, nameN; // also var, const\n\nexport default expression;\nexport default function (…) { … } // also class, function*\nexport default function name1(…) { … } // also class, function*\nexport { name1 as default, … };\n\n// Stage 1 proposal - Lee Byron\nexport * from …;\nexport { name1, name2, …, nameN } from …;\nexport { import1 as name1, import2 as name2, …, nameN } from …;\nexport default from ...;\nexport { default } from ...;\n```\n\n### Main characteristics:\n#### Modules are executed once\n- once a module is required, it is parsed and kept in memory\n\n#### Static module structure[[3]]((https://github.com/andrei-cacio/es-modules#references))\n- all `import`'s and `export`'s must be declared top level\n- `import`'s are hoisted\n- all `import`'s are read only views on exports [[13]](https://github.com/andrei-cacio/es-modules#references)\n```javascript\n// module.js\nexport default 1+1;\nexport const a = { b: 2 };\n```\n\n```javascript\n//index.js\nimport * as module from './module';\n\nmodule.a.b = 3; //SyntaxError: Cannot assign to read-only object\n```\n\nor \n\n```javascript\nimport { a } from './module';\n\na = 2 //SyntaxError\n```\n- benefits:\n    - dead code elimination\n    - preparation for HTTP2\n    - variable checking (linting, etc.)\n    - faster property lookups [[16]]((https://github.com/andrei-cacio/es-modules#references))\n\n```javascript\nvar lib = require('lib');\nlib.someFunc();\n```\n\n```javascript\nimport * as lib from 'lib';\nlib.someFunc();\n```\n\n#### Exporting live bindings\nUnlike commonjs, ES modules imports are live bindings to the original primitives. (Objects are passed by references so they will be mutated anyways).\n\n```javascript\n//counter.js\nlet counter = 0;\nconst incrementCounter = () =\u003e counter++;\n\nexport { counter, incrementCounter };\n```\n```javascript\n//index.js\nimport { counter, incrementCounter };\n\nconsole.log(counter); // 0\nincrementCounter();\nconsole.log(counter); //1\n```\n\n#### Unit testing modules\nThere are multiple strategies of testing modules. We can split the module types into three categories:\n 1. simple/independent modules (no dependencies)\n 2. modules which have local dependencies\n 3. modules which have 3rd party dependencies\n\n## ES modules native\n### Syntax\n#### `import` as a keyword for static module parsing\n- browser support: `\u003cscript type=\"module\"\u003e\u003c/script\u003e` \n    - are parsed under `use strict` mode\n    - scoped environment \n- module script tags are differed\n- only paths like '/' or './' are supported\n- each import does a new fetch for the file\n\n```javascript\n\u003cscript type=\"module\"\u003e\n    import { counter, incrementCounter } from './counter.js';\n        \n        document.body.append(`${counter}\\n`);\n        incrementCounter();\n        document.body.append(`${counter}\\n`);\n\u003c/script\u003e\n```\n    \n#### `import()` as a function for dynamic module loading \n- stage 3 proposal[[8]](https://github.com/andrei-cacio/es-modules#references)\n\n```javascript\nimport('./counter.js').then(counterModule =\u003e {\n    console.log(counterModule.counter); // 0\n    counterModule.incrementCounter();\n    console.log(counterModule.counter); // 1\n});\n```\n\n# References\n1. [ECMAScript modules in browsers - Jake Archibald](https://jakearchibald.com/2017/es-modules-in-browsers/)\n2. [ES6 Modules in Depth - Nicolás Bevacqua](https://ponyfoo.com/articles/es6-modules-in-depth)\n3. [Exploring ES6 - Chapter 16 \"Modules\" - Dr. Axel Rauschmayer](http://exploringjs.com/es6/ch_modules.html)\n4. [ES6 In Depth: Modules - Jason Orendorff](https://hacks.mozilla.org/2015/08/es6-in-depth-modules/)\n5. [import - MDN docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)\n6. [export - MDN docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export)\n7. [Cyclic deps - Nodejs docs](https://nodejs.org/api/modules.html#modules_cycles)\n8. [ES Proposals: import() - Domenic Denicola](https://github.com/tc39/proposal-dynamic-import)\n9. [ES Proposals: export ns from - Lee Byron](https://github.com/leebyron/ecmascript-export-ns-from)\n10. [ES Proposals: export * as ns from - Lee Byron](https://github.com/leebyron/ecmascript-export-ns-from)\n11. [The Revealing Module - Addy Osmani](https://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript)\n12. [Writing Modular JavaScript With AMD, CommonJS \u0026 ES Harmony - Addy Osmani](https://addyosmani.com/writing-modular-js/)\n13. [Exploring ES6 - 16.3.5 Imports are read-only views on exports - Dr. Axel Rauschmayer](http://exploringjs.com/es6/ch_modules.html#_imports-are-read-only-views-on-exports)\n14. [ES Modules and NodeJS: Hard Choices - Rod Vagg](https://nodesource.com/blog/es-modules-and-node-js-hard-choices/)\n15. [ES6 Modules in Chrome Canary M60](https://medium.com/@samthor/es6-modules-in-chrome-canary-m60-ba588dfb8ab7)\n16. [PICing on Javascript for fun and profit - CHRIS LEARY](http://blog.cdleary.com/2010/09/picing-on-javascript-for-fun-and-profit/)\n17. [Optimizing Dynamically-Typed Object-Oriented Languages With Polymorphic Inline Caches Paper](http://www.selflanguage.org/_static/published/pics.pdf)\n18. [EcmaScript Specifications 7th Edition June 2016 - Modules section](https://www.ecma-international.org/ecma-262/7.0/#sec-modules)\n19. [WHATWG Integration with the ES Spec](https://html.spec.whatwg.org/multipage/webappapis.html#integration-with-the-javascript-module-system)\n20. [ES Modules interview with Bradley Farias](https://survivejs.com/blog/es-modules-interview/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandrei-cacio%2Fes-modules","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandrei-cacio%2Fes-modules","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandrei-cacio%2Fes-modules/lists"}