{"id":39321,"date":"2025-11-18T11:55:25","date_gmt":"2025-11-18T19:55:25","guid":{"rendered":"https:\/\/cloudinary.com\/blog\/?p=39321"},"modified":"2025-11-18T11:55:26","modified_gmt":"2025-11-18T19:55:26","slug":"what-is-esm-in-javascript","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/","title":{"rendered":"What is ESM in JavaScript?"},"content":{"rendered":"\n<p>If you have ever bounced between import and require, or puzzled over .mjs and .cjs files, you are not alone. Modern JavaScript projects often juggle bundlers, Node versions, and browser targets, which makes module formats feel more complicated than they need to be.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Question:<\/h2>\n\n\n\n<p><em>Hi folks,<\/em><br><em>I keep seeing ESM mentioned in docs and configs and I am confused about when to use it. What is ESM in JavaScript? How is it different from CommonJS? I am building a full-stack app and want to use imports in both the browser and Node.<\/em><\/p>\n\n\n\n<p><em>What are the best practices for setting up ESM, handling dynamic imports, and interop with CommonJS modules? Any tips on pitfalls to avoid would be appreciated.<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Answer:<\/h2>\n\n\n\n<p>ESM stands for ECMAScript Modules. It is the standardized module system for JavaScript, supported natively by modern browsers and Node. ESM uses the import and export keywords, enables static analysis for better tree-shaking and performance, and encourages clearer dependency graphs.<\/p>\n\n\n\n<p>In contrast, CommonJS is an older effort to create a standardized module system, but primarily for server-side JavaScript. These are synchronous and <em>can<\/em> be used by ESM, but ESM modulus can\u2019t consume CommonJS ones.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Key characteristics of ESM<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Syntax:<\/strong> <code>import<\/code> and <code>export<\/code> instead of <code>require<\/code> and <code>module.exports<\/code>.<\/li>\n\n\n\n<li><strong>Static structure:<\/strong> Imports are hoisted and must be at the top level, which enables tree-shaking.<\/li>\n\n\n\n<li><strong>Top-level await: <\/strong>Supported in ESM modules in modern environments.<\/li>\n\n\n\n<li><strong>Strict mode: <\/strong>ESM is always in strict mode.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">ESM in the browser<\/h3>\n\n\n\n<p>Modern browsers can load ESM directly using a script tag with type=&#8221;module&#8221;.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"module\"<\/span>&gt;<\/span><span class=\"javascript\">\n\u00a0 <span class=\"hljs-keyword\">import<\/span> { greet } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'.\/utils.js'<\/span>;\n\u00a0 greet(<span class=\"hljs-string\">'world'<\/span>);\n<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>You can also use dynamic imports to lazy-load code:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ Lazy-load a heavy module only when needed<\/span>\n<span class=\"hljs-keyword\">const<\/span> { heavyFeature } = <span class=\"hljs-keyword\">await<\/span> <span class=\"hljs-keyword\">import<\/span>(<span class=\"hljs-string\">'.\/heavy.js'<\/span>);\nheavyFeature();<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">ESM in Node<\/h3>\n\n\n\n<p>Node supports ESM in two main ways:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Set <code>\"type\": \"module\"<\/code> in package.json, then .js files are treated as ESM.<\/li>\n\n\n\n<li>Use the .mjs extension for ESM files regardless of package.json.<\/li>\n<\/ul>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ package.json<\/span>\n{\n\u00a0 <span class=\"hljs-string\">\"type\"<\/span>: <span class=\"hljs-string\">\"module\"<\/span>\n}\n\n<span class=\"hljs-comment\">\/\/ src\/main.js<\/span>\n<span class=\"hljs-keyword\">import<\/span> fs <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'node:fs\/promises'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { greet } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'.\/utils.js'<\/span>;\n\n<span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-keyword\">await<\/span> fs.readFile(<span class=\"hljs-string\">'.\/README.md'<\/span>, <span class=\"hljs-string\">'utf8'<\/span>));\ngreet(<span class=\"hljs-string\">'Node ESM'<\/span>);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Interop with CommonJS<\/h3>\n\n\n\n<p>Sometimes you must mix ESM and CJS.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Importing CJS from ESM: often use dynamic import or createRequire.<\/li>\n<\/ul>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ ESM file that needs a CJS module<\/span>\n<span class=\"hljs-keyword\">import<\/span> { createRequire } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'node:module'<\/span>;\n<span class=\"hljs-keyword\">const<\/span> <span class=\"hljs-built_in\">require<\/span> = createRequire(<span class=\"hljs-keyword\">import<\/span>.meta.url);\n<span class=\"hljs-keyword\">const<\/span> cjsLib = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'.\/legacy.cjs'<\/span>); <span class=\"hljs-comment\">\/\/ CommonJS module<\/span>\ncjsLib.run();<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li>Importing ESM from CJS: prefer dynamic import.<\/li>\n<\/ul>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ CommonJS file<\/span>\n(<span class=\"hljs-keyword\">async<\/span> () =&gt; {\n\u00a0 <span class=\"hljs-keyword\">const<\/span> { greet } = <span class=\"hljs-keyword\">await<\/span> <span class=\"hljs-keyword\">import<\/span>(<span class=\"hljs-string\">'.\/utils.js'<\/span>);\n\u00a0 greet(<span class=\"hljs-string\">'from CJS'<\/span>);\n})();<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Common pitfalls<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>File extensions:<\/strong> In ESM you typically must include the .js extension in relative imports.<\/li>\n\n\n\n<li><strong>Default vs named exports:<\/strong> Importing default requires a different syntax than named exports.<\/li>\n\n\n\n<li><code>__dirname<\/code> <strong>and<\/strong> <code>__filename<\/code><strong>:<\/strong> Not available in ESM. Use <code>import.meta.url<\/code> with URL APIs.<\/li>\n\n\n\n<li><strong>JSON import: <\/strong>Use <code>import<\/code> with an assertion in newer runtimes.<\/li>\n<\/ul>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">import<\/span> config <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'.\/config.json'<\/span> assert { <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-string\">'json'<\/span> };<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Performance and bundling tips<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Prefer ESM-ready packages to enable tree-shaking and smaller bundles.<\/li>\n\n\n\n<li>Use dynamic imports for route-level code splitting.<\/li>\n\n\n\n<li>Keep assets cacheable and served from a CDN. If you are serving images and videos, review <a href=\"https:\/\/cloudinary.com\/guides\/web-performance\/understanding-image-hosting-for-websites\">how image hosting works for performance and caching<\/a>.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Quick example &#8211; authoring and consuming ESM<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ utils.js<\/span>\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">greet<\/span>(<span class=\"hljs-params\">name<\/span>) <\/span>{\n\u00a0 <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">`Hello, <span class=\"hljs-subst\">${name}<\/span>!`<\/span>);\n}\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> VERSION = <span class=\"hljs-string\">'1.0.0'<\/span>;\n\n<span class=\"hljs-comment\">\/\/ app.js<\/span>\n<span class=\"hljs-keyword\">import<\/span> { greet, VERSION } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'.\/utils.js'<\/span>;\ngreet(<span class=\"hljs-string\">'ESM'<\/span>);\n<span class=\"hljs-built_in\">console<\/span>.log(VERSION);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Using ESM with Cloudinary for media delivery<\/h3>\n\n\n\n<p>After you set up ESM in your app, you can import modern SDKs directly and keep your bundle lean. For example, in a front-end project you can use Cloudinary\u2019s ESM-friendly URL Generation library to build optimized image URLs at runtime, then let your bundler tree-shake unused parts.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ In the browser with ESM<\/span>\n<span class=\"hljs-keyword\">import<\/span> { Cloudinary } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@cloudinary\/url-gen'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { fill } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@cloudinary\/url-gen\/actions\/resize'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { format } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@cloudinary\/url-gen\/actions\/delivery'<\/span>;\n\n<span class=\"hljs-keyword\">const<\/span> cld = <span class=\"hljs-keyword\">new<\/span> Cloudinary({ <span class=\"hljs-attr\">cloud<\/span>: { <span class=\"hljs-attr\">cloudName<\/span>: <span class=\"hljs-string\">'demo'<\/span> }});\n<span class=\"hljs-keyword\">const<\/span> img = cld.image(<span class=\"hljs-string\">'samples\/landscapes\/nature'<\/span>)\n\u00a0 .resize(fill().width(<span class=\"hljs-number\">600<\/span>).height(<span class=\"hljs-number\">400<\/span>))\n\u00a0 .delivery(format(<span class=\"hljs-string\">'auto'<\/span>));\n\n<span class=\"hljs-built_in\">document<\/span>.getElementById(<span class=\"hljs-string\">'hero'<\/span>).src = img.toURL();<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This pattern plays nicely with CDNs and clean <a href=\"https:\/\/cloudinary.com\/glossary\/image-url\">image URLs<\/a>, and you can choose efficient formats for the client.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Summary<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>ESM is the standard module system with import and export, supported in browsers and Node.<\/li>\n\n\n\n<li>It enables static analysis, tree-shaking, and top-level await for cleaner, faster builds.<\/li>\n\n\n\n<li>Use &#8220;type&#8221;: &#8220;module&#8221; or .mjs in Node, script type=&#8221;module&#8221; in the browser, and dynamic imports for code splitting.<\/li>\n\n\n\n<li>Interop with CommonJS via dynamic import or createRequire where needed.<\/li>\n\n\n\n<li>Combine ESM with a CDN-friendly asset workflow and optimized image URLs to minimize payloads and improve performance.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Learn More<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/cloudinary.com\/tools\/png-to-webp\">PNG to WebP Converter<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/cloudinary.com\/tools\/image-to-jpg\">Image to JPG Converter<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/cloudinary.com\/guides\/video\/video-as-a-service\">Video as a Service &#8211; Guide<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/cloudinary.com\/tools\/image-upscale\">Image Upscaling and Quality Enhancement<\/a><\/li>\n<\/ul>\n\n\n\n<p>Ready to streamline media in your ESM apps? <a href=\"https:\/\/cloudinary.com\/users\/register_free\">Sign up for Cloudinary free<\/a> to optimize, transform, and deliver images and video at scale.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you have ever bounced between import and require, or puzzled over .mjs and .cjs files, you are not alone. Modern JavaScript projects often juggle bundlers, Node versions, and browser targets, which makes module formats feel more complicated than they need to be. Question: Hi folks,I keep seeing ESM mentioned in docs and configs and [&hellip;]<\/p>\n","protected":false},"author":88,"featured_media":39267,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[423],"class_list":["post-39321","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-questions"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>What is ESM in JavaScript?<\/title>\n<meta name=\"description\" content=\"If you have ever bounced between import and require, or puzzled over .mjs and .cjs files, you are not alone. Modern JavaScript projects often juggle\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"What is ESM in JavaScript?\" \/>\n<meta property=\"og:description\" content=\"If you have ever bounced between import and require, or puzzled over .mjs and .cjs files, you are not alone. Modern JavaScript projects often juggle\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2025-11-18T19:55:25+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-11-18T19:55:26+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1763149247\/QA_javascript_featured_image\/QA_javascript_featured_image.jpg?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"1999\" \/>\n\t<meta property=\"og:image:height\" content=\"1100\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"damjanantevski\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/\"},\"author\":{\"name\":\"damjanantevski\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/43592e43c12520a1e867d456b1e8cf7e\"},\"headline\":\"What is ESM in JavaScript?\",\"datePublished\":\"2025-11-18T19:55:25+00:00\",\"dateModified\":\"2025-11-18T19:55:26+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/\"},\"wordCount\":615,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1763149247\/QA_javascript_featured_image\/QA_javascript_featured_image.jpg?_i=AA\",\"keywords\":[\"Questions\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2025\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/\",\"url\":\"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/\",\"name\":\"What is ESM in JavaScript?\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1763149247\/QA_javascript_featured_image\/QA_javascript_featured_image.jpg?_i=AA\",\"datePublished\":\"2025-11-18T19:55:25+00:00\",\"dateModified\":\"2025-11-18T19:55:26+00:00\",\"description\":\"If you have ever bounced between import and require, or puzzled over .mjs and .cjs files, you are not alone. Modern JavaScript projects often juggle\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1763149247\/QA_javascript_featured_image\/QA_javascript_featured_image.jpg?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1763149247\/QA_javascript_featured_image\/QA_javascript_featured_image.jpg?_i=AA\",\"width\":1999,\"height\":1100},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"What is ESM in JavaScript?\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/43592e43c12520a1e867d456b1e8cf7e\",\"name\":\"damjanantevski\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/3b40c995531fe4d510212a06c9d4fc666d2cb8efbfebc98a94191701accf4817?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/3b40c995531fe4d510212a06c9d4fc666d2cb8efbfebc98a94191701accf4817?s=96&d=mm&r=g\",\"caption\":\"damjanantevski\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"What is ESM in JavaScript?","description":"If you have ever bounced between import and require, or puzzled over .mjs and .cjs files, you are not alone. Modern JavaScript projects often juggle","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/","og_locale":"en_US","og_type":"article","og_title":"What is ESM in JavaScript?","og_description":"If you have ever bounced between import and require, or puzzled over .mjs and .cjs files, you are not alone. Modern JavaScript projects often juggle","og_url":"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/","og_site_name":"Cloudinary Blog","article_published_time":"2025-11-18T19:55:25+00:00","article_modified_time":"2025-11-18T19:55:26+00:00","og_image":[{"width":1999,"height":1100,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1763149247\/QA_javascript_featured_image\/QA_javascript_featured_image.jpg?_i=AA","type":"image\/jpeg"}],"author":"damjanantevski","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/"},"author":{"name":"damjanantevski","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/43592e43c12520a1e867d456b1e8cf7e"},"headline":"What is ESM in JavaScript?","datePublished":"2025-11-18T19:55:25+00:00","dateModified":"2025-11-18T19:55:26+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/"},"wordCount":615,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1763149247\/QA_javascript_featured_image\/QA_javascript_featured_image.jpg?_i=AA","keywords":["Questions"],"inLanguage":"en-US","copyrightYear":"2025","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/","url":"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/","name":"What is ESM in JavaScript?","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1763149247\/QA_javascript_featured_image\/QA_javascript_featured_image.jpg?_i=AA","datePublished":"2025-11-18T19:55:25+00:00","dateModified":"2025-11-18T19:55:26+00:00","description":"If you have ever bounced between import and require, or puzzled over .mjs and .cjs files, you are not alone. Modern JavaScript projects often juggle","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1763149247\/QA_javascript_featured_image\/QA_javascript_featured_image.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1763149247\/QA_javascript_featured_image\/QA_javascript_featured_image.jpg?_i=AA","width":1999,"height":1100},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/questions\/what-is-esm-in-javascript\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"What is ESM in JavaScript?"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/43592e43c12520a1e867d456b1e8cf7e","name":"damjanantevski","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/3b40c995531fe4d510212a06c9d4fc666d2cb8efbfebc98a94191701accf4817?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/3b40c995531fe4d510212a06c9d4fc666d2cb8efbfebc98a94191701accf4817?s=96&d=mm&r=g","caption":"damjanantevski"}}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1763149247\/QA_javascript_featured_image\/QA_javascript_featured_image.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/39321","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/88"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=39321"}],"version-history":[{"count":1,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/39321\/revisions"}],"predecessor-version":[{"id":39322,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/39321\/revisions\/39322"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/39267"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=39321"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=39321"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=39321"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}