<?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: Sebastian Wrzalek</title>
    <description>The latest articles on DEV Community by Sebastian Wrzalek (@swrzalek).</description>
    <link>https://dev.to/swrzalek</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F812949%2F752554cd-7da6-4ae2-a75e-055a16ab126d.jpeg</url>
      <title>DEV Community: Sebastian Wrzalek</title>
      <link>https://dev.to/swrzalek</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/swrzalek"/>
    <language>en</language>
    <item>
      <title>AI Helps Us Write Code Faster. So Why Aren’t Projects Moving Faster?</title>
      <dc:creator>Sebastian Wrzalek</dc:creator>
      <pubDate>Sat, 27 Jun 2026 08:40:00 +0000</pubDate>
      <link>https://dev.to/swrzalek/ai-helps-us-write-code-faster-so-why-arent-projects-moving-faster-49jo</link>
      <guid>https://dev.to/swrzalek/ai-helps-us-write-code-faster-so-why-arent-projects-moving-faster-49jo</guid>
      <description>&lt;p&gt;We can generate code faster than ever.&lt;/p&gt;

&lt;p&gt;Features that once took several days can now be implemented in a few hours. Boilerplate disappears almost instantly. Tests, migrations, API clients, and entire components can be produced before we have finished describing the task.&lt;/p&gt;

&lt;p&gt;On paper, software teams should be moving at an incredible speed.&lt;/p&gt;

&lt;p&gt;But that is often not what happens.&lt;/p&gt;

&lt;p&gt;The code is produced faster, yet the project itself does not feel much faster. Pull requests become larger. Reviews take longer. Debugging becomes less predictable. Engineers spend more time trying to understand changes they did not write.&lt;/p&gt;

&lt;p&gt;Anyone who has used coding agents in a real business environment has probably noticed this contradiction:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;AI accelerates code generation, but it does not automatically accelerate software development.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In many teams, code review is already becoming the new bottleneck. Adding another AI agent to review the output may help catch local issues, but it does not solve the deeper problem.&lt;/p&gt;

&lt;p&gt;The problem is not necessarily the quality of the generated code.&lt;/p&gt;

&lt;p&gt;The problem is that our ability to understand the system is no longer keeping up with our ability to change it.&lt;/p&gt;

&lt;p&gt;A recent paper by Margaret-Anne Storey gave me a useful framework for thinking about this. It describes software health through three connected forms of debt: technical debt, cognitive debt, and intent debt.&lt;/p&gt;

&lt;p&gt;Together, they form the &lt;strong&gt;Triple Debt Model&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Technical Debt Is Only One Part of the Problem
&lt;/h2&gt;

&lt;p&gt;Most developers are already familiar with technical debt.&lt;/p&gt;

&lt;p&gt;We introduce a workaround because a deadline is approaching. We duplicate some logic because extracting the correct abstraction would take longer. We leave a poorly designed module in place because replacing it would be risky.&lt;/p&gt;

&lt;p&gt;The decision helps us move faster today, but makes future changes more expensive.&lt;/p&gt;

&lt;p&gt;The Triple Debt Model argues that technical debt is only one dimension of software health.&lt;/p&gt;

&lt;p&gt;There are two other forms of debt that become especially important when AI generates a growing percentage of the code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Technical debt lives in the code
&lt;/h3&gt;

&lt;p&gt;Technical debt is the structural mess we already know how to identify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;duplicated logic,&lt;/li&gt;
&lt;li&gt;unclear abstractions,&lt;/li&gt;
&lt;li&gt;tightly coupled modules,&lt;/li&gt;
&lt;li&gt;missing tests,&lt;/li&gt;
&lt;li&gt;outdated dependencies,&lt;/li&gt;
&lt;li&gt;temporary solutions that became permanent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It makes the system harder to modify, but it is usually visible.&lt;/p&gt;

&lt;p&gt;We can inspect it. Static-analysis tools can detect parts of it. Tests can expose it. Refactoring can reduce it.&lt;/p&gt;

&lt;p&gt;AI is also reasonably good at helping with this type of debt. It can find duplication, suggest cleaner abstractions, add tests, and refactor repetitive code.&lt;/p&gt;

&lt;p&gt;Unfortunately, clean code does not guarantee a healthy project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cognitive debt lives in people
&lt;/h3&gt;

&lt;p&gt;Cognitive debt accumulates when the team’s understanding of the system erodes.&lt;/p&gt;

&lt;p&gt;The application may still work. The code may even look clean. However, fewer people can confidently explain how the important parts fit together.&lt;/p&gt;

&lt;p&gt;This can happen naturally as a system grows, but AI can accelerate it.&lt;/p&gt;

&lt;p&gt;An agent can generate several hundred lines of code in a few minutes. A developer can verify that the tests pass, scan the implementation, and approve the change.&lt;/p&gt;

&lt;p&gt;What may never happen is the slower process of building a mental model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why was this approach chosen?&lt;/li&gt;
&lt;li&gt;Which assumptions does it rely on?&lt;/li&gt;
&lt;li&gt;What other parts of the system depend on it?&lt;/li&gt;
&lt;li&gt;What would make this design stop working?&lt;/li&gt;
&lt;li&gt;Which alternatives were considered?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The code enters the repository, but the corresponding understanding never fully enters the team.&lt;/p&gt;

&lt;p&gt;Do this repeatedly and the project slowly becomes something that engineers operate without truly understanding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Intent debt lives in artifacts
&lt;/h3&gt;

&lt;p&gt;Intent debt appears when the reasoning behind a system is not recorded.&lt;/p&gt;

&lt;p&gt;The code shows us what the system does today. It rarely tells us what the team originally intended, which constraints shaped the design, or which outcomes must be preserved.&lt;/p&gt;

&lt;p&gt;For example, imagine finding an unusual caching mechanism in a critical module.&lt;/p&gt;

&lt;p&gt;Is it there because of a previous production incident? Is it protecting an external API with strict rate limits? Is it compensating for a temporary infrastructure limitation? Or is it simply an old implementation that nobody removed?&lt;/p&gt;

&lt;p&gt;Without the original context, both humans and AI agents are forced to guess.&lt;/p&gt;

&lt;p&gt;That missing context is intent debt.&lt;/p&gt;

&lt;p&gt;It can live in many places:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;undocumented architectural decisions,&lt;/li&gt;
&lt;li&gt;incomplete requirements,&lt;/li&gt;
&lt;li&gt;outdated tickets,&lt;/li&gt;
&lt;li&gt;missing domain explanations,&lt;/li&gt;
&lt;li&gt;pull requests that describe what changed but not why,&lt;/li&gt;
&lt;li&gt;comments that explain implementation details without explaining constraints.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Intent debt has always existed. The difference is that agents now make decisions at a speed and scale that greatly increases the cost of missing intent.&lt;/p&gt;




