
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title><![CDATA[ The Cloudflare Blog ]]></title>
        <description><![CDATA[ Get the latest news on how products at Cloudflare are built, technologies used, and join the teams helping to build a better Internet. ]]></description>
        <link>https://blog.cloudflare.com</link>
        <atom:link href="https://blog.cloudflare.com/" rel="self" type="application/rss+xml"/>
        <language>en-us</language>
        <image>
            <url>https://blog.cloudflare.com/favicon.png</url>
            <title>The Cloudflare Blog</title>
            <link>https://blog.cloudflare.com</link>
        </image>
        <lastBuildDate>Sun, 05 Apr 2026 17:38:41 GMT</lastBuildDate>
        <item>
            <title><![CDATA[Connecting to production: the architecture of remote bindings]]></title>
            <link>https://blog.cloudflare.com/connecting-to-production-the-architecture-of-remote-bindings/</link>
            <pubDate>Wed, 12 Nov 2025 14:00:00 GMT</pubDate>
            <description><![CDATA[ Remote bindings allow you to connect your local Worker code to deployed Cloudflare resources like R2 and D1. Come along on the technical journey of how we built this feature to create a seamless local development experience. ]]></description>
            <content:encoded><![CDATA[ <p>Remote bindings are bindings that connect to a deployed resource on your Cloudflare account <i>instead </i>of a locally simulated resource – and recently, we announced that <a href="https://blog.cloudflare.com/cloudflare-developer-platform-keeps-getting-better-faster-and-more-powerful/#connect-to-production-services-and-resources-from-local-development-with-remote-bindings-now-ga"><u>remote bindings are now generally available</u></a>. </p><p>With this launch, you can now connect to deployed resources like <a href="https://developers.cloudflare.com/r2/"><u>R2 buckets</u></a> and <a href="https://www.cloudflare.com/developer-platform/products/d1/"><u>D1 databases</u></a> while running Worker code on your local machine. This means you can test your local code changes against real data and services, without the overhead of deploying for each iteration. </p><p>In this blog post, we’ll dig into the technical details of how we built it, creating a seamless local development experience.</p>
    <div>
      <h3>Developing on the Workers platform</h3>
      <a href="#developing-on-the-workers-platform">
        
      </a>
    </div>
    <p>A key part of the <a href="https://www.cloudflare.com/developer-platform/products/workers/"><u>Cloudflare Workers platform</u></a> has been the ability to develop your code locally without having to deploy it every time you wanted to test something – though the way we’ve supported this has changed greatly over the years. </p><p>We started with <code>wrangler</code> dev running in remote mode. This works by deploying and connecting to a preview version of your Worker that runs on Cloudflare’s network every time you make a change to your code, allowing you to test things out as you develop. However, remote mode isn’t perfect — it’s complex and hard to maintain. And the developer experience leaves a lot to be desired: slow iteration speed, unstable debugging connections, and lack of support for multi-worker scenarios. </p><p>Those issues and others motivated a significant investment in a fully local development environment for Workers, which was released in mid-2023 and became the <a href="https://blog.cloudflare.com/wrangler3/"><u>default experience for wrangler dev</u></a>. Since then, we've put a huge amount of work into the local dev experience with <a href="https://developers.cloudflare.com/workers/wrangler/"><u>Wrangler</u></a>, the <a href="https://developers.cloudflare.com/workers/vite-plugin/"><u>Cloudflare Vite plugin</u></a> (alongside <a href="https://developers.cloudflare.com/workers/testing/vitest-integration/"><u>@cloudflare/vitest-pool-workers</u></a>) &amp; <a href="https://developers.cloudflare.com/workers/testing/miniflare/"><u>Miniflare</u></a>.</p><p>Still, the original remote mode remained accessible via a flag: <code>wrangler dev --remote</code>. When using remote mode, all the DX benefits of a fully local experience and the improvements we’ve made over the last few years are bypassed. So why do people still use it? It enables one key unique feature: binding to remote resources while locally developing. When you use local mode to develop a Worker locally, all of your <a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/"><u>bindings</u></a> are simulated locally using local (initially empty) data. This is fantastic for iterating on your app’s logic with test data – but sometimes that’s not enough, whether you want to share resources across your team, reproduce bugs tied to real data, or just be confident that your app will work in production with real resources.</p><p>Given this, we saw an opportunity: If we could bring the best parts of remote mode (i.e. access to remote resources) to <code>wrangler dev</code>, there’d be one single flow for developing Workers that would enable many use cases, while not locking people out of the advancements we’ve made to local development. And that’s what we did! </p><p>As of Wrangler v4.37.0 you can pick on a per-binding basis whether a binding should use remote or local resources, simply by specifying the <code>remote</code> option. It’s important to re-emphasise this—you only need to add <code>remote: true!</code> There’s no complex management of API keys and credentials involved, it all just works using Wrangler’s existing Oauth connection to the Cloudflare API.</p>
            <pre><code>{
  "name": "my-worker",
  "compatibility_date": "2025-01-01",
  "kv_namespaces": [{
    "binding": "KV",
    "id": "my-kv-id",
  },{
    "binding": "KV_2",
    "id": "other-kv-id",
    "remote": true
  }],
  "r2_buckets": [{
    "bucket_name": "my-r2-name",
    "binding": "R2"
  }]
}</code></pre>
            <p>The eagle-eyed among you might have realised that some bindings already worked like this, accessing remote resources from local dev. Most prominently, the <a href="https://developers.cloudflare.com/workers-ai/configuration/bindings/"><u>AI binding</u></a> was a trailblazer for what a general remote bindings solution could look like. From its introduction, the AI binding always connected to a remote resource, since a true local experience that supports all the different models you can use with Workers AI would be impractical and require a huge upfront download of AI models. </p><p>As we realised different products within Workers needed something similar to remote bindings (Images and Hyperdrive, for instance), we ended up with a bit of a patchwork of different solutions. We’ve now unified under a single remote bindings solution that works for all binding types.</p>
    <div>
      <h3>How we built it</h3>
      <a href="#how-we-built-it">
        
      </a>
    </div>
    <p>We wanted to make it really easy for developers to access remote resources without having to change their production Workers code, and so we landed on a solution that required us to fetch data from the remote resource at the point of use in your Worker.</p>
            <pre><code>const value = await env.KV.get("some-key")</code></pre>
            <p><sup><i>The above code snippet shows accessing the “some-key” value in the env.KV </i></sup><a href="https://developers.cloudflare.com/kv/api/read-key-value-pairs/"><sup><i><u>KV namespace</u></i></sup></a><sup><i>, which is not available locally and needs to be fetched over the network.</i></sup></p><p>So if that was our requirement, how would we get there? For instance, how would we get from a user calling <code>env.KV.put(“key”, “value”)</code> in their Worker to actually storing that in a remote KV store? The obvious solution was perhaps to use the <a href="https://developers.cloudflare.com/api/resources/kv/subresources/namespaces/subresources/values/methods/update/"><u>Cloudflare API</u></a>. We could have just replaced the entire env locally with stub objects that made API calls, transforming <code>env.KV.put()</code> into PUT <code>http:///accounts/{account_id}/storage/kv/namespaces/{namespace_id}/values/{key_name}</code>. </p><p>This would’ve worked great for KV, R2, D1, and other bindings with mature HTTP APIs, but it would have been a pretty complex solution to implement and maintain. We would have had to replicate the entire bindings API surface and transform every possible operation on a binding to an equivalent API call. Additionally, some binding operations don’t have an equivalent API call, and wouldn’t be supportable using this strategy.</p><p>Instead, we realised that we already had a ready-made API waiting for us — the one we use in production! </p>
    <div>
      <h3>How bindings work under the hood in production</h3>
      <a href="#how-bindings-work-under-the-hood-in-production">
        
      </a>
    </div>
    <p>Most bindings on the Workers platform boil down to essentially a <a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/"><u>service binding</u></a>. A service binding is a link between two Workers that allows them to communicate over HTTP or <a href="https://blog.cloudflare.com/javascript-native-rpc/"><u>JSRPC</u></a> (we’ll come back to JSRPC later). </p><p>For example, the KV binding is implemented as a service binding between your authored Worker and a platform Worker, speaking HTTP. The JS API for the KV binding is implemented in the Workers runtime, and translates calls like <code>env.KV.get()</code> to HTTP calls to the Worker that implements the KV service. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4PwugWAyVPMq086BKt9cjh/cfea7dbb50b9b2983bd21fcb7b80334d/image2.png" />
          </figure><p><i><sup>Diagram showing a simplified model of how a KV binding works in production</sup></i></p><p>You may notice that there’s a natural async network boundary here — between the runtime translating the <code>env.KV.get()</code> call and the Worker that implements the KV service. We realised that we could use that natural network boundary to implement remote bindings. Instead of the <i>production</i> runtime translating <code>env.KV.get()</code> to an HTTP call, we could have the <i>local</i> runtime (<a href="https://github.com/cloudflare/workerd"><u>workerd</u></a>) translate <code>env.KV.get()</code> to an HTTP call, and then send it directly to the KV service, bypassing the production runtime. And so that’s what we did!</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7JNPZ2MM5IZ4TSXfN0qywV/804b7997d115405bc3f4d335cb21e626/image3.png" />
          </figure><p><sup><i>Diagram showing a locally run worker with a single KV binding, with a single remote proxy client that communicates to the remote proxy server, which in turn communicates with the remote KV</i></sup></p><p>The above diagram shows a local Worker running with a remote KV binding. Instead of being handled by the local KV simulation, it’s now being handled by a remote proxy client. This Worker then communicates with a remote proxy server connected to the real remote KV resource, ultimately allowing the local Worker to communicate with the remote KV data seamlessly.</p><p>Each binding can independently either be handled by a remote proxy client (all connected to the same remote proxy server) or by a local simulation, allowing for very dynamic workflows where some bindings are locally simulated while others connect to the real remote resource, as illustrated in the example below:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6yUYvFjpxGv7GcC12l7zr1/a7d46f33869448e1f3f13540d741ff40/image1.png" />
          </figure><p><sup><i>The above diagram and config shows a Worker (running on your computer) bound to 3 different resources—two local (KV &amp; R2), and one remote (KV_2)</i></sup></p>
    <div>
      <h3>How JSRPC fits in</h3>
      <a href="#how-jsrpc-fits-in">
        
      </a>
    </div>
    <p>The above section deals with bindings that are backed by HTTP connections (like KV and R2), but modern bindings use <a href="https://blog.cloudflare.com/javascript-native-rpc/"><u>JSRPC</u></a>. That means we needed a way for the locally running <code>workerd </code>to speak JSRPC to a production runtime instance. </p><p>In a stroke of good luck, a parallel project was going on to make this possible, as detailed in the <a href="https://blog.cloudflare.com/capnweb-javascript-rpc-library/"><u>Cap’n Web blog</u></a>. We integrated that by making the connection between the local <code>workerd</code> instance and the remote runtime instance communicate over <a href="https://github.com/cloudflare/capnweb"><u>websockets using Cap’n Web</u></a>, enabling bindings backed by JSRPC to work. This includes newer bindings like <a href="https://developers.cloudflare.com/images/transform-images/transform-via-workers/"><u>Images</u></a>, as well as JSRPC service bindings to your own Workers.</p>
    <div>
      <h3>Remote bindings with Vite, Vitest and the JavaScript ecosystem</h3>
      <a href="#remote-bindings-with-vite-vitest-and-the-javascript-ecosystem">
        
      </a>
    </div>
    <p>We didn't want to limit this exciting new feature to only <code>wrangler dev</code>. We wanted to support it in our Cloudflare Vite Plugin and vitest-pool-workers packages, as well as allowing any other potential tools and use cases from the JavaScript ecosystem to also benefit from it.</p><p>In order to achieve this, the wrangler package now exports utilities such as <code>startRemoteProxySession</code> that allow tools not leveraging <code>wrangler dev</code> to also support remote bindings. You can find more details in the <a href="https://developers.cloudflare.com/workers/development-testing/#remote-bindings"><u>official remote bindings documentation</u></a>.</p>
    <div>
      <h3>How do I try this out?</h3>
      <a href="#how-do-i-try-this-out">
        
      </a>
    </div>
    <p>Just use <code>wrangler dev</code>! As of Wrangler v4.37.0 (<code>@cloudflare/vite-plugin</code> v1.13.0, <code>@cloudflare/vitest-pool-workers</code> v0.9.0), remote bindings are available in all projects, and can be turned on a per-binding basis by adding <code>remote: true</code> to the binding definition in your <a href="https://developers.cloudflare.com/workers/wrangler/configuration/"><u>Wrangler config file</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[R2]]></category>
            <category><![CDATA[D1]]></category>
            <guid isPermaLink="false">60miu6u2Fk0E5CPdKOCYWX</guid>
            <dc:creator>Samuel Macleod</dc:creator>
            <dc:creator>Dario Piotrowicz</dc:creator>
        </item>
        <item>
            <title><![CDATA[Re-introducing the Cloudflare Workers Playground]]></title>
            <link>https://blog.cloudflare.com/workers-playground/</link>
            <pubDate>Thu, 28 Sep 2023 13:00:43 GMT</pubDate>
            <description><![CDATA[ Today, we’re excited to announce an updated Cloudflare Workers playground, where users can develop and test Workers before sharing or deploying them ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Since the very <a href="/introducing-cloudflare-workers/">initial announcement</a> of Cloudflare Workers, we’ve provided a playground. The motivation behind that being a belief that users should have a convenient, low-commitment way to play around with and learn more about Workers.</p><p>Over the last few years, while <a href="https://www.cloudflare.com/developer-platform/workers/">Cloudflare Workers</a> and our <a href="https://www.cloudflare.com/developer-platform/products/">Developer Platform</a> have changed and grown, the original playground has not. Today, we’re proud to announce a revamp of the playground that demonstrates the power of Workers, along with new development tooling, and the ability to share your playground code and deploy instantly to Cloudflare’s global network.</p>
    <div>
      <h3>A focus on origin Workers</h3>
      <a href="#a-focus-on-origin-workers">
        
      </a>
    </div>
    <p>When Workers was first introduced, many of the examples and use-cases centered around middleware, where a Worker intercepts a request to an origin and does something before returning a response. This includes things like: modifying headers, redirecting traffic, helping with A/B testing, or caching. Ultimately the Worker isn’t acting as an origin in these cases, it sits between the user and the destination.</p><p>While Workers are still great for these types of tasks, for the updated playground, we decided to focus on the Worker-as-origin use-case. This is where the Worker receives a request and is responsible for returning the full response. In this case, the Worker is the destination, not middle-ware. This is a great way for you to develop more complex use-cases like user interfaces or APIs.</p>
    <div>
      <h3>A new editor experience</h3>
      <a href="#a-new-editor-experience">
        
      </a>
    </div>
    <p>During Developer Week in May, we <a href="/improved-quick-edit/">announced</a> a new, authenticated dashboard editor experience powered by VSCode. Now, this same experience is available to users in the playground.</p><p>Users now have a more robust IDE experience that supports: multi-module Workers, type-checking via JSDoc comments and the <a href="https://www.npmjs.com/package/@cloudflare/workers-types">`workers-types` package</a>, pretty error pages, and real previews that update as you edit code. The new editor only supports <a href="/workers-javascript-modules/">Module syntax</a>, which is the preferred way for users to develop new Workers.</p><p>When the playground first loads, it looks like this:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6mfWVX3KmQjEM1YQ7W0sjN/2d0cc6ec11fd81a59ef151a912aa5a2a/image4-18.png" />
            
            </figure><p>The content you see on the right is coming from the code on the left. You can modify this just as you would in a code editor. Once you make an edit, it will be updated shortly on the right as demonstrated below:</p><div>
  
</div>
<p></p><p>You’re not limited to the starter demo. Feel free to edit and remove those files to create APIs, user interfaces, or any other application that you come up with.</p>
    <div>
      <h3>Updated developer tooling</h3>
      <a href="#updated-developer-tooling">
        
      </a>
    </div>
    <p>Along with the updated editor, the new playground also contains numerous developer tools to help give you visibility into the Worker.</p><p>Playground users have access to the same Chrome DevTools technology that we use in the Wrangler CLI and the Dashboard. Within this view, you can: view logs, view network requests, and profile your Worker among other things.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5nlF1OQyvv1NhGcf6cNKZI/c51f5a2d0980f545cc8519d59ae51c03/Screenshot-2023-09-12-at-4.12.10-PM.png" />
            
            </figure><p>At the top of the playground, you’ll also see an “HTTP” tab which you can use to test your Worker against various HTTP methods.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4wjS7nrqnVdcfqVSk7DI0w/9d7b5ad7a29c027ab1b68cb665b073a7/Screenshot-2023-09-12-at-4.08.49-PM.png" />
            
            </figure>
    <div>
      <h3>Share what you create</h3>
      <a href="#share-what-you-create">
        
      </a>
    </div>
    <p>With all these improvements, we haven’t forgotten the core use of a playground—to share Workers with other people! Whatever your use-case; whether you’re building a demo to showcase the power of Workers or sending someone an example of how to fix a specific issue, all you need to do is click “Copy Link” in the top right of the Playground then paste the URL in any URL bar.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6LpxCAHIMkHpuc3UDMcHAJ/019a198ee37f89ab9eb9d3eb0c19a355/Screenshot-2023-09-28-at-13.35.41.png" />
            
            </figure><p>The unique URL will be shareable and deployable as long as you have it. This means that you could create quick demos by creating various Workers in the Playground, and bookmark them to share later. They won’t expire.</p>
    <div>
      <h3>Deploying to the Supercloud</h3>
      <a href="#deploying-to-the-supercloud">
        
      </a>
    </div>
    <p>We also wanted to make it easier to go from writing a Worker in the Playground to deploying that Worker to Cloudflare’s global network. We’ve included a “Deploy” button that will help you quickly deploy the Worker you’ve just created.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6PxsN7ji6lsDeLmbG6fZmV/00ce6d09999333fe2f7321cb61f3d5c9/image5-10.png" />
            
            </figure><p>If you don’t already have a Cloudflare account, you will also be guided through the onboarding process.</p>
    <div>
      <h3>Try it out</h3>
      <a href="#try-it-out">
        
      </a>
    </div>
    <p>This is now available to all users in Region:Earth. Go to <a href="https://workers.cloudflare.com/playground">https://workers.cloudflare.com/playground</a> and give it a go!</p> ]]></content:encoded>
            <category><![CDATA[Birthday Week]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Dashboard]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <guid isPermaLink="false">7GiFEdoyaqaiVfqZzzyF6g</guid>
            <dc:creator>Adam Murray</dc:creator>
            <dc:creator>Samuel Macleod</dc:creator>
        </item>
        <item>
            <title><![CDATA[A whole new Quick Edit in Cloudflare Workers]]></title>
            <link>https://blog.cloudflare.com/improved-quick-edit/</link>
            <pubDate>Wed, 17 May 2023 13:00:57 GMT</pubDate>
            <description><![CDATA[ We’re proud to announce an improved dashboard editor experience that allows users to edit multimodule Workers, use real edge previews, and debug their Workers more easily - all powered by Workers and VSCode for the Web. ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2B1L3aFtxDPZhKGtqfkFxy/f35e5927cfc211894c5fed5c17466eeb/image1-42.png" />
            
            </figure><p>Quick Edit is a development experience for Cloudflare Workers, embedded right within the Cloudflare dashboard. It’s the fastest way to get up and running with a new worker, and lets you quickly preview and deploy changes to your code.</p><p>We’ve spent a lot of recent time working on upgrading the <i>local</i> development experience to be as <a href="/miniflare-and-workerd/">useful as possible</a>, but the Quick Edit experience for editing Workers has stagnated since the release of <a href="/just-write-code-improving-developer-experience-for-cloudflare-workers/">workers.dev</a>. It’s time to give Quick Edit some love and bring it up to scratch with the expectations of today's developers.</p><p>Before diving into what’s changed—a quick overview of the current Quick Edit experience:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/68vBJYkfVP0kh5oNFxCXFX/a977ab2c917072d0b7cbd359b95bc486/download-11.png" />
            
            </figure><p>We used the robust <a href="https://microsoft.github.io/monaco-editor/">Monaco editor</a>, which took us pretty far—it’s even what VSCode uses under the hood! However, Monaco is fairly limited in what it can do. Developers are used to the full power of their local development environment, with advanced IntelliSense support and all the power of a full-fledged IDE. Compared to that, a single file text editor is a step-down in expressiveness and functionality.</p>
    <div>
      <h2>VSCode for Web</h2>
      <a href="#vscode-for-web">
        
      </a>
    </div>
    <p>Today, we’re rolling out a new Quick Edit experience for Workers, powered by <a href="https://code.visualstudio.com/docs/editor/vscode-web">VSCode for Web</a>. This is a huge upgrade, allowing developers to work in a familiar environment. This isn’t just about familiarity though—using VSCode for Web to power Quick Edit unlocks significant new functionality that was previously only possible with a local development setup using <a href="/10-things-i-love-about-wrangler/">Wrangler</a>.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7Dg5Pph7cGcx3fKb4zMiYZ/f26625e62400119738e40a0d366d57c0/download--1--7.png" />
            
            </figure>
    <div>
      <h3>Support for multiple modules!</h3>
      <a href="#support-for-multiple-modules">
        
      </a>
    </div>
    <p>Cloudflare Workers released support for the <a href="/workers-javascript-modules/">Modules syntax</a> in 2021, which is the recommended way to write Workers. It leans into modern JavaScript by leveraging the ES Module syntax, and lets you define Workers by exporting a default object containing event handlers.</p>
            <pre><code>export default {
 async fetch(request, env) {
   return new Response("Hello, World!")
 }
}</code></pre>
            <p>There are two sides of the coin when it comes to ES Modules though: exports <i>and imports</i>. Until now, if you wanted to organise your worker in multiple modules you had to use Wrangler and a local development setup. Now, you’ll be able to write multiple modules in the dashboard editor, and import them, just as you can locally. We haven’t enabled support for importing modules from npm yet, but that’s something we’re actively exploring—stay tuned!</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7iWt9JogEsGbMwwlZgI9dt/0ca18de31eba4518ec230707211cceb6/download--2--6.png" />
            
            </figure>
    <div>
      <h3>Edge Preview</h3>
      <a href="#edge-preview">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2BCsQLD1rEt5zDC2FMVN58/06ac07ce324b0a3e1ba9ddfd41c009dc/download--3--4.png" />
            
            </figure><p>When editing a worker in the dashboard, Cloudflare spins up a preview of your worker, deployed from the code you’re currently working on. This helps speed up the feedback loop when developing a worker, and makes it easy to test changes without impacting production traffic (see also, <a href="/announcing-wrangler-dev-the-edge-on-localhost/">wrangler dev</a>).</p><p>However, the in-dashboard preview hasn’t historically been a high-fidelity match for the deployed Workers runtime. There were various differences in behaviour between the dashboard preview environment and a deployed worker, and it was difficult to have full confidence that a worker that worked in the preview would work in the deployed environment.</p><p>That changes today! We’ve changed the dashboard preview environment to use the same system that powers <a href="/announcing-wrangler-dev-the-edge-on-localhost/"><code>wrangler dev</code></a>. This means that your preview worker will be run on Cloudflare's global network, the same environment as your deployed workers.</p>
    <div>
      <h3>Helpful error messages</h3>
      <a href="#helpful-error-messages">
        
      </a>
    </div>
    <p>In the previous dashboard editor, the experience when your code throws an error wasn’t great. Unless you wrap your worker code in a try-catch handler, the preview will show a blank page when your worker throws an error. This can make it really tricky to debug your worker, and is pretty frustrating. With the release of the new Quick Editor, we now wrap your worker with error handling code that shows helpful error pages, complete with error stack traces and detailed descriptions.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/39MmsVyio0cM7lPDy4JtEg/570a8fed7b3aa76cd4ef547bff819224/download--4--4.png" />
            
            </figure>
    <div>
      <h3>Typechecking</h3>
      <a href="#typechecking">
        
      </a>
    </div>
    <p>TypeScript is incredibly popular, and developers are more and more used to writing their workers in TypeScript. While the dashboard editor still only allows JavaScript files (and you’re unable to write TypeScript directly) we wanted to support modern typed JavaScript development as much as we could. To that end, the new dashboard editor has full support for <a href="https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html">JSDoc TypeScript syntax</a>, with <a href="https://www.npmjs.com/package/@cloudflare/workers-types">the TypeScript environment for workers preloaded</a>. This means that writing code with type errors will show a familiar squiggly red line, and Cloudflare APIs like HTMLRewriter will be autocompleted.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4vXG2YZQvTAdXe9hghyD67/164bb87679259a6a27bb6bb92dcb3cea/download--5--4.png" />
            
            </figure><div></div>
<p></p>
    <div>
      <h2>How we built it</h2>
      <a href="#how-we-built-it">
        
      </a>
    </div>
    <p>It wouldn’t be a Cloudflare blog post without a deep dive into the nuts and bolts of what we’ve built!</p><p>First, an overview—how does this work at a high level? We embed VSCode for Web in the Cloudflare dashboard as an <code>iframe</code>, and communicate with it over a <a href="https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel"><code>MessageChannel</code></a>. When the <code>iframe</code> is loaded, the Cloudflare dashboard sends over the contents of your worker to a VSCode for Web extension. This extension seeds an in-memory filesystem from which VSCode for Web reads. When you edit files in VSCode for Web, the updated files are sent back over the same <code>MessageChannel</code> to the Cloudflare dashboard, where they’re uploaded as a previewed worker to Cloudflare's global network.</p><p>As with any project of this size, the devil is in the details. Let’s focus on a specific area —how we communicate with VSCode for Web’s <code>iframe</code> from the Cloudflare dashboard.</p><p>The <a href="https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel"><code>MessageChannel</code></a> browser API enables relatively easy cross-frame communication—in this case, from an iframe embedder to the iframe itself. To use it, you construct an instance and access the <code>port1</code> and <code>port2</code> properties:</p>
            <pre><code>const channel = new MessageChannel()

// The MessagePort you keep a hold of
channel.port1

// The MessagePort you send to the iframe
channel.port2</code></pre>
            <p>We store a reference to the <code>MessageChannel</code> to use across component renders with <code>useRef()</code>, since React would otherwise create a new <code>MessageChannel</code> instance with every render.</p><p>With that out of the way, all that remains is to send <code>channel.port2</code> to VSCode for Web’s iframe, via a call to <code>postMessage()</code>.</p>
            <pre><code>// A reference to the iframe embedding VSCode for Web
const editor = document.getElementById("vscode")

// Wait for the iframe to load 
editor.addEventListener('load', () =&gt; {
	// Send over the MessagePort
editor.contentWindow.postMessage('PORT', '*', [
channel.port2
]);
});</code></pre>
            <p>An interesting detail here is how the <code>MessagePort</code> is sent over to the iframe. The third argument to <code>postMessage()</code> indicates a sequence of <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Transferable_objects">Transferable objects</a>. This <i>transfers</i> ownership of <code>port2</code> to the iframe, which means that any attempts to access it in the original context will throw an exception.</p><p>At this stage the dashboard has loaded an iframe containing VSCode for Web, initialised a <code>MessageChannel</code>, and sent over a <code>MessagePort</code> to the iframe. Let’s switch context—the iframe now needs to catch the <code>MessagePort</code> and start using it to communicate with the embedder (Cloudflare’s dashboard).</p>
            <pre><code>window.onmessage = (e) =&gt; {
if (e.data === "PORT") {
	// An instance of a MessagePort
const port = e.ports[0]
}
};</code></pre>
            <p>Relatively straightforward! With not <i>that</i> much code, we’ve set up communication and can start sending more complex messages across. Here’s an example of how we send over the initial worker content from the dashboard to the VSCode for Web iframe:</p>
            <pre><code>// In the Cloudflare dashboard

// The modules that make up your worker
const files = [
  {
    path: 'index.js',
    contents: `
		import { hello } from "./world.js"
export default {
			fetch(request) {
				return new Response(hello)
			}
		}`
  },
  {
    path: 'world.js',
    contents: `export const hello = "Hello World"`
  }
];

channel.port1.postMessage({
  type: 'WorkerLoaded',
  // The worker name
  name: 'your-worker-name',
  // The worker's main module
  entrypoint: 'index.js',
  // The worker's modules
  files: files
});</code></pre>
            <p>If you’d like to learn more about our approach, you can explore the code we’ve open sourced as part of this project, including the <a href="https://github.com/cloudflare/workers-sdk/tree/main/packages/quick-edit-extension">VSCode extension</a> we’ve written to load data from the Cloudflare dashboard, our <a href="https://github.com/cloudflare/workers-sdk/tree/main/packages/quick-edit">patches to VSCode</a>, and our <a href="https://github.com/cloudflare/workers-sdk/tree/main/packages/solarflare-theme">VSCode theme</a>.</p>
    <div>
      <h2>We’re not done!</h2>
      <a href="#were-not-done">
        
      </a>
    </div>
    <p>This is a huge overhaul of the dashboard editing experience for Workers, but we’re not resting on our laurels! We know there’s a long way to go before developing a worker in the browser will offer the same experience as developing a worker locally with Wrangler, and we’re working on ways to close that gap. In particular, we’re working on adding Typescript support to the editor, and supporting syncing to external Git providers like GitHub and GitLab.</p><p>We’d love to hear any feedback from you on the new editing experience—come say hi and ask us any questions you have on the <a href="https://discord.cloudflare.com">Cloudflare Discord</a>!</p> ]]></content:encoded>
            <category><![CDATA[Developer Week]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <guid isPermaLink="false">72WrH18NXIGrxYukjwVtxr</guid>
            <dc:creator>Samuel Macleod</dc:creator>
            <dc:creator>Adam Murray</dc:creator>
        </item>
    </channel>
</rss>