How to use npm with ASP.NET core

I use npm to manage jQuery, Bootstrap, Font Awesome, and similar client libraries that I need for my main ASP.NET application.

The approach that worked for me began by adding the package.json file to the project, which looks like this:

{ "version": "1.0.0", "name": "myapp", "private": true, "devDependencies": { }, "dependencies": { "bootstrap": "^3.3.6", "font-awesome": "^4.6.1", "jquery": "^2.2.3" } } 

npm restores these packages to the node_modules folder, which is at the same level as wwwroot in the project directory:

enter image description here

Since ASP.NET Core serves static files from the wwwroot folder, and node_modules does not exist, I had to make a couple of changes to make this work, first: adding app.UseFileServer right before the application. UseStaticFiles in my Startup.cs file:

 app.UseFileServer(new FileServerOptions() { FileProvider = new PhysicalFileProvider( Path.Combine(Directory.GetCurrentDirectory(), @"node_modules")), RequestPath = new PathString("/node_modules"), EnableDirectoryBrowsing = true }); app.UseStaticFiles(); 

and the second, including node_modules in my PublicationsOpions in the project.json file:

 "publishOptions": { "include": [ "web.config", "wwwroot", "Views", "node_modules" ] }, 

This works in my development environment, and it also works when I deploy it in my Azure App Service instance, jquery, bootstrap and font-awesome static files are well served, but I'm not sure about this implementation.

What is the right approach for this?

This solution appeared after collecting a large number of bits of information from several sources and attempts by some that did not work, and it seems a little strange that they should serve these files from outside wwwroot.

Any advice is appreciated.

+101
c # npm asp.net-mvc asp.net-core gulp
Jun 21 '16 at 4:19
source share
9 answers

By publishing the entire node_modules folder, the node_modules folder you deploy a lot more files than you really need.

Instead, use the wwwroot task tool as part of the build process to package wwwroot files for you and deploy them to the wwwroot folder. It will also allow you to consolidate and minimize your assets at the same time, instead of serving each individual library individually.

You can also completely remove the FileServer configuration and rely on UseStaticFiles instead.

Gulp is currently selected to perform VS tasks. Add gulpfile.js to the root directory of your project and configure it to handle static files when publishing.

For example, you can add the following scripts section to your project.json :

  "scripts": { "prepublish": [ "npm install", "bower install", "gulp clean", "gulp min" ] }, 

Which will work with the following gulpfile (by default when scaffolding with yo ):

 /// <binding Clean='clean'/> "use strict"; var gulp = require("gulp"), rimraf = require("rimraf"), concat = require("gulp-concat"), cssmin = require("gulp-cssmin"), uglify = require("gulp-uglify"); var webroot = "./wwwroot/"; var paths = { js: webroot + "js/**/*.js", minJs: webroot + "js/**/*.min.js", css: webroot + "css/**/*.css", minCss: webroot + "css/**/*.min.css", concatJsDest: webroot + "js/site.min.js", concatCssDest: webroot + "css/site.min.css" }; gulp.task("clean:js", function (cb) { rimraf(paths.concatJsDest, cb); }); gulp.task("clean:css", function (cb) { rimraf(paths.concatCssDest, cb); }); gulp.task("clean", ["clean:js", "clean:css"]); gulp.task("min:js", function () { return gulp.src([paths.js, "!" + paths.minJs], { base: "." }) .pipe(concat(paths.concatJsDest)) .pipe(uglify()) .pipe(gulp.dest(".")); }); gulp.task("min:css", function () { return gulp.src([paths.css, "!" + paths.minCss]) .pipe(concat(paths.concatCssDest)) .pipe(cssmin()) .pipe(gulp.dest(".")); }); gulp.task("min", ["min:js", "min:css"]); 
+36
Jun 21 '16 at 7:43
source share

