<?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: Dawid Nitka</title>
    <description>The latest articles on DEV Community by Dawid Nitka (@nagell).</description>
    <link>https://dev.to/nagell</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1230391%2Fb73c8f4a-9b91-489e-b826-150bf4f776fc.png</url>
      <title>DEV Community: Dawid Nitka</title>
      <link>https://dev.to/nagell</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nagell"/>
    <language>en</language>
    <item>
      <title>Creating a scalable Monorepo for Vue - Nx</title>
      <dc:creator>Dawid Nitka</dc:creator>
      <pubDate>Sun, 01 Jun 2025 13:00:02 +0000</pubDate>
      <link>https://dev.to/nagell/creating-a-scalable-monorepo-for-vue-nx-59il</link>
      <guid>https://dev.to/nagell/creating-a-scalable-monorepo-for-vue-nx-59il</guid>
      <description>&lt;p&gt;As your codebase grows, so does the complexity of managing multiple apps and libraries. At this point Nx can help with its &lt;a href="https://nx.dev/features/explore-graph" rel="noopener noreferrer"&gt;graph&lt;/a&gt;, but more importantly it can orchestrate all builds and tests in monorepo and keep you sane while managing dozens of packages. &lt;/p&gt;

&lt;p&gt;In essence Nx is capable of running tasks in parallel based on what has changed from the previous commit. It also respects dependencies, ensuring that libraries needed by others are built first.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Project Graph &amp;amp; Dependency Awareness&lt;/strong&gt; &lt;br&gt;
Nx automatically analyzes your workspace and builds a project graph, understanding how your apps and libraries depend on each other. This &lt;br&gt;
allows you to build or test only what has changed and furthermore what is directly influenced by it, based on the changes between the current and the previous commit.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Code Generation&lt;/strong&gt;&lt;br&gt;
Nx provides some nice generators for scaffolding new apps, libraries, &lt;br&gt;
etc. I found them to be decent for Vue, but if you like it your way you can of course just ignore them. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Advanced Caching&lt;/strong&gt;&lt;br&gt;
Nx caches build and test results, so repeated commands are lightning &lt;br&gt;
fast. It can even share cache results across CI runs and between developers (Caution: sharing is a nice but paid feature - still very useful for enterprise clients).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Powerful CI/CD&lt;/strong&gt;&lt;br&gt;
Nx can run tasks in parallel, only for affected projects, and provides detailed output for CI pipelines.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  How to Configure Nx in Your Monorepo
&lt;/h2&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Install Nx
&lt;/h3&gt;

&lt;p&gt;If you’re starting from scratch, you can create a new Nx workspace with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpx create-nx-workspace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In an existing monorepo, install Nx as a dev dependency and run &lt;code&gt;init&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm add &lt;span class="nt"&gt;-D&lt;/span&gt; nx

nx init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Nx Workspace Structure
&lt;/h3&gt;

