<?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>DEV Community: Viktor Pasynok</title>
    <description>The latest articles on DEV Community by Viktor Pasynok (@binjospookie).</description>
    <link>https://dev.to/binjospookie</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%2F435365%2F5224de51-8c1a-46db-af71-32ed6dd1192d.jpeg</url>
      <title>DEV Community: Viktor Pasynok</title>
      <link>https://dev.to/binjospookie</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/binjospookie"/>
    <language>en</language>
    <item>
      <title>Managing Complex Front-End Apps: Lessons Learned (and a Tool I Built to Help)</title>
      <dc:creator>Viktor Pasynok</dc:creator>
      <pubDate>Sun, 02 Feb 2025 18:19:24 +0000</pubDate>
      <link>https://dev.to/binjospookie/managing-complex-front-end-apps-lessons-learned-and-a-tool-i-built-to-help-500b</link>
      <guid>https://dev.to/binjospookie/managing-complex-front-end-apps-lessons-learned-and-a-tool-i-built-to-help-500b</guid>
      <description>&lt;p&gt;I’ve been working on large front-end applications for a while, and one of the biggest challenges isn’t just managing features—it’s managing the connections between them. Dependencies, startup order, feature toggles, conditional modules… it gets messy fast.&lt;/p&gt;

&lt;p&gt;I recently hit a point where existing tools felt limiting. So, instead of hacking around the problem, I built a tool: app-compose.&lt;/p&gt;

&lt;p&gt;It’s not another framework or state manager. Think of it as a lightweight system for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Managing feature dependencies (both strict and optional).&lt;/li&gt;
&lt;li&gt;Controlling startup sequences with minimal boilerplate.&lt;/li&gt;
&lt;li&gt;Handling feature toggles without sprinkling if conditions everywhere.&lt;/li&gt;
&lt;li&gt;Debugging why something started, skipped, or failed (because tracing this manually sucks).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The idea isn’t revolutionary, but it’s been a game-changer for how I organize complex apps. I also made sure the docs are clear, with simple examples and analogies to keep things beginner-friendly.&lt;/p&gt;

&lt;p&gt;I’d love to hear how others manage this kind of complexity. What’s worked for you? What tools do you rely on?&lt;br&gt;
And if you’re curious, here’s the project: &lt;a href="https://github.com/grlt-hub/app-compose" rel="noopener noreferrer"&gt;GitHub link&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>react</category>
    </item>
    <item>
      <title>Why Feature Toggles Could Be Your Front-End's Worst Nightmare</title>
      <dc:creator>Viktor Pasynok</dc:creator>
      <pubDate>Wed, 13 Nov 2024 16:03:41 +0000</pubDate>
      <link>https://dev.to/binjospookie/feature-toggles-in-front-end-applications-taming-the-complexity-37jh</link>
      <guid>https://dev.to/binjospookie/feature-toggles-in-front-end-applications-taming-the-complexity-37jh</guid>
      <description>&lt;p&gt;Feature toggles (or feature flags) have become a fundamental part of front-end development. They provide a way to dynamically enable or disable features without deploying new code, making it possible to run A/B tests, roll out features gradually, or easily turn off problematic functionality. However, with all the benefits they bring, feature toggles can also lead to serious challenges.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hidden Complexity of Feature Toggles
&lt;/h2&gt;