enter image description here

  • Using npm to manage client libraries is a good choice (unlike Bower or NuGet), you think in the right direction :)
  • Separation of server (ASP.NET Core) and client (e.g., Angular 2, Ember, React) projects into separate folders (otherwise your ASP.NET project may have a lot of noise unit tests for the client -side code, node_modules, create artifacts etc.). Front-end developers working in the same team with you will be grateful for this :)
  • Restore npm modules at the solution level (similar to how you restore packages through NuGet and not to the project folder), this way you can have modulation and integration tests in a separate folder (unlike client-side JavaScript tests inside your ASP.NET Core project )
  • FileServer may not be FileServer ; StaticFiles should be sufficient to serve static files (.js, images, etc.).
  • Using Webpack to link your client code to one or more fragments (packs)
  • You may not need Gulp / Grunt if you use a bundle module like Webpack
  • Write build automation scripts in ES2015 + JavaScript (unlike Bash or PowerShell), they will work cross-platform and will be more accessible to various web developers (each of them speaks JavaScript today).
  • Rename wwwroot to public , otherwise the folder structure in Azure Web Apps will be confused ( D:\Home\site\wwwroot\wwwroot vs D:\Home\site\wwwroot\public )
  • Publish only compiled output to Azure Web Apps (you should never push node_modules to the web hosting server). See tools/deploy.js for an example.

