Now that we have in place all needed packages (libs and apps) and established connections between them, we have to take care of required configs like vite.config.ts
, .eslint.cjs
and postcss.config.cjs
. We could add all of them multiple times, but as we have monorepo let's use it to our advantage.
You can create a global configs
directory in the root of monorepo and add all common configs there, like: vite.application.ts
, vite.service.ts
, etc.
Later you can import them into apps and libs in the config files and refine them with some overwrites. Of course the overwriting or rather merging step can be a bit problematic. Luckily there are already tested solutions out there like this nice merge function made by John Hildenbiddle - link
Merge sample - useful for vite config objects
export default merge
/**
* Recursively merges the specified object instances
* @param instances Instances to merge, from left to right
*/
function merge(...instances) {
let i = instances.length - 1
while (i > 0) {
instances[i - 1] = mergeWith(instances[i - 1], instances[i])
i--
}
return instances[0]
}
/**
* Merge an instance with another one
* @param target Object to merge the custom values into
* @param source Object with custom values
* @author inspired by [jhildenbiddle](https://stackoverflow.com/a/48218209).
*/
function mergeWith(target, source) {
const isObject = obj => obj && typeof obj === 'object'
if (isObject(target) && isObject(source)) {
Object.keys(source).forEach((key) => {
const targetValue = target[key]
const sourceValue = source[key]
if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
target[key] = targetValue.concat(sourceValue)
}
else if (isObject(targetValue) && isObject(sourceValue)) {
target[key] = merge(Object.assign({}, targetValue), sourceValue)
}
else {
target[key] = sourceValue
}
})
}
return target
}
Check out the implementation in the sample repo. Usage sample can be found in the app.
Eslint, postcss, etc
The same applies to other repeatable configs like eslint
. No matter if you are using the old syntax (8.x.x) or the newer one using export default
(9.x.x) - you can still add a bunch of custom configs like I did here to import them as needed in the apps and libs (sample)
Generally speaking, in monorepo you can make your life easier by reusing many common configs by sharing them. After a bit of initial cost, adding yet another app or lib will be much easier.
If you want to know more about creating a monorepo check out other tutorials in the series. If you prefer testing things on your own - try this template, where I put all of this into work.
In the next one, we will talk about builds and parallelization through Nx. Stay tuned ;)
Top comments (0)