&lt;p&gt;When you start using feature toggles in a front-end project, everything may seem straightforward: add a toggle, check its value, and determine if a feature should run or not. But as your project scales and you add more toggles, the complexity increases exponentially. Here are some of the common problems that arise:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configuration Overload&lt;/strong&gt;: A small project might have only a handful of toggles, but larger applications can have dozens or even hundreds. Managing which toggles are on, off, or in some intermediate state becomes cumbersome. Developers might have to juggle multiple configurations for different environments, making debugging more difficult.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Interdependencies Between Features&lt;/strong&gt;: A more insidious problem comes from the way features interact. Features that are meant to be toggled independently can have hidden dependencies. If one toggle changes the behavior of a shared component, another feature relying on that component might break in unexpected ways. It becomes harder to reason about the codebase, and simple changes can have unintended consequences.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Codebase Fragmentation&lt;/strong&gt;: As you add feature toggles, your code starts to split into different execution paths based on toggle states. Over time, this can make the codebase hard to navigate. You may have conditional checks scattered throughout, and the readability and maintainability of the code suffer. Refactoring becomes a dangerous task, as ensuring all toggle states are handled correctly is tricky and error-prone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Testing Challenges&lt;/strong&gt;: To confidently release new features, you must test the application in all possible toggle configurations. As the number of toggles grows, the combinations become unmanageable. Even if you automate testing, it can become prohibitively expensive to cover every scenario, especially as features are turned on and off.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance Overhead&lt;/strong&gt;: Feature toggles can also introduce performance issues. Checking a toggle’s state isn’t costly on its own, but when many toggles are checked repeatedly in the render process, it can degrade performance. Moreover, toggles often require infrastructure for configuration, increasing the load on your backend.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How Do We Manage Feature Toggle Complexity?
&lt;/h2&gt;

&lt;p&gt;Handling feature toggles well requires thoughtful strategies and sometimes specialized tools. Some approaches include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Centralizing Configuration&lt;/strong&gt;: Instead of sprinkling toggle logic throughout your codebase, try to centralize it. Use a dedicated service or module to manage the state of all toggles and handle complex dependencies in one place.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strict Dependency Management&lt;/strong&gt;: Carefully track which features depend on others. Document these relationships and, if possible, enforce constraints in code to ensure that features are toggled in a way that makes sense.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated Testing and Analysis&lt;/strong&gt;: Invest in automated tools that can analyze toggle coverage. Some systems can warn you when a change might break an existing toggle configuration or generate test cases for common scenarios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Periodic Cleanup&lt;/strong&gt;: Feature toggles shouldn’t live forever. Once a feature is stable and rolled out to all users, remove the toggle and the associated logic to simplify the codebase. A regular cleanup process can help prevent “toggle bloat.”&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introducing app-compose: A New Way to Manage Dependencies
&lt;/h2&gt;

&lt;p&gt;When feature toggles are used in an application with many interdependent parts, managing these dependencies can feel overwhelming. This is where a tool like app-compose can help.&lt;/p&gt;

&lt;p&gt;app-compose allows you to define features as isolated containers, each with explicit dependencies. Instead of having to manually track which features are ready or handle complex chains of conditions, app-compose orchestrates everything for you. By using app-compose, you can ensure that features only initialize when their dependencies are in the right state, significantly reducing the risk of hidden bugs or runtime errors.&lt;/p&gt;