&lt;p&gt;Nx expects some sub-directories with &lt;code&gt;package.json&lt;/code&gt; or it's internal &lt;code&gt;project.json&lt;/code&gt; file by default as a marker of a package. Sample structure can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/
├── apps/
│   └── app_1/
├── libs/
│   └── commons/
│   └── ui/
├── nx.json
├── workspace.json (or project.json or package.json files)
├── tsconfig.base.json
├── pnpm-workspace.yaml
└── package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;apps/&lt;/strong&gt;: Applications (SPA, SSR, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;libs/&lt;/strong&gt;: Reusable libraries (UI, utilities, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;nx.json&lt;/strong&gt;: Nx-specific configuration (project graph, tasks, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;workspace.json&lt;/strong&gt;: Project definitions (can be split into per-project &lt;code&gt;project.json&lt;/code&gt; or &lt;code&gt;package.json&lt;/code&gt;),&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;pnpm-workspace.yaml&lt;/strong&gt;: Defines workspace packages for pnpm&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Nx Plugins
&lt;/h3&gt;

&lt;p&gt;Nx supports plugins for frameworks and tools. For example, to add Vue support:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm add &lt;span class="nt"&gt;-D&lt;/span&gt; @nx/vue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or for Storybook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm add &lt;span class="nt"&gt;-D&lt;/span&gt; @nx/storybook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the mentioned plugins you can run and utilize Nx commands for these frameworks, but also use them for scaffolding new projects.&lt;/p&gt;

&lt;p&gt;To start with using commands as well as Nx packages I recommend the vscode plugin &lt;a href="https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console" rel="noopener noreferrer"&gt;Nx Console&lt;/a&gt;. It’s a great tool for exploring available options and features.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Nx Commands
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Run a target:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  pnpm nx build:staging @monorepo/app_1
  pnpm nx lint @monorepo/commons
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Run for affected (changed from the last commit) projects only:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  pnpm nx affected &lt;span class="nt"&gt;-t&lt;/span&gt; build:staging
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Start the project graph:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  pnpm nx graph
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;List of installed and available plugins:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  pnpm nx list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;graph&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;It helps you visualize the dependencies between your packages. If you want to categorize your packages correctly in this browser based tool, I recommend either generating &lt;code&gt;workspace.json&lt;/code&gt; or a bunch of &lt;code&gt;project.json&lt;/code&gt; files, or as in my case (the simplest one) just adding this to your &lt;code&gt;package.json&lt;/code&gt; files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@monorepo/ui"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"nx"&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;"projectType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"library"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// or "application"&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;&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%2F5dl6yzmdfsv8jgwhr9ul.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%2F5dl6yzmdfsv8jgwhr9ul.png" alt="Image description" width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;affected&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Running locally the &lt;code&gt;affected&lt;/code&gt; command will work with default settings only if creating branch and making some changes as it compares your branch to the &lt;code&gt;main&lt;/code&gt;. But you can always explicitly compare the current state with a state from a couple of commits ago for test purposes.&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;# run lint for packages which changed &lt;/span&gt;
&lt;span class="c"&gt;# between the current state and the state from 5 commits ago&lt;/span&gt;
pnpm nx affected &lt;span class="nt"&gt;-t&lt;/span&gt; lint &lt;span class="nt"&gt;--base&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;HEAD~5 &lt;span class="nt"&gt;--head&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;HEAD  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F8hleux4vwvev7vqbz9d4.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%2F8hleux4vwvev7vqbz9d4.png" alt="Nx lint run result" width="737" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the result of running lint for all packages in my monorepo template. &lt;/p&gt;

&lt;p&gt;Not very spectacular, I know, but imagine how much build time you can save with a big monorepo while running this command on your server and executing commands in parallel only for the changed parts!&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is the last article in this series. If you want to learn more about creation of monorepo with Vue, check out other tutorials. If you prefer starting with a solid foundation - try this &lt;a href="https://github.com/Nagell/monorepo_template" rel="noopener noreferrer"&gt;template&lt;/a&gt;, where I’ve put all of this into practice.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>monorepo</category>
      <category>vue</category>
      <category>nx</category>
      <category>pnpm</category>
    </item>
    <item>
      <title>Creating a scalable Monorepo for Vue - Shared configs</title>
      <dc:creator>Dawid Nitka</dc:creator>
      <pubDate>Sat, 22 Feb 2025 12:20:09 +0000</pubDate>
      <link>https://dev.to/nagell/creating-a-scalable-monorepo-for-vue-shared-configs-2bfo</link>
      <guid>https://dev.to/nagell/creating-a-scalable-monorepo-for-vue-shared-configs-2bfo</guid>
      <description>&lt;p&gt;Now that we have in place all needed packages (libs and apps) and established connections between them, we have to take care of required configs like &lt;code&gt;vite.config.ts&lt;/code&gt;, &lt;code&gt;.eslint.cjs&lt;/code&gt; and &lt;code&gt;postcss.config.cjs&lt;/code&gt;. We could add all of them multiple times, but as we have monorepo let's use it to our advantage.&lt;/p&gt;

&lt;p&gt;You can create a global &lt;code&gt;configs&lt;/code&gt; directory in the root of monorepo and add all common configs there, like: &lt;code&gt;vite.application.ts&lt;/code&gt;, &lt;code&gt;vite.service.ts&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;Later you can import them into apps and libs in the config files and refine them with some overwrites. Of course the overwriting or rather merging step can be a bit problematic. Luckily there are already tested solutions out there like &lt;a href="https://stackoverflow.com/questions/27936772/how-to-deep-merge-instead-of-shallow-merge/48218209#48218209" rel="noopener noreferrer"&gt;this nice merge function&lt;/a&gt; made by John Hildenbiddle.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Merge sample
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;merge&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Recursively merges the specified object instances
 * @param instances Instances to merge, from left to right
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mergeWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Merge an instance with another one
 * @param target Object to merge the custom values into
 * @param source Object with custom values
 * @author inspired by [jhildenbiddle](https://stackoverflow.com/a/48218209).
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;mergeWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;source&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;isObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;isObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;key&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;targetValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&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;sourceValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;targetValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sourceValue&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;targetValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sourceValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;targetValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;isObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sourceValue&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="nx"&gt;targetValue&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;sourceValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sourceValue&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;return&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this you can add your &lt;code&gt;vite.application.ts&lt;/code&gt; template:&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;path&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;path&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;nxViteTsPaths&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;@nx/vite/plugins/nx-tsconfig-paths.plugin&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="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;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;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;(),&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;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;open&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="na"&gt;preview&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&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;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;nxViteTsPaths&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt;

    &lt;span class="c1"&gt;// Uncomment this if you are using workers.&lt;/span&gt;
    &lt;span class="c1"&gt;// worker: {&lt;/span&gt;
    &lt;span class="c1"&gt;//     plugins: () =&amp;gt; [ nxViteTsPaths() ],&lt;/span&gt;
    &lt;span class="c1"&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="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cwd&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="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;reportCompressedSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;commonjsOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;transformMixedEsModules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the &lt;code&gt;index.ts&lt;/code&gt; file collecting all the configs:&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="nx"&gt;merge&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;./merge&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;getProxyConfiguration&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;./proxyConfig&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;applicationConfiguration&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.application&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UserConfig&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;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getProxyConfiguration&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Returns Vite build configuration for client applications,
 * optionally amended with the specified options
 * @param options Custom build options
 * @returns Vite build configuration
 */&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;getApplicationConfiguration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserConfig&lt;/span&gt; &lt;span class="o"&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;return&lt;/span&gt; &lt;span class="nf"&gt;getConfiguration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;applicationConfiguration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Returns Vite build configuration amended with the specified options
 * @param configuration Default build options
 * @param options Custom build options
 * @returns Vite build configuration
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getConfiguration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserConfig&lt;/span&gt; &lt;span class="o"&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="c1"&gt;// Default configuration&lt;/span&gt;
        &lt;span class="nx"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// Custom options to override the default configuration&lt;/span&gt;
        &lt;span class="nx"&gt;options&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Handy when you need to peek into that final build configuration&lt;/span&gt;
    &lt;span class="c1"&gt;// console.warn(JSON.stringify(result, null, 2))&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally the usage of the whole template can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// eslint-disable-next-line&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;getApplicationConfiguration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getProxyConfiguration&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;./../../config/vite&lt;/span&gt;&lt;span class="dl"&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="nf"&gt;getApplicationConfiguration&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;cacheDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../node_modules/.vite/apps/app_1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&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;5005&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// sample proxy configuration&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;getProxyConfiguration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://localhost:7148/&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;preview&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;5005&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;outDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../dist/apps/app_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="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that instead of standard &lt;code&gt;export default { … }&lt;/code&gt; we are using the &lt;code&gt;getApplicationConfiguration(…)&lt;/code&gt;. It allows us to use the predefined template and overwrite some specific parts.&lt;/p&gt;

&lt;p&gt;Check out the implementation in the sample &lt;a href="https://github.com/Nagell/monorepo_template/tree/main/config/vite" rel="noopener noreferrer"&gt;repo&lt;/a&gt;. Usage sample can be found in the &lt;a href="https://github.com/Nagell/monorepo_template/blob/main/apps/app_1/vite.config.ts" rel="noopener noreferrer"&gt;app&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Eslint, postcss, etc
&lt;/h2&gt;

&lt;p&gt;The same applies to other repeatable configs like &lt;code&gt;eslint&lt;/code&gt;. No matter if you are using the old syntax (8.x.x) or the newer one using &lt;code&gt;export default&lt;/code&gt; (9.x.x) - you can still add a bunch of custom configs like I did &lt;a href="https://github.com/Nagell/monorepo_template/tree/main/config/eslint" rel="noopener noreferrer"&gt;here&lt;/a&gt; to import them as needed in the apps and libs (&lt;a href="https://github.com/Nagell/monorepo_template/blob/main/apps/app_1/.eslintrc.cjs" rel="noopener noreferrer"&gt;sample&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Generally speaking, in monorepo you can make your life easier by reusing many common configs by sharing them. After a bit of initial cost, adding yet another app or lib will be much easier.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you want to learn more about creation of monorepo with Vue, check out other tutorials in the series. If you prefer starting with a solid foundation - try this &lt;a href="https://github.com/Nagell/monorepo_template" rel="noopener noreferrer"&gt;template&lt;/a&gt;, where I’ve put all of this into practice.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the next one, we will talk about builds and parallelization with Nx. &lt;/p&gt;

</description>
      <category>monorepo</category>
      <category>vue</category>
      <category>nx</category>
      <category>pnpm</category>
    </item>
    <item>
      <title>Creating a scalable Monorepo for Vue - Libs vs Apps</title>
      <dc:creator>Dawid Nitka</dc:creator>
      <pubDate>Sat, 25 Jan 2025 18:00:12 +0000</pubDate>
      <link>https://dev.to/nagell/creating-a-scalable-monorepo-for-vue-libs-vs-apps-489l</link>
      <guid>https://dev.to/nagell/creating-a-scalable-monorepo-for-vue-libs-vs-apps-489l</guid>
      <description>&lt;p&gt;One of the steps in creating a monorepo is splitting apps and libraries. But how to take them apart? What is a library and do you have to publish it somewhere?&lt;/p&gt;

&lt;p&gt;The simplest answer is that a library is reusable code. To name a few, it can be your UI library, API files that will be reused, or even some library with useful functions—our well-known: &lt;code&gt;helperThis&lt;/code&gt;, &lt;code&gt;helperThat&lt;/code&gt;, ... In the case of Vue, it can also include a bunch of compostables (ex. &lt;code&gt;useSomething&lt;/code&gt;). There's no need to publish them anywhere. They will be used directly from your libraries.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the consumer (app)
&lt;/h2&gt;

&lt;p&gt;Let's assume you already have a couple of candidates to put them outside your app and reuse them. The next question is how to connect them.&lt;/p&gt;

&lt;p&gt;In the previous post I mentioned adding libraries to the &lt;code&gt;package.json&lt;/code&gt; (sample below) file, but it's only one side of the story.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@monorepo/app_1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"module"&lt;/span&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="c1"&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;"dependencies"&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;"@monorepo/commons"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"workspace:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"@monorepo/ui"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"workspace:*"&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="c1"&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; &lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the provider (library)
&lt;/h2&gt;

&lt;p&gt;The other side which is the library has to define all files that should be approachable from outside. Of course, it can be just some index file, but it could be a sub-directory as well - there's no need to set every file independently. All this has to be put in the library's &lt;code&gt;package.json&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@monorepo/commons"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"exports"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/index.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"./composables/*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/composables/*"&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;"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="c1"&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;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Typescript and intellisense
&lt;/h2&gt;

&lt;p&gt;The sample above should give you already an idea of how to connect things. To use it you can just:&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="nx"&gt;someHelper&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;@monorepo/commons/composables/analytics&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will still notice that TypeScript running in the background cannot recognize imported libraries. To solve this add explicit such paths to the project's &lt;code&gt;tsconfig.json&lt;/code&gt; file (section &lt;code&gt;paths&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&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;"compilerOptions"&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;"paths"&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;"@monorepo/commons"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"../../libs/commons/src/*"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c1"&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;The first part is what you want to use during the import and the second is a direct path to the file or directory.&lt;/p&gt;

&lt;p&gt;As a bonus it also makes Vue components show you all expected parameters in the form of intellisense as if they were added directly to your project.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up custom paths
&lt;/h3&gt;

&lt;p&gt;I explicitly set &lt;code&gt;@monorepo/commons&lt;/code&gt; to point to the library's &lt;code&gt;/src&lt;/code&gt; directory. If the &lt;code&gt;/src&lt;/code&gt; directory is exported in the library's &lt;code&gt;package.json&lt;/code&gt;, it's enough to make it work.&lt;/p&gt;

&lt;p&gt;You can also define your own, so-to-say, "nicknames". This practice is often used to create paths that are shorter and thus easier to use and remember.&lt;/p&gt;

&lt;p&gt;For example, instead of using:&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="nx"&gt;someHelper&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;@monorepo/commons/composables/analytics&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you could use&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="nx"&gt;someHelper&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;@monorepo/commons/analytics&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To achieve this, define such a shortcut in the library's &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-doc"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@monorepo/commons"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"exports"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/index.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"./composables/*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/composables/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"./analytics/*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/composables/analytics/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and also add it to the app's &lt;code&gt;tsconfig.json&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&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;"compilerOptions"&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;"paths"&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;"@monorepo/commons"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"../../libs/commons/src/*"&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;"@monorepo/commons/composables/*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"../../libs/commons/src/composables/*"&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;"@monorepo/commons/analytics"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"../../libs/commons/src/composables/analytics/*"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c1"&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; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you want to learn more about creation of monorepo with Vue, check out other tutorials in the series. If you prefer starting with a solid foundation - try this &lt;a href="https://github.com/Nagell/monorepo_template" rel="noopener noreferrer"&gt;template&lt;/a&gt;, where I’ve put all of this into practice.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>monorepo</category>
      <category>vue</category>
      <category>nx</category>
      <category>pnpm</category>
    </item>
    <item>
      <title>Creating a scalable Monorepo for Vue - Workspaces</title>
      <dc:creator>Dawid Nitka</dc:creator>
      <pubDate>Tue, 14 Jan 2025 21:56:28 +0000</pubDate>
      <link>https://dev.to/nagell/creating-a-scalable-monorepo-for-vue-workspaces-5dlk</link>
      <guid>https://dev.to/nagell/creating-a-scalable-monorepo-for-vue-workspaces-5dlk</guid>
      <description>&lt;p&gt;In the previous post, I mentioned so-called workspaces. This is a good starting point which also will show how to structure your future and existing projects. The first one (starting without any projects) is easy, the second (existing ones) requires a bit more work but with a bit of luck, everything should run smoothly.&lt;/p&gt;

&lt;p&gt;The below steps describe how to do this with &lt;a href="https://pnpm.io/workspaces" rel="noopener noreferrer"&gt;pnpm&lt;/a&gt;. You could also use &lt;a href="https://yarnpkg.com/features/workspaces" rel="noopener noreferrer"&gt;yarn berry&lt;/a&gt; or &lt;a href="https://classic.yarnpkg.com/lang/en/docs/workspaces/" rel="noopener noreferrer"&gt;yarn classic&lt;/a&gt;. In such case this approach works slightly differently by adding such structure description to the &lt;code&gt;package.json&lt;/code&gt; file. The rest is quite similar.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Wait, but why not npm? I've heard that it also has workspaces.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;AFAIK it's still not monorepo-ready due to serious problems with hoisting and the lack of ability to solve such dependencies. A good explanation of the struggle with npm caveats is provided in &lt;a href="https://medium.com/@d.ts/how-to-use-npm-workspace-d155076da956" rel="noopener noreferrer"&gt;this article&lt;/a&gt; ;)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you want to know more about creating a monorepo check out other tutorials in the series. If you prefer testing things on your own - try this &lt;a href="https://github.com/Nagell/monorepo_template" rel="noopener noreferrer"&gt;template&lt;/a&gt;, where I put all of this into work.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Let's get to the work
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install pnpm if you don't have it yet:&lt;br&gt;
&lt;/p&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;--global&lt;/span&gt; pnpm
&lt;span class="c"&gt;#or&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--global&lt;/span&gt; corepack@latest
corepack &lt;span class="nb"&gt;enable &lt;/span&gt;pnpm
corepack use pnpm@latest-10
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;or you can follow the other options from the &lt;a href="https://pnpm.io/installation" rel="noopener noreferrer"&gt;pnpm installation guide&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a new directory with a &lt;code&gt;package.json&lt;/code&gt; file structured as follows:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight json-doc"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your_company_or_so"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"private"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&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="c1"&gt;// all repeating dependencies&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="c1"&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;/li&gt;
&lt;li&gt;
&lt;p&gt;Add a &lt;code&gt;pnpm-workspace.yaml&lt;/code&gt; file in the root directory to define your workspace structure:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;packages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;apps/*'&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;libs/*'&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;whatever_else/*'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a bunch of sub-directories like &lt;code&gt;apps&lt;/code&gt;, &lt;code&gt;libs&lt;/code&gt;, etc. as defined in your workspace file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Put your projects into the mentioned directories and/or create new ones.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cut out the repeating &lt;code&gt;dependencies&lt;/code&gt; and &lt;code&gt;devDependencies&lt;/code&gt; from your projects' &lt;code&gt;package.json&lt;/code&gt; files in the sub-directories and place them in the root &lt;code&gt;package.json&lt;/code&gt; file. These are now connected to all your projects - exceptions are possible (read below).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete all your &lt;code&gt;node_modules&lt;/code&gt; in the sub-directories if you copied them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;As mentioned in the previous post, you can directly connect your libraries to the projects by modifying the app's &lt;code&gt;package.json&lt;/code&gt; file like so (more on this in the next article):&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight json-doc"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@monorepo/app_1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"module"&lt;/span&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="c1"&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;"dependencies"&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;"@monorepo/commons"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"workspace:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"@monorepo/ui"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"workspace:*"&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="c1"&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;/li&gt;
&lt;li&gt;
&lt;p&gt;Go to the root directory and install dependencies for all the projects at once:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm i
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;What about the dependencies that are not identical?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;First consider bringing them to the same version, preferably the newer ones.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It's too time-consuming right now.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I get it—deadlines, and so on. You can just leave them where they are. I would still strongly recommend having only one version of Vue, React, Typescript, etc., because the more packages tied to the same version, the easier it is to update all your projects at once and deal with refactors after updating all the projects in one go.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Fine, I updated what I could, but there are still some dependencies requiring different versions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's fine, there is nothing wrong with it. Decide which version is more common and move this one to the root &lt;code&gt;package.json&lt;/code&gt;. The less common version will stay in the &lt;code&gt;package.json&lt;/code&gt; file of the project that is using it. This way, you signal your package manager that you need that specific version in a particular project, and it will be installed independently.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What about dependencies that are used only once? Should I move them as well?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's up to you. If you assume that they will be used more often, sure, move them. Are they used only once for this specific project, and it's highly unlikely that it will change? Nah, you don't have to move it and pollute the root &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Adding new dependencies
&lt;/h2&gt;

&lt;p&gt;If you need to add something new to your monorepo you have two options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Install a package for the entire workspace - run it in the root directory&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# for dependencies &lt;/span&gt;
pnpm add &amp;lt;package-name&amp;gt; &lt;span class="nt"&gt;-w&lt;/span&gt;

&lt;span class="c"&gt;# for devDependencies&lt;/span&gt;
pnpm add &amp;lt;package-name&amp;gt; &lt;span class="nt"&gt;-Dw&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install it only for one of the apps / libs - run it in the app / lib directory&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# for dependencies&lt;/span&gt;
pnpm add &amp;lt;package-name&amp;gt;

&lt;span class="c"&gt;# for devDependencies&lt;/span&gt;
pnpm add &amp;lt;package-name&amp;gt; &lt;span class="nt"&gt;-D&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;I have some problems with dependencies with different versions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can try omitting this one migration to the root &lt;code&gt;package.json&lt;/code&gt; file and keeping it in the projects' &lt;code&gt;package.json&lt;/code&gt; files instead.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you want to learn more about creation of monorepo with Vue, check out other tutorials in the series. If you prefer starting with a solid foundation - try this &lt;a href="https://github.com/Nagell/monorepo_template" rel="noopener noreferrer"&gt;template&lt;/a&gt;, where I’ve put all of this into practice.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>monorepo</category>
      <category>vue</category>
      <category>nx</category>
      <category>pnpm</category>
    </item>
    <item>
      <title>Creating a scalable Monorepo for Vue - Intro</title>
      <dc:creator>Dawid Nitka</dc:creator>
      <pubDate>Tue, 14 Jan 2025 21:29:45 +0000</pubDate>
      <link>https://dev.to/nagell/creating-a-scalable-monorepo-for-vue-intro-4nnm</link>
      <guid>https://dev.to/nagell/creating-a-scalable-monorepo-for-vue-intro-4nnm</guid>
      <description>&lt;p&gt;Hello world,&lt;/p&gt;

&lt;p&gt;which means that this is my first article — first of many — as I intend to write a series on creating a monorepo structure for Vue.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  What problem are we trying to solve?
&lt;/h2&gt;

&lt;p&gt;Vue has become quite popular over the years, and more mid-size companies — and even some big names like Nintendo, Adobe, or Gitlab to name a few — are adopting it. Sometimes, they even choose it as the primary Framework for their products. That's why growing codebases containing many Vue packages are becoming common.&lt;/p&gt;

&lt;p&gt;Juggling with projects and packages, publishing, updating, and dealing with the consequences of postponing the last step longer than we intended, due to fast-paced workflows. Many of us were already there, or are right now. This raises the question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is there a good alternative and what are the trade-offs?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this series, I'll try to deliver some answers, as well as provide one of the solutions which you can see complete in this &lt;a href="https://github.com/Nagell/monorepo_template" rel="noopener noreferrer"&gt;template&lt;/a&gt;. Feel free to use it as a base to kickstart your project or simply try it out.&lt;/p&gt;

&lt;p&gt;If you have any questions, feel free to leave a comment or add a &lt;a href="https://github.com/Nagell/monorepo_template/issues/new?labels=enhancement&amp;amp;template=feature-request---.md" rel="noopener noreferrer"&gt;suggestion&lt;/a&gt; in the sample repo.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Monorepo
&lt;/h2&gt;

&lt;p&gt;There is at least one good option on which we will focus as it's definitely a mature and battle-proven one - monorepo.&lt;/p&gt;

&lt;p&gt;In contrary to microservices, which have a bunch of additional complexity this one embraces strengths of a monolith structure. I recommend a very good article on that matter from Maxi Ferreira - &lt;a href="https://frontendatscale.com/issues/45/" rel="noopener noreferrer"&gt;May I Interest You In a Modular Monolith?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The simple explanation is that we put everything into one directory. That's it? Well... not exactly. There are many additional possibilities, but let's start with the easy stuff.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  One repo, but not much more
&lt;/h3&gt;

&lt;p&gt;In the simplest form, it means that we create one repository with a bunch of sub-directories for our projects and libraries (packages) and that's it. The rest stays as it is: pushing to the origin, publishing with &lt;a href="https://docs.npmjs.com/cli/v11/commands/npm-publish" rel="noopener noreferrer"&gt;npm&lt;/a&gt; or &lt;a href="https://lerna.js.org/docs/features/version-and-publish" rel="noopener noreferrer"&gt;Lerna&lt;/a&gt;. Maybe even with &lt;a href="https://github.com/semantic-release/semantic-release" rel="noopener noreferrer"&gt;semantic-release&lt;/a&gt; if you've already made some optimization of the process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Many projects in one place -&amp;gt; less opened windows&lt;/li&gt;
&lt;li&gt;Better overview of your team's work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More branches -&amp;gt; potential chaos in the git tree&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Add workspace
&lt;/h3&gt;

&lt;p&gt;But what about managing external dependencies and consuming your libraries (packages)?&lt;/p&gt;

&lt;p&gt;If you don't want to go to every project and update dependencies manually you should consider so-called workspaces. More about them in the next article in the series. In short, they will allow you to update more, maybe even all dependencies at once, and still keep full control over your projects, when some more granular interference will be required.&lt;/p&gt;

&lt;h4&gt;
  
  
  Sample workspace configuration with pnpm
&lt;/h4&gt;

&lt;p&gt;To enable workspace features in pnpm, you need a &lt;code&gt;pnpm-workspace.yaml&lt;/code&gt; file at the root of your repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;packages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;apps/*'&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;libs/*'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file will tell pnpm to treat all projects in the &lt;code&gt;apps&lt;/code&gt; and &lt;code&gt;libs&lt;/code&gt; directories as workspace packages.&lt;br&gt;&lt;br&gt;
More about it in the &lt;a href="https://pnpm.io/workspaces" rel="noopener noreferrer"&gt;pnpm workspace docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With &lt;a href="https://pnpm.io/" rel="noopener noreferrer"&gt;pnpm&lt;/a&gt;, you can manage workspaces and dependencies across all your projects in monorepo.&lt;br&gt;
A couple of basic commands:&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;# Add a dependency to all projects in the workspace&lt;/span&gt;
pnpm add &amp;lt;package-name&amp;gt; &lt;span class="nt"&gt;-w&lt;/span&gt;

&lt;span class="c"&gt;# Add a devDependency to all projects in the workspace&lt;/span&gt;
pnpm add &amp;lt;package-name&amp;gt; &lt;span class="nt"&gt;-Dw&lt;/span&gt;

&lt;span class="c"&gt;# Add a dependency to a specific project&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;apps/app_1
pnpm add &amp;lt;package-name&amp;gt;

&lt;span class="c"&gt;# Add a devDependency to a specific project&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;apps/app_1
pnpm add &amp;lt;package-name&amp;gt; &lt;span class="nt"&gt;-D&lt;/span&gt;

&lt;span class="c"&gt;# Update all dependencies in the workspace to their latest versions&lt;/span&gt;
pnpm update &lt;span class="nt"&gt;--latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster update of dependencies for many projects at once&lt;/li&gt;
&lt;li&gt;Less juggling with versions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires updating more projects at once if they are tied to the same dependency in the root directory. They can still be split but it's somehow contrary to the goal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Add direct connection of dependencies
&lt;/h3&gt;

&lt;p&gt;The workspaces are allowing us to manage external and internal dependencies way more easily. But what if I told you that you can directly use your other projects without even building them, not even mentioning publishing? With correct typescript configuration, you can even have types and intellisense still working. That is what you can achieve by connecting other of your libraries (previously packages) in your &lt;code&gt;package.json&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@monorepo/app_1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"module"&lt;/span&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="c1"&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;"dependencies"&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;"@monorepo/commons"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"workspace:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"@monorepo/ui"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"workspace:*"&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="c1"&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;Notice the asterisks instead of version numbers. These mean that we are using whatever version is the newest. In our case, it's always the local one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Always the current version (also while developing in branches)&lt;/li&gt;
&lt;li&gt;No need to publish libraries as packages and reinstall them&lt;/li&gt;
&lt;li&gt;No local linking required to try out new library versions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After a merge, dependencies might differ, potentially causing problems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This caveat can be mitigated with good test coverage and TypeScript running automatically through the complete codebase on the server before every build (which I highly recommend, regardless; ex. on the &lt;code&gt;dev&lt;/code&gt; branch). This can be easily automated with &lt;a href="https://typicode.github.io/husky/" rel="noopener noreferrer"&gt;husky&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you want to learn more about creation of monorepo with Vue, check out other tutorials in the series. If you prefer starting with a solid foundation - try this &lt;a href="https://github.com/Nagell/monorepo_template" rel="noopener noreferrer"&gt;template&lt;/a&gt;, where I’ve put all of this into practice.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>monorepo</category>
      <category>vue</category>
      <category>nx</category>
      <category>pnpm</category>
    </item>
  </channel>
</rss>
