Introduction
In the world of software development, code reusability is paramount. However, code often becomes tightly coupled with a specific application, making it difficult to reuse in other projects. This blog post explores various code sharing strategies specifically tailored for large JavaScript projects involving multiple applications and frameworks, like Angular, Vue, and Node.js backends. We'll delve into project structure, shared libraries, and version control, providing a comprehensive guide to efficient code sharing.
Setting Up a Multi-App Project
Imagine a project with three distinct applications: a customer-facing Angular app, an admin interface built with Vue, and a Node.js backend powered by Cloud Functions. The first step involves creating each of these applications within a parent directory. Using tools like Angular CLI (`ng new`), Vue CLI, and Firebase CLI, we can initialize these applications. It's important to note that each app, including the Cloud Functions directory, comes with its own `package.json` file, signifying a separate Node.js project. Firebase can then be initialized in the root directory, allowing orchestration of deployments for the frontend apps and backend functions.
Mono Repo vs. Multi-Repo: Choosing the Right Structure
Once the multi-app project is set up, a crucial decision arises: Should you adopt a mono repo or maintain multiple repositories? A mono repo consolidates all projects into a single Git repository. This approach promotes code synchronization across apps, simplifies pull request management, and ensures consistent versioning, as seen in large projects like Angular. Tools like Lerna and NX are designed to streamline mono repo management. However, mono repos can reduce flexibility, making individual app testing and deployment more complex. The multi-repo approach, conversely, offers greater flexibility, enabling independent teams to work with preferred tooling and practices. Smaller teams or independent developers often benefit from this approach.
Code Reusability with Shared Libraries
Regardless of the chosen repository structure, code reuse can be achieved through shared libraries. Create a new directory, for example, named "Shared Stuff," and initialize an npm package using `npm init`. This library will house code intended to be shared between projects. An `index.ts` file serves as the main entry point, and the `package.json` file should be configured to include the `types` property, pointing to `index.d.ts` to allow for the TypeScript definitions to be created when building the package. Shared interfaces and business logic can then be defined within this library. For example:
// Shared Stuff/index.ts
export interface User {
id: string;
name: string;
email: string;
}
export function createID(): string {
return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
}
A build script needs to be added to the `package.json` to allow the library to be packaged. This can be achieved with the following:
// Shared Stuff/package.json
"scripts": {
"build": "tsc index.ts -d"
}
This can then be built from the command line with `npm run build`. To use the shared library, install it as a dependency in the desired app using `npm install` with the path to the shared library. The shared library can be installed locally, or from a remote npm organization, if you company has one set up. Import and utilize the shared code just like any other npm package. For example, in the Angular app:
// Angular App/src/app/app.component.ts
import { Component } from '@angular/core';
import { createID } from 'shared-stuff';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = createID();
}
Version Control and Submodules
The root project directory, containing configuration files for Firebase deployments, should also be placed under version control by initializing a Git repository using `git init` and adding and committing the changes with `git add` and `git commit`. Nested Git repositories (the individual apps) are treated as submodules. While submodules can be complex, in a multi-repo context, they serve as placeholders representing the project structure. Each app remains an independent, manageable project.
Conclusion
Efficient code sharing is crucial for large JavaScript projects involving multiple applications. Choosing between mono repos and multi-repos depends on team size, project complexity, and desired flexibility. Shared libraries provide a reliable way to reuse code and interfaces across projects, improving maintainability and development speed. Finally, incorporating version control for the entire project, while understanding the implications of submodules, ensures proper management and collaboration. By implementing these strategies, developers can build scalable and maintainable JavaScript applications.
Keywords
- Code Sharing
- JavaScript Projects
- Mono Repo
- Multi Repo
- Shared Libraries
0 Comments