Node.js is an open-source runtime that lets you run JavaScript outside the browser. It uses Google’s V8 engine and a non-blocking I/O model, which makes it fast and well-suited for build tools and server-side applications. I use Node.js in all of my main projects to automate CSS compilation, JS bundling, and theme packaging. In the DevWP series, I demonstrate how to properly set up and use Node.js and explain the benefits of automation.
Installing nvm on macOS
To manage multiple versions of Node.js easily, you can use nvm (Node Version Manager). Visit the NVM for macOS page for the latest instructions and version.
Install and Verify nvm
Run the install script, restart your terminal, then verify:
# Install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
# After restarting terminal, verify installation
nvm -vManaging Node.js Versions with nvm
Once nvm is installed, use the following commands to install and switch between Node.js versions:
# Install the latest Node.js
nvm install node
# Install a specific version or the latest LTS
nvm install 20.14.0
nvm install --lts
# Set default version
nvm alias default node
# Check current version
node -v
# View installed and available versions
nvm ls
nvm ls-remote
# Update to the latest LTS and migrate packages
nvm install 'lts/*' --reinstall-packages-from=currentNode.js on Windows
This walkthrough covers the Windows installation using the official Node.js installer.
Download the LTS version from the Node.js Official Site. The Windows installer adds Node.js and NPM to your system PATH automatically, so you can use them from any terminal window right away. Run through the installer prompts, then verify both installed correctly:
# Verify Node.js and NPM are installed
node -v
npm -vNPM: Node Package Manager
NPM (Node Package Manager) handles your project’s dependencies — installing, updating, and running packages from the command line. Every Node.js project uses a package.json file to track its dependencies, scripts, and metadata. When you install a package, NPM downloads it into a local node_modules folder and records the exact version in package-lock.json so every developer on the project gets the same versions. NPM Website
How Do You Install NPM Packages?
Use the --save-dev flag (or -D) for tools that are only needed during development — linters, compilers, bundlers, and test runners. These get listed under devDependencies in your package.json and won’t be included in production builds. Omitting the flag (or using --save) adds the package to dependencies, which is meant for runtime libraries your application needs to function. For WordPress theme development, almost everything is a dev dependency since the compiled output is what ships.
npm install package-to-install --save-dev
# Shorthand version
npm i package-to-install -DWhat NPM Packages Do You Need for WordPress Development?
- Autoprefixer: Automatically adds vendor prefixes to CSS rules. Autoprefixer on NPM
- Bootstrap: Front-end component framework — provides the grid system, responsive utilities, and UI components used in the DevWP theme. Bootstrap on NPM | Bootstrap Site
- Chokidar-CLI: A fast cross-platform command line utility to watch file system changes. Chokidar CLI on GitHub
- Concurrently: Run multiple commands concurrently. Concurrently on NPM
- Directory Archiver: Compress directories into a zip file with options to exclude specific files or directories. Dir Archiver on NPM
- FontAwesome: A popular icon library and toolkit. FontAwesome on NPM
- PostCSS CLI: A command-line interface for PostCSS. PostCSS CLI on NPM
- Sass: A powerful CSS preprocessor. Sass on NPM
- Terser: A JavaScript compressor toolkit for ES6+. Terser on NPM
Install all packages with one command:
npm install @fortawesome/fontawesome-free autoprefixer bootstrap chokidar-cli concurrently dir-archiver postcss-cli sass terser --save-devFull package.json File
Create a package.json file in the root of your theme and paste the following code. Then, run npm install to install all dependencies:
{
"name": "devwp",
"version": "1.4.6",
"description": "DevWP WordPress Development Training Theme",
"author": "PixemWeb",
"license": "GPL-3.0",
"devDependencies": {
"@fortawesome/fontawesome-free": "^6.5.2",
"autoprefixer": "^10.4.19",
"bootstrap": "^5.3.3",
"chokidar-cli": "^3.0.0",
"concurrently": "^8.2.2",
"dir-archiver": "^2.1.0",
"postcss-cli": "^11.0.0",
"sass": "^1.77.0",
"terser": "^5.31.0"
},
"scripts": {
"copyfonts": "cp node_modules/@fortawesome/fontawesome-free/webfonts/*.{ttf,woff2} ./webfonts/",
"copyBS5": "cp -r node_modules/bootstrap/scss ./src/sass/bootstrap",
"buildcss": "sass --style expanded --source-map src/sass/style.scss dist/css/style.css && sass --style expanded --source-map src/sass/editor-styles.scss dist/css/editor-styles.css && sass --style compressed --source-map src/sass/style.scss ./style.css && sass --style compressed --source-map src/sass/editor-styles.scss dist/css/editor-styles.min.css && postcss style.css --use autoprefixer -o style.css --map && postcss dist/css/editor-styles.min.css --use autoprefixer -o dist/css/editor-styles.min.css --map",
"buildjs": "node concatmin.js",
"build": "npm run buildcss && npm run buildjs",
"watchcss": "chokidar \"src/sass/**/*.scss\" -c \"npm run buildcss\"",
"watchjs": "chokidar \"src/js/**/*.js\" -c \"npm run buildjs\"",
"watch": "concurrently \"npm run watchcss\" \"npm run watchjs\"",
"dev": "dir-archiver --src . --dest ../devwp-dev.zip --exclude .DS_Store .git composer.lock node_modules vendor package-lock.json .phpcs-cache .phpunit.result.cache",
"prod": "dir-archiver --src . --dest ../devwp-prod.zip --exclude .DS_Store .git composer.lock node_modules vendor package-lock.json .stylelintrc.json .gitattributes .github .gitignore composer.json package.json phpcs.xml.dist .editorconfig .phan .phpcs-cache concatmin.js phpmd.xml phpstan.neon.dist phpunit.xml psalm.xml stubs tests phpinsights.php .phpunit.result.cache devwp-vars-1.txt devwp-vars-2.txt"
}
}Running Scripts from package.json
npm install first to install all dependencies before using any scripts.Run any script with npm run script-name. The three you’ll use most often:
- build — run before committing to compile all CSS and JS
- watch — run during active development to auto-rebuild on save
- prod — run when you’re ready to package the theme for distribution
# Build everything
npm run build
# Watch for changes during development
npm run watch
# Package for production
npm run prodI’ve been using this exact Node.js and NPM setup across all of my WordPress projects for years. Once you get comfortable with the build and watch scripts, you’ll wonder how you ever developed without them. For a deeper look at the package.json setup, check out the Package JSON walkthrough video. For the rest of the dev environment, see my guides on Git, Composer, and VS Code.
