Visual Studio 2017 年在 MVC 应用程序上使用 SystemJs 和 Webpack

Using SystemJs and Webpack on an MVC application in Visual Studio 2017

我正在使用 Visual Studio 2017 开发托管在 MVC 应用程序 (.Net 4.6) 中的 Angular 4.1 SPA 应用程序。我使用 @angular/cli 创建了 Angular 部分,然后将其合并到现有的 MVC 应用程序中。它的结构如 CandorDeveloper 文章 (http://candordeveloper.com/2017/04/12/how-to-use-angular-cli-with-visual-studio-2017/) 中所述。

这一切都很好,但由于@angular/cli 使用 Webpack,它非常慢。对 Html、typescript 或 css 的任何更改都需要大约 4 分钟的构建。我以前有一个设置相同但没有使用 @angular/cli 或 Webpack 的应用程序。它仍然是一个 Visual Studio 2017 MVC 应用程序(.Net 4.6)托管一个 Angular 4.1 SPA 应用程序,但它使用了 SystemJs。它的构建速度非常快,我在 VS2017 中拥有与任何 .net Web 应用程序相同的出色调试体验。因此,我想我会尝试同时使用 SystemJs 和 Webpack。

我的想法是在 VS2017 "Debug" 模式下使用 SystemJs 构建应用程序以获得速度和便利性,然后使用 Webpack for "Release" 模式构建生产版本并能够使用 AOT .为了尝试实现这一点,我将以下内容放入我的 _Layout.cshtml 文件中:

@if(!HttpContext.Current.IsDebuggingEnabled)
{
    <script type="text/javascript" src="~/Scripts/NgApp/inline.bundle.js"></script>
    <script type="text/javascript" src="~/Scripts/NgApp/polyfills.bundle.js"></script>
    <script type="text/javascript" src="~/Scripts/NgApp/styles.bundle.js"></script>
    <script type="text/javascript" src="~/Scripts/NgApp/vendor.bundle.js"></script>
    <script type="text/javascript" src="~/Scripts/NgApp/main.bundle.js"></script>
}
else
{
    <!-- 1. Load libraries -->
    <!-- Polyfill(s) for older browsers -->
    <script src="~/MyAppCli/node_modules/core-js/client/shim.min.js"></script>
    <script src="~/MyAppCli/node_modules/zone.js/dist/zone.js"></script>
    <script src="~/MyAppCli/node_modules/systemjs/dist/system.src.js"></script>
    <script src="~/MyAppCli/src/systemjs.config.js"></script>
    <script>
        System.import('src/main.js')
        .catch(function (err) { console.error(err); });
    </script>
}

我在项目的预构建事件中添加了:

if $(ConfigurationName) == Release  (
echo "cd $(SolutionDir)MyApp\MyAppCli" &&^
cd "$(SolutionDir)MyApp\MyAppCli" &&^
echo "building v" &&^
npm run build
)

然后我将 systemjs 添加到 package.json 文件的 devDependencies 并创建了一个合适的 systemjs.config.js 文件。

我的systemjs.config.js:

(function (global)
{
System.config({
    paths: {
        // paths serve as alias 
        'npm:': MyAppCli/node_modules/'
    },
    // map tells the System loader where to look for things 
    map: {
        // our app is within the app folder 
        'app': 'src',


        // angular bundles 
        '@angular/animations': 'npm:@angular/animations/bundles/animations.umd.js',
        '@angular/animations/browser': 'npm:@angular/animations/bundles/animations-browser.umd.js',
        '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
        '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
        '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
        '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
        '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
        '@angular/platform-browser/animations': 'npm:@angular/platform-browser/bundles/platform-browser-animations.umd.js',
        '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
        '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
        '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',


        // other libraries 
        'cldr-data': 'npm:cldr-data',
        'rxjs': 'npm:rxjs',
        'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
        'jszip': 'npm:jszip',
        'systemjs-plugin-json': 'npm:systemjs-plugin-json',


        // Kendo UI for Angular scopes 
        '@progress': 'npm:@progress',
        '@telerik': 'npm:@telerik'
    },
    meta: {
        '*.json': {
            loader: 'systemjs-plugin-json'
        }
    },
    // packages tells the System loader how to load when no filename and/or no extension 
    packages: {
        app: {
            defaultExtension: 'js',
            meta: {
                './*.js': {
                    loader: 'systemjs-angular-loader.js'
                }
            }
        },


        rxjs: {
            defaultExtension: 'js'
        },


        jszip: {
            defaultExtension: 'js',
            main: './dist/jszip.js'
        },


        'systemjs-plugin-json': {
            defaultExtension: 'js',
            main: 'json.js'
        },


        // Kendo UI for Angular packages 
        'npm:@progress/kendo-angular-buttons': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-angular-charts': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-angular-dateinputs': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-angular-dropdowns': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-angular-dialog': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-angular-grid': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-angular-inputs': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-angular-intl': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-angular-l10n': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-angular-excel-export': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-angular-layout': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-angular-scrollview': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-angular-sortable': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-angular-popup': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-angular-resize-sensor': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-angular-upload': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-charts': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-data-query': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-date-math': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-drawing': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-file-saver': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-intl': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-ooxml': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@progress/kendo-popup-common': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@telerik/kendo-draggable': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@telerik/kendo-dropdowns-common': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@telerik/kendo-intl': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        },


        'npm:@telerik/kendo-inputs-common': {
            main: './dist/npm/main.js',
            defaultExtension: 'js'
        }
       }
    });
})(this); 

该项目可以在 "Release" 中找到(使用 Webpack),并且可以使用 @angular/cli 构建或提供服务。问题是尝试使用 SystemJs 在 "Debug" 中 运行 它。它开始正常并加载 main.js 文件但无法加载 app.module。我收到错误: “(SystemJS) XHR 错误(404 未找到)加载 http://localhost/MyApp/MyAppCli/src/app/app.modulehttp://localhost/MyApp/MyAppCli/src/main.js"

http://localhost/MyApp/MyAppCli/src/app/app.module 加载为 "./app/app.module" 时出错

主要文件和应用程序结构是:

MyApp
  |-----MyAppCli
  |        |----src
  |        |     |----app
  |        |     |     |----app.module.js
  |        |     |      
  |        |     |----main.js
  |        |     |----systemjs.config.js
  |        |     |----systemjs-angular-loader.js
  |        |
  |        |----node_modules
  |        |----package.json
  |
  |-----Views
  |       |----Shared
  |              |----_Layout.cshtml
  |
  |-----web.config

是否可以同时使用 Systemjs 和 Webpack?如果可以,我该如何让它工作?

请帮忙。

谢谢yurzui!你的最后一条评论解决了这个问题。一旦我有 'map': { app: 'MyAppCli/src' 在 systemjs.config.js 和 System.import('app/main') 在 _Layout.cshtml (我没有使用Index.html) 它起作用了。我现在可以在我的项目中同时使用 Systemjs 和 Webpack。唯一奇怪的是,IE11 加载速度非常慢,但可以快速关闭,而 Chrome 加载速度非常快,但关闭 VS2017 调试器需要很长时间。我猜这是一个 VS2017 错误,它们具有针对 IE 和 Chrome 的新调试功能,因为 Firefox 加载和卸载速度很快,但在 VS2017 中没有断点调试。

再次感谢!