When relaunching Snitt, I noticed a lot of code duplication across projects. Custom landing pages for each app isn't a priority, and neither is using a different tech stack for each one, as that would lead to a maintenance nightmare and slow down development. I've settled on a reliable tech stack with Expo (React Native) & Next.js for now. This allows me to focus on solving real problems and shipping new apps quickly, rather than reimplementing the same code or dealing with the hassle of maintaining duplicates in multiple places.
To streamline my workflow and reduce code duplication, I've consolidated all company projects into a single monorepo. Currently, this setup includes Fast Rhymes, Snitt, and the company landing page. These projects share a lot in common, though each has unique complexities and services. All web projects are built with Next.js, while mobile projects use Expo (React Native). Within the monorepo, each project is scoped separately under "apps," while a shared package directory—still in its early stages—contains common constants and will eventually host more reusable components and utilities.
Since all web projects are deployed to Vercel, it was natural to choose Turborepo. With its remote caching, builds are nicely optimized. Which not only speeds up our CI/CD pipeline, but also improves the local development experience, since the cache is shared.
One of the key benefits of using a monorepo is the effortless sharing of code across projects. By placing common components, utilities, and configurations in shared packages, It significantly reduces duplication and maintains consistency. This approach not only streamlines development but also enhances code quality across all projects, ultimately leading to faster delivery and more efficient workflows.
Adopting a monorepo approach comes with its own set of challenges. The increased complexity of the build system and potential for conflicts between projects can sometimes lead to unexpected issues. You need to invest time in properly structuring your monorepo and establishing clear guidelines for code organization and dependency management. Having conflicting React and React Native versions can be a challenge. So be prepared to play “whac-a-mole” with some weird errors.
While adopting Turborepo, I encountered a breaking change in a minor release, which was a bit concerning. However, I guess that's expected with tools built by Vercel nowadays unfortunately.
Another issue I faced was with trying to use pnpm. React Native didn't seem to like the dependency hosting of pnpm no matter what hoisting settings I tried to use, so sticking with yarn for now is ideal for monorepos with React Native projects.
Despite the challenges, adopting a monorepo approach for code sharing has proven to be a good strategy. The benefits of code reusability, consistency across projects, and improved development efficiency allows for shipping quality apps a lot faster.
Andor Davoti - 08/10/2024