Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/Production dependency Optimization By running the command 'npm prune --omit=dev' #2848

Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 137 additions & 0 deletions deps/analyze-dependencies.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
#!/bin/sh

# ==============================================
# README
# ==============================================
# This script analyzes the difference between production and development dependencies
# in a Node.js project. It generates files containing top-level dependencies for both
# production-only and all dependencies (production + development) using `npm ls` and `jq`.
# The results are saved in a `deps` folder, and a comparison is performed to identify
# differences between the two sets of dependencies.
#
# Purpose:
# - To identify dev-only and prod-only dependencies.
# - To provide insight into potential misclassified dependencies.
#
# Prerequisites:
# 1. Ensure `jq` is installed on your system. If not installed, use the following commands
# based on your operating system:
# - **Alpine Linux**: `apk add --no-cache jq`
# - **Debian/Ubuntu**: `apt-get update && apt-get install -y jq`
# - **RHEL/CentOS**: `yum install -y jq`
# - **MacOS (with Homebrew)**: `brew install jq`
# - **Windows**: Download the appropriate binary from https://stedolan.github.io/jq/download/
#
# 2. Ensure the script has execute permissions:
# ```sh
# chmod +x ./deps/analyze-dependencies.sh
# ```
#
# 3. Ensure `npm` is installed and properly set up in the current environment.
#
# Usage:
# 1. Navigate to the root of your Node.js project where `package.json` is located.
# 2. Run the script:
# ```sh
# ./deps/analyze-dependencies.sh
# ```
# 3. The script will:
# - Generate files for production and dev+prod dependencies in the `deps` folder.
# - Sort and compare the dependency lists for differences.
#
# Output:
# - The following files will be created in the `deps` folder:
# - `prod-deps.json`: Top-level production dependencies.
# - `dev-deps.json`: Top-level dev+prod dependencies.
# - `prod-deps-keys.json`: Keys of production dependencies.
# - `dev-deps-keys.json`: Keys of dev+prod dependencies.
# - A `diff` will be displayed showing the differences between production and dev dependencies.
#
# Notes:
# - Modify the script if your codebase structure differs or if additional processing is required.
# ==============================================

set -e

# Function to check and install jq
install_jq_if_missing() {
echo "Checking if jq is installed..."
if ! command -v jq >/dev/null 2>&1; then
echo "jq is not installed."
echo "Error: jq is required but not installed. Please install jq first:"
echo "Alpine: apk add --no-cache jq"
echo "Debian/Ubuntu: apt-get update && apt-get install -y jq"
echo "RHEL/CentOS: yum install -y jq"
echo "MacOS (with Homebrew): brew install jq"
echo "Windows: Download jq from https://stedolan.github.io/jq/download/"
exit 1
else
echo "jq is already installed."
fi
}

# Run the jq installation check
install_jq_if_missing

echo "Checking if package.json exists..."
if [ ! -f "package.json" ]; then
echo "Error: No package.json found in the current directory."
exit 1
fi

# Create the deps folder if it does not exist
DEPS_FOLDER="deps"
echo "Creating the $DEPS_FOLDER folder for storing dependency files..."
mkdir -p "$DEPS_FOLDER"

# Check if .env file exists and load it
if [ -f ".env" ]; then
. ./.env
else
echo "Warning: .env file not found"
fi

# Check if NODE_ENV is set
if [ -z "$NODE_ENV" ]; then
echo "Warning: NODE_ENV is not set"
NODE_ENV="development" # Set default to development
fi

echo "Current NODE_ENV: $NODE_ENV"

# Check for production environment
if [ "$NODE_ENV" = "production" ]; then
echo "Skipping npm install in production environment"
else
echo "Installing dependencies (if necessary) to ensure npm ls commands run accurately..."
npm install
fi

echo "Generating list of production dependencies (top-level only)..."
if ! npm ls --omit=dev --json > "$DEPS_FOLDER/prod-deps.json" 2>/dev/null; then
echo "Warning: npm ls command produced errors, results may be incomplete"
fi

echo "Generating list of dev+prod dependencies (top-level only)..."
if ! npm ls --prod=false --json > "$DEPS_FOLDER/dev-deps.json" 2>/dev/null; then
echo "Warning: npm ls command produced errors, results may be incomplete"
fi

# Extract just the top-level dependencies' keys. If a key is absent, we fall back to an empty object "{}".
echo "Extracting top-level dependencies from prod-deps.json..."
jq '.dependencies? // {} | keys' "$DEPS_FOLDER/prod-deps.json" > "$DEPS_FOLDER/prod-deps-keys.json"
echo "Extracting top-level dependencies from dev-deps.json..."
jq '.dependencies? // {} | keys' "$DEPS_FOLDER/dev-deps.json" > "$DEPS_FOLDER/dev-deps-keys.json"

# Sort them and compare side by side. We'll use textual diff to highlight any differences.
echo "Comparing top-level production vs. dev dependencies..."
sort "$DEPS_FOLDER/prod-deps-keys.json" -o "$DEPS_FOLDER/prod-deps-keys.json"
sort "$DEPS_FOLDER/dev-deps-keys.json" -o "$DEPS_FOLDER/dev-deps-keys.json"
diff "$DEPS_FOLDER/prod-deps-keys.json" "$DEPS_FOLDER/dev-deps-keys.json" || true

