webapi tag new net dotnet asp c# asp.net-mvc npm gulp asp.net-core

c# - tag - forms asp net core



Cómo usar npm con ASP.NET Core (9)

Estoy usando npm para administrar jQuery, Bootstrap, Font Awesome y bibliotecas de clientes similares que necesito para mi aplicación ASP.NET Core.

El enfoque que funcionó para mí comenzó agregando un archivo package.json al proyecto, que se ve así:

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

npm restaura estos paquetes en la carpeta node_modules que está en el mismo nivel que wwwroot en el directorio del proyecto:

Como ASP.NET Core sirve los archivos estáticos de la carpeta wwwroot, y node_modules no está allí, tuve que hacer un par de cambios para que esto funcione, el primero: agregar app.UseFileServer justo antes de app.UseStaticFiles en mi Startup. archivo cs:

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

y el segundo, que incluye node_modules en mis publishingOptions en el archivo project.json:

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

Esto funciona en mi entorno de desarrollo y también funciona cuando lo implemento en mi instancia de Azure App Service, los archivos estáticos jquery, bootstrap y font-awesome se sirven bien, pero no estoy seguro de esta implementación.

¿Cuál es el enfoque correcto para hacer esto?

Esta solución surgió después de recopilar muchos bits de información de varias fuentes y probar algunos que no funcionaron, y parece un poco extraño tener que servir estos archivos desde fuera de wwwroot.

cualquier consejo será apreciado enormemente.


¿Cuál es el enfoque correcto para hacer esto?

Hay muchos enfoques "correctos", solo tiene que decidir cuál es la mejor suite que necesita. Parece que no estás entendiendo cómo usar node_modules ...

Si está familiarizado con NuGet , debe pensar en npm como su contraparte del lado del cliente. Donde el directorio node_modules es como el directorio bin para NuGet . La idea es que este directorio sea solo una ubicación común para almacenar paquetes, en mi opinión, es mejor dependency de los paquetes que necesita como lo ha hecho en package.json . Luego use un corredor de tareas como https://docs.asp.net/en/latest/client-side/using-gulp.html por ejemplo, para copiar los archivos que necesita en la ubicación deseada de wwwroot .

Escribí una ievangelistblog.wordpress.com/2016/01/13/… sobre esto en enero que detalla npm , Gulp y muchos otros detalles que aún son relevantes hoy en día. Además, alguien llamó la atención sobre mi pregunta SO que hice y finalmente me respondí aquí , lo que probablemente sea útil.

gulpfile.js un Gist que muestra el gulpfile.js como ejemplo.

En su Startup.cs todavía es importante usar archivos estáticos:

app.UseStaticFiles();

Esto asegurará que su aplicación pueda acceder a lo que necesita.


Al publicar toda su carpeta node_modules , está implementando muchos más archivos de los que realmente necesitará en producción.

En su lugar, use un corredor de tareas como parte de su proceso de compilación para empaquetar los archivos que necesita e implementarlos en su carpeta wwwroot . Esto también le permitirá concatenar y minimizar sus activos al mismo tiempo, en lugar de tener que servir a cada biblioteca individual por separado.

Luego, también puede eliminar por completo la configuración de UseStaticFiles y confiar en UseStaticFiles en UseStaticFiles lugar.

Actualmente, gulp es el corredor de tareas VS elegido. Agregue un gulpfile.js a la raíz de su proyecto y configúrelo para procesar sus archivos estáticos en la publicación.

Por ejemplo, puede agregar la siguiente sección de scripts a su project.json :

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

