Skip to main content

Syncing Extensions, Plugins, and Modules

Learning Focus

By the end of this module, you will be able to synchronize modular application components (plugins, themes, scripts) while avoiding the common traps of syncing bloated dependency directories.

Modular Application Structure

Most modern systems rely on a modular architecture where the core logic is extended by plugins, themes, or modules. These components are often the most frequently changed parts of an application.

/app/
├── modules/ ← Custom business logic modules (sync these)
├── plugins/ ← Third-party extensions
├── themes/ ← UI and presentation layers
├── vendor/ ← PERSISTENT dependencies (handle with care)
└── scripts/ ← Deployment and maintenance scripts

Syncing Custom Components

Deploying a Specific Module or Theme

When you've only modified one part of the system, it's faster and safer to sync only that directory.

Syncing a single custom theme
rsync -avz --exclude='.git/' --exclude='node_modules/' \
/local/dev/themes/my-custom-ui/ \
user@production:/var/www/app/themes/my-custom-ui/

Syncing All Plugins/Extensions

Use this when you need to mirror the entire extension ecosystem from staging to production.

Mirroring plugins
rsync -avz --delete \
/staging/app/plugins/ \
user@production:/var/www/app/plugins/
warning

The --delete flag will remove any plugins from the destination that aren't present on the source. Always use --dry-run (-n) first to verify what will be removed.


Managing Dependencies (Vendor and node_modules)

Dependency directories are unique because they are usually managed by tools (npm, composer, pip) rather than manually edited.

The Problem with Syncing Dependencies

  1. Size: These directories can contain tens of thousands of small files, making rsync indexing very slow.
  2. Platform Specifics: Compiled binaries (like bcrypt or sharp in Node.js) may not work if the source and destination OS/architecture differ.
  3. Environment Flux: Syncing these can lead to version mismatches between the code and its dependencies.

The Correct Strategy

Avoid syncing these directories. Instead, sync the lockfiles and rebuild on the destination.

ActionCommand
Syncingrsync -av package.json package-lock.json user@remote:/app/
Rebuildingssh user@remote "cd /app && npm ci --production"

Deployment Exclusions

When syncing code components, always exclude files that add bulk or expose environment metadata.

Professional sync with comprehensive exclusions
rsync -avz \
--exclude='.git/' \
--exclude='.github/' \
--exclude='node_modules/' \
--exclude='src/tests/' \
--exclude='*.log' \
--exclude='.DS_Store' \
/local/app/modules/ user@remote:/var/www/app/modules/
Exclusion PatternReason
.git/Version history is for development; adds massive bulk to transfers.
node_modules/Rebuild on the server to ensure platform compatibility.
*.logLogs are unique to the local environment and clutter production.
tests/Unit tests aren't usually needed for execution in production.

Real-World Comparison

FrameworkExtension DirectorySync Best Practice
WordPresswp-content/plugins/Sync custom plugins; exclude cache.
Laravelpackages/Sync local packages; use Composer for vendor/.
Drupalmodules/custom/Always sync custom/ separately from contrib/.
Express.jsroutes/ or controllers/Sync all source; rebuild node_modules/.
Magentoapp/code/Sync custom extensions; ignore generated/ and pub/static/.

Common Pitfalls

PitfallConsequencePrevention
Syncing .gitDramatically slows down sync and exposes repo history on the server.Add --exclude='.git/'.
Overwriting with --deleteAccidental deletion of production-only extensions.Always verify with --dry-run first.
Mixing build artifactsDeploying unminified or dev-only assets.Sync from a dist/ or build/ folder if available.
Permission DriftModules fail to load due to wrong ownership.Run chown after sync to match the web user.

What's Next