<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Monorepo | Nerdpress.org</title>
	<atom:link href="https://nerdpress.org/tag/monorepo/feed/" rel="self" type="application/rss+xml" />
	<link>https://nerdpress.org</link>
	<description>...dev, tech problems and solutions.</description>
	<lastBuildDate>Fri, 12 Apr 2024 08:01:50 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>Monorepo with NPM workspaces</title>
		<link>https://nerdpress.org/2024/04/12/monorepo-with-npm-workspaces/</link>
		
		<dc:creator><![CDATA[Ivo Bathke]]></dc:creator>
		<pubDate>Fri, 12 Apr 2024 08:01:50 +0000</pubDate>
				<category><![CDATA[JS]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[NPM]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Monorepo]]></category>
		<category><![CDATA[nodejs]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=3300</guid>

					<description><![CDATA[<p>I recently converted a project into a Monorepo.I had a cli part and an Astro StaticSiteGenerator part. At some point I felt like these parts would be entangled too much so I decided to separate them. Since they were still related they should stay in one repo but have their own dependencies and separate processes. &#8230; </p>
<p class="link-more"><a href="https://nerdpress.org/2024/04/12/monorepo-with-npm-workspaces/" class="more-link">Continue reading<span class="screen-reader-text"> "Monorepo with NPM workspaces"</span></a></p>
The post <a href="https://nerdpress.org/2024/04/12/monorepo-with-npm-workspaces/">Monorepo with NPM workspaces</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>I recently converted a project into a Monorepo.<br />I had a cli part and an Astro StaticSiteGenerator part. <br />At some point I felt like these parts would be entangled too much so I decided to separate them. Since they were still related they should stay in one repo but have their own dependencies and separate processes. I still could have kept this in one Astro project with a cli folder but so it feels cleaner structured.</p>



<p>I chose NPM as my package manager since it comes bundled with node and so I decided to try out <a href="https://docs.npmjs.com/cli/v7/using-npm/workspaces" title="">NPM workspaces</a> as my MonoRepo approach.</p>



<p>So here are my takeaways</p>



<span id="more-3300"></span>



<p><strong>1.  Setup</strong></p>



<ul class="wp-block-list">
<li>The NPM workspaces Monorepo has one root dir with one package.json which defines the workspaces, but besides this it is more or less empty. The package.json defines a workspace directory which contains the sub projects. <br />As of now you can&#8217;t use <code>npm init</code> for this but have to create the main package.json manually.</li>
</ul>


<pre class="wp-block-code"><span><code class="hljs language-javascript">  <span class="hljs-string">"name"</span>: <span class="hljs-string">"workspaces-example"</span>,
  <span class="hljs-string">"workspaces"</span>: &#91;
    <span class="hljs-string">"packages/*"</span>
  ],</code></span></pre>


<figure class="wp-block-image size-full"><a href="https://nerdpress.org/wp-content/uploads/2024/04/npm-workspaces-directories.png"><img fetchpriority="high" decoding="async" width="258" height="210" src="https://nerdpress.org/wp-content/uploads/2024/04/npm-workspaces-directories.png" alt="" class="wp-image-3303"/></a></figure>



<ul class="wp-block-list">
<li>The sub projects each have their own package.json with all necessary dependencies for this specific project. The sub projects can be initialised by <code>npm init -w packages/cli</code></li>



<li>To add dependencies you can add the workspace to the <code>npm add</code> command and the dependency will be added to the respective package.json:<br /><code>npm add commander -w packages/cli</code><br />To install dependencies, run <code>npm i</code> from the root directory. This will install all deps of all workspaces in a node_modules folder in the root directory, but none in the projects in the workspaces folder. This already is a win because it will avoid having dependency duplettes.<br />However if you have conflicting versions of the same dependency in your packages, you will have a separate node_modules directory with the only the specific version for this single package.</li>
</ul>



<figure class="wp-block-image size-full"><a href="https://nerdpress.org/wp-content/uploads/2024/04/npm-workspaces-conflicting-versions-directories-1.png"><img decoding="async" width="272" height="354" src="https://nerdpress.org/wp-content/uploads/2024/04/npm-workspaces-conflicting-versions-directories-1.png" alt="" class="wp-image-3306" srcset="https://nerdpress.org/wp-content/uploads/2024/04/npm-workspaces-conflicting-versions-directories-1.png 272w, https://nerdpress.org/wp-content/uploads/2024/04/npm-workspaces-conflicting-versions-directories-1-231x300.png 231w" sizes="(max-width: 272px) 100vw, 272px" /></a></figure>



<p><br /><strong>2. Development</strong></p>



<ul class="wp-block-list">
<li>Updating dependencies can happen just like adding dependencies:<br /><kbd>npm update commander -w packages/cli</kbd></li>



<li>When you need different versions of a dependency in your workspaces, NPM will create a new node_modules folder in the one divergating workspace with only the dependency where you have the different version.</li>



<li>When you need to share code between workspaces you can import code from one package of the workspaces in another package just as a normal dependency from the NPM registry. <br />For example when you want to share types in a typescript project you can add a types workspace and just import in the other workspaces files. <br /><code>import {Name} from "types";</code></li>



<li>It is probably good practice to add shortcut scripts to your main package.json to run commands of your workspaces. So you don&#8217;t need to change to the workspaces directory, which is of course still possible.</li>
</ul>


<pre class="wp-block-code"><span><code class="hljs language-javascript">  <span class="hljs-string">"scripts"</span>: {
    <span class="hljs-string">"hello-cli"</span>: <span class="hljs-string">"npm --workspace=@workspaces-example/cli run hello"</span>,
    <span class="hljs-string">"hello-web"</span>: <span class="hljs-string">"npm --workspace=@workspaces-example/web run hello"</span>
  }
</code></span></pre>


<p><strong>3. Deploy</strong></p>



<ul class="wp-block-list">
<li>Deploying from a Monrepo needs to take the different packages into account, which need to be deployed separately but from the same CI config. <br />For Github Actions i used a path directive which changes to the package directory and runs instructions there. <br /><code>with: <br />  path: packages/astro</code></li>



<li>Other prefabricated actions like f.e. <kbd>actions/deploy-pages</kbd> have a <br /><kbd>working-directory: ./packages/astro</kbd> <br />directive which have the same effect.</li>
</ul>



<p>You can check out the example project here: <a href="https://github.com/ivoba/npm-workspaces-example" target="_blank" rel="noopener" title="">https://github.com/ivoba/npm-workspaces-example</a></p>



<p>One probably does not necessarily need a Monorepo for this example, but it is good to know that Monorepos are quite simple to achieve just with NPM, in case you need to.</p>The post <a href="https://nerdpress.org/2024/04/12/monorepo-with-npm-workspaces/">Monorepo with NPM workspaces</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
