{
    "componentChunkName": "component---src-templates-blog-post-tsx",
    "path": "/blog/2023-04-27-deno-is-the-easiest-way-to-author-npm-packages/",
    "result": {"data":{"blogPost":{"title":"Deno is the best tool for maintaining NPM packages","slug":"/blog/2023-04-27-deno-is-the-easiest-way-to-author-npm-packages/","authorNodes":[{"name":"Charles Lowell","slug":"/people/charles-lowell/"}],"markdown":{"html":"<blockquote>\n<p><strong>TL;DR</strong> Even if you primarily run your JavaScript in Node, Deno is a\nfantastic tool for building and distributing packages on NPM (and\neverywhere else). This article shows how to publish modules to both\n<a href=\"https://deno.land/x\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://deno.land/x</a> and <a href=\"https://npmjs.org\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://npmjs.org</a> using nothing more than\nthe deno CLI.</p>\n</blockquote>\n<p><strong>myth</strong>: You need to use <code class=\"language-text\">node</code> and <code class=\"language-text\">npm</code> , <code class=\"language-text\">yarn</code> , <code class=\"language-text\">pnpm</code> , et al. to\npublish packages to <a href=\"https://npmjs.org\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://npmjs.org</a></p>\n<p><strong>Fact</strong>: Deno is perfectly capable of maintaining NPM packages. Studies\nconclusively show that maintaining NPM packages with Deno instead of Node is up\nto 900% more stress free.<sup id=\"fnref-1\"><a href=\"#fn-1\" class=\"footnote-ref\">1</a></sup></p>\n<p>As you may or may not know, here at Frontside <a href=\"https://frontside.com/blog/2022-12-01-deno-is-blazing-fast-for-humans/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">we’re migrating toward\nDeno as our primary tool for JavaScript\ndevelopment</a>. That means that we’ll not only use Deno\nfrom the get-go to develop our new JavaScript projects and publish\nthem to <a href=\"https://deno.land/x\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">deno.land</a>, but over time we’ll also migrate our existing\nrepositories that use Node as the primary development tool. But that\ndoesn’t mean we’re rejecting the Node ecosystem – far from it!</p>\n<p>We have a ton of NPM packages <a href=\"https://www.npmjs.com/package/@frontside/graphgen\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">already</a>\n<a href=\"https://www.npmjs.com/package/effection\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">developed</a> that <a href=\"https://www.npmjs.com/package/@interactors/core\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">we</a> and <a href=\"https://www.npmjs.com/package/@simulacrum/ldap-simulator\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">our\nclients</a> critically <a href=\"https://www.npmjs.com/package/@simulacrum/auth0-simulator\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">rely on</a>. Moving\nforward we want all of our new packages to be available to all\nJavaScript developers, not just those that happen to run their\nprograms on Deno. And finally there is our work with\n<a href=\"https://backstage.io\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Backstage</a>, which comprises the lion’s share of our\nbusiness. It runs on Node and will do so for years to come. In a\nnutshell: we have been and are going to continue to be deeply\nintegrated with the Node community for the long haul.</p>\n<p>But given this, how will we swap over to use Deno without\nlosing what we have in terms of our existing install base of NPM\npackages and Node applications? Simple intuition tells us we should\nuse Node to develop Node packages and Deno to develop Deno modules:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 470px; flex:1.64;\"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/d0302dfd964f61bd8cb8109a96f9dfd1/f96db/dev-publish-silo.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 60.9375%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAABVElEQVQoz41SXauCQBDd//+HfPAlBEV9MCIyklAjC7L8Sk2NbOIMbHi7em8Dw+jOzNmzM0ccj0dar9e02+047vd76vueYM/n85fLXNd1XB8EAccwDDknAGjbNjmOQ7quk6Zp9Hg86D+73+8MZpomzWYzms/nfC5kQZ7nVBTFuwFswKIsS6rrmm63G38fDgc6n89cE8cxnU4napqGsixjZ8C2bZn2crnkm2FoRiMiGuAAjqKIgWCr1Yp7cInnefxsASafNnb2rYmx4U8t5LMGS4APz4Xc3DAOAafYT/WJMdpTTx6CTeUFdLfdbnmwvu9TkiR/PlnqsKoq2mw274XIzQv8qKrKOkS0LOurxUBG6IFuFUVh8B9LgSSG1MEEApeDh5wgHTC6Xq+cAyswhewulwtjMCAEbRgG60gCQujQG0YAAOgRda7rUpqmDA6GGBP6FosF51/4UZvRq82xngAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Deno for publishing to Deno ecosystem and Node for publishing to Node ecosystem\"\n        title=\"Deno for publishing to Deno ecosystem and Node for publishing to Node ecosystem\"\n        src=\"/static/d0302dfd964f61bd8cb8109a96f9dfd1/f96db/dev-publish-silo.png\"\n        srcset=\"/static/d0302dfd964f61bd8cb8109a96f9dfd1/72799/dev-publish-silo.png 320w,\n/static/d0302dfd964f61bd8cb8109a96f9dfd1/f96db/dev-publish-silo.png 470w\"\n        sizes=\"(max-width: 470px) 100vw, 470px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n  </a>\n    </span></p>\n<p>But as it turns out, Deno has excellent capabilities to build NPM\npackages that we use every day, allowing us to both have our cake and\neat it too. With a slight tweak to how we think about versioning, we\ncan get all the DX goodness of Deno, but our code is accessible to the\nwidest possible audience of developers on both deno.land and NPM.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 582px; flex:2.05;\"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/4ee5aab68bb8b5b9400d9b70a36db19d/7c1cd/one-tool-for-both.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 48.75000000000001%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABCUlEQVQoz4VSyaqEQAzs//8pT95FBBVxAXdRwX03j8rQg4i+KQi9mJSpSgv6gfM8Oe57IE1TsiyLw3VdvhMy6Vr0RiZR1zX1fc/h+z4ZhkFBEHwIj+MgGfdO7mTIAUkcxzTPMzVNQ6ZpUp7nTFhVFYk3iXfSZVmoKAoax/GbC1LZLchxFpqmka7rhBVFT+i6jsn2fX/08goBM5MkIcdxuHBdVw4Ut23Lf8b6pEDacLVMoF1MCQTbtrEEEEMavMqyjIZhYDmyQwmQ3O0SSEIxyN6Ab9M0fScL89E1BqGqKimKQp7nfST/GsjdK5zLsqQoilhJGIZsGe7Q8eM7/C+uQIe2bfOzwVuE0j81OAm1l1LcbQAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Deno for publishing to both Deno and Node package managers\"\n        title=\"Deno for publishing to both Deno and Node package managers\"\n        src=\"/static/4ee5aab68bb8b5b9400d9b70a36db19d/7c1cd/one-tool-for-both.png\"\n        srcset=\"/static/4ee5aab68bb8b5b9400d9b70a36db19d/72799/one-tool-for-both.png 320w,\n/static/4ee5aab68bb8b5b9400d9b70a36db19d/7c1cd/one-tool-for-both.png 582w\"\n        sizes=\"(max-width: 582px) 100vw, 582px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n  </a>\n    </span></p>\n<p>The key change in thinking that enables this transition is to move\naway from package.json as the final source of truth regarding the\npackage version and to replace it instead with a humble git tag. Each\nreleased version will have a single tag to represent it, with the\nresult that package.json goes from being authoritative to just another\nbuild artifact. In short, moving forward we’re following this mantra:\nIf it doesn’t have a tag, it ain’t a release.</p>\n<h2 id=\"tag-once-publish-twice\" style=\"position:relative;\"><a href=\"#tag-once-publish-twice\" aria-label=\"tag once publish twice permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Tag once. Publish twice.</h2>\n<p>With that mental shift in place, we can implement the following\nscheme:</p>\n<ol>\n<li>Wait until a release tag is pushed</li>\n<li>Then use it to build and publish to both deno.land/x and npmjs.com</li>\n</ol>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 582px; flex:1.21;\"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/756ab11c71a5d4b4951ef67258345665/7c1cd/tag-to-publish.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 82.5%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAAAsTAAALEwEAmpwYAAABt0lEQVQ4y42T2W7jMAxF/f9/lac8TSZANiCdNAtiZ3PjRd4l6g5IN67duHEJEIJs6ojLlWOtBVuz6hwmOMBELoy6gLI79Me7uCXTie0zpwOrMphgj8r9K7Dq+Afa/wf9sYH232AtDQMbGBlQcsOQvYJ1gFTEsKb8PERy8Mup+fa7kkmDyqQJbh/8DeQJSHkEq4snyFDZvBJR47x3uBSeZBvWl+VPmX+/qM6wUE3JP2XSBzqfz1gul+Lr9foLKKnnESj16+HoQvraB2ULggBJkiBNU+x2OywWC2y327qHTQ9sLR3RYnyCvr09CZnjwjDE4XBAURSI4xjz+Ryn00nA1+u1zrBTpkydYCJPxP2AMoAPcFYPK8sSURQhyzIopSTGmUwmmE6n4LUqy86LscoDqESsFG63q2Q4pASHa79cLthsNnKTMQZaG+gihQp8hGEkpT3sIY92Gzqy4eDVaiUfqqqS1Bmc5xlc14XneZ/7HFrrl89QgJwR9+V7cNv4H8fc73dx3/flgv1+j/F4jNFoJBU2L6V9Q5+3jSthKGuQq+HpHo9HGRj/c169giE4y4fbxbDZbCba/A8sNTHL91F8rwAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"The 1.0.0 git tag causes a 1.0.0 version on both deno.land and npmjs.org\"\n        title=\"The 1.0.0 git tag causes a 1.0.0 version on both deno.land and npmjs.org\"\n        src=\"/static/756ab11c71a5d4b4951ef67258345665/7c1cd/tag-to-publish.png\"\n        srcset=\"/static/756ab11c71a5d4b4951ef67258345665/72799/tag-to-publish.png 320w,\n/static/756ab11c71a5d4b4951ef67258345665/7c1cd/tag-to-publish.png 582w\"\n        sizes=\"(max-width: 582px) 100vw, 582px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n  </a>\n    </span></p>\n<p>We’ll spend the rest of this blog post showing how we will do this for\nboth platforms.</p>\n<h3 id=\"stage-1-the-release-tag\" style=\"position:relative;\"><a href=\"#stage-1-the-release-tag\" aria-label=\"stage 1 the release tag permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Stage 1: The release tag</h3>\n<p>For all projects, a release tag is a combination of a “version prefix”\nfollowed by a semantic version number. The most common version prefix\nis the letter ‘\"v\"’, so for example, the semantic version <code class=\"language-text\">1.3.5</code> would be\ntagged with <code class=\"language-text\">\"v1.3.5\"</code> . The beta version <code class=\"language-text\">1.6.0-beta.3</code> would be tagged\nwith <code class=\"language-text\">\"v1.6.0-beta.3\"</code>.</p>\n<blockquote>\n<p>💡 While <code class=\"language-text\">\"v\"</code> is the most common version prefix for a single module,\nmonorepos that contain multiple distributed modules will need to use\na more specific version prefix for tags like <code class=\"language-text\">“package-a-v,”</code> which\nwill result in release tags like <code class=\"language-text\">package-a-v2.0.0</code></p>\n</blockquote>\n<h3 id=\"stage-2-build-and-publish\" style=\"position:relative;\"><a href=\"#stage-2-build-and-publish\" aria-label=\"stage 2 build and publish permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Stage 2: Build and Publish</h3>\n<h4 id=\"21-publish-to-denoland\" style=\"position:relative;\"><a href=\"#21-publish-to-denoland\" aria-label=\"21 publish to denoland permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2.1: Publish to deno.land</h4>\n<p>The <a href=\"https://deno.land/x\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">deno.land</a> build/publish is almost a gimme since it uses git\ntags natively. All we have to do is create and register the webhook\nfor our module and we’re done!  Moving forward, every time\n<a href=\"https://deno.land/x\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">deno.land</a> sees a release tag, it will snapshot our source at that\ntag and make that version available to users – in perpetuity.</p>\n<h4 id=\"22-publish-to-npm\" style=\"position:relative;\"><a href=\"#22-publish-to-npm\" aria-label=\"22 publish to npm permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2.2: Publish to NPM</h4>\n<p>There’s a little more work to be done getting our package onto NPM,\nbut with a helping hand from Deno, we can do it in just two steps:</p>\n<ol>\n<li>Write a script to take a version number and build an NPM package corresponding to it.</li>\n<li>Implement a GitHub workflow to listen for a release tag and then invoke the script from (1) to build the package and publish it to <a href=\"https://npmjs.org\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://npmjs.org</a></li>\n</ol>\n<p>You might be asking yourself, “How are we going to take a bare ESM\nmodule implemented in <em>TypeScript</em> and just whip up a script that does\nall the things needed to end up with a valid NPM package?”</p>\n<p>The short answer is that the script practically writes itself! That's\nbecause Deno has our backs with a brilliant little tool called <a href=\"https://github.com/denoland/dnt\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">dnt</a> or\n<strong>D</strong>eno to <strong>N</strong>ode <strong>T</strong>ransform. <a href=\"https://github.com/denoland/dnt\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">dnt</a> is downright amazing, and its capabilities\nare way undersold. Whether we're creating a new package that we want\nto publish everywhere or we are just migrating repositories from Node\nto Deno, <a href=\"https://github.com/denoland/dnt\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">dnt</a> is the secret sauce we use that does all the heavy\nlifting for us.</p>\n<p><a href=\"https://github.com/denoland/dnt\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">dnt</a> works by taking a single ES module entry point as the input and\ngenerating a feature-complete NPM package containing all its exports\nas the output. Along the way, it does all the terrible, tedious,\nun-fun, and error-prone things you hate about NPM-ing, such as\nmaintaining the list of dependencies, compiling typescript, generating\nsource maps and typings files, creating both commonjs as well as esm\nbuilds, and optionally vendoring any dependencies. The results work\nfor users consuming the package from TS, JS, on the browser or the\nnode – including every possible combination of those – and you didn't\nhave to think about any of it. Magic!</p>\n<p>I won’t go into all of the details because the <a href=\"https://github.com/denoland/dnt#setup\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">dnt setup\ninstructions</a> are very thorough, but as an example, look at\nour build script at\n<a href=\"https://github.com/thefrontside/graphgen/blob/v1.8.1/tasks/build-npm.ts\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">tasks/build-npm.ts</a>\nin the <a href=\"https://www.npmjs.com/package/@frontside/graphgen\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">GraphGen</a> repository. It can build any version of\nour package, but here’s how we would invoke it to build version\n<code class=\"language-text\">1.0.0</code></p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">$ deno run -A tasks/build-npm.ts 1.0.0\n[dnt] Transforming...\n[dnt] Running npm install...\nadded 6 packages, and audited 7 packages in 1s\nfound 0 vulnerabilities\n[dnt] Building project...\n[dnt] Emitting declaration files...\n[dnt] Emitting ESM package...\n[dnt] Emitting script package...\n[dnt] Complete!</code></pre></div>\n<p>Now that we have the script to build an NPM package from source, the\nonly remaining step is to add a GitHub workflow to be able to call\nit. Here is an <a href=\"https://github.com/thefrontside/graphgen/blob/v1/.github/workflows/npm-release.yml\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">example from the GraphGen\nrepository</a>. Each\nstep below is linked to the relevant section in it, but the overall\nsequence is:</p>\n<ol>\n<li><a href=\"https://github.com/thefrontside/graphgen/blob/v1.8.1/.github/workflows/npm-release.yml#L4-L9\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Listen for any tag that matches our release pattern</a></li>\n<li><a href=\"https://github.com/thefrontside/graphgen/blob/v1.8.1/.github/workflows/npm-release.yml#L28-L30\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Capture the target version number based off the tag that triggered the workflow</a></li>\n<li><a href=\"https://github.com/thefrontside/graphgen/blob/v1.8.1/.github/workflows/npm-release.yml#L39-L42\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Invoke our dnt script to build an NPM package corresponding to the captured version number</a></li>\n<li><a href=\"https://github.com/thefrontside/graphgen/blob/v1.8.1/.github/workflows/npm-release.yml#L44-L48\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Publish the built package to https://npmjs.org</a></li>\n</ol>\n<p>It’s about as straightforward as a GitHub workflow can get, and with\nit in place, we can now publish to two locations – just by creating a\ntag. (Trust me, it feels even easier when you try it yourself.)</p>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>Like many JavaScript developers, we have a heavy investment in the\nNode ecosystem, which means that we rely on NPM to distribute most of\nour code. However, because of Deno’s excellent support for NPM and NPM\ndistribution, we’ve been able to forge ahead with migrating more and\nmore of our repositories so they can use Deno as their primary\nJavaScript development tool – without sacrificing any of our NPM\naudience. Not only is Deno perfectly capable of managing NPM packages,\nbut from our point of view it is actually a more pleasant experience\nthan doing so with Node itself.  I hope I’ve shown that if you’re\nthinking of giving Deno a spin it isn’t an either/or proposition. You\ncan happily develop with Deno yet still publish your code to NPM,\nwhere it can be consumed just the way it always was by applications\nrunning on Node. That means that you can adopt it incrementally at a\npace that makes sense for you and your organization.</p>\n<p>So what are you waiting for?</p>\n<div class=\"footnotes\">\n<hr>\n<ol>\n<li id=\"fn-1\">Results obtained by conducting a survey of me.<a href=\"#fnref-1\" class=\"footnote-backref\">↩</a></li>\n</ol>\n</div>","frontmatter":{"date":"May 01, 2023","description":"Even if you primarily run your JavaScript in Node, Deno is a fantastic tool for building and distributing packages on NPM (and everywhere else). This article shows how to publish modules to both https://deno.land/x and https://npmjs.org using nothing more than the deno CLI.","tags":["Deno","Node","NPM"],"img":{"childImageSharp":{"fixed":{"src":"/static/2c1fe6c214acbe17dd3db9dfd6237dd3/31987/2020-07-29-simulator-social.png"}}}}}}},"pageContext":{"id":"bc7ec12a-ebab-59c7-b15b-880f92af92d2"}},
    "staticQueryHashes": ["1241260443"]}