Sharing configs in multi module javascript project - javascript

Let's say we have a project with lots of sub-packages:
👩‍🍳 project root
🍔sup package a
package.json
tsconfig.json
webpack.config.js
🍟 sub package b
package.json
tsconfig.json
webpack.config.js
This kind of structure most likely contains lots of redundancies, in both, settings and dependencies. I would like to have a way to manage these common settings and dependencies in a centralized way.
For example:
If a new sup package 🌮 is added, it would be nice, if common settings could be inherited from some kind of a centralized setting-thingy
If the version of a dependency, that is used in several sub packages, is changed, I would like to have a way to change the version at some central point, so that all sub packages "see" the new version.
I would like to change a property in all tsconfig.json's in one step, instead of editing all tsconfig.json's manually.
🤩In essence, I want to apply the DRY-principle to a project configuration.
I looked into npm workspaces, lerna, yarn, webpack, but didn't find anything that would do all of that. How could this be achieved?
🙄In Java, I would come close to this using Maven. There I could at least manage the versions of my dependencies in a central config. Isn't there something like that in the JavaScript universe?

Related

Must i specify dependencies in package json file

I just recently heard of the package.json file but all my small projects have always worked without it.
I've installed many npm modules globally and always use var x = require("express");"just for example" without even initializing the package.json and putting express as a dependency.
Is it really important
First of all, I strongly doubt require("express") will work out of the box without having the express package installed in your project's node_modules folder, but just globally. There are ways to accomplish this, though.
But even if you accomplished to require packages from the global installation folder, what happens if you have multiple packages requiring different versions of the same package? There may be breaking changes between major versions of packages. So if you install a new version of package xy globally, older projects of yours expecting a different version of package xy may stop working.
On just your local machine, you can achieve all that, still without a package.json though.
The main purpose of the package.json comes clear, when you want to share your project with other people. Aside from some basic information (like a package name and some description), it will also list the dependencies which need to be installed for the project to be runable. While the necessary dependencies may exist on your machine, how will you make sure, they are also installed on a different machine without having them listed somewhere? And the place for listing the dependencies of a package is -- surprise surprise --- the package.json file ...
They are global, not in your project so when you do the deploy, you will must have to install all global for each server.
Yuu can install packages-cli global, but project dependencies ( also dev on dev dependencies) is better have its own package.json so you can deploy.
Also if you share your project, how someone will know what packages is needed.
The better is to have for each project its own package.json on its root folder, even if you always use the same libs.

Best way to handle an npm packages dependencies?

I am trying to breakout a couple of Vue.js components from a primary application into an npm package stored on a repository. This package can then be imported and used across two separate sites. I am using Webpack to bundle everything but have had a few queries about the layout that should be used.
Seeing that things like Vue.js and Vuex will installed as dependencies on the main application, I know that the package will have access to these once installed on the two main applications.
My primary confusion is how do I deal with dependencies that belong to the package only, do I bundle this as part of the webpack and will running npm install on the applications automatically install the 'dependencies dependencies' if you will? Is there a general standard for these things?
The simplest thing to do is list them in your dependencies section in package.json. The package manager tool you're using (usually either npm or 'yarn`) will take responsibility for deduping the dependences, so if your parent app and your subproject both have the same dependencies, you'll only end up with one copy in the final bundle.
I would strongly suggest that you be looser on version numbers in the component projects then you are in the parent project. So in the parent maybe you say the dependency is "vue": "1.2.3" and in the component project it's "vue": "^1.1.0" or something along those lines. This way the parent can control the specific versions and your component picks up the actual version from the parent.

Can I review which node_modules I need?

Is there a way to review which node_modules packages are used in my create-react-app project and delete modules which are not in use? Other than manually reviewing all used packages and their dependencies?
I'd like to reduce the amount of space used up by the project. It's committed to a resources repository, and the node_modules folder alone triples the space used.
For repo size (assuming you're using git):
git rm -r --cached ./node_modules
Add the line /node_modules to your .gitignore file
git add .
git commit -m "Remove node_modules from repo"
For build size:
create-react-app is pretty good at tree shaking, so you shouldn't need to worry too much about this. Certain packages may have more modular ways of importing, which can help - usually these will be documented on a package-by-package basis. For example, Material UI icons supports two import syntaxes:
// option 1
import AccessAlarmIcon from '#material-ui/icons/AccessAlarm'
import ThreeDRotation from '#material-ui/icons/ThreeDRotation'
// option 2
import { AccessAlarm, ThreeDRotation } from '#material-ui/icons'
Of these, option 1 is likely to yield the smallest bundle size.
For size on your development machine:
The biggest difference you can make here (assuming you have other projects) is probably switching to something like pnpm, which stores node_modules centrally on your local machine and then links out to them from your project, rather than having many instances of identical modules.
For general housekeeping and tidiness:
You could try using a tool such as depcheck to detect unused dependencies. This is probably overkill, though, unless it's a particular pain point for your project.
Probably the easiest way is not to include the node modules by adding it to the gitignore file (or creating one), but if that's not an option, probably just unsintall the unneeded packages

Sharing config/dot files as a package?

In the npm ecosystem it is becoming a common practice to configure various libraries using either dotfiles, package.json entries, or *.config.js files.
In order to establish common practices across different projects in our organization, I would like to be able to provide defaults for these configs (eslint, babel, vue, npmrc, editorconfig, jest.config, postcss.config, etc?) as a package that can be installed using npm and affect projects using it.
I can't just add those files in a dependency, but I could write a command to copy a group of files to the root of a repository. I'm wondering if there are standard/accepted ways of approaching this problem.

Publish NPM package with only non-bundled dependencies

Lets say we're developing a small javascript library L.
The code is in ES6. To use some utility function, like debounce, we install lodash as a dependency.
At build the webpack transpiles the code, bundling the tree shaked lodash code, and we end up with a nice little javascript file we want to publish and share as a npm package.
Now, the package.json file lists lodash as a dependency. But that is only true at build time, it is not really needed in production.
What's the proper way to handle this kind of situation?
Does it make sense to consider lodash a devDependency? As such, only webpack's externals would be "real" dependencies?
Or should we somehow tamper the package.json file before publishing it?
Do you know any real examples of projects handling this question?
Webpack "merges" the code of the project with that of the used code of the non-external dependencies into some bundle.js file. This file is then published to NPM, along with a package.json file, which lists all of the dependencies, independently of these being external or embedded.
All of the code of packages referenced in dependencies (or optionalDependencies, or peerDependencies) is expected to be "production" code.
While code in devDependencies is expected to be used only at "development" time, and is thus "development" code. Under this principle, I believe that it would be incorrect to declare non-external dependencies as development dependencies.
However, if all dependencies, embedded or external, are declared equally in the published package.json file, there is no way for a runtime environment to know which are the real dependencies that need to be made available to the package — the ones that the package will import at runtime and which better be available.
For the Node.js environment, bundles and Webpack are not normally used, so this never came to be an issue — all dependencies are always installed (never merged/bundled).
However, if you use the package.json file to drive some web-packages runtime environment, the way that dependencies are currently included in published package.json is not suitable.
You might want to take a look at Pika Web's devDependencies package.json property, which aims to solve a comparable problem (even though their mojo is "a future without Webpack"). They also introduce the concept of publishing a different package.json file than that which is checked-in (tampering the package.json before publishing, as you say).
Interestingly, it looks like a related tool, Pika Pack, caught the attention of NPM folks and is being considered to become part of NPM. So, maybe, NPM has become aware of the specific package format needs of web projects' workflows.

Categories