Lo que funcionaría con el siguiente archivo de trago (el valor predeterminado cuando se andamia con 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"]);



He encontrado una mejor manera de administrar paquetes JS en mi proyecto con los corredores de tareas NPM Gulp / Grunt. No me gusta la idea de tener un NPM con otra capa de biblioteca javascript para manejar la "automatización", y mi requisito número uno es ejecutar la actualización npm sin ninguna otra preocupación si necesito ejecutar cosas de gulp, si copió con éxito todo y viceversa.

La forma NPM:

  • El minificador JS ya está incluido en el núcleo de ASP.net, busque bundleconfig.json para que esto no sea un problema para mí (no compilar algo personalizado)
  • Lo bueno de NPM es que tiene una buena estructura de archivos, por lo que siempre puedo encontrar las versiones precompiladas / minimizadas de las dependencias en node_modules / module / dist
  • Estoy usando un script NPM node_modules / .hooks / {eventname} que maneja la copia / actualización / eliminación de los archivos Project / wwwroot / lib / module / dist / .js, puede encontrar la documentación aquí https://docs.npmjs.com/misc/scripts (actualizaré el script que estoy usando para git una vez que esté más pulido) No necesito corredores de tareas adicionales ( herramientas .js que no me gustan) lo que mantiene mi proyecto limpio y simple.

La forma de pitón:

https://pypi.python.org/pyp ... pero en este caso necesita mantener las fuentes manualmente


Instale el paquete y el minificador en las extensiones de Visual Studio

Luego crea un bundleconfig.json e ingresa lo siguiente como:

// 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 } ]

Por lo tanto, el paquete y el minificador (basado en gulp) tiene acceso a los archivos fuente (que deben excluirse de Visual Studio y también de GIT) y los coloca en wwwroot como se especifica

solo el efecto secundario cada vez que lo guarde lo ejecutará (o puede configurarlo o ejecutarlo manualmente)


Por favor, disculpe la duración de esta publicación.

Este es un ejemplo de trabajo con ASP.NET Core versión 2.5.

Algo importante es que project.json está obsoleto ( ver aquí ) a favor de .csproj . Un problema con .csproj . El archivo es la gran cantidad de características y el hecho de que no hay una ubicación central para su documentación ( ver aquí ).

Una cosa más, este ejemplo está ejecutando ASP.NET core en un contenedor Docker Linux (alpine 3.9); entonces los caminos reflejarán eso. También usa gulp ^ 4.0. Sin embargo, con algunas modificaciones, debería funcionar con versiones anteriores de ASP.NET Core, Gulp, NodeJS y también sin Docker.

Pero aquí hay una respuesta:

gulpfile.js ver el ejemplo de trabajo real aquí

// 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 };

Agregue un destino en el archivo .csproj . Tenga en cuenta que también agregamos un Watch para mirar y excluir si aprovechamos el comando 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>

Ahora, cuando se dotnet run build , también instalará y compilará módulos de nodo.


Shawn Wildermuth tiene una buena guía aquí: https://wildermuth.com/2017/11/19/ASP-NET-Core-2-0-and-the-End-of-Bower

El artículo enlaza con el archivo de saltos en GitHub donde implementó la estrategia en el artículo. Puede copiar y pegar la mayor parte del contenido del archivo gulp en el suyo, pero asegúrese de agregar los paquetes apropiados en package.json en devDependencies: gulp gulp-uglify gulp-concat rimraf merge-stream


Te doy dos respuestas. npm combinado con otras herramientas es poderoso pero requiere algo de trabajo para configurarlo. Si solo desea descargar algunas bibliotecas, puede usar el Administrador de bibliotecas (publicado en Visual Studio 15.8).

NPM (avanzado)

Primero agregue package.json en la raíz de su proyecto. Agregue el siguiente contenido:

{ "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" } }

Esto hará que NPM descargue Bootstrap, JQuery y otras bibliotecas que se usan en un nuevo proyecto principal de asp.net a una carpeta llamada node_modules. El siguiente paso es copiar los archivos en un lugar apropiado. Para hacer esto, usaremos gulp, que también fue descargado por NPM. Luego agregue un nuevo archivo en la raíz de su proyecto llamado gulpfile.js . Agregue el siguiente contenido:

/// <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")); });