Visit the ASP.NET Starter Kit on GitHub (Disclaimer: I'm the author)

+40
Jun 21 '16 at 6:21
source share

Install Bundler and Minifier in Visual Studio Extensions

Then you create bundleconfig.json and enter the following, for example:

 // Configure bundling and minification for the project. // More info at https://go.microsoft.com/fwlink/?LinkId=808241 [ { "outputFileName": "wwwroot/js/jquery.min.js", "inputFiles": [ "node_modules/jquery/dist/jquery.js" ], // Optionally specify minification options "minify": { "enabled": true, "renameLocals": false }, // Optionally generate .map file "sourceMap": false } ] 

Thus, the package and minifier (based on gulp) has access to the source files (which should be excluded from Visual Studio, and also excluded from GIT) and puts them in wwwroot, as indicated

only a side effect every time you save, it will run (or you can install it or run it manually)

+26
Nov 07 '17 at 21:46
source share

I give you two answers. NPM in combination with other tools is powerful, but requires configuration to configure. If you just want to download some libraries, you can use the library manager instead (released in Visual Studio 15.8).

NPM (Advanced)

First add package.json to the root directory of your project. Add the following content:

 { "version": "1.0.0", "name": "asp.net", "private": true, "devDependencies": { "gulp": "3.9.1", "del": "3.0.0" }, "dependencies": { "jquery": "3.3.1", "jquery-validation": "1.17.0", "jquery-validation-unobtrusive": "3.2.10", "bootstrap": "3.3.7" } } 

This will force NPM to load Bootstrap, JQuery, and other libraries used in the new asp.net base project into a folder named node_modules. The next step is to copy the files to the appropriate location. For this, we will use gulp, which was also loaded by NPM. Then add a new file to the root directory of your project called gulpfile.js . Add the following content:

 /// <binding AfterBuild='default' Clean='clean' /> /* This file is the main entry point for defining Gulp tasks and using Gulp plugins. Click here to learn more. http://go.microsoft.com/fwlink/?LinkId=518007 */ var gulp = require('gulp'); var del = require('del'); var nodeRoot = './node_modules/'; var targetPath = './wwwroot/lib/'; gulp.task('clean', function () { return del([targetPath + '/**/*']); }); gulp.task('default', function () { gulp.src(nodeRoot + "bootstrap/dist/js/*").pipe(gulp.dest(targetPath + "/bootstrap/dist/js")); gulp.src(nodeRoot + "bootstrap/dist/css/*").pipe(gulp.dest(targetPath + "/bootstrap/dist/css")); gulp.src(nodeRoot + "bootstrap/dist/fonts/*").pipe(gulp.dest(targetPath + "/bootstrap/dist/fonts")); gulp.src(nodeRoot + "jquery/dist/jquery.js").pipe(gulp.dest(targetPath + "/jquery/dist")); gulp.src(nodeRoot + "jquery/dist/jquery.min.js").pipe(gulp.dest(targetPath + "/jquery/dist")); gulp.src(nodeRoot + "jquery/dist/jquery.min.map").pipe(gulp.dest(targetPath + "/jquery/dist")); gulp.src(nodeRoot + "jquery-validation/dist/*.js").pipe(gulp.dest(targetPath + "/jquery-validation/dist")); gulp.src(nodeRoot + "jquery-validation-unobtrusive/dist/*.js").pipe(gulp.dest(targetPath + "/jquery-validation-unobtrusive")); }); 

This file contains JavaScript code that runs when building and cleaning up the project. It will copy all the necessary files to lib2 ( not to lib - you can easily change this ). I used the same structure as in the new project, but it is easy to change it to another place. If you are moving files, be sure to update _Layout.cshtml as well. Please note that all files in the lib2 directory will be deleted when the project is cleaned.

If you right-click on gulpfile.js , you can select Task Runner Explorer . From here, you can run gulp manually to copy or clean files.

Gulp can also be useful for other tasks, such as minimizing JavaScript and CSS files:

https://docs.microsoft.com/en-us/aspnet/core/client-side/using-gulp?view=aspnetcore-2.1

Library Manager (Simple)

Right-click on your project and select Manage Client Libraries . The libman.json file is now open. In this file you specify which library and files to use and where they should be stored locally. Really easy! The following file copies the default libraries that are used when creating a new ASP.NET Core 2.1 project:

 { "version": "1.0", "defaultProvider": "cdnjs", "libraries": [ { "library": "jquery@3.3.1", "files": [ "jquery.js", "jquery.min.map", "jquery.min.js" ], "destination": "wwwroot/lib/jquery/dist/" }, { "library": "jquery-validate@1.17.0", "files": [ "additional-methods.js", "additional-methods.min.js", "jquery.validate.js", "jquery.validate.min.js" ], "destination": "wwwroot/lib/jquery-validation/dist/" }, { "library": "jquery-validation-unobtrusive@3.2.10", "files": [ "jquery.validate.unobtrusive.js", "jquery.validate.unobtrusive.min.js" ], "destination": "wwwroot/lib/jquery-validation-unobtrusive/" }, { "library": "twitter-bootstrap@3.3.7", "files": [ "css/bootstrap.css", "css/bootstrap.css.map", "css/bootstrap.min.css", "css/bootstrap.min.css.map", "css/bootstrap-theme.css", "css/bootstrap-theme.css.map", "css/bootstrap-theme.min.css", "css/bootstrap-theme.min.css.map", "fonts/glyphicons-halflings-regular.eot", "fonts/glyphicons-halflings-regular.svg", "fonts/glyphicons-halflings-regular.ttf", "fonts/glyphicons-halflings-regular.woff", "fonts/glyphicons-halflings-regular.woff2", "js/bootstrap.js", "js/bootstrap.min.js", "js/npm.js" ], "destination": "wwwroot/lib/bootstrap/dist" }, { "library": "list.js@1.5.0", "files": [ "list.js", "list.min.js" ], "destination": "wwwroot/lib/listjs" } ] } 

If you are moving files, be sure to update _Layout.cshtml as well.

+16
Jul 27 '18 at 11:40
source share

Instead of trying to serve the node modules folder, you can also use Gulp to copy what you need for wwwroot.

https://docs.asp.net/en/latest/client-side/using-gulp.html

It can also help.

Visual Studio 2015 ASP.NET 5, Gulp task not to copy files from node_modules

+7
Jun 21 '16 at 4:28
source share

What is the right approach for this?

There are many “right” approaches, you just decide which one best suits your needs. You don't seem to understand how to use node_modules ...

If you are familiar with NuGet , you should think of npm as your client side. Where the node_modules directory node_modules similar to the bin directory for NuGet . The idea is that this directory is just a general place to store packages, in my opinion, it is better to take dependency on the packages you need, as you did in package.json . Then use a task runner such as Gulp to copy the files you need to the desired wwwroot .

I wrote a blog post about this in January that details npm , Gulp, and a host of other details that are still relevant today. Also, someone paid attention to my SO question that I asked and ended up answering me here , which is probably helpful.

I created a Gist that shows an example of gulpfile.js .

It is still important to use static files in your Startup.cs :

 app.UseStaticFiles(); 

This ensures that your application can access what it needs.

+5
Jun 22 '16 at 11:55
source share

Sean Wildermouth has a good guide: https://wildermuth.com/2017/11/19/ASP-NET-Core-2-0-and-the-End-of-Bower

The article refers to the gulpfile on GitHub, where he implemented the strategy in the article. You can simply copy and paste most of the gulpfile content into your file, but be sure to add the appropriate packages in package.json to devDependencies: gulp gulp-uglify gulp-concat rimraf merge-stream

+1
Jan 05 '18 at 21:39
source share

I found the best way to manage JS packages in my project using NPM Gulp / Grunt task handlers. I don’t like the idea of ​​having NPM with a different javascript library layer to handle “automation”, and my number one requirement is to just start the npm update without worrying about whether I need to run gulp things if it successfully copied everything and vice versa.

NPM method:

  • The JS minifier is already included in the ASP.net core, look for bundleconfig.json, so this is not a problem for me (without compiling something non-standard)
  • The advantage of NPM is that it has a good file structure, so I can always find precompiled / minimized versions of dependencies in the file node_modules / module / dist
  • I use the NPM script node_modules / .hooks / {eventname}, which handles copying / updating / deleting Project / wwwroot / lib / module / dist / .js files, you can find the documentation here https://docs.npmjs.com/misc / scripts (I will update the script that I use for git as soon as it is more polished). I don’t need additional task performers (.js tools that I don’t like) which makes my project clean and simple.

Python path:

https://pypi.python.org/pyp ... but in this case you need to support sources manually

+1
Mar 16 '18 at 17:34
source share

Please excuse the length of this post.

This is a working example of using ASP.NET Core version 2.5.

It should be noted that project.json is deprecated ( see here ) in favor of .csproj . The problem with .csproj . A file is a large number of functions and the fact that there is no central location for its documentation ( see here ).

Another thing, this example is running the ASP.NET kernel in a Docker Linux container (alpine 3.9); therefore, the paths will reflect this. It also uses gulp ^ 4.0. However, with some changes, it should work with older versions of ASP.NET Core, Gulp, NodeJS, as well as without Docker.

But here is the answer:

gulpfile.js see a real working example here

 // ROOT and OUT_DIR are defined in the file above. The OUT_DIR value comes from .NET Core when ASP.net us built. const paths = { styles: { src: '${ROOT}/scss/**/*.scss', dest: '${OUT_DIR}/css' }, bootstrap: { src: [ '${ROOT}/node_modules/bootstrap/dist/css/bootstrap.min.css', '${ROOT}/node_modules/startbootstrap-creative/css/creative.min.css' ], dest: '${OUT_DIR}/css' }, fonts: {// enter correct paths for font-awsome here. src: [ '${ROOT}/node_modules/fontawesome/...', ], dest: '${OUT_DIR}/fonts' }, js: { src: '${ROOT}/js/**/*.js', dest: '${OUT_DIR}/js' }, vendorJs: { src: [ '${ROOT}/node_modules/jquery/dist/jquery.min.js' '${ROOT}/node_modules/bootstrap/dist/js/bootstrap.min.js' ], dest: '${OUT_DIR}/js' } }; // Copy files from node_modules folder to the OUT_DIR. let fonts = () => { return gulp .src(paths.styles.src) .pipe(gulp.dest(paths.styles.dest)); }; // This compiles all the vendor JS files into one, jsut remove the concat to keep them seperate. let vendorJs = () => { return gulp .src(paths.vendorJs.src) .pipe(concat('vendor.js')) .pipe(gulp.dest(paths.vendorJs.dest)); } // Build vendorJs before my other files, then build all other files in parallel to save time. let build = gulp.series(vendorJs, gulp.parallel(js, styles, bootstrap)); module.exports = {// Only add what we intend to use externally. default: build, watch }; 

Add the target to the .csproj file. Please note that we also added Watch to view and exclude if we use dotnet run watch .

app.csprod

  <ItemGroup> <Watch Include="gulpfile.js;js/**/*.js;scss/**/*.scss" Exclude="node_modules/**/*;bin/**/*;obj/**/*" /> </ItemGroup> <Target Name="BuildFrontend" BeforeTargets="Build"> <Exec Command="yarn install" /> <Exec Command="yarn run build -o $(OutputPath)" /> </Target> 

Now that dotnet run build it also installs and collects node modules.

0
May 19 '19 at
source share



All Articles