&lt;h2&gt;
  
  
  AI Changes the Kind of Debt We Accumulate
&lt;/h2&gt;

&lt;p&gt;Before AI-assisted development, producing code required a significant amount of human effort.&lt;/p&gt;

&lt;p&gt;That effort was not always efficient, but it forced developers to spend time thinking about the system. While implementing a feature, we naturally built some understanding of the surrounding modules, dependencies, and constraints.&lt;/p&gt;

&lt;p&gt;Coding agents remove part of that friction.&lt;/p&gt;

&lt;p&gt;That is useful, but some of the removed friction was also where learning happened.&lt;/p&gt;

&lt;p&gt;A developer can now describe a task, review the output, run the tests, and merge the result without ever constructing a complete mental model of the implementation.&lt;/p&gt;

&lt;p&gt;The team appears to be moving faster because more code reaches production.&lt;/p&gt;

&lt;p&gt;At the same time, cognitive and intent debt may be accumulating underneath that velocity.&lt;/p&gt;

&lt;p&gt;This creates a dangerous trade:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We reduce the cost of producing code while increasing the cost of understanding and safely changing it later.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At first, the trade looks extremely profitable. Features ship faster and backlogs shrink.&lt;/p&gt;

&lt;p&gt;The cost appears later, when the system needs to be debugged, extended, migrated, or redesigned.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Development Velocity Starts to Collapse
&lt;/h2&gt;

&lt;p&gt;The slowdown rarely happens through one dramatic failure.&lt;/p&gt;

&lt;p&gt;It usually appears through small changes in team behaviour.&lt;/p&gt;

&lt;h3&gt;
  
  
  Developers stop deeply reviewing generated code
&lt;/h3&gt;

&lt;p&gt;Reading code is difficult.&lt;/p&gt;

&lt;p&gt;Reading a large amount of code that you did not write is even more difficult. When AI produces changes continuously, reviewers eventually begin to focus on surface-level signals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the implementation look reasonable?&lt;/li&gt;
&lt;li&gt;Are the tests passing?&lt;/li&gt;
&lt;li&gt;Are there any obvious security problems?&lt;/li&gt;
&lt;li&gt;Does the pull request solve the requested task?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are useful checks, but they are not the same as understanding the change.&lt;/p&gt;

&lt;p&gt;Over time, reviewers may stop asking whether the implementation fits the deeper design of the system. Authors may also struggle to explain the code because they guided its generation rather than constructing it themselves.&lt;/p&gt;

&lt;p&gt;The pull request is approved, but no one has fully absorbed the new behaviour.&lt;/p&gt;

&lt;h3&gt;
  
  
  Agents optimize for the wrong objective
&lt;/h3&gt;

&lt;p&gt;An advanced coding agent needs more than access to the repository.&lt;/p&gt;

&lt;p&gt;It needs to understand the goal of the system and the constraints that shaped it.&lt;/p&gt;

&lt;p&gt;Suppose an agent discovers two services performing similar work. From the code alone, merging them may look like an obvious improvement.&lt;/p&gt;

&lt;p&gt;What the agent may not know is that the services were intentionally separated because they have different security boundaries, deployment schedules, ownership models, or regulatory requirements.&lt;/p&gt;

&lt;p&gt;Without that context, the agent can produce a technically elegant solution that is completely wrong for the business.&lt;/p&gt;

&lt;p&gt;This is where intent debt becomes particularly dangerous.&lt;/p&gt;

&lt;p&gt;Agents are very capable of optimizing the implementation they can see. They are much less reliable when the real objective was never recorded.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code review turns into an investigation
&lt;/h3&gt;

&lt;p&gt;As shared understanding disappears, code review changes.&lt;/p&gt;

&lt;p&gt;Instead of discussing whether a solution is appropriate, reviewers first have to reconstruct how the relevant part of the system works.&lt;/p&gt;

&lt;p&gt;A seemingly simple pull request leads to questions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why does this module depend on that service?&lt;/li&gt;
&lt;li&gt;Is this behaviour intentional?&lt;/li&gt;
&lt;li&gt;Who owns this workflow?&lt;/li&gt;
&lt;li&gt;Will changing this break another customer path?&lt;/li&gt;
&lt;li&gt;Why was the existing implementation designed this way?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The review takes longer, but the answers remain uncertain.&lt;/p&gt;

&lt;p&gt;Eventually, the safest response becomes: “Let’s not change it yet.”&lt;/p&gt;

&lt;p&gt;That is the moment when a productive codebase starts becoming a fragile one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Warning Signs of Cognitive and Intent Debt
&lt;/h2&gt;

&lt;p&gt;Unlike a failing test, cognitive debt does not produce a clear error message.&lt;/p&gt;

&lt;p&gt;You have to look for it in the way the team works.&lt;/p&gt;

&lt;h3&gt;
  
  
  Engineers avoid particular modules
&lt;/h3&gt;

&lt;p&gt;Every mature project has difficult areas.&lt;/p&gt;

&lt;p&gt;The stronger warning sign is when developers avoid a module not because the code is obviously bad, but because nobody knows what might break.&lt;/p&gt;

&lt;p&gt;The module has become a black box. Changes are delayed, wrapped in additional conditions, or assigned only to the one person believed to understand it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Important knowledge exists in one or two people
&lt;/h3&gt;

&lt;p&gt;A project becomes fragile when critical design decisions exist only in someone’s memory.&lt;/p&gt;

&lt;p&gt;You may hear phrases such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Ask Anna; she built that part.”&lt;/li&gt;
&lt;li&gt;“I think Mark knows why this works that way.”&lt;/li&gt;
&lt;li&gt;“We should wait until they are back from holiday.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not only a staffing risk. It is evidence that the system’s intent has not been externalized.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pull requests take longer to review
&lt;/h3&gt;

&lt;p&gt;Large AI-generated pull requests can look complete while being difficult to reason about.&lt;/p&gt;

&lt;p&gt;Review comments become vague:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“This seems fine.”&lt;/li&gt;
&lt;li&gt;“I think this should work.”&lt;/li&gt;
&lt;li&gt;“The tests are green.”&lt;/li&gt;
&lt;li&gt;“Let’s monitor it after deployment.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When both the author and reviewer are uncertain, review becomes a ceremony rather than a transfer of understanding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Small architectural changes cause unexpected side effects
&lt;/h3&gt;

&lt;p&gt;A team with a strong mental model can usually predict the approximate impact of a change.&lt;/p&gt;

&lt;p&gt;When simple modifications regularly break unrelated functionality, it suggests that the actual dependency structure is no longer understood.&lt;/p&gt;

&lt;p&gt;The problem may involve technical debt, but repeated surprise is also a strong signal of cognitive debt.&lt;/p&gt;




