organises set of related files/modules that are responsible of doing some task. In node.js every package has a package.json which has the metadata about that package
we don’t want to write the same thing over and over again. Hence, we create packages that can be published as modules so that other people can use them directly.
log(){ console.log('Example of CJS module system'); } // expose log to other modules module.exports = { log }; // File index.js var logModule = require('./log'); logModule.log(); • No static analyzing, as you get an object, so property lookup is at runtime. • You always get a copy of an object, so you won’t get live changes from the module itself. • No tree shaking, because when you import you get an object.
log(){ console.log('Example of CJS module system'); } // expose log to other modules module.exports = { log } // File index.js var logModule = require('./log'); logModule.log(); • No static analyzing, as you get an object, so property lookup is at runtime. • You always get a copy of an object, so you won’t get live changes from the module itself. • No tree shaking, because when you import you get an object.
log.js const log = () => { console.log('Example of ES module system'); } export default log // File index.js import log from "./log" log(); • Much cleaner. • Import via “import” and export via “export” • Static analyzing — You can determine imports and exports at compile time (statically) . This opens up doors for Tree Shaking. • When you import, you get back actual value, so any change is a live changes in the module itself.
=> { console.log('Welcome to the world of ES'); }; } } ES CJS exports.__esModule = true; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function”); } } var ecmascript = function ecmascript() { _classCallCheck(this, ecmascript); this.showMessage = function () { console.log('Welcome to the world of ES'); }; }; exports.default = ecmascript; (“modules”: false) (“modules”: “commonjs”)
=> { console.log('Welcome to the world of ES'); }; } } ES CJS exports.__esModule = true; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function”); } } var ecmascript = function ecmascript() { _classCallCheck(this, ecmascript); this.showMessage = function () { console.log('Welcome to the world of ES'); }; }; exports.default = ecmascript; # Type Size (Bytes) 1 RAW 112 2 ES 146 3 CJS 398 (“modules”: false) (“modules”: “commonjs”)
context of JavaScript for live code inclusion(import whatever is required). " •It relies on the static structure of ES module syntax, that is, “import” and “export”.
=> console.log('shake'); const bake = () => console.log('bake'); //can be tree shaken as we export as es modules export { shake, bake }; // File index.js import { shake } from './shakebake.js' // only "shake" is included in the output
=> console.log('shake'); const bake = () => console.log('bake'); //can be tree shaken as we export as es modules export { shake, bake }; // File index.js import { shake } from './shakebake.js' // only "shake" is included in the output Non Tree Shakeable ❌ // File shakebake.js const shake = () => console.log('shake'); const bake = () => console.log('bake'); //cannot be tree shaken as we have exported an object export default { shake, bake }; // File index.js import { shake } from './shakebake.js' // both "shake" and "bake" are included in the output
in ESM! • <script type=“module”> ➡ deferred by default. • Even if we add the <script type=“module”/> multiple times on the page it gets executed just once. • Global variables is global to that module (lexical scope) and not to the window scope. • You can optimize the delivery of your modules further by using <link rel=“modulepreload”> PS: This is still anexperimental feature.
in ESM? • <script type=“module”> ➡ deferred by default. • Even if we add the <script type=“module”/> multiple times on the page it gets executed just once. • Global variables are global to that module (lexical scope) and not to the window scope. • You can optimize the delivery of your modules further by using <link rel=“modulepreload”> PS: This is still anexperimental feature.
in ESM? • <script type=“module”> ➡ deferred by default. • Even if we add the <script type=“module”/> multiple times on the page it gets executed just once. • Global variables are global to that module (lexical scope) and not to the window scope. • You can optimize the delivery of your modules further by using <link rel=“modulepreload”> PS: This is still anexperimental feature.
one module system to another as per the language specs. Tools: Babel PS: Babel is a compiler and not transpiler Bundling: It is a technique most commonly used in today’s “module-based” development where common functionalities can be extracted into a flat bundle at build time. Tools: Webpack/Rollup Various JS Module Systems CommonJS Target Bundle/ Compile ESM +
the specific components in your application. import { Button } from 'ui-kit' module: "dist/index.mjs" // ---> The module field in package.json 2. if the consumer application use legacy bundling tools, the author should add support for CJS module system as well. import { Button } from 'ui-kit' main: "dist/index.js" // ---> The main field in package.json
the specific components in your application. import { Button } from 'ui-kit' module: "dist/index.mjs" // ---> The module field in package.json 2. if the consumer application use legacy bundling tools, the author should add support for CJS module system as well. import { Button } from 'ui-kit' main: "dist/index.js" // ---> The main field in package.json 3. If the consumer doesn't have ^webpack-4 then no sideEffects benefit. import Button from 'ui-kit/es/Button' import Button from 'ui-kit/cjs/Button'
the specific components in your application. import { Button } from 'ui-kit' module: "dist/index.mjs" // ---> The module field in package.json 2. if the consumer application use legacy bundling tools, the author should add support for CJS module system as well. import { Button } from 'ui-kit' main: "dist/index.js" // ---> The main field in package.json 3. If the consumer doesn't have ^webpack-4 then no sideEffects benefit. import Button from 'ui-kit/es/Button' import Button from 'ui-kit/cjs/Button' 4. Consumer application should be able to directly consume the package i.e 'ui-kit' with <script type="module"> i.e no tree shaking, no side effects in the browser. import Button from "https://unpkg.com/ui-kit/es/Button/index.mjs"
the default and named imports in the application. import api, { get, post } from 'api' module: "dist/index.mjs" // ---> The module field in package.json
the default and named imports in the application. import api, { get, post } from 'api' module: "dist/index.mjs" // ---> The module field in package.json 2. if the consumer application use legacy bundling tools, the author should add support for CJS module system as well. import api, { get, post } from 'api' main: "dist/index.js" // ---> The main field in package.json
the default and named imports in the application. import api, { get, post } from 'api' module: "dist/index.mjs" // ---> The module field in package.json 2. if the consumer application use legacy bundling tools, the author should add support for CJS module system as well. import api, { get, post } from 'api' main: "dist/index.js" // ---> The main field in package.json 3. Consumer application should be able to directly consume the package i.e 'ui-kit' with <script type="module"> i.e no tree shaking, no side effects in the browser. import api, { get, post } from “https://unpkg.com/api/dist/index.mjs” import api, { get, post } from “https://unpkg.com/api/dist/index.js”
ESM + Advice: Bundle/Compile? Component Library: 1. Babelify the source and target CJS and ES. 2. Create “index.mjs” with re-exports. Core Packages: 1. Bundle the source with Rollup and target CJS and ES. Component Library
for empty arrays. So they want to make changes to this package. After making changes they publish a minor version of the module to npm. > npm version minor -m "Upgrade to %s for reasons” > npm publish
CommonJS ESM Core Package Component Library Bundle/ Compile Advice: npm publish/monorepos? Well, If you’re publishing something to be used globally you have to publish it to npm. If you’re building something that is private within your team/org give monorepos a try.