How to use local-only dependencies in PNPM workspace - monorepo

I have a general PNPM question regarding Monorepos. Let me describe a simplified problem statement:
Monorepo contains two packages: foo#1.0.0 and bar#1.0.0
The foo package is a library which is published to NPM
The bar package is a private library which is not published to NPM. There is no need for it to be published since it will not be consumed by end-users
foo depends on bar
foo uses the Workspace protocol to link to bar, ie. "bar": "workspace: *"
Locally, everything runs great. But when I publish foo, bar will try to point to an external package on the NPM registry. What I want to happen is for bar to be bundled with foo. I have tried using bundledDependencies, but without any luck.
Any ideas on how this can be achieved? I could publish bar to NPM as a private package, but I would prefer not to.

Related

Forcing yarn to "refetch" a package

I have a project that uses a UIKit. The Main project and UI Kit is all in Typescript and React.
Both the main project and the uikit are hosted in git.
In the main project t have a dependency line for the UIKIT that fetches the repo from github.
All this works fine.
When I need to make changes to the uikit, I make change in the code, then run the build steps and upload to git (on a dev branch)
In the main project t then modify the dependency link for the project
I will change it from
"#something-libs/uikit": "somegit/someprojectuikit",
to this (add the branch name at the end)
"#something-libs/uikit": "somegit/someprojectuikit#dev",
this works fine and when I run yarn install, it fetches the latest version of the dependency.
Now, say I need to make another change? I do that and upload to git.
The changes are then not reflected in the main project because yarn is not fetching the latest version. As a work around y just change the link back to the old version without the #dev part, rerun yarn install and then change it back to "#something-libs/uikit": "somegit/someprojectuikit#dev" and rerun install again.
Any suggestions how i can tell yarn "hey, the package has changed, go fetch it again"
There are several options for how to solve this, the easiest one is to use the command
yarn upgrade {package_name}
In your case, the command will look like this:
yarn upgrade #something-libs/uikit
After running the upgrade command, you will get the latest commit from your github repository in node_modules/#something-libs/uikit

Create NPM Package with dependencies just for examples

I'm working on an NPM package right now.
The main code for the package (repo/src/maincode.js) has a few dev dependencies and a few dependencies needed to run it. When the user installs the npm package (through npm i) these dependencies will need be installed.
Now, that being said, I also want to create a react project that showcases this npm package, and have it live in the same repo, in an examples directory (repo/examples/react/app.js). This react app may have its own dependencies and dev dependencies, but I really don't want all of these to be forced onto the user when they're installing my npm package just to use in their projects.
How might I go about solving this problem? Is there a way to create a set of dependencies that are only installed if you are running a particular script, or running example code ?
You can give the examples directory its own package.json file and instruct folks who want to run the examples to cd into the examples directory and run npm i there. Any code in the examples directory that imports a module will look in its own node_modules before checking the node_modules in the parent directory.
The MarkoJS examples repository takes this approach and even makes it more granular. Instead of having a single package.json for the examples directory, there is a package.json for each separate example.
If you want, you can create a helper script in the main package.json for the user so they can do something like npm run build-examples and it will do the npm install for them as part of the process.

How to create a privately shared component library which can be used across multiple react projects

Following Scenario
Project 1 needs to use CustomButton.jsx
Project 2 needs to use CustomButton.jsx
Current Solution
Copy paste CustomButton.jsx into both Project 1 & 2.
Desired Solution
Create Project 3 which includes CustomButton.jsx
Store Project 3 in a shared environment (like a public company directory e.g. D://dev/react/my-component-library)
Install Project 3 via npm for Project 1 & 2 and add dependency to package.json to keep consistency accross git clones.
Import CustomButton.jsx with import statement in Project 1 & 2: import { CustomButton } from "my-component-library"
Questions
What kind of Project is Project 3? Is it build with create-react-app or which other tool can be used?
How can I create a local/private npm package out of Project 3?
How can I utilize a shared, local environment for that private package.
How can I use the package in Project 1 & 2?
The components are fairly simple and don't contain complex logic.
EDIT
This shouldn't cost me anything (private npm does) or use 3rd party hosting, since I already have a privately shared environment/server/directory and I can host/store the packages there.
I solved this problem in vue. But the steps should be pretty similar in react.
1. Create a project with your components (create-react-app should be fine. You will export your components only anyway, that's why the project setup is irrelevant. It is just useful for development and to test your components.)
2. Use rollup.js to bundle your react components (there are many tutorials online, just google "rollup react component library")
3. Add a new script to your package.json to bundle your app using rollup -c.
Then use npm pack to create the package.
"build:lib": "rollup -c && npm pack"
This will create a zipped package with only the files you need with following pattern:
[package-name]-[package-version].tgz e.g. my-react-components-0.1.0.tgz
You can influence the resulting package of npm pack by modifying attributes in your package.json, e.g. "version", "name", "main", "files" will influence the output.
4. Now you can install your packages locally from another project:
npm i ../path/to/library/my-react-components-0.1.0.tgz
This will add a new dependency to your package.json:
"my-react-components": "file: ../path/to/library/my-react-components-0.1.0.tgz"
5. Based on your rollup setup you can then use your library like any other library:
import { MyComponent } from "my-react-components";
You might also have to import the styles:
import "my-react-components/index.css"
If you need a more detailed explanation on a step, just comment below and I will add further information.
1. Project 3 is just like any npm packages (e.g. ui library) you install, you can build with create-react-app, or not to if you want. Simply export everything you want to share from that library and import them from your main project like when you use any library. You may publish it to npm like this, or use private repo like Nexus
2. For npm, you may check the tutorial I mentioned above. For Nexus, google and you may come up with something like this
3 & 4. After publishing your package, you can do npm install your-package in any of your project.
You have many options for that. You can do it by creating an org on npm (details here). Also, you can use bits n pieces (details here). You even can prefer something more simple like yarn workspaces (details here).

How to import a React component I've made locally without node_modules?

I built a react component (my-shared-component) that I would like to use with other projects locally. I used rollup to bundle my component and the output is a dist folder.
In order to avoid publishing my component to npm yet, I used npm link. However, when I do npm link <my-shared-component> in my host component, the entire shared component folder is added inside my node_modules, including my component's node_modules library, source files, etc - This causes several bugs in my host app.
Obviously I don't want to do, if I had published my component to npm and then used npm -i my-shared-component, only my dist folder would've been installed.
I can I mimic this behavior locally using npm-link? I want to use the packaged version of my-shared-component.
Thank you!
I ended up solving the case by using npm pack inside my my-shared-component and then npm i ../.../full-path/my-shared-component-1.0.0.tgz inside my host app.
That way I only get the packed bundled version of my-shared-component without the node_modules and source code.
This does mean that I have to pack my shared component every time which is not ideal. If anyone has any better solution please let me know.
Thanks

Using Private Repo NPM Package as Dependency With Source Files Needing Compilation

Can't find a good answer anywhere. We have a private Github repo that is an Angular module and the source needs to be built (concat, minified, etc.) and put in a dist file when consumed or installed as a dependency.
Notes:
dist is ignored, so it never resides on Github (tried tracking this, too many conflicts with several developers)
we are currently using a post install hook to build the dependency package source (this does NOT seem like the right thing to do, also forces the project consuming the dependency package to have the necessary build dependencies)
Q What is the right way (or the common ways) to build a private repo npm package dependency, resulting in a dist folder with the proper built files?

Resources