Skip to content

How to Run npm Build Commands from a Batch Script

Learn how to execute npm build commands in Windows Batch scripts for automated CI/CD pipelines, including dependency installation, error handling, and environment-specific configurations.

npm (Node Package Manager) is the standard build and dependency management tool for JavaScript and TypeScript projects. From simple frontend builds to complex full-stack applications, npm scripts orchestrate compilation, bundling, testing, and deployment. Running npm commands from a Batch Script enables automated CI/CD pipelines, scheduled builds, and repeatable deployment workflows for Node.js-based applications.

In this guide, we will explore how to execute npm build commands from a Batch Script, covering installation, common scripts, error handling, and production-grade build automation.

Prerequisites

Verify Node.js and npm are installed:

@echo off
node --version >nul 2>&1
if %errorlevel% neq 0 (
    echo [ERROR] Node.js not found. Install from https://nodejs.org/
    pause
    exit /b 1
)

for /f "delims=" %%V in ('node --version') do echo Node.js: %%V
for /f "delims=" %%V in ('call npm --version') do echo npm:     %%V

Method 1: Basic npm Build

@echo off
setlocal

echo =============================================
echo   NPM BUILD
echo =============================================
echo.

:: Install dependencies
echo [1/2] Installing dependencies...
call npm ci --silent
if %errorlevel% neq 0 (
    echo [ERROR] npm ci failed.
    pause
    exit /b 1
)
echo   Done.

:: Build
echo [2/2] Building...
call npm run build
if %errorlevel%==0 (
    echo.
    echo [SUCCESS] Build complete.
) else (
    echo.
    echo [ERROR] Build failed.
)

pause

npm ci vs. npm install

Command Behavior Best For
npm install Installs/updates based on package.json, may modify package-lock.json Development
npm ci Installs exactly from package-lock.json, deletes node_modules first CI/CD, automated builds

Always use npm ci in automated scripts for deterministic, reproducible builds.

Method 2: Full Build Pipeline

@echo off
setlocal enabledelayedexpansion

for /f "tokens=2 delims==" %%T in ('wmic os get LocalDateTime /value') do set "dt=%%T"
set "logfile=build_%dt:~0,8%_%dt:~8,4%.log"

echo =============================================
echo   NPM BUILD PIPELINE
echo   %date% %time:~0,8%
echo =============================================
echo.

:: Stage 1: Clean install
echo [1/4] Installing dependencies...
call npm ci --silent >> "%logfile%" 2>&1
if !errorlevel! neq 0 (
    echo   [FAIL] Dependency installation failed.
    echo   See %logfile% for details.
    pause
    exit /b 1
)
echo   Done.

:: Stage 2: Lint
echo [2/4] Linting...
call npm run lint >> "%logfile%" 2>&1
if !errorlevel! neq 0 (
    echo   [FAIL] Lint errors. Fix them before building.
    echo   See %logfile% for details.
    pause
    exit /b 1
)
echo   Done.

:: Stage 3: Test
echo [3/4] Running tests...
call npm test >> "%logfile%" 2>&1
if !errorlevel! neq 0 (
    echo   [FAIL] Tests failed.
    echo   See %logfile% for details.
    pause
    exit /b 1
)
echo   Done.

:: Stage 4: Build
echo [4/4] Building production bundle...
call npm run build >> "%logfile%" 2>&1
if !errorlevel! neq 0 (
    echo   [FAIL] Build failed.
    echo   See %logfile% for details.
    pause
    exit /b 1
)
echo   Done.

:: Verify output
echo.
if exist "dist" (
    echo Build output:
    set "fcount=0"
    for /r "dist" %%F in (*) do set /a fcount+=1
    echo   !fcount! files in dist\
) else (
    echo   [WARNING] dist\ directory not found.
)

echo.
echo =============================================
echo   BUILD COMPLETE
echo   Log: %logfile%
echo =============================================

pause

Method 3: Build with Environment Configuration

Pass environment-specific settings to the build:

@echo off
setlocal enabledelayedexpansion

:: Select environment
if "%~1"=="" (
    echo Usage: build.bat [dev^|staging^|production]
    set /p "env=Select environment: "
) else (
    set "env=%~1"
)

echo Building for: !env!
echo.

:: Set environment variables
if /i "!env!"=="production" (
    set "NODE_ENV=production"
    set "API_URL=https://api.myapp.com"
) else if /i "!env!"=="staging" (
    set "NODE_ENV=production"
    set "API_URL=https://staging-api.myapp.com"
) else if /i "!env!"=="dev" (
    set "NODE_ENV=development"
    set "API_URL=http://localhost:3001"
) else (
    echo [ERROR] Unknown environment: !env!
    echo   Valid options: dev, staging, production
    pause
    exit /b 1
)

:: Install and build
call npm ci --silent
if !errorlevel! neq 0 (
    echo [ERROR] Dependency installation failed.
    pause
    exit /b 1
)

call npm run build
if !errorlevel!==0 (
    echo [SUCCESS] Built for !env!.
) else (
    echo [ERROR] Build failed.
)

pause

Method 4: Monorepo Build (Workspaces)

For projects using npm workspaces:

@echo off
setlocal

echo =============================================
echo   MONOREPO BUILD
echo =============================================
echo.

:: Install all workspace dependencies
echo [1/3] Installing workspace dependencies...
call npm ci --silent
if %errorlevel% neq 0 (
    echo [ERROR] Dependency installation failed.
    pause
    exit /b 1
)
echo   Done.

:: Build all workspaces
echo [2/3] Building all packages...
call npm run build --workspaces --if-present
if %errorlevel% neq 0 (
    echo [ERROR] Build failed.
    pause
    exit /b 1
)
echo   Done.

:: Or build specific packages
echo [3/3] Building specific packages...
call npm run build -w packages/api
if %errorlevel% neq 0 (
    echo [ERROR] API package build failed.
    pause
    exit /b 1
)

call npm run build -w packages/frontend
if %errorlevel% neq 0 (
    echo [ERROR] Frontend package build failed.
    pause
    exit /b 1
)

echo.
echo [SUCCESS] All packages built.
pause

Method 5: Build and Deploy Script

Complete build-to-deployment workflow:

@echo off
setlocal enabledelayedexpansion

set "app_name=MyWebApp"
set "deploy_dir=deploy"

echo =============================================
echo   BUILD AND DEPLOY: %app_name%
echo =============================================
echo.

:: Read version
set "version=unknown"
for /f "delims=" %%V in ('node -p "require('./package.json').version" 2^>nul') do set "version=%%V"
echo Version: !version!
echo.

:: Step 1: Clean install
echo [1/5] Installing dependencies...
call npm ci --silent
if !errorlevel! neq 0 (
    echo   [FAIL] Dependency installation failed.
    pause
    exit /b 1
)
echo   OK.

:: Step 2: Lint
echo [2/5] Linting...
call npm run lint --silent 2>nul
if !errorlevel! neq 0 (
    echo   [WARN] Lint issues found.
) else (
    echo   OK.
)

:: Step 3: Test
echo [3/5] Testing...
call npm test -- --watchAll=false
if !errorlevel! neq 0 (
    echo   [FAIL] Tests failed. Aborting.
    pause
    exit /b 1
)
echo   OK.

:: Step 4: Build
echo [4/5] Building production bundle...
set "NODE_ENV=production"
call npm run build
if !errorlevel! neq 0 (
    echo   [FAIL] Build failed.
    pause
    exit /b 1
)
echo   OK.

:: Step 5: Package
echo [5/5] Packaging...
if not exist "%deploy_dir%" mkdir "%deploy_dir%"

set "package=%deploy_dir%\%app_name%_v!version!.zip"

:: Remove existing package to avoid stale artifacts
if exist "!package!" del "!package!"

powershell -noprofile -command "Compress-Archive -Path 'dist\*' -DestinationPath '!package!' -Force"
if !errorlevel! neq 0 (
    echo   [FAIL] Packaging failed.
    pause
    exit /b 1
)

for %%F in ("!package!") do set "size=%%~zF"

echo.
echo =============================================
echo   BUILD COMPLETE
echo   Package: !package!
echo   Size:    !size! bytes
echo   Version: !version!
echo =============================================

pause

Running Custom npm Scripts

Projects often define custom scripts in package.json:

@echo off

:: Run any custom script defined in package.json
call npm run dev          & REM Start dev server
call npm run lint:fix     & REM Auto-fix lint issues
call npm run test:coverage & REM Run tests with coverage
call npm run deploy       & REM Custom deploy script
call npm run storybook    & REM Start Storybook

Common Mistakes

The Wrong Way: Using npm Without call

:: WRONG - Script terminates after npm finishes
npm run build
echo This never executes

Output Concern: npm.cmd is a Batch file. Running it without call causes the calling script to terminate. Always use call npm in Batch scripts.

The Wrong Way: Using npm install in CI

:: WRONG for CI - May produce non-deterministic builds
call npm install
call npm run build

npm install may update package-lock.json and install slightly different dependency versions than tested. Use npm ci in automated builds for exact reproducibility.

The Wrong Way: Not Setting NODE_ENV

:: WRONG - Development dependencies and logging included in production build
call npm run build
:: Bundle includes source maps, debug tools, and is not minified

Set NODE_ENV=production before building to ensure bundlers (Webpack, Vite) optimize the output with minification, tree-shaking, and removal of development-only code.

Best Practices

  1. Always use call npm: Prevents Batch script termination.
  2. Use npm ci for automation: Ensures deterministic, reproducible dependency installation.
  3. Set NODE_ENV=production: Triggers production optimizations in bundlers.
  4. Fail fast: Check %errorlevel% after each step and abort on first failure.
  5. Log build output: Redirect to log files for debugging failed builds.

Conclusion

Running npm build commands from a Batch Script is accomplished by calling npm with the appropriate scripts defined in package.json. The essential detail is using call npm instead of plain npm to prevent script termination. By structuring builds as staged pipelines (install, lint, test, build, package), using npm ci for deterministic dependency resolution, and setting proper environment variables for production optimization, teams create reliable JavaScript build automation that works consistently across developer machines and CI/CD servers.

Navigation