Este archivo contiene un código JavaScript que se ejecuta cuando se construye y limpia el proyecto. Copiará todos los archivos necesarios a lib2 ( no lib, puede cambiar esto fácilmente ). He usado la misma estructura que en un nuevo proyecto, pero es fácil cambiar archivos a una ubicación diferente. Si mueve los archivos, asegúrese de actualizar también _Layout.cshtml . Tenga en cuenta que todos los archivos en el directorio lib2 se eliminarán cuando se limpie el proyecto.

Si hace clic derecho en gulpfile.js , puede seleccionar Task Runner Explorer . Desde aquí puede ejecutar gulp manualmente para copiar o limpiar archivos.

Gulp también podría ser útil para otras tareas como minify JavaScript y CSS-files:

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

Gerente de Biblioteca (Simple)

Haga clic derecho en su proyecto y seleccione Administrar bibliotecas laterales del cliente . El archivo libman.json ya está abierto. En este archivo, especifica qué biblioteca y archivos usar y dónde deben almacenarse localmente. Muy simple! El siguiente archivo copia las bibliotecas predeterminadas que se utilizan al crear un nuevo proyecto ASP.NET Core 2.1:

{ "version": "1.0", "defaultProvider": "cdnjs", "libraries": [ { "library": "[email protected]", "files": [ "jquery.js", "jquery.min.map", "jquery.min.js" ], "destination": "wwwroot/lib/jquery/dist/" }, { "library": "[email protected]", "files": [ "additional-methods.js", "additional-methods.min.js", "jquery.validate.js", "jquery.validate.min.js" ], "destination": "wwwroot/lib/jquery-validation/dist/" }, { "library": "[email protected]", "files": [ "jquery.validate.unobtrusive.js", "jquery.validate.unobtrusive.min.js" ], "destination": "wwwroot/lib/jquery-validation-unobtrusive/" }, { "library": "[email protected]", "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": "[email protected]", "files": [ "list.js", "list.min.js" ], "destination": "wwwroot/lib/listjs" } ] }

Si mueve los archivos, asegúrese de actualizar también _Layout.cshtml .


  • Usar npm para administrar bibliotecas del lado del cliente es una buena opción (a diferencia de Bower o NuGet), está pensando en la dirección correcta :)
  • Divida los proyectos del lado del servidor (ASP.NET Core) y del lado del cliente (por ejemplo, Angular 2, Ember, React) en carpetas separadas (de lo contrario, su proyecto ASP.NET puede tener mucho ruido: pruebas unitarias para el código del lado del cliente, node_modules carpeta, construir artefactos, etc.). Los desarrolladores front-end que trabajan en el mismo equipo que tú te lo agradecerán :)
  • Restaure los módulos npm en el nivel de la solución (de manera similar a cómo restaura paquetes a través de NuGet, no en la carpeta del proyecto), de esta manera también puede tener pruebas de unidad e integración en una carpeta separada (en lugar de tener pruebas de JavaScript del lado del cliente dentro de su Proyecto ASP.NET Core).
  • Es posible que el uso no necesite FileServer , tener StaticFiles debería ser suficiente para servir archivos estáticos (.js, imágenes, etc.)
  • Use Webpack para agrupar su código del lado del cliente en uno o más fragmentos (paquetes)
  • Es posible que no necesite Gulp / Grunt si está utilizando un paquete de módulos como Webpack
  • Escriba scripts de automatización de compilación en ES2015 + JavaScript (a diferencia de Bash o PowerShell), funcionarán multiplataforma y serán más accesibles para una variedad de desarrolladores web (todos hablan JavaScript hoy en día)
  • Cambie el nombre de wwwroot a public , de lo contrario, la estructura de carpetas en Azure Web Apps será confusa ( D:/Home/site/wwwroot/wwwroot vs D:/Home/site/wwwroot/public )
  • Publique solo la salida compilada en Azure Web Apps (nunca debe enviar node_modules a un servidor de alojamiento web). Ver tools/deploy.js como ejemplo.

Visite ASP.NET Core Starter Kit en GitHub (descargo de responsabilidad: soy el autor)