&lt;h2&gt;
  
  
  Automated AI Review Will Not Fix This
&lt;/h2&gt;

&lt;p&gt;It is tempting to respond by adding another agent.&lt;/p&gt;

&lt;p&gt;One agent writes the code. Another reviews it. Perhaps a third checks the architecture and generates documentation.&lt;/p&gt;

&lt;p&gt;These tools can help, but they do not automatically restore shared understanding.&lt;/p&gt;

&lt;p&gt;An AI reviewer can identify a potential race condition or missing validation. It cannot recover a business constraint that was never documented. It cannot guarantee that the engineering team understands the resulting design.&lt;/p&gt;

&lt;p&gt;The risk is that we create a closed loop in which agents produce, review, explain, and approve changes while humans supervise the process from an increasing distance.&lt;/p&gt;

&lt;p&gt;The pipeline may look efficient.&lt;/p&gt;

&lt;p&gt;The team’s ability to reason about the system may still be declining.&lt;/p&gt;




&lt;h2&gt;
  
  
  Understanding Has to Become a Deliverable
&lt;/h2&gt;

&lt;p&gt;For years, software teams have treated code as the main output of development.&lt;/p&gt;

&lt;p&gt;In an AI-assisted environment, that is no longer enough.&lt;/p&gt;

&lt;p&gt;Every meaningful change should also preserve or improve the team’s understanding of the system.&lt;/p&gt;

&lt;p&gt;That does not mean documenting every line of code. It means recording the information that cannot be reliably reconstructed from the implementation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;why a solution was selected,&lt;/li&gt;
&lt;li&gt;which constraints influenced it,&lt;/li&gt;
&lt;li&gt;which alternatives were rejected,&lt;/li&gt;
&lt;li&gt;what assumptions must remain true,&lt;/li&gt;
&lt;li&gt;which business outcome the implementation protects,&lt;/li&gt;
&lt;li&gt;what future developers and agents should avoid changing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pull requests should not only prove that the code works. They should make the intent of the change visible.&lt;/p&gt;

&lt;p&gt;Architecture Decision Records, focused design notes, meaningful test names, short diagrams, and clear pull-request descriptions become more valuable—not less—when agents are involved.&lt;/p&gt;

&lt;p&gt;The goal is not to slow development down for the sake of process.&lt;/p&gt;

&lt;p&gt;The goal is to prevent short-term coding speed from destroying long-term development speed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Words
&lt;/h2&gt;

&lt;p&gt;AI is changing the economics of software development.&lt;/p&gt;

&lt;p&gt;Producing code is becoming cheaper. Understanding code is not.&lt;/p&gt;

&lt;p&gt;That difference explains why teams can generate more code without seeing the same improvement in overall project efficiency.&lt;/p&gt;

&lt;p&gt;Technical debt still matters, but it is no longer the full picture. A codebase can be clean and well-tested while the team has lost the knowledge required to change it safely. It can contain detailed implementation documentation while still missing the reasons behind its most important decisions.&lt;/p&gt;

&lt;p&gt;Today, high cognitive debt may feel like a small drag on the engineering team.&lt;/p&gt;

&lt;p&gt;Tomorrow, it can become a system that nobody feels safe modifying.&lt;/p&gt;

&lt;p&gt;The teams that benefit most from AI will not simply be the ones that generate the most code. They will be the ones that find a way to generate code without losing their understanding of what they are building and why.&lt;/p&gt;

&lt;p&gt;In the next articles, I plan to explore practical frameworks and engineering processes that can help teams reduce cognitive and intent debt while still taking advantage of AI-assisted development.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>discuss</category>
      <category>productivity</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Stop Making These 5 Common Vue Mistakes!</title>
      <dc:creator>Sebastian Wrzalek</dc:creator>
      <pubDate>Fri, 27 Jun 2025 22:12:38 +0000</pubDate>
      <link>https://dev.to/swrzalek/5-common-vue-mistakes-to-avoid-5e7d</link>
      <guid>https://dev.to/swrzalek/5-common-vue-mistakes-to-avoid-5e7d</guid>
      <description>&lt;h3&gt;
  
  
  1. Treating Everything as Reactive
&lt;/h3&gt;

&lt;p&gt;Vue's &lt;code&gt;ref&lt;/code&gt; is an excellent way to manage reactive state, but not everything should be reactive. When using Vue, developers often mistakenly treat all variables as reactive. For values that will remain static and never change, define them using &lt;code&gt;const&lt;/code&gt;. Reserve &lt;code&gt;ref&lt;/code&gt; or &lt;code&gt;reactive&lt;/code&gt; exclusively for state that truly needs to update the view.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Incorrect:&lt;/strong&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;createdBy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;JohnDoe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// If username never changes, this is unnecessary.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Correct:&lt;/strong&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;createdBy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;JohnDoe&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;h3&gt;
  
  
  2. Using &lt;code&gt;watch()&lt;/code&gt; Without Understanding State Flow
&lt;/h3&gt;

&lt;p&gt;It's easy to misuse watchers (&lt;code&gt;watch()&lt;/code&gt;) when you don’t fully grasp how your application's data flow works. Watchers can create hidden side-effects and subtle race conditions if logic is scattered and improperly managed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❌&lt;/strong&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;comments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&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;article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;

&lt;span class="nf"&gt;fetchArticle&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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;article&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;article&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="nf"&gt;fetchComments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;article&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="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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;comments&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;&lt;strong&gt;✅&lt;/strong&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;comments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&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;article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&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;fetchArticleAndComments&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;article&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;articleData&lt;/span&gt; &lt;span class="p"&gt;}&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;fetchArticle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;articleData&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="na"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;commentsData&lt;/span&gt; &lt;span class="p"&gt;}&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;fetchComments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;articleData&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;comments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;commentsData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;fetchArticleAndComments&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use watchers only as escape hatches, not as the default approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Using &lt;code&gt;v-if&lt;/code&gt; Where &lt;code&gt;v-show&lt;/code&gt; Fits
&lt;/h3&gt;

&lt;p&gt;Many Vue developers use &lt;code&gt;v-if&lt;/code&gt; unnecessarily. &lt;code&gt;v-if&lt;/code&gt; mounts and destroys elements or components, making it ideal for one-time, conditional rendering. However, frequent toggles should use &lt;code&gt;v-show&lt;/code&gt;, as it simply toggles CSS display, making it much more efficient.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use &lt;code&gt;v-show&lt;/code&gt; when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Elements toggle frequently.&lt;/li&gt;
&lt;li&gt;The cost of mounting/destroying elements repeatedly is high.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;❌&lt;/strong&gt;&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;v-if=&lt;/span&gt;&lt;span class="s"&gt;"isVisible"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Toggle me frequently!&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;&lt;strong&gt;✅&lt;/strong&gt;&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;v-show=&lt;/span&gt;&lt;span class="s"&gt;"isVisible"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Toggle me frequently!&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Computed Properties Mutating State
&lt;/h3&gt;

