Интеграция Angular и Webpack в ASP.NET приложение MVC [закрыто]

Я ищу запись с шагами, которые я могу выполнить, чтобы добавить Angular к существующему приложению MVC, которое живет в области моего решения. Я нашел запись, которая показывает мне, как добавить угловой, используя глоток.JS файл, который извлекает необходимые папки node_modules и transpiles мой TS файлов в файлы JS. Я хотел бы сделать то же самое вместо использования webpack.

enter image description here

В настоящее время мой пакет.json выглядит так.

{
    "version": "1.0.0",
    "name": "aspnet",
    "private": true,
    "scripts": {},
    "dependencies": {
        "@angular/animations": "4.3.5",
        "@angular/common": "4.3.5",
        "@angular/compiler": "4.3.5",
        "@angular/compiler-cli": "4.3.5",
        "@angular/core": "4.3.5",
        "@angular/forms": "4.3.5",
        "@angular/http": "4.3.5",
        "@angular/platform-browser": "4.3.5",
        "@angular/platform-browser-dynamic": "4.3.5",
        "@angular/platform-server": "4.3.5",
        "@angular/router": "4.3.5",
        "@angular/upgrade": "4.3.5",
        "angular-in-memory-web-api": "0.3.2",
        "bootstrap": "3.3.7",
        "core-js": "2.5.0",
        "ie-shim": "0.1.0",
        "rxjs": "5.4.3",
        "zone.js": "0.8.16",
        "systemjs": "^0.20.18"
    },
    "devDependencies": {
        "gulp": "^3.9.1",
        "gulp-clean": "^0.3.2",
        "gulp-concat": "^2.6.1",
        "gulp-tsc": "~1.3.2",
        "gulp-typescript": "^3.2.2",
        "path": "^0.12.7",
        "typescript": "^2.4.2"
    }
}

этой это запись, за которой я следил, которая использует gulp, и это работает.

но я бы предпочел использовать webpack вместо задачи gulp.

1 ответов


я надеюсь, что это поможет вам найти идею, потому что наши проекты также должны интегрировать webpack и ASP.NET MVC вместе. Отметил, что это мое собственное предложение, чтобы был лучший способ сделать это. Ниже то, что мы делаем.

Регистрация исходный код на Github

module 1

1. Структура проекта

мы разделили наш проект на две папки: клиент и сервер. Эта воля находиться в mvc5-угловой-webpack папка и эта папка будет зафиксирована в репозитории

mvc5-angular-webpack/
├── Server/
│   ├── WebApplication/
│   │     ├── Controllers/
│   │     ├── Scripts/
│   │     ├── Web.config
│   │     ├── Many more folder and file...
│   │        
│   └── Web-Core.sln
│   
├── Client/
    ├── modules
    │     ├── angularModule-1/
    │     │      ├── main.ts
    │     │      ├── app.modules.ts
    │     │      ├── app.component.ts
    │     │      ├── Many more file...
    │     │
    │     ├── angularModule-2/
    │     │      ├── main.ts
    │     │      ├── app.modules.ts
    │     │      ├── app.component.ts
    │     │      ├── Many more file...
    │     ├── polyfill.ts
    │     ├── vendor.ts
    │
    └── build.bat
    └── npm-shrinkwrap.json
    └── package.json
    └── tsconfig.json
    └── tslint.json
    └── webpack.config.js
  • на сервер Папка, мы добавили решение MVC с именем Web-Core.sln и весь проект общей библиотеки написан на C#.
  • на клиент папка содержит только front-end связанные вещи. Чтобы построить проект front, просто вызовите build.bat. Я расскажу об этом файле позже. Внутри модулей папка, наш проект создаст каждую подпапку для каждого модуля.

наш веб-сайт имеет некоторый модуль, все еще использующий рендеринг на стороне сервера с помощью pure Razor. И есть некоторый модуль, написанный в клиентском коде с AngularJS и Angular.

2. Настроить webpack

предположим, что вы настроили все typescript и npm уже. Посмотрим, что у меня внутри!--19-->

