npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

serverless-plugin-artifact-manager

v1.0.6

Published

A serverless plugin that dynamically manages artifactDirectoryName to ensure CloudFormation detects code changes

Readme

Serverless Artifact Directory Manager Plugin

A Serverless Framework plugin that dynamically manages artifactDirectoryName to ensure CloudFormation properly detects Lambda code changes.

🎯 Purpose

When deploying Lambda functions, CloudFormation uses the artifactDirectoryName to determine if there have been code changes. If this path doesn't change between deployments, CloudFormation assumes no code changes occurred and skips the Lambda update - even if your code has actually changed.

This plugin solves that problem by:

  • ✅ Generating unique artifact directory names for each deployment
  • ✅ Ensuring CloudFormation always detects code changes
  • ✅ Supporting multiple naming strategies (timestamp, hash, hybrid)
  • ✅ Providing variable resolvers for flexible configuration

📦 Installation

npm install --save-dev serverless-plugin-artifact-directory-manager

🚀 Usage

Basic Usage

Add the plugin to your serverless.yml:

plugins:
  - serverless-plugin-artifact-directory-manager

package:
  excludeDevDependencies: false
  individually: ${env:SERVERLESS_WEBPACK_INDIVIDUALLY, false}
  artifactDirectoryName: ${artifactDir:fullPath}
  patterns:
    - "!.vscode/**"
    - "!.test/**"
    - "!./logo.png"
    - "!node_modules/**"

Advanced Usage

Configure the plugin behavior:

plugins:
  - serverless-plugin-artifact-directory-manager

custom:
  artifactDirectoryManager:
    strategy: hash            # Options: 'hash' (default), 'timestamp', 'hybrid'
    includeGitCommit: true   # Include git commit hash in directory name
    verbose: true            # Enable verbose logging
    enableCache: true        # Enable build caching (default: true for hash/hybrid, false for timestamp)

package:
  artifactDirectoryName: ${artifactDir:fullPath}

🔧 Configuration Options

Strategy Options

  • hash (default): Changes only when code changes (most efficient, only rebuilds when necessary)
  • timestamp: Changes with every deployment (guarantees uniqueness but may cause unnecessary rebuilds)
  • hybrid: Combines both approaches for guaranteed uniqueness and change detection

📊 Strategy Tradeoffs

| Strategy | Efficiency | Reliability | Use Case | Pros | Cons | |----------|------------|-------------|----------|------|------| | hash ⭐ | 🟢 High | 🟡 Good | Most projects | • Only updates when code changes• Faster deployments• Lower AWS costs• Matches original behavior | • Rare edge cases where CloudFormation needs update but hash doesn't change | | timestamp | 🔴 Low | 🟢 Perfect | Critical systems | • Guarantees CloudFormation detection• Never misses updates• Simple and predictable | • Updates Lambda on every deploy• Slower deployments• Higher AWS costs• Unnecessary cold starts | | hybrid | 🟡 Medium | 🟢 Perfect | High-change environments | • Best of both worlds• Content-aware + guaranteed unique• Good for rapid development | • Slightly larger hash• More complex logic• Still updates more than pure hash |

🤔 When to Use Each Strategy

Choose hash (default) when:

  • ✅ You want optimal performance and efficiency
  • ✅ Your deployments should only update when code actually changes
  • ✅ You trust the content-based detection (works for 99% of cases)
  • ✅ You want to minimize AWS Lambda update costs

Choose timestamp when:

  • ✅ You have critical systems that must never miss an update
  • ✅ CloudFormation reliability is more important than efficiency
  • ✅ You're debugging deployment issues and want to force updates
  • ✅ You have compliance requirements for deployment tracking

Choose hybrid when:

  • ✅ You're in rapid development with frequent deployments
  • ✅ You want content-awareness but also guaranteed uniqueness
  • ✅ You need a balance between efficiency and reliability
  • ✅ You're migrating from timestamp and want a safer transition

💡 Pro Tips

  • Start with hash - it's the most efficient and matches your original setup
  • Use timestamp temporarily if you suspect deployment detection issues
  • Consider hybrid for development environments with frequent changes

Variable Resolvers

The plugin provides several variable resolvers you can use in your serverless.yml:

package:
  artifactDirectoryName: ${artifactDir:fullPath}  # Full path: serverless/myservice/dev/2024-01-15T10-30-00-abc123def456

# Or use individual components:
custom:
  myTimestamp: ${artifactDir:timestamp}    # 2024-01-15T10-30-00
  myHash: ${artifactDir:hash}              # abc123def456
  myPrefix: ${artifactDir:prefix}          # serverless/myservice/dev
  myService: ${artifactDir:service}        # myservice
  myStage: ${artifactDir:stage}            # dev
  myRegion: ${artifactDir:region}          # us-east-1

📋 Commands

Show Plugin Information

serverless artifact-info           # Basic info
serverless artifact-info --verbose # Detailed info