&lt;p&gt;Computed properties in Vue should always be pure and free from side effects. A common subtle mistake is directly mutating state within computed properties, especially with array methods like &lt;code&gt;reverse()&lt;/code&gt; or &lt;code&gt;sort()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❌&lt;/strong&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;reversedNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&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;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;// This mutates the original array!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅&lt;/strong&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;reversedNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&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;numbers&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;// Creates a new array, maintaining purity&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Overusing Pinia/Vuex Store
&lt;/h3&gt;

&lt;p&gt;State management libraries like Pinia or Vuex are powerful, but it's important not to overuse them. As Dan Abramov says, "Flux libraries are like glasses: you'll know when you need them."&lt;/p&gt;

&lt;p&gt;Initially, manage state with props, emits, and local state. Consider using a store when you have deeply nested components or need shared state across multiple component branches. Excessive reliance on stores can lead to unintended complexity and side effects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Guidelines for using a store wisely:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use local state or component props/emits first.&lt;/li&gt;
&lt;li&gt;Consider a store when dealing with shared state across unrelated components.&lt;/li&gt;
&lt;li&gt;Avoid overloading the store with local, component-specific state.&lt;/li&gt;
&lt;li&gt;Avoid circular dependencies - store A in store B and store B in store A&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Thanks for reading
&lt;/h3&gt;

&lt;p&gt;If you liked it leave some ❤️&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Building a Microfrontend Architecture with Vue 3, Vite, Single-SPA</title>
      <dc:creator>Sebastian Wrzalek</dc:creator>
      <pubDate>Sun, 02 Mar 2025 15:05:01 +0000</pubDate>
      <link>https://dev.to/swrzalek/building-a-microfrontend-architecture-with-vue-3-vite-single-spa-b6d</link>
      <guid>https://dev.to/swrzalek/building-a-microfrontend-architecture-with-vue-3-vite-single-spa-b6d</guid>
      <description>&lt;h2&gt;
  
  
  Microfrontends with Vue 3, Vite, and Single-SPA
&lt;/h2&gt;

&lt;p&gt;Microfrontends have become a popular approach for scaling frontend applications, especially in environments where multiple teams work on various parts of the app independently. In this guide, we'll explore how to build a simple microfrontend application using &lt;strong&gt;Vue 3&lt;/strong&gt;, &lt;strong&gt;Vite&lt;/strong&gt;, &lt;strong&gt;Single-SPA&lt;/strong&gt;, and &lt;strong&gt;vite-plugin-single-spa&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction to Microfrontends&lt;/li&gt;
&lt;li&gt;Understanding Single-SPA Framework&lt;/li&gt;
&lt;li&gt;Demo Project&lt;/li&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;Creating the Secondary (Microfrontend) Application&lt;/li&gt;
&lt;li&gt;Configuring the Secondary App&lt;/li&gt;
&lt;li&gt;Handling Different Bundle Locations&lt;/li&gt;
&lt;li&gt;Registering the Microfrontend in the Root Project&lt;/li&gt;
&lt;li&gt;Testing the Setup&lt;/li&gt;
&lt;li&gt;The Problem&lt;/li&gt;
&lt;li&gt;The Second Problem&lt;/li&gt;
&lt;li&gt;Final Words&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Introduction to Microfrontends
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;"The idea behind Micro Frontends is to think about a website or web app as a composition of features which are owned by independent teams. Each team has a distinct area of business or mission it cares about and specializes in. A team is cross-functional and develops its features end-to-end, from database to user interface."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Microfrontends are an architectural approach that extends the concept of microservices to the frontend. Instead of building a single monolithic frontend application, the app is divided into smaller, manageable pieces called &lt;strong&gt;microfrontends&lt;/strong&gt;. Each microfrontend is a self-contained application with its own codebase, framework, and deployment pipeline.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of Microfrontends:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt; – Multiple teams can work independently on different features.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility&lt;/strong&gt; – Each microfrontend can use its own tech stack.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resilience&lt;/strong&gt; – Failures in one microfrontend don’t affect others.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Understanding Single-SPA Framework
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Single-SPA&lt;/strong&gt; is a framework that allows multiple microfrontends, potentially using different frameworks (e.g., Vue, React), to coexist and operate within the same application. It manages the lifecycle of each microfrontend, enabling them to load and unload dynamically based on routing configurations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2Fpako%3AeNqFkF1PwjAYhf9K815pAhuMfbELExC9wmAgeuFGTOnKNtnapR8qMv67HYsRE6O9Oid9znve9gCEpxQi2Jb8jeRYKDRfJgyZM4kfJBVr1O9foenFqmBZSfur-wlaCJJTqQRWXFx27LSlmiXXiiJbUExUg67jZSvQXUEE3wrOFGXp-hf-VdMGzeJHTf9nMct0iUWDbuJJJ__ILFROBTolZYNu487_4KUJdBGpN5nAdY7OXjovtpTsSUk75DT5W5KyIDtTlUCuVC0j25ZdVNbYepEWF5mdAHrelJjtuphpbPugBxUVFS5S8_OH9ioBs1tFE4iMTLHYJZCwo-GwVny1ZwQiJTTtgeA6yyHa4lIap-sUKzorsFm9-kJqzJ44P7cQHeAdosC1HGc88sf-IBw7vuf0YA_RMPQtz_O9wAkD13ODcXjswcdpwMDywnAUDDzHHfnB0HPd4yex8LH6%3Ftype%3Dpng" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2Fpako%3AeNqFkF1PwjAYhf9K815pAhuMfbELExC9wmAgeuFGTOnKNtnapR8qMv67HYsRE6O9Oid9znve9gCEpxQi2Jb8jeRYKDRfJgyZM4kfJBVr1O9foenFqmBZSfur-wlaCJJTqQRWXFx27LSlmiXXiiJbUExUg67jZSvQXUEE3wrOFGXp-hf-VdMGzeJHTf9nMct0iUWDbuJJJ__ILFROBTolZYNu487_4KUJdBGpN5nAdY7OXjovtpTsSUk75DT5W5KyIDtTlUCuVC0j25ZdVNbYepEWF5mdAHrelJjtuphpbPugBxUVFS5S8_OH9ioBs1tFE4iMTLHYJZCwo-GwVny1ZwQiJTTtgeA6yyHa4lIap-sUKzorsFm9-kJqzJ44P7cQHeAdosC1HGc88sf-IBw7vuf0YA_RMPQtz_O9wAkD13ODcXjswcdpwMDywnAUDDzHHfnB0HPd4yex8LH6%3Ftype%3Dpng" alt="enter image description here" width="785" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Single-SPA Components:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Root Configuration&lt;/strong&gt; – Responsible for rendering the HTML page and registering applications. Each application is registered with:

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;name&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;function&lt;/strong&gt; to load the application’s code
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;function&lt;/strong&gt; to determine when the application is active or inactive
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Applications&lt;/strong&gt; – Microfrontends functioning as SPAs packaged into modules. Each application must implement methods to bootstrap, mount, and unmount itself from the DOM.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Core Concepts of Single-SPA:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Application Registrations&lt;/strong&gt; – Register each microfrontend as an application.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lifecycle Methods&lt;/strong&gt; – Each microfrontend has lifecycle methods (mount, unmount, etc.).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Routing&lt;/strong&gt; – Single-SPA can load microfrontends based on URL paths.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example:
&lt;/h3&gt;

