Skip to content
This repository was archived by the owner on Nov 22, 2024. It is now read-only.

feat(schematics): add prerendering scripts to express-schematic #1206

Closed
wants to merge 11 commits into from

Conversation

MarkPieszak
Copy link
Contributor

@MarkPieszak MarkPieszak commented Jul 19, 2019

Fixes #1201

  • Prerendering Added
  • Sitemap auto creation for prerendering
  • Updated webpack, tsconfig conditionally if prerendering is skipped
  • Basic prerender script setup
    • Errors in prerendering get propagated so if anything goes wrong it won't finish.

routes.json
Routes create sitemap.xml for prerendering.

Example:
image

@MarkPieszak MarkPieszak requested review from vikerman and CaerusKaru and removed request for vikerman July 19, 2019 20:55
@MarkPieszak MarkPieszak marked this pull request as ready for review July 19, 2019 20:55
@vikerman
Copy link
Contributor

Please see if you can add an option to the schematics to just add the prender parts - So that it can be added to an existing Universal project.

@MarkPieszak
Copy link
Contributor Author

MarkPieszak commented Jul 23, 2019

Added Flag --prerenderOnly (defaults to False), to only add prerender scripts, file, and add the needed exports to main.server @vikerman

"include": ["<%= stripTsExtension(serverFileName) %>.ts"]
"include": [
"<%= stripTsExtension(serverFileName) %>.ts",
"<%= stripTsExtension(prerenderFileName) %>.ts"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be excluded when using skipPrerender?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot find anywhere were an existing the server.tsconfig is being modified, since when not using skipUniversal option the tsconfig will be created by the @schematics/angular universal schematic.

noop() : externalSchematic('@schematics/angular', 'universal', options),

https://github.com/angular/angular-cli/blob/master/packages/schematics/angular/universal/files/root/__tsconfigFileName__.json.template

server: './<%= stripTsExtension(serverFileName) %>.ts'
server: './<%= stripTsExtension(serverFileName) %>.ts',
// This is our script for Static Prerendering
prerender: './<%= stripTsExtension(prerenderFileName) %>.ts'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be excluded when using skipPrerender?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it should, let me know if I did the templating incorrectly, I couldn't find many good examples within other CLI schematics! :)

<%= skipPrerender ? '' : '"<%= stripTsExtension(prerenderFileName) %>.ts"' %>

@@ -16,5 +16,7 @@
"dom"
]
},
"include": ["<%= stripTsExtension(serverFileName) %>.ts"]
"include": [
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are missing the closing ]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, fixed!

}

// Writes rendered HTML to index.html, replacing the file if it already exists.
previousRender = previousRender.then(_ => renderModuleFactory(AppServerModuleNgFactory, {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there is an error here, would this throw with unhandled promise rejection?

Copy link
Contributor Author

@MarkPieszak MarkPieszak Sep 3, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it actually throws it regardless, which is great! For example a (<any>window).test = '123'; thrown in an app components code (that will pass ng build, etc) will throw an error when trying to build the prerender like shown below.

image

import {join} from 'path';

// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const {AppServerModuleNgFactory, LAZY_MODULE_MAP, provideModuleMap, renderModuleFactory, enableProdMode} = require('./<%= getServerDistDirectory() %>/main');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't renderModuleFactory, enableProdMode in @angular/platform-server and @angular/core?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes they are but they're actually exported in the server/main.ts file. This prevents us from having 2 copies of Angular.
Something @vikerman actually figured out!

@@ -16,5 +16,8 @@
"dom"
]
},
"include": ["<%= stripTsExtension(serverFileName) %>.ts"]
"include": [
"<%= stripTsExtension(serverFileName) %>.ts"<%= skipPrerender ? '' : ',' %>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be simplified a bit.

  "include": [
    "<%= stripTsExtension(serverFileName) %>.ts"<% if (!skipPrerender) { %>,
     <%= stripTsExtension(prerenderFileName) %>.ts"<% } %>
  ]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can do if's 😆 🤦‍♂
I was working on this way way too early this morning!
Let me clean this up

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haha happens to me as well 😜

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed everything thanks again Alan, great catches :)

server: './<%= stripTsExtension(serverFileName) %>.ts',
<%= skipPrerender ? "" : "// This is our script for Static Prerendering" %>
<%= skipPrerender ? "" : "prerender: './<%= stripTsExtension(prerenderFileName) %>.ts'"

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: remove extra line

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

@@ -7,7 +7,10 @@ module.exports = {
mode: 'none',
entry: {
// This is our Express server for Dynamic universal
server: './<%= stripTsExtension(serverFileName) %>.ts'
server: './<%= stripTsExtension(serverFileName) %>.ts',
<%= skipPrerender ? "" : "// This is our script for Static Prerendering" %>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

  entry: {
    // This is our Express server for Dynamic universal
    server: './<%= stripTsExtension(serverFileName) %>.ts'<% if(!skipPrerender) { %>,
    // This is our script for Static Prerendering
    "prerender": './<%= stripTsExtension(prerenderFileName) %>.ts' %><% } %>
  },

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

@@ -194,12 +219,16 @@ function addExports(options: UniversalOptions): Rule {
const mainSourceFile = getTsSourceFile(host, mainPath);
let mainText = getTsSourceText(host, mainPath);
const mainRecorder = host.beginUpdate(mainPath);
const enableProdModeExport = generateExport(mainSourceFile, ['enableProdMode'],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: we should actually check if these exports already exists prior to adding them. Since, we will add these exports in the universal schematics as well

@@ -194,12 +219,16 @@ function addExports(options: UniversalOptions): Rule {
const mainSourceFile = getTsSourceFile(host, mainPath);
let mainText = getTsSourceText(host, mainPath);
const mainRecorder = host.beginUpdate(mainPath);
const enableProdModeExport = generateExport(mainSourceFile, ['enableProdMode'],
'@angular/core');
const renderModuleFactoryExport = generateExport(mainSourceFile, ['renderModuleFactory'],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this target version 8 or 9? Is so probable we should change renderModuleFactory to renderModule

Some more context here: angular/angular-cli#15517

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually regarding the later two comments if we wait for version 9 you don’t need to add them because they will be adde by default in the cli version 9.

Also, for existing project I will do a migration to add these exports

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually regarding the later two comments if we wait for version 9 you don’t need to add them because they will be adde by default in the cli version 9.

Also, for existing project I will do a migration to add these exports

const routeData = require('./routes.json');

// Faster server renders w/ Prod mode (dev mode never needed)
enableProdMode();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this still needed since it's already defined in main.server.ts?

@@ -25,6 +25,11 @@
"format": "path",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

skipPrerender doesn't seem to be defined in the schema.

@vikerman
Copy link
Contributor

vikerman commented Dec 6, 2019

Superseded by #1357

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Jan 6, 2020
@CaerusKaru CaerusKaru deleted the feat/express-schematic-prerendering branch January 6, 2020 20:58
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Static site pre-rendering entrypoint
4 participants