title: Creating a usable library on npm... with yarn workspaces
body: <p><strong>I'm looking for feedback on a pattern I coded</strong> while tinkering around.</p>
  <h3>Context</h3>
  <p>I'm creating a package for my company, which going to be released publicly. The DX (Developer Experience) is the most important thing for us, and for such I'm picking the latest trends in dev: Typescript, esm, etc... I want to propose multiple modules and make the import easy to use, similar to (for example) nextjs's <code>next/Router</code>.</p>
  <p><strong>[EDIT]</strong> I found about <a href="https://stackoverflow.com/questions/49858168/how-to-publish-typescript-modules-on-npm-without-dist-in-import">this thread</a> and cross-referenced for exposure.</p>
  <h3>First steps</h3>
  <p>I started my first attempt with a simple single package, tsconfig and src/, tests/ and dist/ folder. Nothing incredibly exotic there, but if you've been doing that, you know that publishing this will result in your import paths to contain <code>dist</code> later on.</p>
  <p>You <em>can</em> fix this by using package.json's <code>main</code> field, but that'd do only for the top-level module; you could use <code>exports</code>, but it doesn't work well with Typescript. The easiest fix is to <code>cp package.json dist/ &amp;&amp; npm publish dist/</code>, and here you go, problem solved.</p>
  <p>Then I thought that to test this, I'd be <code>npm link</code> my dist/ folder, virtually creating &quot;a package in package&quot; with few problems:</p>
  <ul>
  <li>the <code>cp package.json dist/</code> part would grow to have <code>*.md</code>, and who knows what else/how it'd grow (and I'd like not to have build script files)</li>
  <li>I'd still have to build a test app to test my library on the DX level, and where to host it?</li>
  </ul>
  <p>So I thought: why not elevate it all to be a monorepo?</p>
  <h3>Turning point</h3>
  <p>The tree structure would move from:</p>
  <pre><code>myLib/
    package.json → build + test + publish script
    tsconfig.json
    jest.config.json
    .npmignore → managing what to distribute
    ...lots of config files
    src/
    dist/
    tests/
  </code></pre>
  <p>to:</p>
  <pre><code>myLib/
    package.json → workspaces
    src-pkg/
      package.json → build script
      tsconfig.json → localized conf for build
    dist-pkg/
      package.json → publish script
    test-pkg/
      package.json → test script
      jest.config.json → localized conf for test
  </code></pre>
  <p>To pass the built files from <code>src-pkg</code> to <code>dist-pkg</code>, i only need to point the folder in tsc (<code>tsc --project . --outDir ../dist-pkg</code>)</p>
  <p>It's even possible to restore the same flow as in a single package by orchestrating workspaces command in npm scripts on the top level, such as:</p>
  <pre><code>{
    &quot;workspaces&quot;: [&quot;src-pkg&quot;, &quot;test-pkg&quot;, &quot;dist-pkg&quot;],
    &quot;scripts&quot;: {
      &quot;build&quot;: &quot;yarn workspace src-pkg run build&quot;,
      &quot;test&quot;: &quot;yarn workspace test-pkg run test&quot;,
      &quot;publish&quot;: &quot;yarn workspace dist-pkg run publish&quot;
    }
  }
  </code></pre>
  <h3>Stepping back</h3>
  <p><strong>The perks</strong> of this structure is mostly in the test-pkg. It can easily test src-pkg or dist-pkg at will, since both of the structures are meant to be flat and similar. so that, the workflow can be tested before the build, or after.</p>
  <p>Also (and this is my main area of interest), <em>by being outside of the src-pkg the test-pkg has the PoV of a consumer of my library</em> (Typescript context and all) - especially if using the dist-pkg as dependency - and so I can work efficiently on the developer experience exactly as if I was my future customers.</p>
  <p>There are small other things, notably the stability of expansion by using a monorepo, or also that I can provide a separated &quot;public friendly&quot; readme in the dist-pkg while having more internals/private details in the src-pkg manifests.</p>
  <p><strong>The drawbacks</strong> are notably the management of semver (src-pkg and dist-pkg being separated) and also that it's a structure I've never seen before... and it feels a bit like a misuse of the monorepo structure.</p>
  <hr />
  <p>So, I've built it and it works... but even if it's possible to build doesn't mean it should be.</p>
  <p>People building libraries and SDKs, what do y'all think?</p>
  <p>Thanks for your feedback.</p>