&lt;p&gt;A React or Vue SPA can be registered as an application. When active, it listens to URL routing events and renders content on the DOM; when inactive, it stops listening to routing events and is fully removed from the DOM.&lt;/p&gt;




&lt;h2&gt;
  
  
  Demo Project
&lt;/h2&gt;

&lt;p&gt;In this article, we’ll build both the &lt;strong&gt;root&lt;/strong&gt; application—responsible for orchestrating the mounting and unmounting of microfrontends—and a &lt;strong&gt;sample microfrontend&lt;/strong&gt; for demonstration. Although the official recommendation discourages using a framework in the root configuration, this project uses a Vue application at the root to provide a consistent layout, global navigation, and cohesive styling across all microfrontends.&lt;/p&gt;




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

&lt;p&gt;Let’s create our root application. This project uses Vue as its framework:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create vue@latest

✔ Project name: … root
✔ Add TypeScript? … Yes
✔ Add JSX Support? … No
✔ Add Vue Router &lt;span class="k"&gt;for &lt;/span&gt;Single Page Application development? … Yes
✔ Add Pinia &lt;span class="k"&gt;for &lt;/span&gt;state management? … No
✔ Add Vitest &lt;span class="k"&gt;for &lt;/span&gt;Unit Testing? … No 
✔ Add an End-to-End Testing Solution? › No
✔ Add ESLint &lt;span class="k"&gt;for &lt;/span&gt;code quality? …  Yes
✔ Add Prettier &lt;span class="k"&gt;for &lt;/span&gt;code formatting? …  Yes
✔ Add Vue DevTools 7 extension &lt;span class="k"&gt;for &lt;/span&gt;debugging? &lt;span class="o"&gt;(&lt;/span&gt;experimental&lt;span class="o"&gt;)&lt;/span&gt; … No

&lt;span class="nb"&gt;cd &lt;/span&gt;root
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run format
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After creating the root application, install the necessary dependencies:&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; &lt;span class="nt"&gt;--save&lt;/span&gt; single-spa-vue vite-plugin-single-spa single-spa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, integrate &lt;code&gt;vite-plugin-single-spa&lt;/code&gt; within your &lt;code&gt;vite.config.ts&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fileURLToPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;URL&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;node:url&lt;/span&gt;&lt;span class="dl"&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;defineConfig&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;vite&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;vue&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;@vitejs/plugin-vue&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;vitePluginSingleSpa&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;vite-plugin-single-spa&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// https://vite.dev/config/&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;vue&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; 
    &lt;span class="nf"&gt;vitePluginSingleSpa&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
      &lt;span class="na"&gt;imo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3.1.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="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;alias&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="s1"&gt;@&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;fileURLToPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src&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;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&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;
  
  
  Creating the Secondary (Microfrontend) Application
&lt;/h2&gt;

&lt;p&gt;Before we configure the root application to load a microfrontend, let’s create another Vue app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create vue@latest

✔ Project name: … app
✔ Add TypeScript? … Yes
✔ Add JSX Support? … No
✔ Add Vue Router &lt;span class="k"&gt;for &lt;/span&gt;Single Page Application development? … Yes
✔ Add Pinia &lt;span class="k"&gt;for &lt;/span&gt;state management? … No
✔ Add Vitest &lt;span class="k"&gt;for &lt;/span&gt;Unit Testing? … No 
✔ Add an End-to-End Testing Solution? › No
✔ Add ESLint &lt;span class="k"&gt;for &lt;/span&gt;code quality? …  Yes
✔ Add Prettier &lt;span class="k"&gt;for &lt;/span&gt;code formatting? …  Yes
✔ Add Vue DevTools 7 extension &lt;span class="k"&gt;for &lt;/span&gt;debugging? &lt;span class="o"&gt;(&lt;/span&gt;experimental&lt;span class="o"&gt;)&lt;/span&gt; … No

&lt;span class="nb"&gt;cd &lt;/span&gt;app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install additional dependencies for this new app:&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; &lt;span class="nt"&gt;--save&lt;/span&gt; single-spa-vue vite-plugin-single-spa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Below is the directory structure so far:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;single-spa-demo
├── root
│   ├── src
│   ├── vite.config.ts
│   └── package.json
└── app
    ├── src
    ├── vite.config.ts
    └── package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Configuring the Secondary App
&lt;/h2&gt;

&lt;p&gt;We must configure the Vite Single-SPA plugin so the Vue application outputs a microfrontend:&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;// ### app/vite.config.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;fileURLToPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;URL&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;node:url&lt;/span&gt;&lt;span class="dl"&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;defineConfig&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;vite&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;vue&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;@vitejs/plugin-vue&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;vitePluginSingleSpa&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;vite-plugin-single-spa&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// https://vitejs.dev/config/&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;vue&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;vitePluginSingleSpa&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mife&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;serverPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;spaEntryPoints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/main.ts&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="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;alias&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="s1"&gt;@&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;fileURLToPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src&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;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&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="c1"&gt;// Ensure the dev server uses the same port as set in the plugin&lt;/span&gt;
  &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4101&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, &lt;code&gt;vitePluginSingleSpa({ type: 'mife', serverPort: 4101 })&lt;/code&gt; configures the plugin, identifying this build as a microfrontend and setting the development server to port 4101.&lt;/p&gt;

&lt;h3&gt;
  
  
  Main File Modifications
&lt;/h3&gt;