const webpack = require('webpack')
const path = require('path')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const entryPath = path.resolve(__dirname, 'modules')
const corePath = path.resolve(__dirname, '../Server/WebApplication/Scripts/ng2')
const module1 = `${entryPath}/angularModule-1`
const module2 = `${entryPath}/angularModule-2`

module.exports = (envOptions) => {
    envOptions = envOptions || {};

    const config = {
        entry: {
            'polyfills': `${entryPath}/polyfill.ts`,
            'vendors': `${entryPath}/vendor.ts`,
            'module1': `${module1}/main.ts`,
            'module2': `${module2}/main.ts`            
        },
        output: {
            path: corePath,
            filename: '[name].js',
            sourceMapFilename: "[name].js.map"            
        },
        resolve: {
            extensions: ['.ts', '.js', '.html']
        },
        module: {
            rules: [
                {
                    test: /\.ts$/,
                    loaders: ['awesome-typescript-loader', 'angular2-template-loader']
                },
                {
                    test: /\.html$/,
                    loader: 'raw-loader'
                },
                {
                    test: /\.css$/,
                    loader: 'raw-loader'
                }
            ]
        },
        devtool: 'source-map',
        plugins: [
            new webpack.NoEmitOnErrorsPlugin(),
            new webpack.optimize.CommonsChunkPlugin({
                name: ['vendors', 'polyfills']
            })
        ]
    }

    if (envOptions.MODE === 'prod') {
        config.plugins.push(
            new UglifyJsPlugin()
        )
    }

    return config;
}

поэтому в основном он будет пытаться разрешите каталог на верхнем уровне и поместите все скомпилированные файлы в Скрипты / ng2 внутри сервер.

3. Настройка сценария npm

после настройки webpack, мы в основном добавим еще несколько сценариев для запуска во время процесса сборки. Добавьте следующий код

"scripts": {
    "tsc": "tsc",
    "tsc:w": "tsc -w",
    "dev": "webpack-dev-server --https --open",
    "watch": "webpack --config webpack.config.js --watch",
    "build": "webpack --config webpack.config.js",
    "build:html": "webpack --config webpack-html-plugin.config.js --env.MODE=prod",
    "build:prod": "webpack --config webpack.config.js --env.MODE=prod"    
}

4. Настроить build.bat

в начале угловой интеграции 2, мы создали пустой проект веб-приложения для интерфейсной цели и добавили этот проект в качестве зависимости от нашего WebApplication. Но наша бэкэнд-команда позже пожаловалась на то, как медленно идет процесс front-end. Потому что им не нужен проект front-end для сборки каждый раз, когда WebApplication строится.

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

call npm install --production  --loglevel verbose
echo "Build Angular projects"
npm run build:prod

на call продолжить, потому что некоторые из команд прерывают командную строку. См.здесь

скрипт здесь очень простой. Во-первых, мы запускаем установку npm для восстановления всех необходимых зависимостей. Тогда звоните build:prod как мы определили на package.json раньше. Webpack позаботится о связывании нашего кода Typescript в три больших файла JavaScript как vendors.js, polyfills.js и module1.js.

наша команда использовала Jenkins для развертывание, поэтому наши dev ops просто нужно включить, чтобы запустить build.bat и все готово. Если вы хотите запускать его каждый раз, когда ваш проект был построен, вы можете установить его внутри события pre-build или post-build.

pre-build and post-build Источник изображения

5. Ссылка на скомпилированный файл JavaScript в представлении.

обычно мы возвращаем только один вид в области, как показано ниже. The my-angular-app это то, что мы определили в app.component.ts

.cshtml по
<script src="~/Scripts/ng2/polyfills.js"></script>
<script src="~/Scripts/ng2/vendors.js"></script>
<script src="~/Scripts/ng2/module1.js"></script>

<my-angular-app>
    Loading...
</my-angular-app>

HomeController.cs

public ActionResult Module1()
{
    return View();
}

это немного недостаток, если мы используем в производстве. Потому что после обновления скомпилированного JavaScript браузер иногда сохраняет старую версию файла из-за кэширования. Мы должны иметь механизм для предоставления уникального имени для файлов после развертывания. Есть 3 варианта для нас, чтобы сделать так.