&lt;p&gt;Here’s a simple example of how app-compose can simplify dependency management:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createContainer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;compose&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="s1"&gt;@grlt-hub/app-compose&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchToggles&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;referral&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;featureToggle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createContainer&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;featureToggle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;start&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="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="nf"&gt;fetchToggles&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="na"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&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="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;referral&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createContainer&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;referral&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;dependsOn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;featureToggle&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;enable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deps&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;deps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;featureToggle&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;referral&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;start&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="na"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;compose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;up&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;featureToggle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;referral&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;fetchToggles&lt;/strong&gt;: Fetches the feature toggles and returns an object indicating whether each feature is enabled or disabled.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;featureToggle&lt;/strong&gt;: A container that fetches the toggles. The data is made available via its api.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;referral&lt;/strong&gt;: A container that depends on featureToggle. It checks if the referral feature is enabled using the enable method. If the feature is not enabled, the referral container will not start.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With app-compose, taming the complexity of feature toggles becomes not just manageable but structured and efficient.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://grlt-hub.github.io/app-compose/" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/grlt-hub/app-compose" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>opensource</category>
      <category>frontend</category>
      <category>typescript</category>
    </item>
    <item>
      <title>How to create scalable, module-based applications with ease.</title>
      <dc:creator>Viktor Pasynok</dc:creator>
      <pubDate>Thu, 07 Nov 2024 16:07:42 +0000</pubDate>
      <link>https://dev.to/binjospookie/how-to-create-scalable-module-based-applications-with-ease-8h9</link>
      <guid>https://dev.to/binjospookie/how-to-create-scalable-module-based-applications-with-ease-8h9</guid>
      <description>&lt;p&gt;Modern applications thrive on modular architecture, adapting seamlessly to evolving business needs. To achieve &lt;strong&gt;true modularity&lt;/strong&gt;, though, you need more than just independent components—you need an &lt;strong&gt;efficient&lt;/strong&gt; way to bring them together. This means &lt;strong&gt;controlling&lt;/strong&gt; how modules load, in what order, and with which dependencies. It gets even trickier when you want to turn off parts of the system &lt;strong&gt;without any traces&lt;/strong&gt; in the code, like &lt;code&gt;if/else&lt;/code&gt; statements, and without affecting the &lt;strong&gt;stability&lt;/strong&gt; of other components.&lt;/p&gt;

&lt;p&gt;The simplest example: imagine your application has numerous interconnected features. Sometimes, you need to disable one of them. Here’s the catch: some features may directly depend on it, while others may be affected indirectly (transitively). If you overlook these dependencies, your app might crash. And if you need to disable more than one feature, the combinations can become complex and error-prone. It would be ideal to have a way to explicitly describe feature dependencies and safely disable them without missing anything.&lt;/p&gt;

&lt;p&gt;For instance, like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createContainer&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;start&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="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="nf"&gt;fetchUser&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="na"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&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="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;accounts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createContainer&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;accounts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;dependsOn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;start&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;user&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="nf"&gt;fetchAccounts&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="nx"&gt;user&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;id&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="na"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&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="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;enable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&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;user&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;id&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&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;wallets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createContainer&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wallets&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;dependsOn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;start&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="na"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&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 expect something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;compose.up start

user: &lt;span class="s1"&gt;'idle'&lt;/span&gt;,     accounts: &lt;span class="s1"&gt;'idle'&lt;/span&gt;,     wallets: &lt;span class="s1"&gt;'idle'&lt;/span&gt;
user: &lt;span class="s1"&gt;'pending'&lt;/span&gt;,  accounts: &lt;span class="s1"&gt;'idle'&lt;/span&gt;,     wallets: &lt;span class="s1"&gt;'idle'&lt;/span&gt;
user: &lt;span class="s1"&gt;'done'&lt;/span&gt;,     accounts: &lt;span class="s1"&gt;'idle'&lt;/span&gt;,     wallets: &lt;span class="s1"&gt;'idle'&lt;/span&gt;

&lt;span class="c"&gt;# if user.data.id&lt;/span&gt;
user: &lt;span class="s1"&gt;'done'&lt;/span&gt;,    accounts: &lt;span class="s1"&gt;'pending'&lt;/span&gt;,  wallets: &lt;span class="s1"&gt;'idle'&lt;/span&gt;
user: &lt;span class="s1"&gt;'done'&lt;/span&gt;,    accounts: &lt;span class="s1"&gt;'done'&lt;/span&gt;,     wallets: &lt;span class="s1"&gt;'pending'&lt;/span&gt;
user: &lt;span class="s1"&gt;'done'&lt;/span&gt;,    accounts: &lt;span class="s1"&gt;'done'&lt;/span&gt;,     wallets: &lt;span class="s1"&gt;'done'&lt;/span&gt;

&lt;span class="c"&gt;# else&lt;/span&gt;
user: &lt;span class="s1"&gt;'done'&lt;/span&gt;,    accounts: &lt;span class="s1"&gt;'off'&lt;/span&gt;,      wallets: &lt;span class="s1"&gt;'off'&lt;/span&gt;