&lt;p&gt;The microfrontend must know how to bootstrap, mount, and unmount itself from the DOM. Update &lt;code&gt;main.ts&lt;/code&gt; accordingly:&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;// ### app/main.ts ###&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&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;./App.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./assets/main.css&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;singleSpaVue&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;single-spa-vue&lt;/span&gt;&lt;span class="dl"&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;createApp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;h&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;vue&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;router&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;./router&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;vueLifecycles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;singleSpaVue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;createApp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;appOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;render&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="nf"&gt;h&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="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;handleInstance&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="o"&gt;=&amp;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;use&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="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;mountVue&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="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;createApp&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="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mount&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&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;// Only mount the app in standard SPA mode during development&lt;/span&gt;
&lt;span class="k"&gt;if &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;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MODE&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;development&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;mountVue&lt;/span&gt;&lt;span class="p"&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;const&lt;/span&gt; &lt;span class="nx"&gt;bootstrap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vueLifecycles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bootstrap&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;const&lt;/span&gt; &lt;span class="nx"&gt;mount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vueLifecycles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mount&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;const&lt;/span&gt; &lt;span class="nx"&gt;unmount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vueLifecycles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unmount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because Single-SPA handles mounting and unmounting, we cannot mount the application in production in the usual way. However, we still want to support standalone development, so we only mount if &lt;code&gt;import.meta.env.MODE&lt;/code&gt; is development.&lt;/p&gt;

&lt;p&gt;Below is an example of how to differentiate development modes in your &lt;code&gt;package.json&lt;/code&gt;:&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;"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;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vite --mode development"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev:sspa"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vite --mode staging"&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;With these changes, the microfrontend is ready to be consumed by the root project.&lt;/p&gt;




&lt;h2&gt;
  
  
  Handling Different Bundle Locations
&lt;/h2&gt;

&lt;p&gt;One challenge is that the microfrontend’s entry file (&lt;code&gt;main.ts&lt;/code&gt;) is served at different URLs in development vs. production:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Development:&lt;/strong&gt; &lt;code&gt;http://localhost:4101/src/main.ts&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build:&lt;/strong&gt; &lt;code&gt;http://localhost:4101/main.js&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will address this discrepancy using native import maps. Within the root project, create two files for mapping these paths:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;root/src/importMap.dev.json&lt;/code&gt;
&lt;/h3&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;"imports"&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;"@howlydev/app"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:4101/src/main.ts"&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;h3&gt;
  
  
  &lt;code&gt;root/src/importMap.json&lt;/code&gt;
&lt;/h3&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;"imports"&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;"@howlydev/app"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:4101/main.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="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;These files instruct the root application to resolve the microfrontend’s path differently based on environment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Registering the Microfrontend in the Root Project
&lt;/h2&gt;

&lt;p&gt;Create a file named &lt;code&gt;single-spa.setup.ts&lt;/code&gt; in your root app:&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;// ### root/single-spa.setup.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;registerApplication&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;single-spa&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;apps&lt;/span&gt; &lt;span class="o"&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;app&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;@howlydev/app&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;function&lt;/span&gt; &lt;span class="nf"&gt;registerSpas&lt;/span&gt;&lt;span class="p"&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;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;moduleName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;of&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;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apps&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;registerApplication&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="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;app&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="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* @vite-ignore */&lt;/span&gt; &lt;span class="nx"&gt;moduleName&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;activeWhen&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="nx"&gt;route&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;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;runSpas&lt;/span&gt;&lt;span class="p"&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;function&lt;/span&gt; &lt;span class="nf"&gt;runSpas&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;start&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;ul&gt;
&lt;li&gt;
&lt;strong&gt;registerApplication&lt;/strong&gt;: Tells Single-SPA which application to load and on which route path.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;start()&lt;/strong&gt;: Initializes Single-SPA, enabling the lifecycle of registered applications.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Testing the Setup
&lt;/h2&gt;

&lt;p&gt;Run both the root and microfrontend applications in separate terminals:&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="c"&gt;# In the root folder&lt;/span&gt;
npm run dev

&lt;span class="c"&gt;# In the app folder&lt;/span&gt;
npm run dev:sspa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the URL for your root application (e.g., &lt;code&gt;http://localhost:5173/&lt;/code&gt;). The microfrontend should be dynamically loaded and displayed when its route is accessed.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;When you navigate to the route that initializes the microfrontend, you may notice unexpected behavior: because both the root application and the microfrontend use Vue, there are two Vue instances running. Additionally, the microfrontend is not rendered within the &lt;code&gt;router-view&lt;/code&gt; controlled by the root’s Vue Router.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxcwzrem278due9731jac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxcwzrem278due9731jac.png" alt="enter image description here" width="800" height="606"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inspecting the DOM reveals that both the root and microfrontend instances are active, but the microfrontend content is appended directly to the body (or another top-level element) rather than where the root router expects it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0uixg7oo75akqj78nyt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0uixg7oo75akqj78nyt.png" alt="enter image description here" width="800" height="181"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To fix this, you can leverage Vue’s &lt;code&gt;Teleport&lt;/code&gt; feature to “teleport” the microfrontend’s content into a specified container within the root application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- ### app/App.vue ### --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Teleport&lt;/span&gt; &lt;span class="na"&gt;to=&lt;/span&gt;&lt;span class="s"&gt;".container"&lt;/span&gt; &lt;span class="na"&gt;:disabled=&lt;/span&gt;&lt;span class="s"&gt;"isTeleportDisabled"&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;style=&lt;/span&gt;&lt;span class="s"&gt;"background-color: lightcoral"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello From the Microfrontend&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;router-view&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;router-link&lt;/span&gt; &lt;span class="na"&gt;to=&lt;/span&gt;&lt;span class="s"&gt;"/foo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Go to Foo&lt;span class="nt"&gt;&amp;lt;/router-link&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;router-link&lt;/span&gt; &lt;span class="na"&gt;to=&lt;/span&gt;&lt;span class="s"&gt;"/bar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Go to Bar&lt;span class="nt"&gt;&amp;lt;/router-link&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/ul&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;/Teleport&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isTeleportDisabled&lt;/span&gt; &lt;span class="o"&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;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MODE&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&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;Meanwhile, in your root application, ensure there is a &lt;code&gt;.container&lt;/code&gt; element available to receive this teleported content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;### root/App.vue ###
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;main&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;
        &lt;span class="nt"&gt;&amp;lt;router-view&lt;/span&gt; &lt;span class="nt"&gt;/&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;/main&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&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;Here, the microfrontend’s content is rendered where you want it, and the teleport is disabled during standalone (development) mode so you can still see the microfrontend by itself.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Second Problem
&lt;/h2&gt;

&lt;p&gt;A common requirement is that each microfrontend can handle its own internal routing. In this example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The root application doesn’t “know” about &lt;code&gt;/app&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;The microfrontend expects its base route to be &lt;code&gt;/&lt;/code&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When you visit &lt;code&gt;"/app"&lt;/code&gt;, you might see a warning in the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Vue Router warn]: No match found for location with path "/app"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Though you can’t fully suppress these warnings (see &lt;a href="https://github.com/vuejs/router/issues/359" rel="noopener noreferrer"&gt;this Vue Router issue&lt;/a&gt;), you can enable routing in the microfrontend by changing the base path, we will go even further and pass it from root application:&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="err"&gt;###&lt;/span&gt; &lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;single&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;spa&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt; &lt;span class="err"&gt;###&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;apps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;app&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@howlydev/app&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;function&lt;/span&gt; &lt;span class="nf"&gt;registerSpas&lt;/span&gt;&lt;span class="p"&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;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;moduleName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;of&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;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apps&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nf"&gt;registerApplication&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="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
      &lt;span class="na"&gt;app&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="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* @vite-ignore */&lt;/span&gt; &lt;span class="nx"&gt;moduleName&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  
      &lt;span class="na"&gt;activeWhen&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="nx"&gt;route&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="na"&gt;customProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="na"&gt;basePath&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="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="cm"&gt;/* &amp;lt;-- this is new */&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;runSpas&lt;/span&gt;&lt;span class="p"&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;function&lt;/span&gt; &lt;span class="nf"&gt;runSpas&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nf"&gt;start&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 will pass our &lt;code&gt;basePath&lt;/code&gt; to the router.&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="err"&gt;###&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt; &lt;span class="err"&gt;###&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&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;./App.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./assets/main.css&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;singleSpaVue&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;single-spa-vue&lt;/span&gt;&lt;span class="dl"&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;createApp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;h&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;vue&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="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="s1"&gt;./router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;  

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Props&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="na"&gt;basePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;vueLifecycles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;singleSpaVue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
  &lt;span class="nx"&gt;createApp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="na"&gt;appOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nf"&gt;render&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;basePath&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;h&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="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="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="na"&gt;basePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;basePath&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="na"&gt;handleInstance&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="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Props&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;basePath&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;mountVue&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="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;createApp&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="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;router&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;mount&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&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="k"&gt;if &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;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MODE&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;development&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;mountVue&lt;/span&gt;&lt;span class="p"&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;const&lt;/span&gt; &lt;span class="nx"&gt;bootstrap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vueLifecycles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bootstrap&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;const&lt;/span&gt; &lt;span class="nx"&gt;mount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vueLifecycles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mount&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;const&lt;/span&gt; &lt;span class="nx"&gt;unmount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vueLifecycles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unmount&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="err"&gt;###&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt; &lt;span class="err"&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;createRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createWebHistory&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;vue-router&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;FooView&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;@/views/FooView.vue&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="nx"&gt;BarView&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;@/views/BarView.vue&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;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;basePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/app&lt;/span&gt;&lt;span class="dl"&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="nf"&gt;createRouter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
  &lt;span class="na"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;createWebHistory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;basePath&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  
  &lt;span class="na"&gt;routes&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;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/foo&lt;/span&gt;&lt;span class="dl"&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;foo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
          &lt;span class="na"&gt;component&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FooView&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;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/bar&lt;/span&gt;&lt;span class="dl"&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;bar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
          &lt;span class="na"&gt;component&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BarView&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our router is now a function that accepts &lt;code&gt;basePath&lt;/code&gt; as an argument and returns Router instance that can be used by a Vue app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Words
