Reputation: 2471
I am building a SPA with Angular 8.0.0. I am running into the exact same issue as described in this Github issue. Note that there is another related SO question with no accepted answer.
None of the suggested workarounds in the GitHub issue have worked for me. The Angular team has closed the issue and suggested posting a SO question.
Background
The app works initially when loading the root route http://localhost:4200/
The app redirects to /records/list
which works correctly.
When navigating to other routes in the application by clicking on [routerLink]
links, it works with no issues. For example, clicking on this link generated by [routerLink]
works:
http://localhost:4200/record/Item?RecordID=1
<a
[routerLink]="/record/Item]]"
[queryParams]="{RecordID: id}"
queryParamsHandling="merge"
>
{{ id }}
</a>
However, when reloading the page OR typing the link directly into the browser (without clicking on a routerlink) the app does NOT load and this error message appears.
Note: The problem happens with both ng serve in the dev environment and ng build on the web server. The problem only happens on initial load with ng serve, but it happens on any page reload or direct navigation on the ng build web server. I am using a minimal express app to run the web server and I might experiment with using nginx instead.
The browser just shows a blank screen with the error message:
Cannot GET /record/Item/detail
Console error:
Refused to load the image 'http://localhost:4200/favicon.ico' because it violates the following Content Security Policy directive: "default-src 'none'". Note that 'img-src' was not explicitly set, so 'default-src' is used as a fallback.
Here is the Angular routing module:
app-routing.module.this
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { RecordsTableComponent } from './components/records/table/records-table/records-table.component';
import { RecordLandingComponent } from './components/records/landing/record-landing/record-landing.component';
import { RecordDetailComponent } from './components/records/detail/record-detail/record-detail.component';
import { RecordStatusComponent } from './components/records/status/record-status/record-status.component';
import { RecordProposalComponent } from './components/records/proposal/record-proposal/record-proposal.component';
import { RecordsSearchComponent } from './components/records/search/records-search/records-search.component';
import { RecordChangesGuard } from './guards/records/record-changes/record-changes.guard';
import { RecordParamsGuard } from './guards/records/record-params/record-params.guard';
const routes: Routes = [
{ path: 'records/list', component: RecordsTableComponent },
{ path: 'records/search', component: RecordsSearchComponent },
{
path: 'record/:RecordType',
component: RecordLandingComponent, canActivate: [RecordParamsGuard],
children: [
{ path: '', redirectTo: 'detail', pathMatch: 'full' },
{ path: 'new', component: RecordDetailComponent, canDeactivate: [RecordChangesGuard] },
{ path: 'detail', component: RecordDetailComponent, canDeactivate: [RecordChangesGuard] },
{ path: 'status', component: RecordStatusComponent },
{ path: 'proposal', component: RecordProposalComponent },
]
},
{ path: '**', redirectTo: '/records/list' },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Upvotes: 0
Views: 6797
Reputation: 71
In your index.html add a meta tag in the head
`<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: http://localhost:4200;>`
Upvotes: 0
Reputation: 2471
A big thanks to @Xesenix for pointing out that the problem may be caused by the custom server. I made some adjustments to the express server I am using to serve the angular distribution created by ng build. The server appears to be working now pending more thorough testing. Here is the updated app.js.
const express = require('express');
const http = require('http');
const app = express();
// Set name of directory where angular distribution files are stored
const dist = 'dist';
// Set port
const port = process.env.PORT || 4201;
// Serve static assets
app.get('*.*', express.static(dist, { maxAge: '1y' }));
// Serve application paths
app.all('*', function (req, res) {
res.status(200).sendFile(`/`, { root: dist });
});
// Create server to listen for connections
const server = http.createServer(app);
server.listen(port, () => console.log("Node Express server for " + app.name + " listening on port " + port));
Upvotes: 0