compose.up &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I created the &lt;a href="https://github.com/grlt-hub/app-compose" rel="noopener noreferrer"&gt;@grlt-hub/app-compose&lt;/a&gt; library, which makes this a reality.&lt;/p&gt;

&lt;p&gt;The library offers convenient functions for creating and composing modules into a single system. Each module is encapsulated in a container with a clear configuration, including parameters like &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;dependsOn&lt;/code&gt;, &lt;code&gt;optionalDependsOn&lt;/code&gt;, &lt;code&gt;start&lt;/code&gt;, and &lt;code&gt;enable&lt;/code&gt;. Developers describe containers and launch them using &lt;code&gt;compose.up&lt;/code&gt; fn, without the need to worry about the order of execution. This approach makes working with containers intuitive and close to natural language.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provides a &lt;strong&gt;simple and intuitive developer experience (DX)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Designed with a focus on &lt;strong&gt;quality&lt;/strong&gt; and &lt;strong&gt;performance&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Weighs less than &lt;strong&gt;1.5 kB&lt;/strong&gt;, making it lightweight.&lt;/li&gt;
&lt;li&gt;Covered by &lt;strong&gt;100% tests&lt;/strong&gt;, including &lt;strong&gt;type tests&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Ensures high performance, suitable for &lt;strong&gt;scalable applications&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Includes &lt;strong&gt;debugging tools&lt;/strong&gt; to facilitate the development process.&lt;/li&gt;
&lt;li&gt;Offers the ability to &lt;strong&gt;visualize the system&lt;/strong&gt; composed of containers effectively (including transitive dependencies and their paths).&lt;/li&gt;
&lt;li&gt;Follows &lt;strong&gt;semantic versioning&lt;/strong&gt; (semver), guaranteeing &lt;strong&gt;stability&lt;/strong&gt; and &lt;strong&gt;predictability&lt;/strong&gt; of changes with each release.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ready to simplify your modular architecture? Dive into app-compose and experience efficient, scalable dependency management. Check it out and let us know how it transforms your projects!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/grlt-hub/app-compose" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://grlt-hub.github.io/app-compose/" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Clean up your code with ease</title>
      <dc:creator>Viktor Pasynok</dc:creator>
      <pubDate>Mon, 22 Jan 2024 14:30:00 +0000</pubDate>
      <link>https://dev.to/binjospookie/clean-up-your-code-with-ease-1gn7</link>
      <guid>https://dev.to/binjospookie/clean-up-your-code-with-ease-1gn7</guid>
      <description>&lt;p&gt;Hi, I am the creator of the &lt;a href="https://github.com/space307/pure-index"&gt;Pure Index&lt;/a&gt; tool. Its essential purpose is to clean your packages of unused exports with ease. In this article, I share a brief story of its inception.&lt;/p&gt;

&lt;p&gt;I work in a monorepo that contains dozens of packages from which we build a website as a team. One of the problems we have encountered is dead code. For example, a &lt;em&gt;TextCountDown&lt;/em&gt; component was written a couple of years ago, and the code where it was used was removed at some point. Ideally, the component should have been removed as well, but it wasn't. Yes, it was a mistake, but it happened, and we needed to find a way to prevent such situations in the future.&lt;/p&gt;

&lt;p&gt;What tools would have helped at that point? ESLint? Perhaps, but ESLint would not have identified &lt;em&gt;TextCountDown&lt;/em&gt; as unused because it was exported from a file. And that's where &lt;em&gt;ts-prune&lt;/em&gt; came on the scene. Its first run was both a disappointment and a joy for us. The significant number of unused exports displayed in the console meant that removing them would reduce the code base's size, build time, etc. We removed hundreds of such exports and all the dead code in a few iterations. That's how it seemed to us...&lt;/p&gt;

