Browse Source

ssr added to app theme

feature/ssr-migration-schematic
erdemcaygor 1 year ago
parent
commit
c3702ade90
  1. 63
      templates/app/angular/angular.json
  2. 15
      templates/app/angular/package.json
  3. 11
      templates/app/angular/src/app/app.config.server.ts
  4. 57
      templates/app/angular/src/app/app.config.ts
  5. 8
      templates/app/angular/src/app/app.routes.server.ts
  6. 7
      templates/app/angular/src/main.server.ts
  7. 4
      templates/app/angular/src/main.ts
  8. 69
      templates/app/angular/src/server.ts
  9. 1
      templates/app/angular/tsconfig.json
  10. 16
      templates/app/angular/tsconfig.server.json

63
templates/app/angular/angular.json

@ -21,7 +21,7 @@
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/MyProjectName",
"outputPath": "dist/MyProjectName/browser",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
@ -183,6 +183,67 @@
"options": {
"lintFilePatterns": ["src/**/*.ts", "src/**/*.html"]
}
},
"server": {
"builder": "@angular-devkit/build-angular:server",
"options": {
"outputPath": "dist/MyProjectName/server",
"main": "src/server.ts",
"tsConfig": "tsconfig.server.json",
"inlineStyleLanguage": "scss"
},
"configurations": {
"production": {
"outputHashing": "media",
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
]
},
"development": {
"buildOptimizer": false,
"optimization": false,
"sourceMap": true,
"extractLicenses": false,
"vendorChunk": true
}
},
"defaultConfiguration": "production"
},
"serve-ssr": {
"builder": "@angular-devkit/build-angular:ssr-dev-server",
"configurations": {
"development": {
"browserTarget": "MyProjectName:build:development",
"serverTarget": "MyProjectName:server:development"
},
"production": {
"browserTarget": "MyProjectName:build:production",
"serverTarget": "MyProjectName:server:production"
}
},
"defaultConfiguration": "development"
},
"prerender": {
"builder": "@angular-devkit/build-angular:prerender",
"options": {
"routes": [
"/"
]
},
"configurations": {
"production": {
"browserTarget": "MyProjectName:build:production",
"serverTarget": "MyProjectName:server:production"
},
"development": {
"browserTarget": "MyProjectName:build:development",
"serverTarget": "MyProjectName:server:development"
}
},
"defaultConfiguration": "production"
}
}
}

15
templates/app/angular/package.json

@ -8,7 +8,11 @@
"build:prod": "ng build --configuration production",
"watch": "ng build --watch --configuration development",
"test": "ng test",
"lint": "ng lint"
"lint": "ng lint",
"dev:ssr": "ng run MyProjectName:serve-ssr",
"serve:ssr": "node dist/MyProjectName/server/main.js",
"build:ssr": "ng build && ng run MyProjectName:server",
"prerender": "ng run MyProjectName:prerender"
},
"private": true,
"dependencies": {
@ -29,8 +33,11 @@
"@angular/localize": "~19.1.0",
"@angular/platform-browser": "~19.1.0",
"@angular/platform-browser-dynamic": "~19.1.0",
"@angular/platform-server": "~19.1.0",
"@angular/router": "~19.1.0",
"@angular/ssr": "^19.1.9",
"bootstrap-icons": "~1.8.0",
"express": "^4.18.2",
"rxjs": "~7.8.0",
"tslib": "^2.0.0",
"zone.js": "~0.15.0"
@ -46,10 +53,12 @@
"@angular/cli": "~19.1.0",
"@angular/compiler-cli": "~19.1.0",
"@angular/language-service": "~19.1.0",
"@types/express": "^4.17.17",
"@types/jasmine": "~3.6.0",
"@types/node": "^12.11.1",
"@types/node": "^18.18.0",
"@typescript-eslint/eslint-plugin": "7.16.0",
"@typescript-eslint/parser": "7.16.0",
"browser-sync": "^3.0.0",
"eslint": "^8.0.0",
"jasmine-core": "~4.0.0",
"karma": "~6.3.0",
@ -59,4 +68,4 @@
"karma-jasmine-html-reporter": "^1.7.0",
"typescript": "~5.6.0"
}
}
}

11
templates/app/angular/src/app/app.config.server.ts

@ -0,0 +1,11 @@
import { mergeApplicationConfig, ApplicationConfig } from '@angular/core';
import { provideServerRendering } from '@angular/platform-server';
import { appConfig } from './app.config';
const serverConfig: ApplicationConfig = {
providers: [
provideServerRendering()
]
};
export const config = mergeApplicationConfig(appConfig, serverConfig);

57
templates/app/angular/src/app/app.config.ts

