7

Using NPM Workspaces, I'm sharing one package (components) with others (webapp1 and webapp2). Something like this:

root
  apps   
    webapp1
    webapp2
  packages
    components

Everything is working well, but everything inside components, include source code in the src folder is being shared. Since components' compiled output folder is dist, I'd like to only share that folder. This is how it looks in the root node_modules:

enter image description here

The problem is that when I need to import in webapp1 or webapp2, my import path has to include the dist folder. Here's the intellisense that I get from VS Code:

enter image description here

And this is how I import in webapp1 and webapp2:

import Center from '@mycompany/components/dist/Center'

While everything works, how can I set up my NPM Workspaces so that only the contents of the dist folder is shared in its root?

I've tried NPM's files and .npmignore inside the components folder to ignore everything except for the dist folder, but that doesn't seem to work. The main property in package.json for components is also set to point to dist/index.js:

"main": "dist/index.js"

Interestingly, if I want to import dist/index.js file, I can do it without dist:

import foo from '@mycompany/components'

...however, importing anything other than dist/index.js requires dist to be included in the path.

Johnny Oshika
  • 54,741
  • 40
  • 181
  • 275
  • Very interested to see what answers you get! I tried workspaces today (npm 7.7.5) and was disappointed to realise they don't seem to offer access restrictions. – akauppi Mar 28 '21 at 19:20
  • @akauppi Can you elaborate on what you mean by access restriction? NPM Workspaces is very new and missing a lot of features, but with a bunch of manually created npm scripts inside package.json, I've made it work well for my workflow. – Johnny Oshika Mar 28 '21 at 23:53
  • I probably meant encapsulation. That a sub package would be seen only by its `files` exposed, not everything in the source directory. Now (npm 7.7.5), it looks like a symbolic link to all of the sub package contents. Before, I was using `file:` links and continue doing that since I wasn't able to figure out the benefit workspaces provide. – akauppi Apr 01 '21 at 06:26
  • I think you wrote it better than me: "but everything inside components, include source code in the src folder is being shared. Since components' compiled output folder is dist, I'd like to only share that folder." Same thing I'd like to see. – akauppi Apr 10 '21 at 21:37

2 Answers2

1

You should treat the packages folder as a collection of dist folders in your use case.

In this scenario, you would move your packages/components/src folder somewhere else in your project and then build to packages/components instead of packages/components/dist

root
  apps   
    webapp1
    webapp2
  packages
    components
  src
    components

I have a similar setup in this tooling monorepo I created

nickstaroba
  • 310
  • 1
  • 12
  • 1
    Interesting, can you share what `components`' package.json would look like to point to build folder? Would `main` in package.json be something like `.../../packages/components/index.js`? – Johnny Oshika Aug 16 '21 at 16:39
  • `packages/components/package.json` should be the same as the original `src/components/dist/package.json`. Whatever those settings were... In a library I built which outputs CommonJS and ES Modules, the relevant entries in package.json were: `"main": "index.js"` and `"module": "index.esm.js"` – nickstaroba Aug 17 '21 at 17:10
  • 1
    Works like a charm! – Johnny Oshika Nov 22 '21 at 22:19
1

An alternative to @nicksaroba's approach, if you don't want to restructure your project layout, you can just setup an alias:

// apps/webapp/webpack.config.js

module.exports = {
    // ...
    resolve: {
        alias: {
            "components": "@mycompany/components/dist/"
        }
    },
    // ...
};

pureth
  • 680
  • 6
  • 9