&lt;p&gt;Packages have index files (&lt;code&gt;index.ts&lt;/code&gt;, for example) that describe what the package exports. &lt;em&gt;ts-prune&lt;/em&gt; showed all exports from these files as unused, which was a false positive. Some exports were dead, perhaps whole packages, but not all. The reason was in the import paths. There was no direct connection between &lt;code&gt;import {smth} from 'my-package'&lt;/code&gt; and &lt;code&gt;export {smth} from '~/src/index.ts'&lt;/code&gt;. Maybe it was possible to somehow configure &lt;em&gt;ts-prune&lt;/em&gt; to handle this, but we found a case that wouldn't help.&lt;br&gt;
There is a &lt;em&gt;ui-kit&lt;/em&gt; package whose code is stored in another repository, and the package itself is used in other products and internal systems.That's when I decided to create &lt;em&gt;Pure Index&lt;/em&gt;. In combination with &lt;em&gt;ts-prune&lt;/em&gt;, it allowed the automate the process of searching for dead code as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;search for all unused exports from the index file&lt;/li&gt;
&lt;li&gt;delete them&lt;/li&gt;
&lt;li&gt;run &lt;em&gt;ts-prune&lt;/em&gt; inside the package to remove the dead code&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Finding unnecessary exports involves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;collect all package exports into exports Set&lt;/li&gt;
&lt;li&gt;traverse all files where package import may occur&lt;/li&gt;
&lt;li&gt;if the import is found, remove it from exports Set&lt;/li&gt;
&lt;li&gt;if the size of the exports Set became equal to 0, then exit with success&lt;/li&gt;
&lt;li&gt;if the exports Set size is not equal to 0, then exit with an error&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Pure Index&lt;/em&gt; handles this task in ~400 ms even for large repositories, for example, when analyzing &lt;em&gt;ui-kit&lt;/em&gt; in two repositories that contain more than 15'000+ .ts and tsx files. Of course, Pure Index's algorithm is a bit more complex. You can read about it in the &lt;a href="https://space307.github.io/pure-index/explanation/how-it-works/"&gt;"How Does It Work"&lt;/a&gt; section.&lt;/p&gt;

&lt;p&gt;As an added bonus, &lt;em&gt;Pure Index&lt;/em&gt; allows you to collect all X package imports within a repository. For example, you want to find out how many functions from &lt;em&gt;lodash&lt;/em&gt; you use. Just run &lt;code&gt;pure-index -u lodash&lt;/code&gt;, and you'll get a complete list.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Pure Index&lt;/em&gt; is available on GitHub. Just follow the &lt;a href="https://github.com/space307/pure-index"&gt;link&lt;/a&gt; and start using it.&lt;/p&gt;

&lt;p&gt;P.S. I will be happy if you give a star to the repository and share your opinion about the tool 🌿&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>frontend</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Exports in package.json</title>
      <dc:creator>Viktor Pasynok</dc:creator>
      <pubDate>Sat, 06 Mar 2021 18:01:32 +0000</pubDate>
      <link>https://dev.to/binjospookie/exports-in-package-json-1fl2</link>
      <guid>https://dev.to/binjospookie/exports-in-package-json-1fl2</guid>
      <description>&lt;p&gt;Hi there! I'm a front-end developer and ship my code via npm-packages.&lt;/p&gt;

&lt;p&gt;Once upon a time, I faced problems that led me to the usage of &lt;code&gt;exports&lt;/code&gt; field in &lt;code&gt;package.json&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem #1
&lt;/h2&gt;

&lt;p&gt;Packages may export functions with the same names but doing different things.&lt;/p&gt;

&lt;p&gt;Let's look at 2 state managers: Reatom and Effector. Both of them have a function called &lt;code&gt;createStore&lt;/code&gt;. If we try to export it from the one package (name it &lt;code&gt;vendors&lt;/code&gt;) we'll get this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// @some/vendors/index.ts&lt;/span&gt;

