Подтвердить что ты не робот

Как использовать npm с ядром ASP.NET

Я использую npm для управления jQuery, Bootstrap, Font Awesome и аналогичных клиентских библиотек, которые мне нужны для моего основного приложения ASP.NET.

Подход, который работал у меня, начинался с добавления в проект файла package.json, который выглядит следующим образом:

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

npm восстанавливает эти пакеты в папку node_modules, которая находится на том же уровне, что и wwwroot в каталоге проекта:

введите описание изображения здесь

Поскольку ASP.NET Core обслуживает статические файлы из папки wwwroot, а node_modules не существует, мне пришлось внести пару изменений, чтобы сделать эту работу, первая: добавление app.UseFileServer прямо перед приложением. UseStaticFiles в моем файле Startup.cs:

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

app.UseStaticFiles();

и второй, в том числе node_modules в моих публикацияхOpions в файле project.json:

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

Это работает в моей среде разработки, и это также работает, когда я развертываю его в своем экземпляре службы Azure App Service, файлы jquery, bootstrap и font-awesome статические файлы хорошо обслуживаются, но я не уверен в этой реализации.

Каков правильный подход для этого?

Это решение появилось после сбора большого количества бит информации из нескольких источников и попыток некоторых, которые не работали, и кажется немного странным, что они должны обслуживать эти файлы извне wwwroot.

Приветствуются любые советы.

4b9b3361

Ответ 1

Публикуя всю node_modules папку node_modules вы развертываете гораздо больше файлов, чем вам потребуется на самом деле.

Вместо этого используйте средство wwwroot задач как часть процесса сборки, чтобы упаковать wwwroot вам файлы и развернуть их в папке wwwroot. Это также позволит вам объединять и минимизировать ваши активы одновременно, вместо того, чтобы обслуживать каждую отдельную библиотеку в отдельности.

Вы можете также полностью удалить FileServer конфигурацию и полагаться на UseStaticFiles вместо этого.

В настоящее время Gulp является выбранным для выполнения задач VS. Добавьте gulpfile.js в корневой каталог вашего проекта и настройте его для обработки статических файлов при публикации.

Например, вы можете добавить следующий раздел scripts в ваш project.json:

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

Который будет работать со следующим gulpfile (по умолчанию при скаффолдинге с 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"]);

Ответ 2

введите описание изображения здесь

  • Использование npm для управления клиентскими библиотеками - хороший выбор (в отличие от Bower или NuGet), вы думаете в правильном направлении:)
  • Разделение серверных (ASP.NET Core) и клиентских (например, Angular 2, Ember, React) проектов на отдельные папки (в противном случае в вашем проекте ASP.NET может быть много шумовых модульных тестов для клиента -side code, node_modules, создавать артефакты и т.д.). Разработчики Front-end, работающие в одной команде с вами, будут вам благодарны за это:)
  • Восстановить модули npm на уровне решения (аналогично, как вы восстанавливаете пакеты через NuGet, а не в папку проекта), таким образом, вы можете иметь тесты модуляции и интеграции в отдельной папке (в отличие от клиентского JavaScript тесты внутри вашего проекта ASP.NET Core).
  • Использование может не понадобиться FileServer, наличие StaticFiles должно быть достаточным для обслуживания статических файлов (.js, изображений и т.д.).
  • Использование Webpack для связывания вашего клиентского кода с одним или несколькими фрагментами (пачками)
  • Вам может не понадобиться Gulp/Grunt, если вы используете модуль-расслоение, например Webpack
  • Запишите сценарии автоматизации сборки в ES2015 + JavaScript (в отличие от Bash или PowerShell), они будут работать межплатформенными и будут более доступны для различных веб-разработчиков (каждый из них говорит JavaScript в наши дни).
  • Переименуйте wwwroot в public, иначе структура папок в Azure Web Apps будет путать (D:\Home\site\wwwroot\wwwroot vs D:\Home\site\wwwroot\public)
  • Опубликовать только скомпилированный вывод в Azure Web Apps (вы никогда не должны нажимать node_modules на сервер веб-хостинга). См. tools/deploy.js в качестве примера.

Посетите Стартовый комплект для ASP.NET на GitHub (отказ от ответственности: я автор)

Ответ 3

Установите Bundler и Minifier в расширениях Visual Studio

Затем вы создаете bundleconfig.json и вводите следующее, например:

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

Таким образом, пакет и минификатор (на основе gulp) имеет доступ к исходным файлам (которые должны быть исключены из Visual Studio, а также исключены из GIT) и помещает их в wwwroot, как указано

только побочный эффект каждый раз, когда вы сохраняете, он будет запускаться (или вы можете установить его или запустить его вручную)

Ответ 4

Я даю вам два ответа. NPM в сочетании с другими инструментами является мощным, но требует настройки для настройки. Если вы просто хотите загрузить некоторые библиотеки, вы можете вместо этого использовать диспетчер библиотек (выпущен в Visual Studio 15.8).

NPM (продвинутый уровень)

Сначала добавьте package.json в корневой каталог вашего проекта. Добавьте следующий контент:

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

Это заставит NPM загрузить Bootstrap, JQuery и другие библиотеки, которые используются в новом базовом проекте asp.net, в папку с именем node_modules. Следующим шагом является копирование файлов в соответствующее место. Для этого мы будем использовать gulp, который также был загружен NPM. Затем добавьте новый файл в корневой каталог вашего проекта с именем gulpfile.js. Добавьте следующий контент:

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