echo ""
echo "=========================================="
echo "Finished analyzing dependencies."
echo "$DEPS_FOLDER/prod-deps-keys.json: top-level prod deps."
echo "$DEPS_FOLDER/dev-deps-keys.json: top-level dev+prod deps."
echo "Use 'diff $DEPS_FOLDER/prod-deps-keys.json $DEPS_FOLDER/dev-deps-keys.json' for side-by-side comparison."
119 changes: 119 additions & 0 deletions deps/move-from-diff.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#!/bin/sh

# ==============================================
# README
# ==============================================
# This script analyzes the difference between production and development dependencies
# in a Node.js project. It identifies dev-only dependencies that are used in the
# production code and moves them from `devDependencies` to `dependencies` in the
# project's `package.json` file.
#
# Purpose:
# - To ensure all required production dependencies are correctly categorized.
# - To prevent runtime errors in production due to missing dependencies.
#
# Prerequisites:
# 1. Ensure `analyze-dependencies.sh` has been run beforehand. This script generates:
# - `prod-deps-keys.json`: Contains top-level production dependencies.
# - `dev-deps-keys.json`: Contains top-level dev+prod dependencies.
# These files must exist in the `deps` folder.
#
# 2. Ensure the script has execute permissions:
# ```sh
# chmod +x ./deps/move-from-diff.sh
# ```
#
# 3. Ensure `jq` is installed on the system. If it is missing, install it using the
# appropriate package manager (e.g., `apt-get`, `yum`, or `apk`).
#
# Usage:
# 1. Navigate to the project root directory where `package.json` is located.
# 2. Execute this script:
# ```sh
# ./deps/move-from-diff.sh
# ```
# 3. The script will:
# - Analyze the diff between `prod-deps-keys.json` and `dev-deps-keys.json`.
# - Identify dev-only dependencies used in production code.
# - Move required dependencies from `devDependencies` to `dependencies`.
#
# Output:
# - Any required dependencies will be moved to `dependencies` in `package.json`.
# - A confirmation message will be displayed upon successful execution.
#
# Note:
# - Ensure your production code resides in `./src`, `./lib`, or `./app` folders.
# - Modify the script if your codebase structure differs.
# ==============================================

set -e

# Define the folder where dependency files are stored
DEPS_FOLDER="deps"

echo "Analyzing dependencies from diff output..."

# Check if the necessary files exist in the deps folder
if [ ! -f "$DEPS_FOLDER/prod-deps-keys.json" ] || [ ! -f "$DEPS_FOLDER/dev-deps-keys.json" ]; then
echo "Error: prod-deps-keys.json or dev-deps-keys.json not found in the $DEPS_FOLDER folder. Run analyze-dependencies.sh first."
exit 1
fi

# Generate the diff and extract dev-only packages
DIFF_OUTPUT=$(diff "$DEPS_FOLDER/prod-deps-keys.json" "$DEPS_FOLDER/dev-deps-keys.json" || true)
DEV_ONLY_PACKAGES=$(echo "$DIFF_OUTPUT" | grep '^>' | sed 's/^> //' | tr -d '",')

if [ -z "$DEV_ONLY_PACKAGES" ]; then
echo "No dev-only dependencies found to check."
exit 0
fi

echo "Found dev-only dependencies to check for production usage:"
echo "$DEV_ONLY_PACKAGES"

# Temporary file to store required production dependencies
REQUIRED_FOR_PRODUCTION_FILE=$(mktemp)

for PACKAGE in $DEV_ONLY_PACKAGES; do
echo "Checking if $PACKAGE is used in production..."

# Use grep to check if the package name appears in the production code
if grep -qr "$PACKAGE" ./src; then
echo "$PACKAGE is required in production."
echo "$PACKAGE" >> "$REQUIRED_FOR_PRODUCTION_FILE"
else
echo "$PACKAGE is not used in production."
fi
done

if [ ! -s "$REQUIRED_FOR_PRODUCTION_FILE" ]; then
echo "No dev dependencies are required in production."
rm -f "$REQUIRED_FOR_PRODUCTION_FILE"
exit 0
fi

echo "The following dev dependencies are required in production:"
cat "$REQUIRED_FOR_PRODUCTION_FILE"

# Move required dependencies to production dependencies
while IFS= read -r PACKAGE; do
echo "Moving $PACKAGE to dependencies..."

# First, remove the package from devDependencies
if ! npm uninstall "$PACKAGE" --save-dev; then
echo "Error: Failed to uninstall $PACKAGE from devDependencies"
exit 1
fi
# Install as a production dependency
if ! npm install "$PACKAGE" --save-prod; then
echo "Error: Failed to install $PACKAGE as production dependency"
echo "Warning: Package is now removed from both devDependencies and dependencies"
exit 1
fi

done < "$REQUIRED_FOR_PRODUCTION_FILE"

# Clean up
rm -f "$REQUIRED_FOR_PRODUCTION_FILE"

echo "Required dev dependencies successfully moved to production dependencies."
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
"import:sample-data": "tsx ./src/utilities/loadSampleData.ts",
"import:sample-data:prod": "node ./build/utilities/loadSampleData.js",
"gen:schema": "graphql-inspector introspect ./src/typeDefs/**/**/*.ts --write ./schema.graphql ",
"update:toc": "node scripts/githooks/update-toc.js"
"update:toc": "node scripts/githooks/update-toc.js",
"move-and-prune": "./deps/analyze-dependencies.sh && ./deps/move-from-diff.sh && npm prune --omit=dev"
},
"repository": {
"type": "git",
Expand Down
Loading