&lt;span class="k"&gt;export&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@reatom/core&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="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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;effector&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 faced with a name conflict. This code doesn't work. We can repair it with an &lt;code&gt;as&lt;/code&gt; syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// @some/vendors/index.ts&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createStore&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;reatomCreateStore&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="s1"&gt;@reatom/core&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createStore&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;effectorCreateStore&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="s1"&gt;effector&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;Not that pretty? Yeah, It kills DX. &lt;br&gt;&lt;br&gt;
On the other hand, I propose to avoid the necessity of writing &lt;code&gt;as&lt;/code&gt; every time and resolve name conflicts. Here is an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// @some/vendors/reatom.ts&lt;/span&gt;

&lt;span class="k"&gt;export&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reatom&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// @some/vendors/effector.ts&lt;/span&gt;

&lt;span class="k"&gt;export&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;effector&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 2 different files we write exports as usual and then import needed realization of &lt;code&gt;createStore&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// someFile.ts&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;createStore&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="s1"&gt;vendors/effector&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;
  
  
  Problem #2
&lt;/h2&gt;

&lt;p&gt;Most likely &lt;code&gt;vendors&lt;/code&gt; package contains not only a state manager. It could contain another one lib. Runtypes, for example.&lt;br&gt;
Without using &lt;code&gt;exports&lt;/code&gt; for &lt;code&gt;vendors&lt;/code&gt; imports will look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// someFile.ts&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;createStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Record&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="s1"&gt;vendors&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;It looks mixed. In my opinion, it will be better to write something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// someFile.ts&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;createStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createEvent&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="s1"&gt;vendors/effector&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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;Dictionary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Record&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="s1"&gt;vendors/runtypes&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;It would be nice to encapsulate the names of libraries. It could be useful for refactoring.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// someFile.ts&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;createStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createEvent&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="s1"&gt;vendors/state&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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;Dictionary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Record&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="s1"&gt;vendors/contract&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;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;exports&lt;/code&gt; field in &lt;code&gt;package.json&lt;/code&gt; helps us to achieve our goal.&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.json&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"exports"&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;"./contract"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./build/contract.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;"./state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./build/state.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;"./package.json"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./package.json"&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 just say to bundler how to resolve imports.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But if you use TypeScript you need to do one more thing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is a field named &lt;code&gt;types&lt;/code&gt; in &lt;code&gt;package.json&lt;/code&gt;. It allows us to specify the location of package types.&lt;/p&gt;

&lt;p&gt;Unfortunately, the type of &lt;code&gt;types&lt;/code&gt; is a string. We can't specify types for both &lt;code&gt;contract&lt;/code&gt; and &lt;code&gt;state&lt;/code&gt;. What should we do?&lt;/p&gt;

&lt;p&gt;Field &lt;code&gt;typesVersions&lt;/code&gt; resolves this problem.&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.json&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"typesVersions"&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;"*"&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;"contract"&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="s2"&gt;"build/contract.d.ts"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"state"&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="s2"&gt;"build/state.d.ts"&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="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 do the same thing as for &lt;code&gt;js&lt;/code&gt; files but for &lt;code&gt;d.ts&lt;/code&gt;. And make types working.&lt;/p&gt;

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

&lt;p&gt;Of course, the goal of &lt;code&gt;exports&lt;/code&gt; not only a creation &lt;code&gt;vendors&lt;/code&gt; packages. It could help us to improve DX.&lt;/p&gt;

&lt;p&gt;For example, base import from Effector looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createEvent&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="s1"&gt;effector&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;For supporting old browsers it looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createEvent&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="s1"&gt;effector/compat&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;What else kind of problems &lt;code&gt;exports&lt;/code&gt; resolves? You can see &lt;a href="https://github.com/jkrems/proposal-pkg-exports/"&gt;here&lt;/a&gt;.&lt;br&gt;
Also, you can see the repository with an example &lt;a href="https://github.com/binjospookie/exports-demo"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>npm</category>
      <category>webdev</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