Этот файл содержит код JavaScript, который выполняется при сборке и очистке проекта. Он скопирует все необходимые файлы в lib2 (не в lib - вы можете легко это изменить). Я использовал ту же структуру, что и в новом проекте, но ее легко изменить в другое место. Если вы перемещаете файлы, убедитесь, что вы также обновили _Layout.cshtml. Обратите внимание, что все файлы в каталоге lib2 будут удалены при очистке проекта.

Если вы щелкнете правой кнопкой мыши по gulpfile.js, вы можете выбрать Task Runner Explorer. Отсюда вы можете запустить gulp вручную для копирования или очистки файлов.

Gulp также может быть полезен для других задач, таких как минимизация JavaScript и CSS файлов:

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

Диспетчер библиотек (простой)

Щелкните правой кнопкой мыши по вашему проекту и выберите Управление клиентскими библиотеками. Файл libman.json теперь открыт. В этом файле вы указываете, какую библиотеку и файлы использовать и где они должны храниться локально. Действительно просто! Следующий файл копирует библиотеки по умолчанию, которые используются при создании нового проекта 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"
    }
  ]
}

Если вы перемещаете файлы, убедитесь, что вы также обновили _Layout.cshtml.

Ответ 6

Каков правильный подход для этого?

Есть много "правильных" подходов, вы просто решаете, какой из них наилучшим образом соответствует вашим потребностям. Кажется, вы не понимаете, как использовать node_modules...

Если вы знакомы с NuGet, вы должны подумать о npm как о своей стороне на стороне клиента. Где каталог node_modules похож на каталог bin для NuGet. Идея состоит в том, что этот каталог является просто общим местом для хранения пакетов, на мой взгляд, лучше взять dependency на нужные вам пакеты, как вы это делали в package.json. Затем используйте бегун задачи, например Gulp, чтобы скопировать нужные вам файлы в нужное место wwwroot.

Я написал сообщение в блоге об этом в январе, в котором подробно описаны npm, Gulp и целый ряд других деталей, которые по-прежнему актуальны и сегодня. Кроме того, кто-то обратил внимание на мой вопрос SO, который я задал, и в конечном итоге ответил мне здесь, что, вероятно, полезно.

Я создал Gist, который показывает пример gulpfile.js.

В вашем Startup.cs все еще важно использовать статические файлы:

app.UseStaticFiles();

Это гарантирует, что ваше приложение сможет получить доступ к тем, что ему нужно.

Ответ 7

У Шона Вильдермута есть хорошее руководство: https://wildermuth.com/2017/11/19/ASP-NET-Core-2-0-and-the-End-of-Bower

Статья ссылается на gulpfile на GitHub, где он реализовал стратегию в статье. Вы можете просто скопировать и вставить большую часть содержимого gulpfile в свой файл, но обязательно добавьте соответствующие пакеты в package.json в devDependencies: gulp gulp-uglify gulp-concat rimraf merge-stream

Ответ 8

Я нашел лучший способ управления пакетами JS в моем проекте с помощью обработчиков задач NPM Gulp/Grunt. Мне не нравится идея иметь NPM с другим слоем библиотеки javascript для обработки "автоматизации", и мое требование номер один - просто запустить обновление npm, не беспокоясь о том, нужно ли мне запускать gulp вещи, если он успешно все скопировал и наоборот.

NPM способ:

  • Минификатор JS уже включен в ядро ASP.net, ищите bundleconfig.json, так что это не проблема для меня (не компилируя что-то нестандартное)
  • Преимущество NPM в том, что у него хорошая файловая структура, поэтому я всегда могу найти предварительно скомпилированные/минимизированные версии зависимостей в файле node_modules/module/dist
  • Я использую сценарий NPM node_modules/.hooks/{eventname}, который обрабатывает копирование/обновление/удаление файлов Project/wwwroot/lib/module/dist/.js, вы можете найти документацию здесь https://docs.npmjs.com/misc/scriptsобновлю скрипт, который я использую для git, как только он будет более отшлифован). Мне не нужны дополнительные исполнители задач (инструменты .js, которые мне не нравятся) что делает мой проект чистым и простым.

Путь питона:

https://pypi.python.org/pyp... но в этом случае вам нужно поддерживать источники вручную

Ответ 9

Пожалуйста, извините за длину этого поста.

Это рабочий пример использования ASP.NET Core версии 2.5.

Следует отметить, что project.json устарел (см. Здесь) в пользу .csproj. Проблема с .csproj. Файл - это большое количество функций и тот факт, что для его документации нет центрального расположения (см. здесь).

Еще одна вещь, этот пример - запуск ядра ASP.NET в контейнере Docker Linux (alpine 3.9); поэтому пути будут отражать это. Он также использует gulp ^ 4.0. Однако с некоторыми изменениями он должен работать с более старыми версиями ASP.NET Core, Gulp, NodeJS, а также без Docker.

Но вот ответ:

gulpfile.js увидеть реальный рабочий пример здесь

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

Добавьте цель в файл .csproj. Обратите внимание, что мы также добавили Watch для просмотра и исключения, если мы воспользуемся 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>

Теперь, когда dotnet run build он также устанавливает и собирает модули узлов.

Ответ 10

Гораздо более простой подход - использовать пакет OdeToCode.UseNodeModules. Я только что проверил это с .Net Core 3.0. Все, что вам нужно сделать, это добавить пакет в решение и сослаться на него в методе Configure класса Startup:

app.UseNodeModules();

Я узнал об этом из превосходного создания веб-приложения с ASP.NET Core, MVC, Entity Framework Core, Bootstrap и Angular Pluralsight, разработанного Шоном Вильдермутом.