diff --git a/modules/node/init.zsh b/modules/node/init.zsh
index 0a516f0d..75a7ebb4 100644
--- a/modules/node/init.zsh
+++ b/modules/node/init.zsh
@@ -28,18 +28,28 @@ elif (( ! $+commands[node] )); then
   return 1
 fi
 
-# Load NPM completion.
-if (( $+commands[npm] )); then
-  cache_file="${TMPDIR:-/tmp}/prezto-node-cache.$UID.zsh"
+# Load NPM and known helper completions.
+typeset -A compl_commands=(
+  npm   'npm completion'
+  grunt 'grunt --completion=zsh'
+  gupl  'gulp --completion=zsh'
+)
 
-  if [[ "$commands[npm]" -nt "$cache_file" \
-        || "${ZDOTDIR:-$HOME}/.zpreztorc" -nt "$cache_file" \
-        || ! -s "$cache_file" ]]; then
-    # npm is slow; cache its output.
-    npm completion >! "$cache_file" 2> /dev/null
+for compl_command in "${(k)compl_commands[@]}"; do
+  if (( $+commands[$compl_command] )); then
+    cache_file="${TMPDIR:-/tmp}/prezto-$compl_command-cache.$UID.zsh"
+
+    # Completion commands are slow; cache their output if old or missing.
+    if [[ "$commands[$compl_command]" -nt "$cache_file" \
+          || "${ZDOTDIR:-$HOME}/.zpreztorc" -nt "$cache_file" \
+          || ! -s "$cache_file" ]]; then
+      command ${=compl_commands[$compl_command]} >! "$cache_file" 2> /dev/null
+    fi
+
+    source "$cache_file"
+
+    unset cache_file
   fi
+done
 
-  source "$cache_file"
-
-  unset cache_file
-fi
+unset compl_command{s,}