Using Task Runner and NPM in ASP.NET Core in Visual Studio 2019

by Michael Szul on

If you're a Visual Studio user (and I'll admit, I haven't used Visual Studio in quite some time since I converted to Visual Studio Code), you're relatively used to VS doing all of the heavy lifting for you. For example, if you were using Visual Studio 2017 with the .NET Framework, but had some front-end trickery going on with NPM scripts, you could easily use the Task Runner and NPM Tasks extensions to tie any of the script properties in your package.json file to pre-build or post-build hooks in the VS chain. This way, when you built your ASP.NET application, you didn't have to remember to transpile your TypeScript first.

Things got a little trickier with Visual Studio 2019 and ASP.NET Core. For one, it took a while for the extensions to be updated to work with 2019. Once they did, if your package.json file resided in your wwwroot folder, the Task Runner won't pick it up and parse the scripts. This is a known issue/request reported in GitHub, and something that many developers have run into. The Task Runner needs the package.json file to be in the root of the project folder.

This is easily solved by create a second package.json file in the project root whose sole purpose is to change directories and run the commands in the script properties.

For example, the following package.json file could be in your root directory (the same directory as your *.csproj file:

{
        "scripts": {
          "build": "cd wwwroot && browserify ./static/ts/app.ts -p [ tsify -p ./tsconfig.json ] --debug | exorcist ./static/js/gen/bundle.js.map > ./static/js/gen/bundle.js",
        }
      }
      

The script above is doing a number of things, but the first thing it's doing is a cd to the wwwroot directory prior to executing the rest of the commands. Having this script command--and this file--in the root of the project directory will allow Visual Studio's Task Runner extension to pick up the scripts, and let you bind them to the build process. Once bound, your package.json might look like this:

{
        "scripts": {
          "build": "cd wwwroot && browserify ./static/ts/app.ts -p [ tsify -p ./tsconfig.json ] --debug | exorcist ./static/js/gen/bundle.js.map > ./static/js/gen/bundle.js"
        },
        "-vs-binding": {
          "BeforeBuild": [
            "build"
          ]
        }
      }
      

…and as a result, your build process should run the NPM "build" script prior to building the ASP.NET Core application without you having to issue any additional commands.