We are your Digital Ally™
JS Code Sharing Tactics
tech

JS Code Sharing Tactics

Developers constantly seek to avoid repeating themselves. Here are three practical strategies for sharing JavaScript code across multiple projects, with honest trade-offs for each approach.

Stanislav MiklikJune 11, 2021

Developers constantly seek to follow the DRY (Don't Repeat Yourself) principle by extracting utility functions and creating reusable UI components. While refactoring code within a single project is straightforward, sharing code between separate projects presents distinct challenges that require different approaches.

Tactic 1: Via File System

Approach: Store shared code in a common directory accessible to multiple projects.

A typical directory structure looks like this:

server/
  …
src/
  common/
    …
  … other client folders or files

Advantages

  • Minimal setup requirements
  • Direct visibility of changes enables quick developer feedback
  • Straightforward debugging

Disadvantages

  • No versioning — breaking changes affect all dependent projects simultaneously
  • Poor scalability beyond a few projects
  • Shared code is limited to language features common across all projects
  • Works only with mono-repo structures

Tactic 2: Git Submodules

Approach: Leverage Git's submodule feature to compose multiple repositories, mimicking mono-repo structure while allowing different branches for version control.

Advantages

  • Enables independent versioning across dependent projects
  • Improves scalability compared to the file system approach

Disadvantages

  • Error-prone for developers; requires special commands for cloning and updates
  • Managing multiple branches adds complexity

Tactic 3: Npm Packages

Approach: Use npm as a standard distribution mechanism for shared JavaScript code, supporting both internal team sharing and external distribution.

Package design considerations: Group code by semantic cohesion rather than line count. Utility collections benefit from tree-shaking, which prevents bundle bloat when importing individual functions.

Advantages

  • Explicit semantic versioning simplifies dependency management
  • Enables heterogeneity through transpilation during publishing
  • Functions effectively in both mono-repo and multi-repo environments

Disadvantages

  • Requires more complex setup, including potential private registry configuration
  • Creates separation between the package and dependent code, complicating simultaneous changes
  • Debugging across package boundaries becomes cumbersome with transpilation

Mitigation Strategies

  • Use Storybook for isolated package development
  • Employ yarn link / npm link or Lerna for concurrent refactoring across packages

Conclusion

For most scenarios, the decision comes down to the file system approach versus npm packages. If you are unsure which to choose, start with file system sharing — use absolute imports and central re-exports to keep imports tidy. This foundation makes it easy to migrate to npm packages when the need becomes clear, requiring only minimal import modifications.

© 2026