Deleting NPM Packages with PowerShell

If you develop code in Javascript, you are going to use npm. It’s pretty much unavoidable at this point. All the good developer tools are distributed with npm. If you do this on Windows, you have a problem:


My node_modules directory here is a result of installing gulp, gulp-imagemin and imagemin-pngquant from npm. Already my node_modules directory structure results in a directory structure that I cannot delete.

There are a couple of ways I can fix this easily. For instance, I could install rimraf and use it like this:

npm install -g rimraf
rimraf ./mode_modules

I can also use npm rm gulp, gulp-imagemin, imagemin-pngquant to remove the files. However, these both require npm on the machine. If I’ve shipped the files from my development box (where npm is installed) to my production box (where npm is not installed) and I need to remove them without npm, then there isn’t a good choice. So I developed a clean-up PowerShell cmdlet explicitly node_modules. This is fairly easy to do, so I decided to do this in a non-recursive way – that is, I’m not going to call the same function time and time again.

Here is my code:

function Remove-NodeModules

        if (-not (Test-Path -PathType Container .\node_modules)) {
            throw "Directory .\node_modules does not exist"
        Write-Verbose "[BEGIN] Storing Current Location"
        $CWD = Get-Location
        Write-Verbose "[BEGIN] Entering .node_modules"
        Set-Location .\node_modules 
        Write-Verbose "[PROCESS] Entering Main Loop"
        $LoopCtr = 0
        $CurrentDirectory = (Get-Item -Path ".")
        do {
            Write-Verbose "[PROCESS] LOOP START - Checking Item List"
            $items = (Get-Childitem ".\*\node_modules\*")
            Write-Verbose "[PROCESS] Sub-Module Item List Count = $($items.Length)"
            foreach ($item in $items) {
                $name = $LoopCtr.ToString() + "." + $item.BaseName
                Write-Verbose "[PROCESS] Moving $item to $name"
                Move-Item -Path $item -Destination $name
            Write-Verbose "[PROCESS] Incrementing LoopCtr"
        } while ($items.Length -gt 0);
        Write-Verbose "[END] Restoring Location = $CWD"
        Set-Location $CWD
        Write-Verbose "[END] Removing node_modules"
        Remove-Item -Recurse -Force .\node_modules

Export-ModuleMember -Function Remove-NodeModules

For each module under node_modules, it looks for sub-modules and moves them to the top-level, with a rename at the same time according to the depth. In my case of gulp-imagemin and imagemin-pngquant, the directory tree was 26 levels deep! Once that rename is done, I can remove the node_modules directory easily.

Now I can run Remove-NodeModules -Verbose and see it all happening.

Ok – so rimraf is easier!