Angular 5/ASP.NET - “No ResourceLoader implementation has been provided. Can't read the URL”

Viewed 1163

I'm trying to build a new Angular5/ASP.NET SPA on Visual Studio 2017. Therefore i created a .NET Core->ASP.NET Core-Web Application with Angular, which results in a project containing an Angular4 sample application.

Running this application is no problem at all, the problems start when i try to go on Angular 5 (5.0.1 or 5.0.0, does not matter) with this application.

After doing all necessary steps, the app runs fine in Debug mode. But trying to build and start it in Release (or deploy it to azure) leads to the following error:

An unhandled exception occurred while processing the request.

NodeInvocationException: No ResourceLoader implementation has been provided. Can't read the url "app.component.html"
Error: No ResourceLoader implementation has been provided. Can't read the url "app.component.html"
at Object.get (E:\angular4_spielwiese\vs spielwiese\myAngularApp\myAngularApp\ClientApp\dist\vendor.js:98069:15)
at DirectiveNormalizer.module.exports.DirectiveNormalizer._fetch (E:\angular4_spielwiese\vs spielwiese\myAngularApp\myAngularApp\ClientApp\dist\vendor.js:44087:43)
at DirectiveNormalizer.module.exports.DirectiveNormalizer._preParseTemplate (E:\angular4_spielwiese\vs spielwiese\myAngularApp\myAngularApp\ClientApp\dist\vendor.js:44142:29)
at DirectiveNormalizer.module.exports.DirectiveNormalizer.normalizeTemplate (E:\angular4_spielwiese\vs spielwiese\myAngularApp\myAngularApp\ClientApp\dist\vendor.js:44122:36)
at CompileMetadataResolver.module.exports.CompileMetadataResolver.loadDirectiveMetadata (E:\angular4_spielwiese\vs spielwiese\myAngularApp\myAngularApp\ClientApp\dist\vendor.js:55794:75)
at E:\angular4_spielwiese\vs spielwiese\myAngularApp\myAngularApp\ClientApp\dist\vendor.js:74510:72
at Array.forEach (native)
at E:\angular4_spielwiese\vs spielwiese\myAngularApp\myAngularApp\ClientApp\dist\vendor.js:74509:72
at Array.forEach (native)
at JitCompiler.module.exports.JitCompiler._loadModules (E:\angular4_spielwiese\vs spielwiese\myAngularApp\myAngularApp\ClientApp\dist\vendor.js:74506:75)
Microsoft.AspNetCore.NodeServices.HostingModels.HttpNodeInstance+<InvokeExportAsync>d__7.MoveNext()

What i do for moving to Angular5 is: Change Versions in package.json for all Angular-Modules to 5.0.1, also go to newer version for typescript, rxjs, angular/cli and @ngtools/webpack (1.5.0 -> 1.8.0) So my new package.json looks like this:

{
  "name": "myAngularApp",
  "private": true,
  "version": "0.0.0",
  "scripts": {
    "test": "karma start ClientApp/test/karma.conf.js"
  },
  "dependencies": {
    "@angular/animations": "^5.0.1",
    "@angular/common": "^5.0.1",
    "@angular/compiler": "^5.0.1",
    "@angular/core": "^5.0.1",
    "@angular/forms": "^5.0.1",
    "@angular/http": "^5.0.1",
    "@angular/platform-browser": "^5.0.1",
    "@angular/platform-browser-dynamic": "^5.0.1",
    "@angular/platform-server": "^5.0.1",
    "@angular/router": "^5.0.1",
    "@types/webpack-env": "^1.13.0",
    "angular2-template-loader": "^0.6.2",
    "aspnet-prerendering": "^3.0.1",
    "aspnet-webpack": "^2.0.1",
    "awesome-typescript-loader": "^3.2.1",
    "bootstrap": "^3.3.7",
    "css": "^2.2.1",
    "css-loader": "^0.28.7",
    "es6-shim": "^0.35.3",
    "event-source-polyfill": "0.0.9",
    "expose-loader": "^0.7.3",
    "extract-text-webpack-plugin": "^3.0.2",
    "file-loader": "^1.1.5",
    "html-loader": "^0.5.1",
    "html-webpack-plugin": "^2.30.1",
    "isomorphic-fetch": "^2.2.1",
    "jquery": "^3.2.1",
    "json-loader": "^0.5.4",
    "preboot": "^5.1.7",
    "raw-loader": "^0.5.1",
    "reflect-metadata": "^0.1.10",
    "rxjs": "^5.5.2",
    "style-loader": "^0.19.0",
    "to-string-loader": "^1.1.5",
    "typescript": "^2.6.1",
    "zone.js": "^0.8.18"
  },
  "devDependencies": {
    "@angular/cli": "1.5.0",
    "@angular/compiler-cli": "^5.0.1",
    "@ngtools/webpack": "1.8.0",
    "@types/chai": "4.0.1",
    "@types/jasmine": "2.6.3",
    "chai": "4.0.2",
    "jasmine-core": "2.6.4",
    "karma": "1.7.0",
    "karma-chai": "0.1.0",
    "karma-chrome-launcher": "2.2.0",
    "karma-cli": "1.0.1",
    "karma-jasmine": "1.1.0",
    "karma-webpack": "2.0.3",
    "url-loader": "0.6.2",
    "webpack": "3.8.1",
    "webpack-hot-middleware": "2.20.0",
    "webpack-merge": "4.1.1"
  }
}

