Package Management Strategies
#packages #dependencies #npm #composer #nuget #versioning #security
Last Updated: May 18, 2025 Related: .NET vs Laravel Complete Developer Guide
Quick Navigation
- [[#Universal Principles]]
- [[#.NET Package Management (NuGet)]]
- [[#PHP Package Management (Composer)]]
- [[#JavaScript Package Management (npm/yarn)]]
- [[#Security Best Practices]]
- [[#Automation & CI/CD]]
- [[#Troubleshooting Guide]]
Universal Principles
🎯 Core Package Management Rules
1. Version Consistency
✅ Good: All packages use compatible versions
✅ Good: Document version decisions
✅ Good: Regular updates with testing
❌ Bad: Mixed major versions
❌ Bad: Ignoring security updates
❌ Bad: "It works on my machine" mentality
2. Dependency Minimalism
Principle: Only add packages that provide significant value
- Avoid packages for simple operations you can code yourself
- Prefer established, well-maintained packages
- Consider bundle size impact (especially for frontend)
- Regularly audit and remove unused dependencies
3. Lock File Management
Always commit lock files:
- package-lock.json (npm)
- yarn.lock (yarn)
- packages.lock.json (.NET)
- composer.lock (PHP)
These ensure reproducible builds across environments
🔍 Evaluation Criteria for New Packages
Before Adding Any Package
Red Flags
🚩 No updates in 2+ years
🚩 Many open security issues
🚩 Excessive dependencies
🚩 Poor documentation
🚩 Single maintainer with no backup
🚩 License incompatibility
.NET Package Management (NuGet)
📦 Central Package Management
<!-- Directory.Packages.props at solution root -->
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Identity" Version="8.0.0" />
<PackageVersion Include="Serilog.AspNetCore" Version="7.0.0" />
<PackageVersion Include="AutoMapper" Version="12.0.1" />
<PackageVersion Include="FluentValidation" Version="11.7.1" />
<!-- Development only -->
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.0" />
<PackageVersion Include="Moq" Version="4.20.69" />
<PackageVersion Include="xunit" Version="2.4.2" />
</Project>
<!-- In project files - no versions needed -->
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" />
<PackageReference Include="AutoMapper" />
</Project>
🔧 NuGet Configuration
<!-- nuget.config -->
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="private-feed" value="https://pkgs.dev.azure.com/company/_packaging/internal/nuget/v3/index.json" />
</packageSources>
<packageRestore>
<add key="enabled" value="True" />
<add key="automatic" value="True" />
</packageRestore>
<config>
<add key="repositoryPath" value="packages" />
<add key="defaultPushSource" value="https://api.nuget.org/v3/index.json" />
</config>
<packageManagement>
<add key="format" value="1" />
<add key="disabled" value="False" />
</packageManagement>
</configuration>
📊 Package Analysis Scripts
# analyze-packages.ps1
param(
[string]$SolutionPath = ".",
[switch]$ShowOutdated,
[switch]$ShowVulnerable
)
Write-Host "=== Package Analysis Report ===" -ForegroundColor Green
# Find all project files
$projects = Get-ChildItem -Path $SolutionPath -Recurse -Filter "*.csproj"
foreach ($project in $projects) {
Write-Host "`n--- $($project.Name) ---" -ForegroundColor Yellow
# Show packages
Set-Location $project.Directory
dotnet list package --framework net8.0
if ($ShowOutdated) {
Write-Host "Outdated packages:" -ForegroundColor Red
dotnet list package --outdated
}
if ($ShowVulnerable) {
Write-Host "Vulnerable packages:" -ForegroundColor Red
dotnet list package --vulnerable
}
}
# Global package analysis
Write-Host "`n=== Solution-wide Analysis ===" -ForegroundColor Green
Set-Location $SolutionPath
# Check for version conflicts
Write-Host "Checking for version conflicts..."
dotnet restore --verbosity quiet
if ($LASTEXITCODE -ne 0) {
Write-Host "⚠️ Restore issues detected. Check for version conflicts." -ForegroundColor Red
}
# Generate dependency graph (requires dotnet-depends tool)
if (Get-Command "dotnet-depends" -ErrorAction SilentlyContinue) {
Write-Host "Generating dependency graph..."
dotnet depends --output dependencies.html
Write-Host "✅ Dependency graph saved to dependencies.html" -ForegroundColor Green
}
🚀 Automated Package Updates
# .github/workflows/package-updates.yml
name: Package Updates
on:
schedule:
- cron: '0 2 * * 1' # Every Monday at 2 AM
workflow_dispatch:
jobs:
update-packages:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: '8.0.x'
- name: Install dotnet-outdated
run: dotnet tool install --global dotnet-outdated-tool
- name: Check for outdated packages
run: |
echo "## Outdated Packages" >> $GITHUB_STEP_SUMMARY
dotnet outdated --output json > outdated.json
cat outdated.json >> $GITHUB_STEP_SUMMARY
- name: Update packages (minor versions only)
run: dotnet outdated --upgrade --version-lock Major
- name: Run tests
run: dotnet test
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5
with:
title: 'chore: Update NuGet packages'
body: |
Automated package updates for minor versions only.
Please review the changes and run additional tests if needed.
branch: automated/package-updates
PHP Package Management (Composer)
🎼 Composer Best Practices
{
"name": "company/project",
"description": "Project description",
"type": "project",
"keywords": ["laravel", "php"],
"license": "proprietary",
"require": {
"php": "^8.1",
"laravel/framework": "^10.0",
"guzzlehttp/guzzle": "^7.2",
"laravel/sanctum": "^3.2",
"laravel/tinker": "^2.8"
},
"require-dev": {
"fakerphp/faker": "^1.9.1",
"laravel/pint": "^1.0",
"laravel/sail": "^1.18",
"mockery/mockery": "^1.4.4",
"nunomaduro/collision": "^7.0",
"phpunit/phpunit": "^10.1",
"spatie/laravel-ignition": "^2.0"
},
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"scripts": {
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi"
],
"post-update-cmd": [
"@php artisan vendor:publish --tag=laravel-assets --ansi --force"
],
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
],
"post-create-project-cmd": [
"@php artisan key:generate --ansi"
],
"test": "phpunit",
"test-coverage": "phpunit --coverage-html coverage",
"analyse": "phpstan analyse",
"format": "pint"
},
"extra": {
"laravel": {
"dont-discover": []
}
},
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true,
"allow-plugins": {
"pestphp/pest-plugin": true,
"php-http/discovery": true
}
},
"minimum-stability": "stable",
"prefer-stable": true
}
🔒 Composer Security
# Security audit
composer audit
# Check for known security vulnerabilities
composer require --dev roave/security-advisories:dev-latest
# This package prevents installation of packages with known security issues
# Update composer.json to include:
"require-dev": {
"roave/security-advisories": "dev-latest"
}
# Local security checker (alternative)
composer require --dev enlightn/security-checker
vendor/bin/security-checker security:check
📦 Private Package Repository
// composer.json
{
"repositories": [
{
"type": "composer",
"url": "https://composer.company.com"
},
{
"type": "vcs",
"url": "https://github.com/company/private-package"
}
],
"require": {
"company/private-package": "^1.0"
}
}
// For GitLab/GitHub private repos
{
"repositories": [
{
"type": "vcs",
"url": "git@gitlab.company.com:packages/internal-tools.git"
}
]
}
// Authentication setup
composer config --global gitlab-oauth.gitlab.company.com YOUR_TOKEN
🛠️ Composer Scripts and Automation
{
"scripts": {
"fresh": [
"@php artisan migrate:fresh --seed",
"@php artisan storage:link"
],
"ide-helper": [
"@php artisan ide-helper:generate",
"@php artisan ide-helper:models --nowrite"
],
"quality": [
"pint --test",
"phpstan analyse",
"@test"
],
"deploy": [
"composer install --optimize-autoloader --no-dev",
"@php artisan config:cache",
"@php artisan route:cache",
"@php artisan view:cache"
]
}
}
# Usage
composer run fresh
composer run quality
composer run deploy
JavaScript Package Management (npm/yarn)
📋 Package.json Best Practices
{
"name": "@company/frontend-app",
"version": "1.0.0",
"private": true,
"description": "Frontend application",
"keywords": ["react", "typescript", "vite"],
"author": "Company Name <dev@company.com>",
"license": "UNLICENSED",
"engines": {
"node": ">=18.0.0",
"npm": ">=9.0.0"
},
"browserslist": [
">0.2%",
"not dead",
"not op_mini all"
],
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"typescript": "^5.0.0",
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0"
},
"devDependencies": {
"@vitejs/plugin-react": "^4.0.0",
"vite": "^4.4.0",
"eslint": "^8.45.0",
"prettier": "^3.0.0",
"@testing-library/react": "^13.4.0",
"@testing-library/jest-dom": "^5.16.4",
"vitest": "^0.34.0"
},
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"test": "vitest",
"test:ui": "vitest --ui",
"test:coverage": "vitest --coverage",
"lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"lint:fix": "eslint src --ext ts,tsx --fix",
"format": "prettier --write src",
"type-check": "tsc --noEmit",
"analyze": "npm run build && npx vite-bundle-analyzer",
"clean": "rm -rf node_modules dist",
"reinstall": "npm run clean && npm install"
},
"peerDependencies": {
"react": ">=17.0.0"
}
}
🔧 NPM Configuration
# .npmrc
# Registry configuration
registry=https://registry.npmjs.org/
@company:registry=https://npm.company.com/
# Security and cache settings
audit-level=high
fund=false
save-exact=true
package-lock=true
# Performance
prefer-offline=true
cache-max=3600000
# Private package authentication (if needed)
//npm.company.com/:_authToken=${NPM_TOKEN}
# Node version enforcement
engine-strict=true
🔍 Package Auditing
# Security audit
npm audit
npm audit --audit-level high
npm audit fix
# Check for outdated packages
npm outdated
npm outdated --depth=0
# Update packages
npm update
npx npm-check-updates -u # Update to latest versions
# Bundle analysis
npx webpack-bundle-analyzer build/static/js/*.js
npx vite-bundle-analyzer
# Dependency analysis
npx depcheck # Find unused dependencies
npx license-checker # Check licenses
🚀 Yarn Berry (v3+) Setup
# .yarnrc.yml
yarnPath: .yarn/releases/yarn-3.6.0.cjs
nodeLinker: node-modules
enableGlobalCache: true
compressionLevel: mixed
plugins:
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
packageExtensions:
# Fix peer dependency issues
react-scripts@*:
peerDependencies:
typescript: "*"
# Workspaces configuration
workspaces:
- "packages/*"
- "apps/*"
🏗️ Monorepo Package Management
// Root package.json
{
"name": "@company/monorepo",
"private": true,
"workspaces": [
"packages/*",
"apps/*"
],
"scripts": {
"build": "lerna run build",
"test": "lerna run test",
"lint": "lerna run lint",
"clean": "lerna run clean",
"version": "lerna version",
"publish": "lerna publish",
"bootstrap": "lerna bootstrap"
},
"devDependencies": {
"lerna": "^7.0.0",
"@lerna/run": "^7.0.0"
}
}
// lerna.json
{
"version": "independent",
"npmClient": "npm",
"command": {
"bootstrap": {
"hoist": true
},
"version": {
"allowBranch": ["main", "develop"],
"conventionalCommits": true,
"message": "chore(release): publish",
"registry": "https://registry.npmjs.org"
}
},
"packages": [
"packages/*",
"apps/*"
]
}
Security Best Practices
🔒 Universal Security Measures
1. Automated Security Scanning
# .NET
dotnet list package --vulnerable
dotnet list package --deprecated
# PHP
composer audit
vendor/bin/security-checker security:check
# JavaScript
npm audit
yarn audit
npx audit-ci --moderate
# GitHub Actions
- name: Security Audit
run: |
npm audit --audit-level high
composer audit
dotnet list package --vulnerable
2. Dependency License Compliance
# JavaScript license checking
npx license-checker --summary
npx license-checker --onlyAllow "MIT;Apache-2.0;BSD;ISC"
# .NET license checking (custom PowerShell)
function Check-PackageLicenses {
$packages = dotnet list package --include-transitive --format json | ConvertFrom-Json
foreach ($package in $packages.projects.frameworks.topLevelPackages) {
Write-Host "$($package.id): $($package.resolvedVersion)"
# Check license URL or metadata
}
}
# PHP license checking
composer licenses
composer show --self | grep license
3. Supply Chain Security
# GitHub Dependabot configuration
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
reviewers:
- "security-team"
assignees:
- "lead-developer"
commit-message:
prefix: "deps"
include: "scope"
- package-ecosystem: "composer"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "nuget"
directory: "/"
schedule:
interval: "weekly"
🛡️ Security Policies
# Security Policy Template
## Supported Versions
| Version | Supported |
|---------|-----------|
| 2.x.x | ✅ |
| 1.x.x | ❌ |
## Dependency Security Requirements
1. All dependencies must be regularly updated
2. No packages with known high/critical vulnerabilities
3. License compatibility verification required
4. Security audit before each release
## Reporting Security Issues
- Create private GitHub security advisory
- Email security@company.com
- Include: affected versions, impact assessment, reproduction steps
## Response Timeline
- Acknowledgment: 48 hours
- Initial assessment: 1 week
- Fix deployment: Based on severity
Automation & CI/CD
🔄 Automated Package Management Pipeline
# .github/workflows/package-management.yml
name: Package Management
on:
schedule:
- cron: '0 2 * * 1' # Weekly on Monday
pull_request:
paths:
- 'package.json'
- 'composer.json'
- '*.csproj'
- 'Directory.Packages.props'
workflow_dispatch:
jobs:
audit:
name: Security Audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: '8.0.x'
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
- name: Install Composer
run: curl -sS https://getcomposer.org/installer | php
- name: JavaScript Security Audit
run: |
npm ci
npm audit
- name: PHP Security Audit
run: |
php composer.phar install
php composer.phar audit
- name: .NET Security Audit
run: |
dotnet restore
dotnet list package --vulnerable
update-check:
name: Check for Updates
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check outdated packages
run: |
echo "## Package Updates Available" >> $GITHUB_STEP_SUMMARY
echo "### JavaScript" >> $GITHUB_STEP_SUMMARY
npm outdated >> $GITHUB_STEP_SUMMARY || true
echo "### PHP" >> $GITHUB_STEP_SUMMARY
php composer.phar outdated >> $GITHUB_STEP_SUMMARY || true
echo "### .NET" >> $GITHUB_STEP_SUMMARY
dotnet list package --outdated >> $GITHUB_STEP_SUMMARY || true
🏗️ Package Build and Publish
name: Package Release
on:
push:
tags:
- 'v*'
jobs:
publish-npm:
if: contains(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build package
run: npm run build
- name: Publish to npm
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
publish-nuget:
if: contains(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: '8.0.x'
- name: Restore dependencies
run: dotnet restore
- name: Run tests
run: dotnet test
- name: Pack NuGet package
run: dotnet pack --configuration Release --no-restore --output ./packages
- name: Publish to NuGet
run: dotnet nuget push ./packages/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json
Troubleshooting Guide
🚨 Common Issues and Solutions
Dependency Conflicts
# .NET version conflicts
# 1. Check for conflicting versions
dotnet list package --include-transitive | grep PackageName
# 2. Force specific version in Directory.Packages.props
<PackageVersion Include="ConflictingPackage" Version="1.2.3" />
# 3. Use package downgrade strategy
<PackageReference Include="ConflictingPackage" Version="1.2.3">
<IncludeAssets>compile; build</IncludeAssets>
</PackageReference>
# PHP autoload conflicts
# 1. Clear Composer cache
composer clear-cache
composer dump-autoload
# 2. Check for duplicate class definitions
composer show --tree | grep ConflictingPackage
# JavaScript peer dependency warnings
# 1. Check peer dependencies
npm ls --depth=0
yarn why package-name
# 2. Fix peer dependencies
npm install --save-peer missing-peer-dependency
Performance Issues
# Large node_modules
# 1. Analyze bundle size
npx webpack-bundle-analyzer
npx source-map-explorer build/static/js/*.js
# 2. Remove unused dependencies
npx depcheck
npm uninstall unused-package
# 3. Use production builds
npm run build --production
# Slow Composer installs
# 1. Use composer optimization
composer install --optimize-autoloader --classmap-authoritative
# 2. Enable parallel downloads
composer global require hirak/prestissimo
# 3. Use Composer 2.x
composer self-update --2
Lock File Issues
# Merge conflicts in lock files
# 1. Delete lock file and reinstall
rm package-lock.json && npm install
rm composer.lock && composer install
# 2. Use lock file conflict resolver
npx npm-merge-driver install
git config merge.ours.driver true
# Out of sync lock files
# 1. Verify lock file integrity
npm ci # Fails if package.json and lock file don't match
composer validate --strict
# 2. Update lock file only
npm install --package-lock-only
composer update --lock
🔍 Debugging Commands
# .NET package debugging
dotnet list package --include-transitive --format json > packages.json
dotnet restore --verbosity diagnostic > restore.log
# PHP Composer debugging
composer why-not package/name version
composer depends vendor/package
composer show --tree > dependency-tree.txt
# JavaScript npm debugging
npm ls --depth=0 > package-tree.txt
npm config list
npm doctor
# Yarn debugging
yarn why package-name
yarn check --integrity
yarn cache clean
Templates and Checklists
✅ Package Addition Checklist
## Before Adding a New Package
### Research Phase
- [ ] Package necessity assessment
- [ ] Alternative evaluation (build vs buy)
- [ ] License compatibility check
- [ ] Security audit (vulnerabilities, maintainer track record)
- [ ] Performance impact analysis
- [ ] Documentation quality review
### Technical Evaluation
- [ ] Version compatibility with existing stack
- [ ] Dependency tree analysis
- [ ] Bundle size impact (for frontend packages)
- [ ] TypeScript support (for JS packages)
- [ ] Framework compatibility
### Integration
- [ ] Add to dependency management config
- [ ] Update documentation
- [ ] Add to CI/CD security scanning
- [ ] Test in development environment
- [ ] Create usage examples/guidelines
### Post-Installation
- [ ] Team notification and training
- [ ] Monitor for issues in staging
- [ ] Set up update schedule
- [ ] Document decision rationale
📝 Monthly Package Review Template
# Monthly Package Review - [Date]
## Security Updates
- [ ] Run security audits
- [ ] Review vulnerability reports
- [ ] Apply critical security patches
- [ ] Update security scanning rules
## Version Updates
- [ ] Check for outdated packages
- [ ] Test minor version updates
- [ ] Evaluate major version upgrades
- [ ] Update lock files
## Cleanup
- [ ] Remove unused dependencies
- [ ] Archive deprecated packages
- [ ] Optimize bundle sizes
- [ ] Clean up development dependencies
## Performance Review
- [ ] Bundle size analysis
- [ ] Load time impact assessment
- [ ] Memory usage evaluation
- [ ] Build time optimization
## Actions Taken
- Updated packages: [list]
- Removed packages: [list]
- Security fixes applied: [list]
- Performance improvements: [list]
## Next Month's Focus
- [Priority items for next review]
Related Notes
- .NET vs Laravel Complete Developer Guide
- ASP.NET Core Best Practices
- Laravel Development Setup
- Debugging .NET Applications
Quick Reference Commands
Analysis Commands
# Security
npm audit --audit-level high
composer audit
dotnet list package --vulnerable
# Outdated packages
npm outdated
composer outdated
dotnet list package --outdated
# Dependencies
npm ls --depth=0
composer show --tree
dotnet list package --include-transitive
Update Commands
# Update package managers
npm update -g npm
composer self-update
dotnet tool update -g dotnet-outdated-tool
# Update packages
npm update
composer update
dotnet outdated --upgrade
Tags
#packages #dependencies #security #automation #npm #composer #nuget #versioning
This guide should be reviewed and updated quarterly to reflect new tools and best practices.