i. html-webpack-плагин

если мы работаем с чистым проектом front-end,webpack предоставляет html-webpack-плагин чтобы заботиться о нем, как показано ниже. Технически, он автоматически введет файл JavaScript в наше представление с уникальным идентификатором.

webpack-в html-webpack-плагин.конфиг.js

...
const HtmlWebpackPlugin = require('html-webpack-plugin');
const viewPath = path.resolve(
    __dirname,
    "../Server/WebApplication/Views/Home"
  );
...
entry: {
    polyfills: `${entryPath}/polyfill.ts`,
    vendors: `${entryPath}/vendor.ts`,
    module1: `${module1}/main.ts`      
},
output: {
    path: corePath,
    filename: "[name].[hash].js",
    sourceMapFilename: "[name].[hash].js.map"
}
....
plugins: [,
    ...,
    new HtmlWebpackPlugin({
        template: viewPath + "/loader.cshtml",
        filename: viewPath + "/Module1.cshtml",
        inject: false
    })
]

и в той же папке с указанным представлением Мы создали файл cshtml с именем loader.cshtml

загрузчика.cshtml по

<% for (var chunk in htmlWebpackPlugin.files.chunks) { %>  
    <script src="<%= htmlWebpackPlugin.files.chunks[chunk].entry %>"></script>  
<% } %> 

<my-angular-app>
    Loading...
</my-angular-app>

и запустить npm run build:html о package.json. Если он работает успешно, результат будет выглядеть так.

build html plugin

network html plugin

@{
    ViewBag.Title = "Module 1";
}
<script src="../../Scripts/ng2/vendors.1470de344a0f2260b700.js"></script>
<script src="../../Scripts/ng2/vendors.1470de344a0f2260b700.js"></script>
<script src="../../Scripts/ng2/module1.1470de344a0f2260b700.js"></script>

<my-angular-app>Loading....</my-angular-app>

ii. Определите свою собственную версию JavaScript

в нашем ASP.NET проект MVC немного отличается, потому что мы использовали более одного углового приложения. Таким образом, мы определили версию в классе и добавьте его в конце файла при загрузке JS. Сделав это, мы убедимся, что последняя будет загружена в браузер. Но это вне контекста этого вопроса, поэтому я не буду идти дальше. В принципе, это будет выглядеть как ниже кода.

<script src="@string.Format("{0}?v={1}", "~/Scripts/ng2/polyfills.js", VersionHelper.CurrentVersion())</script>
<script src="@string.Format("{0}?v={1}", "~/Scripts/ng2/vendors.js", VersionHelper.CurrentVersion())</script>
<script src="@string.Format("{0}?v={1}", "~/Scripts/ng2/module1.js", VersionHelper.CurrentVersion())</script>

при подаче его в браузере, он будет выглядеть как

<script src="~/Scripts/ng2/polyfills.js?v=1.1.0"></script>
<script src="~/Scripts/ng2/vendors.js?v=1.1.0"></script>
<script src="~/Scripts/ng2/module1.js?v=1.1.0"></script>

iii. ASP.NET связывание

в Zyllem наша команда не использовала его из-за наших файлов JavaScript настройте внутри модели и отобразите ее позже в представлении.

вы можете просто открыть App_Start\BundleConfig.cs в вашем проекте и конфигурации жгута. Пусть говорят имя module1

bundles.Add(new ScriptBundle("~/bundles/module1").Include(
                "~/Scripts/ng2/polyfills.js",
                "~/Scripts/ng2/vendors.js"
                "~/Scripts/ng2/module1.js"));

и визуализировать внутри представления, делая это.

.cshtml по
@Scripts.Render("~/bundles/module1")

так что при обслуживании в браузере он будет иметь уникальный токен в конце, и он отличается, если вы внесете какие-либо изменения в пакет скриптов.

<script src="/bundles/module1?v=2PbUw0z_gh_Ocp_Vz13rdmmBSG6utLJAXm2lThxYAow1"></script>

если все работает отлично,вы увидите скриншоты ниже.

module 1

module 2


обновление

добавить репозиторий на Github https://github.com/trungk18/mvc5-angular-webpack