&lt;/h2&gt;

&lt;p&gt;Microfrontends can be highly beneficial for large-scale applications, but they’re not always straightforward to implement. As shown here, multiple Vue instances and routing complexities can create unexpected issues. Despite these trade-offs (and alternatives such as &lt;a href="https://github.com/originjs/vite-plugin-federation" rel="noopener noreferrer"&gt;vite-plugin-federation&lt;/a&gt;), microfrontend architecture is worth knowing about. You might ask: &lt;em&gt;is it solving a real problem?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It depends.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you need to build a simple Todo app, it’s probably overkill.
&lt;/li&gt;
&lt;li&gt;If you’re building a Cloud ERP, it might be worth exploring.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ll quote Uncle Bob here:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You should be able to structure your code in a clean, modular fashion within a monolith before considering distribution. If you cannot form clear boundaries in a single-process system, you are unlikely to succeed by splitting it into microservices.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;The full GitHub repository can be found here:&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/swrzalek/vue3-vite-sspa-demo/tree/main" rel="noopener noreferrer"&gt;https://github.com/swrzalek/vue3-vite-sspa-demo/tree/main&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’d like to see a more complex, real-world microfrontend example, let me know in the comments!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you found this article helpful, please leave a like! ❤️&lt;/strong&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to deploy Nuxt 3 app to Netlify with Github Actions</title>
      <dc:creator>Sebastian Wrzalek</dc:creator>
      <pubDate>Wed, 19 Apr 2023 23:04:57 +0000</pubDate>
      <link>https://dev.to/swrzalek/how-to-deploy-nuxt-3-app-to-netlify-with-github-actions-55c7</link>
      <guid>https://dev.to/swrzalek/how-to-deploy-nuxt-3-app-to-netlify-with-github-actions-55c7</guid>
      <description>&lt;p&gt;Deploying a Nuxt 3 app to Netlify seems like a easy job. You can connect repository to Netlify site and it is automatically deployed when you pushed your changes to the origin branch. &lt;br&gt;
Me in the other hand, prefer to have everything in one place, so I wanted to control my CI/CD from Github Actions. In this article I will show you how, let's go!&lt;/p&gt;

&lt;p&gt;As you might not know Nuxt 3 works with Nitro (open engine powering &lt;a href="https://nuxt.com/" rel="noopener noreferrer"&gt;Nuxt&lt;/a&gt;) so normally, the deployment to Netlify does not require any configuration. Nitro will auto-detect that you are in a &lt;a href="https://www.netlify.com/" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt; build environment and build the correct version of your server. But our scenario is not normal so we need to take some additional  steps. &lt;/p&gt;
&lt;h3&gt;
  
  
  Create empty project
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Make sure you have installed yarn, npx (included by default with npm&lt;br&gt;
v5.2+) or npm (v6.1+) and &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;node&lt;/a&gt; with at least&lt;br&gt;
16.x version installed&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn create nuxt-app &amp;lt;project-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside of the &lt;strong&gt;nuxt.config.ts&lt;/strong&gt; file change the preset to &lt;code&gt;netlify&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default defineNuxtConfig({  
    nitro: {  
        preset: 'netlify'  
  },  
  ...
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create workflow configuration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir -p .github/workflows &amp;amp;&amp;amp; touch .github/workflows/main.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the inside of &lt;code&gt;main.yml&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: 'My Workflow'  

on:  
  push:  
    branches:  
    - main  

jobs:  
  deploy:  
    # Operating system to run job on  
  runs-on: ubuntu-latest  

    # Steps in job  
  steps:  
      # Get code from repo  
  - name: Checkout code  
        uses: actions/checkout@v1  
      # Install NodeJS  
  - name: Use Node.js 16.x  
        uses: actions/setup-node@v1  
        with:  
          node-version: 16.10.0  
      # Run npm install and build on our code  
  - run: npm install  
      - run: npm run build  
      # Deploy to Netlify using our dev secrets  
  - name: Deploy to netlify  
        uses: netlify/actions/cli@master  
        env:  
          NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_TOKEN }}  
          NETLIFY_SITE_ID:  ${{ secrets.SITE_ID }} 
        with:  
          args: deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we need to add secrets to our repository settings, you can find it here&lt;br&gt;
