build: add ci task for server-side prerender (#4808)

This adds a new task for Travis CI to prerender an app using
@angular/material. This change starts off by only adding buttons to the
application; more components will be added in a subsequent PR so that
this one stays focused on the set-up.
This commit is contained in:
Jeremy Elbourn
2017-05-25 16:51:11 -07:00
committed by tinayuangao
parent 7db2762d78
commit 97d69fb3f8
11 changed files with 142 additions and 0 deletions
+1
View File
@@ -20,6 +20,7 @@ jobs:
- env: "MODE=e2e"
- env: "MODE=aot"
- env: "MODE=payload"
- env: "MODE=prerender"
- env: "MODE=closure-compiler"
- env: "MODE=saucelabs_required"
- env: "MODE=browserstack_required"
+2
View File
@@ -41,6 +41,8 @@ elif is_closure_compiler; then
./scripts/closure-compiler/build-devapp-bundle.sh
elif is_unit; then
$(npm bin)/gulp ci:test
elif is_prerender; then
./scripts/ci/prerender.sh
fi
# Upload coverage results if those are present.
+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
### Pre-renders the app under src/universal-app with platform-server and dumps the
### output to stdout.
# Go to the project root directory
cd $(dirname $0)/../..
# Build the @angular/material package and copy it into node_modules.
# This is a workaround for https://github.com/angular/angular/issues/12249
rm -rf ./node_modules/@angular/material
gulp material:build-release
cp -r ./dist/releases/material ./node_modules/@angular/
# Compile the kitchen sink app (the generated ngfactories are consumed by the prerender script)
$(npm bin)/ngc -p src/universal-app/tsconfig-ngc.json
# Run the prerender script.
# This does not use ts-node because some of the generated ngfactory.ts files are written into a
# directory called "node_modules"; ts-node intentionally will not treat any file inside of a
# "node_modules" directory as TypeScript (with the opinion that node_modules should only contain JS)
$(npm bin)/tsc -p src/universal-app/tsconfig-prerender.json
node ./src/universal-app/dist/prerender.js
+4
View File
@@ -24,3 +24,7 @@ is_payload() {
is_unit() {
[[ "$MODE" = saucelabs_required || "$MODE" = browserstack_required ]]
}
is_prerender() {
[[ "$MODE" = prerender ]]
}
+11
View File
@@ -0,0 +1,11 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Angular Material Univeral Kitchen Sink Test</title>
<base href="/">
</head>
<body>
<kitchen-sink>Loading...</kitchen-sink>
</body>
</html>
@@ -0,0 +1,3 @@
.kitchen-sink {
color: lightsteelblue;
}
@@ -0,0 +1,15 @@
<h1>Kitchen sink app</h1>
<h2>Buttons</h2>
<button md-button>go</button>
<button md-icon-button>go</button>
<button md-raised-button>go</button>
<button md-fab>go</button>
<button md-mini-fab>go</button>
<a md-button href="https://google.com">Google</a>
<a md-icon-button href="https://google.com">Google</a>
<a md-raised-button href="https://google.com">Google</a>
<a md-fab href="https://google.com">Google</a>
<a md-mini-fab href="https://google.com">Google</a>
@@ -0,0 +1,30 @@
import {Component, NgModule} from '@angular/core';
import {ServerModule} from '@angular/platform-server';
import {BrowserModule} from '@angular/platform-browser';
import {MdButtonModule} from '@angular/material';
@Component({
selector: 'kitchen-sink',
templateUrl: './kitchen-sink.html',
styleUrls: ['./kitchen-sink.css'],
})
export class KitchenSink { }
@NgModule({
imports: [
BrowserModule.withServerTransition({appId: 'kitchen-sink'}),
MdButtonModule,
],
bootstrap: [KitchenSink],
declarations: [KitchenSink],
})
export class KitchenSinkClientModule { }
@NgModule({
imports: [KitchenSinkClientModule, ServerModule],
bootstrap: [KitchenSink],
})
export class KitchenSinkServerModule { }
+15
View File
@@ -0,0 +1,15 @@
import 'reflect-metadata';
require('zone.js/dist/zone-node.js');
import {enableProdMode} from '@angular/core';
import {renderModuleFactory} from '@angular/platform-server';
import {KitchenSinkServerModuleNgFactory} from './dist/aot/kitchen-sink/kitchen-sink.ngfactory';
import {readFileSync} from 'fs-extra';
enableProdMode();
const result = renderModuleFactory(KitchenSinkServerModuleNgFactory, {
document: readFileSync('src/universal-app/index.html', 'utf-8')
});
result.then(html => console.log(html));
+23
View File
@@ -0,0 +1,23 @@
{
"compilerOptions": {
"module": "es2015",
"moduleResolution": "node",
"target": "es6",
"noImplicitAny": false,
"sourceMap": false,
"experimentalDecorators": true,
"outDir": "dist",
"declaration": true,
"typeRoots": ["node_modules/@types"]
},
"exclude": [
"node_modules",
"dist",
"prerender.ts"
],
"angularCompilerOptions": {
"annotationsAs": "static fields",
"annotateForClosureCompiler": true,
"genDir": "./dist/aot"
}
}
+15
View File
@@ -0,0 +1,15 @@
{
"compilerOptions": {
"lib": ["es2015", "dom"],
"target": "es6",
"module": "commonjs",
"moduleResolution": "node",
"outDir": "dist",
"noEmitOnError": true,
"noImplicitAny": true,
"sourceMap": false,
"experimentalDecorators": true,
"types": ["node"]
},
"files": ["prerender.ts"]
}