Then i change AotPlugin in webpack.config.js to AngularCompilerPlugin This is my webpack.config.js:

const path = require('path');
const webpack = require('webpack');
const merge = require('webpack-merge');
const AngularCompilerPlugin = require('@ngtools/webpack').AngularCompilerPlugin;
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;

module.exports = (env) => {
    // Configuration in common to both client-side and server-side bundles
    const isDevBuild = !(env && env.prod);
    const sharedConfig = {
        stats: { modules: false },
        context: __dirname,
        resolve: { extensions: [ '.js', '.ts' ] },
        output: {
            filename: '[name].js',
            publicPath: 'dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix
        },
        module: {
            rules: [
                { test: /\.ts$/, include: /ClientApp/, use: isDevBuild ? ['awesome-typescript-loader?silent=true', 'angular2-template-loader'] : ['awesome-typescript-loader?silent=true', 'angular2-template-loader'] },// '@ngtools/webpack' },
                { test: /\.html$/, use: 'html-loader?minimize=false' },
                { test: /\.css$/, use: [ 'to-string-loader', isDevBuild ? 'css-loader' : 'css-loader?minimize' ] },
                { test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' }
            ]
        },
        plugins: [new CheckerPlugin()]
    };

    // Configuration for client-side bundle suitable for running in browsers
    const clientBundleOutputDir = './wwwroot/dist';
    const clientBundleConfig = merge(sharedConfig, {
        entry: { 'main-client': './ClientApp/boot.browser.ts' },
        output: { path: path.join(__dirname, clientBundleOutputDir) },
        plugins: [
            new webpack.DllReferencePlugin({
                context: __dirname,
                manifest: require('./wwwroot/dist/vendor-manifest.json')
            })
        ].concat(isDevBuild ? [
            // Plugins that apply in development builds only
            new webpack.SourceMapDevToolPlugin({
                filename: '[file].map', // Remove this line if you prefer inline source maps
                moduleFilenameTemplate: path.relative(clientBundleOutputDir, '[resourcePath]') // Point sourcemap entries to the original file locations on disk
            })
        ] : [
            // Plugins that apply in production builds only
            new webpack.optimize.UglifyJsPlugin(),
            new AngularCompilerPlugin({
                tsConfigPath: './tsconfig.json',
                entryModule: path.join(__dirname, 'ClientApp/app/app.module.browser#AppModule'),
                exclude: ['./**/*.server.ts']
            })
        ])
    });

    // Configuration for server-side (prerendering) bundle suitable for running in Node
    const serverBundleConfig = merge(sharedConfig, {
        resolve: { mainFields: ['main'] },
        entry: { 'main-server': './ClientApp/boot.server.ts' },
        plugins: [
            new webpack.DllReferencePlugin({
                context: __dirname,
                manifest: require('./ClientApp/dist/vendor-manifest.json'),
                sourceType: 'commonjs2',
                name: './vendor'
            })
        ].concat(isDevBuild ? [] : [
            // Plugins that apply in production builds only
            new AngularCompilerPlugin({
                tsConfigPath: './tsconfig.json',
                entryModule: path.join(__dirname, 'ClientApp/app/app.module.server#AppModule'),
                exclude: ['./**/*.browser.ts']
            })
        ]),
        output: {
            libraryTarget: 'commonjs',
            path: path.join(__dirname, './ClientApp/dist')
        },
        target: 'node',
        devtool: 'inline-source-map'
    });

    return [clientBundleConfig, serverBundleConfig];
};

When i now start the application (performing npm install, then run webpack with --env.prod switch) with Release-config out of VS2017 i get the stacktrace above. The same thing happens when i deploy the application to Azure.

On localhost if i wait a few seconds and force-reload my browser, the application suddenly works. This does not work on Azure, which is kinda strange to me.

Do you have any suggestions what i might have done wrong or what i am missing?

1 Answers
Related