Skip to main content

How to Run npm Build Commands from a Batch Script

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
info

Always use call npm in Batch scripts. npm.cmd is itself a Batch file, and without call, the current script terminates after npm finishes.

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

CommandBehaviorBest For
npm installInstalls/updates based on package.json, may modify package-lock.jsonDevelopment
npm ciInstalls exactly from package-lock.json, deletes node_modules firstCI/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.