@ -17,30 +17,37 @@ import { provideFeatureManagementConfig } from '@abp/ng.feature-management';
import {ThemeLeptonXModule} from "@abp/ng.theme.lepton-x";
import {SideMenuLayoutModule} from "@abp/ng.theme.lepton-x/layouts";
import {AccountLayoutModule} from "@abp/ng.theme.lepton-x/account";
import {provideClientHydration, withEventReplay, withHttpTransferCacheOptions} from '@angular/platform-browser';
import {provideServerRouting} from "@angular/ssr";
import {provideServerRendering} from "@angular/platform-server";
import {serverRoutes} from "./app.routes.server";
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(appRoutes),
APP_ROUTE_PROVIDER,
provideAbpCore(
withOptions({
environment,
registerLocaleFn: registerLocale(),
})
),
provideAbpOAuth(),
provideAbpThemeShared(),
provideSettingManagementConfig(),
provideAccountConfig(),
provideIdentityConfig(),
provideTenantManagementConfig(),
provideFeatureManagementConfig(),
provideAnimations(),
provideAbpCore(),
importProvidersFrom([
ThemeLeptonXModule.forRoot(),
SideMenuLayoutModule.forRoot(),
AccountLayoutModule.forRoot(),
])
],
export function createAppConfig(ssr: boolean): ApplicationConfig {
return {
providers: [
provideRouter(appRoutes),
APP_ROUTE_PROVIDER,
provideAbpCore(
withOptions({
environment,
registerLocaleFn: registerLocale(),
})
),
provideAbpOAuth({ssr}),
provideAbpThemeShared(),
provideSettingManagementConfig(),
provideAccountConfig(),
provideIdentityConfig(),
provideTenantManagementConfig(),
provideFeatureManagementConfig(),
provideAnimations(),
provideAbpCore(),
importProvidersFrom([
ThemeLeptonXModule.forRoot(),
SideMenuLayoutModule.forRoot(),
AccountLayoutModule.forRoot(),
]), provideClientHydration(withEventReplay(), withHttpTransferCacheOptions({})),
...(ssr ? [provideServerRendering(), provideServerRouting(serverRoutes)] : []),
],
}
};

8
templates/app/angular/src/app/app.routes.server.ts

@ -0,0 +1,8 @@
import {RenderMode, ServerRoute} from "@angular/ssr";
export const serverRoutes: ServerRoute[] = [
{
path: '',
renderMode: RenderMode.Server
}
];

7
templates/app/angular/src/main.server.ts

@ -0,0 +1,7 @@
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import {createAppConfig} from "./app/app.config";
const bootstrap = () => bootstrapApplication(AppComponent, createAppConfig(true));
export default bootstrap;

4
templates/app/angular/src/main.ts

@ -1,5 +1,5 @@
import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import {createAppConfig} from './app/app.config';
import { AppComponent } from './app/app.component';
bootstrapApplication(AppComponent, appConfig).catch(err => console.error(err));
bootstrapApplication(AppComponent, createAppConfig(false)).catch(err => console.error(err));

69
templates/app/angular/src/server.ts

@ -0,0 +1,69 @@
import 'zone.js/node';
import { APP_BASE_HREF } from '@angular/common';
import { CommonEngine } from '@angular/ssr/node';
import * as express from 'express';
import { existsSync } from 'node:fs';
import { join } from 'node:path';
import bootstrap from './main.server';
// The Express app is exported so that it can be used by serverless Functions.
export function app(): express.Express {
const server = express();
const distFolder = join(process.cwd(), 'dist/MyProjectName/browser');
const indexHtml = existsSync(join(distFolder, 'index.original.html'))
? join(distFolder, 'index.original.html')
: join(distFolder, 'index.html');
const commonEngine = new CommonEngine();
server.set('view engine', 'html');
server.set('views', distFolder);
// Example Express Rest API endpoints
// server.get('/api/**', (req, res) => { });
// Serve static files from /browser
server.get('*.*', express.static(distFolder, {
maxAge: '1y'
}));
// All regular routes use the Angular engine
server.get('*', (req, res, next) => {
const { protocol, originalUrl, baseUrl, headers } = req;
commonEngine
.render({
bootstrap,
documentFilePath: indexHtml,
url: `${protocol}://${headers.host}${originalUrl}`,
publicPath: distFolder,
providers: [{ provide: APP_BASE_HREF, useValue: baseUrl }],
})
.then((html) => res.send(html))
.catch((err) => next(err));
});
return server;
}
function run(): void {
const port = process.env['PORT'] || 4000;
// Start up the Node server
const server = app();
server.listen(port, () => {
console.log(`Node Express server listening on http://localhost:${port}`);
});
}
// Webpack will replace 'require' with '__webpack_require__'
// '__non_webpack_require__' is a proxy to Node 'require'
// The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main;
const moduleFilename = mainModule && mainModule.filename || '';
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
run();
}
export default bootstrap;

1
templates/app/angular/tsconfig.json

@ -12,6 +12,7 @@
"importHelpers": true,
"target": "ES2022",
"module": "es2020",
"skipLibCheck": true,
"lib": [
"es2018",
"dom"

16
templates/app/angular/tsconfig.server.json

@ -0,0 +1,16 @@
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
{
"extends": "./tsconfig.app.json",
"compilerOptions": {
"outDir": "./out-tsc/server",
"types": [
"node",
"@angular/localize"
]
},
"files": [
"src/main.server.ts",
"src/server.ts"
]
}
Loading…
Cancel
Save