&lt;a href="https://github.com/%7BGITHUB_USERNAME%7D/%7BREPOSITORY_NAME%7D/settings/secrets/actions" rel="noopener noreferrer"&gt;https://github.com/{GITHUB_USERNAME}/{REPOSITORY_NAME}/settings/secrets/actions&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Obtain a token in the Netlify UI
&lt;/h3&gt;

&lt;p&gt;You can generate an access token manually in your Netlify user settings for  &lt;a href="https://app.netlify.com/user/applications#personal-access-tokens" rel="noopener noreferrer"&gt;&lt;strong&gt;Personal access tokens&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Under  &lt;strong&gt;Personal access tokens&lt;/strong&gt;, select  &lt;strong&gt;New access token&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enter a description.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select  &lt;strong&gt;Generate token&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy the generated token to your clipboard. Once you navigate from the page, the token cannot be seen again.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Save the token as a  &lt;code&gt;NETLIFY_AUTH_TOKEN&lt;/code&gt;  environment variable in your terminal settings or in the UI of a Continuous Integration (CI) tool.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Obtaining Site ID
&lt;/h3&gt;

&lt;p&gt;On your Netlify account&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Go to  &lt;strong&gt;Site settings &amp;gt; General &amp;gt; Site details &amp;gt; Site information&lt;/strong&gt;, and copy the value for  &lt;strong&gt;Site ID&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Push Your Code
&lt;/h3&gt;

&lt;p&gt;Make sure you have pushed your code to the &lt;code&gt;main&lt;/code&gt; branch, this way you will trigger Github Workflow and deploy your app to the world.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Three Concepts you need to know as Senior Software Engineer</title>
      <dc:creator>Sebastian Wrzalek</dc:creator>
      <pubDate>Wed, 19 Apr 2023 17:16:07 +0000</pubDate>
      <link>https://dev.to/swrzalek/three-concepts-you-need-to-know-as-senior-software-engineer-345</link>
      <guid>https://dev.to/swrzalek/three-concepts-you-need-to-know-as-senior-software-engineer-345</guid>
      <description>&lt;p&gt;As a software engineer, you have likely amassed a great deal of technical knowledge and experience in your field. However, there are certain key concepts that are worth knowing. In this article, we will discuss three concepts that every experienced engineer should be familiar with in order to stay ahead of the game.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cohesion
&lt;/h2&gt;

&lt;p&gt;In programming, cohesion refers to the degree to which the elements of a module or a software component work together to achieve a single, well-defined purpose or function. In other words, it's a measure of how closely related the parts of a module are to each other.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fodj8vqcm3fic7u778dvd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fodj8vqcm3fic7u778dvd.png" alt="Coupling and cohesion (en.wikipedia.org)" width="800" height="653"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;High cohesion&lt;/strong&gt; means that the elements within a module are &lt;strong&gt;highly related&lt;/strong&gt; and work together closely to achieve a specific task or function. &lt;strong&gt;Low cohesion&lt;/strong&gt;, on the other hand, means that the elements within a module are &lt;strong&gt;loosely related&lt;/strong&gt; and may not work together efficiently to achieve a specific purpose.&lt;br&gt;
High cohesion is generally considered desirable because it leads to more maintainable and reusable code. It makes it easier to understand and modify a module without affecting the rest of the program. On the other hand, low cohesion can lead to code that is difficult to understand, modify, and maintain, which can result in bugs, errors, and inefficiencies.&lt;br&gt;
Sound great but how to achieve high cohesion and low coupling?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single Responsibility Principle (&lt;strong&gt;SRP&lt;/strong&gt;): Each class or module should have only one responsibility.&lt;/li&gt;
&lt;li&gt;Interface Segregation Principle (&lt;strong&gt;ISP&lt;/strong&gt;): Interfaces should be designed to be as small as possible, with only the methods that are necessary for the implementation of the interface.&lt;/li&gt;
&lt;li&gt;Dependency Inversion Principle (&lt;strong&gt;DIP&lt;/strong&gt;): High-level modules should not depend on low-level modules, but both should depend on abstractions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cognitive Complexity
&lt;/h2&gt;

&lt;p&gt;Cognitive complexity is a measure of the difficulty of understanding and reasoning about a piece of code. It takes into account the number of &lt;strong&gt;distinct paths through the code&lt;/strong&gt;, &lt;strong&gt;the nesting depth of control structures&lt;/strong&gt;, and the number of &lt;strong&gt;logical operators&lt;/strong&gt; and &lt;strong&gt;operands&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe2vgkaw5wqu63nihjk8m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe2vgkaw5wqu63nihjk8m.png" alt="Example of high cognitive complexity" width="800" height="819"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A higher cognitive complexity indicates that the code is more difficult to understand and reason about, which can lead to more bugs, slower development time, and more difficult maintenance.&lt;br&gt;
Code with a low cognitive complexity, on the other hand, is easier to read and understand, which can lead to more efficient development and maintenance.&lt;br&gt;
To make code less complex and easy to read apply Clean Code practice, you can find them for every programming languages, &lt;a href="https://github.com/ryanmcdermott/clean-code-javascript" rel="noopener noreferrer"&gt;here&lt;/a&gt; for Javascript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design Patterns
&lt;/h2&gt;

&lt;p&gt;Design patterns are &lt;strong&gt;reusable solutions&lt;/strong&gt; to commonly &lt;strong&gt;occurring problems&lt;/strong&gt; in software design. They are general solutions that can be applied to different situations in software development, making the design and development process more efficient and effective.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyxmbf4k71ds5x5qngcbd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyxmbf4k71ds5x5qngcbd.png" alt="Adapter - structural design pattern (refactoring.guru)" width="640" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Design patterns provide a common vocabulary and a set of best practices for software designers and developers. They help to ensure that software is &lt;strong&gt;maintainable&lt;/strong&gt;, &lt;strong&gt;flexible&lt;/strong&gt;, and &lt;strong&gt;extensible&lt;/strong&gt;, and that it meets the needs of its users.&lt;br&gt;
Design patterns can be used in a variety of programming languages and environments, including object-oriented programming, functional programming, and web development. They are widely used in software development and are an important tool for creating high-quality, maintainable, and reusable software.&lt;br&gt;
If you want to learn more about design patterns I highly recommend checking out &lt;a href="https://refactoring.guru/design-patterns" rel="noopener noreferrer"&gt;Refactoring Guru&lt;/a&gt;, they provide great examples and graphics that help you understand it quicker.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>architecture</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