🏗️ How It Works

  1. Initialization: The plugin analyzes your project structure and configuration
  2. Hash Generation: Creates a unique identifier based on your chosen strategy:
    • Timestamp: Current deployment time
    • Hash: Content hash of source files, dependencies, and configuration
    • Hybrid: Combination of both
  3. Variable Injection: Makes artifact directory variables available throughout your configuration
  4. Package Update: Automatically updates the package.artifactDirectoryName if needed

Hash Calculation Details

The hash and hybrid strategies calculate content hashes from:

✅ Always Included:

  • package.json - Dependencies and project configuration
  • serverless.yml - Serverless configuration
  • Source files (src/**/*.{js,ts,json,yml,yaml})
  • Module files (when deploying specific modules)

✅ Conditionally Included:

  • package-lock.json, yarn.lock, pnpm-lock.yaml - When present
  • Environment files (.env, .env-hd, .env.local, .env.production) - When present
  • Git commit hash - When includeGitCommit: true

❌ Always Excluded:

  • node_modules/ - Too large and volatile
  • Hidden directories (.git/, .vscode/, etc.)
  • Build artifacts and temporary files

🔍 Example Output

🗂️  Artifact Directory Manager - Configuration Injected
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

📋 Core Properties:
   Service: my-api
   Stage: dev
   Region: us-east-1

📁 Directory Details:
   Timestamp: 2024-01-15T10-30-00
   Hash: abc123def456
   Prefix: serverless/my-api/dev
   Full Path: serverless/my-api/dev/2024-01-15T10-30-00-abc123def456

💡 Usage:
   Use ${artifactDir:fullPath} in your serverless.yml
   Use ${artifactDir:timestamp} for timestamp-only
   Use ${artifactDir:hash} for hash-only
   Use ${artifactDir:prefix} for prefix-only

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

🐛 Debugging

Enable verbose logging:

export ARTIFACT_DIR_DEBUG=true
serverless deploy --verbose

Or use the plugin-specific command:

serverless artifact-info --verbose

🔧 Integration with Existing Setup

Replace Existing Configuration

If you're currently using:

package:
  artifactDirectoryName: ${file(../../serverless/core/dist/serverless-artifact.js):artifactDirectoryName, file(./dist/serverless-artifact.js):artifactDirectoryName, file(./node_modules/@emerald-works/serverless-core/dist/serverless-artifact.js):artifactDirectoryName}

Simply replace with:

plugins:
  - serverless-plugin-artifact-directory-manager

package:
  artifactDirectoryName: ${artifactDir:fullPath}

🚀 Build Caching Optimization

⚡ Intelligent Build Skipping

The plugin includes an intelligent caching system that can dramatically speed up deployments by skipping unnecessary builds and uploads:

custom:
  artifactDirectoryManager:
    strategy: hash           # Required for caching
    enableCache: true       # Enable build caching (default: true for hash/hybrid)

How It Works

  1. Content Hash Analysis: Before running esbuild, the plugin calculates a content hash of your source files
  2. Artifact Detection: Checks if artifacts already exist for the current content hash
  3. Build Skipping: If artifacts exist and content hasn't changed, skips esbuild and packaging entirely
  4. Artifact Reuse: Points to existing zip files, avoiding redundant S3 uploads

Performance Benefits

  • Faster Deployments: Skip build when code hasn't changed (30-90% time savings)
  • 💰 Lower AWS Costs: Avoid unnecessary S3 uploads and Lambda updates
  • 🔋 Reduced CPU Usage: No redundant TypeScript compilation or bundling
  • 🌍 Better Developer Experience: Near-instant deployments for infrastructure-only changes

When Caching Activates

Cache Hit: Build skipped, existing artifacts reused

  • Source files unchanged (package.json, src/*, serverless.yml)
  • Previous successful build exists for this hash
  • All required zip files present

Cache Miss: Normal build process continues

  • Source code modified since last build
  • No previous artifacts found for this hash
  • Missing or corrupted artifact files

Configuration Options

custom:
  artifactDirectoryManager:
    enableCache: true        # Enable/disable caching (default: smart)
    strategy: 'hash'         # Required for caching ('timestamp' disables cache)
    includeGitCommit: true   # Include git state in cache key

Smart Defaults:

  • hash strategy: Cache enabled by default
  • hybrid strategy: Cache enabled by default
  • timestamp strategy: Cache disabled by default

📈 Benefits

  • Guaranteed CloudFormation Detection: Every deployment gets a unique artifact path
  • Flexible Strategies: Choose between timestamp, content-hash, or hybrid approaches
  • Git Integration: Optionally include git commit hashes
  • Easy Migration: Simple drop-in replacement for existing configurations
  • Verbose Logging: Detailed information for debugging and verification
  • Intelligent Caching: Skip builds when code hasn't changed (hash/hybrid strategies)

🤝 Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 License

MIT License - see the LICENSE file for details.

🆘 Support

  • Create an issue on GitHub
  • Check the verbose output with --verbose flag
  • Enable debug logging with ARTIFACT_DIR_DEBUG=true