Skip to content

Commit

Permalink
fix(mobile): re-enable --mobile flag
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffbcross committed Oct 4, 2016
1 parent 2160003 commit 6652ac0
Show file tree
Hide file tree
Showing 10 changed files with 108 additions and 105 deletions.
5 changes: 4 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ env:
- SCRIPT=test
- NODE_SCRIPT=tests/e2e_runner.js
- NODE_SCRIPT="tests/e2e_runner.js --nightly"
# - TARGET=mobile SCRIPT=mobile_test
- TARGET=mobile NODE_SCRIPT="tests/e2e_runner.js --nightly"
matrix:
fast_finish: true
allow_failures:
Expand Down Expand Up @@ -46,6 +46,9 @@ matrix:
- node_js: "6"
os: osx
env: NODE_SCRIPT=tests/e2e_runner.js
- node_js: "6"
os: osx
env: TARGET=mobile NODE_SCRIPT="tests/e2e_runner.js --nightly"

before_install:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
"test": "npm-run-all -c test:packages test:cli",
"e2e": "npm run test:e2e",
"e2e:nightly": "node tests/e2e_runner.js --nightly",
"mobile_test": "mocha tests/e2e/e2e_workflow.spec.js",
"test:e2e": "node tests/e2e_runner.js",
"test:cli": "node tests/runner",
"test:inspect": "node --inspect --debug-brk tests/runner",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,47 +1,14 @@
import 'angular2-universal-polyfills';
import { provide } from '@angular/core';
import { APP_BASE_HREF } from '@angular/common';
import { APP_SHELL_BUILD_PROVIDERS } from '@angular/app-shell';
import {
REQUEST_URL,
ORIGIN_URL,
Bootloader,
BootloaderConfig,
AppConfig
} from 'angular2-universal';
import { AppComponent } from './app/';

const bootloaderConfig: BootloaderConfig = {
platformProviders: [
APP_SHELL_BUILD_PROVIDERS,
provide(ORIGIN_URL, {
useValue: 'http://localhost:4200' // full urls are needed for node xhr
}),
provide(APP_BASE_HREF, { useValue: '/' }),
],
async: true,
preboot: false
}

const appConfig: AppConfig = {
directives: [
// The component that will become the main App Shell
AppComponent
import { NgModule } from '@angular/core';
import { AppShellModule } from '@angular/app-shell';
import { UniversalModule } from 'angular2-universal';
import { AppComponent } from './app';

@NgModule({
imports: [
UniversalModule,
AppShellModule.prerender()
],
providers: [
// What URL should Angular be treating the app as if navigating
provide(REQUEST_URL, { useValue: '/' })
]
}

// The build system will call this function to get a bootloader
export function getBootloader() : Bootloader {
return new Bootloader(bootloaderConfig);
}

// The build system will call this function with the bootloader from
// getBootloader and the contents of the index page
export function serialize(bootloader: Bootloader, template: string) : string {
appConfig.template = template;
return bootloader.serializeApplication(appConfig);
}
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class Module {}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Component } from '@angular/core';<% if (isMobile) { %>
import { APP_SHELL_DIRECTIVES } from '@angular/app-shell';<% } %>
import { Component } from '@angular/core';

@Component({
selector: '<%= prefix %>-root',<% if (inlineTemplate) { %>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';<% if (routing) { %>
import { AppRoutingModule } from './app-routing.module';<% } %>
import { AppRoutingModule } from './app-routing.module';<% } if(isMobile) { %>
import { AppShellModule } from '@angular/app-shell'; <% } %>

import { AppComponent } from './app.component';

Expand All @@ -14,7 +15,8 @@ import { AppComponent } from './app.component';
BrowserModule,
FormsModule,
HttpModule<% if (routing) { %>,
AppRoutingModule<% } %>
AppRoutingModule<% } if(isMobile) { %>,
AppShellModule.runtime()<% } %>
],
providers: [],
bootstrap: [AppComponent]
Expand Down
8 changes: 4 additions & 4 deletions packages/angular-cli/blueprints/ng2/files/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@
"devDependencies": {<% if(isMobile) { %>
"@angular/platform-server": "~2.0.0",
"@angular/service-worker": "0.2.0",
"@angular/app-shell": "0.0.0",
"angular2-universal":"0.104.5",
"angular2-universal-polyfills": "0.4.1",
"preboot": "2.1.2",
"@angular/app-shell": "0.1.0",
"angular2-universal":"2.0.11",
"angular2-universal-polyfills": "2.0.11",
"preboot": "4.5.2",
"parse5": "1.5.1",<% } %>
"@types/jasmine": "^2.2.30",
"angular-cli": "<%= version %>",
Expand Down
7 changes: 0 additions & 7 deletions packages/angular-cli/commands/new.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,6 @@ const NewCommand = Command.extend({
new SilentError(`We currently do not support a name of "${packageName}".`));
}

if (commandOptions.mobile) {
return Promise.reject(new SilentError(
'The --mobile flag has been disabled temporarily while we await an update of ' +
'angular-universal for supporting NgModule. Sorry for the inconvenience.'
));
}

if (!commandOptions.directory) {
commandOptions.directory = packageName;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/angular-cli/models/webpack-build-mobile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const getWebpackMobileConfigPartial = function (projectRoot: string, appC
}
]),
new PrerenderWebpackPlugin({
templatePath: 'index.html',
templatePath: path.resolve(projectRoot, appConfig.root, 'index.html'),
configPath: path.resolve(projectRoot, appConfig.root, 'main-app-shell.ts'),
appPath: path.resolve(projectRoot, appConfig.root)
})
Expand Down
60 changes: 60 additions & 0 deletions packages/angular-cli/utilities/prerender-bootstrapper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/* global Zone */
/**
* This script is meant to be run in a child_process to give fresh
* context to universal (mostly to avoid conflicting angular versions, and stale module caches).
* It can be invoked directly, with absolute paths passed as positional args:
* $ node prerender-bootstrapper.js <project-base-path> <template-path> <app-shell-config-path>
*/
const fs = require('fs');
const path = require('path');
const ts = require('typescript');

const projectRoot = process.argv[2];
const templatePath = process.argv[3];
const appShellConfig = process.argv[4];
const projectNodeModulesDir = path.resolve(projectRoot, '../node_modules');

// Require from absolute path to prevent looking up inside of angular-cli
require(`${projectNodeModulesDir}/angular2-universal-polyfills`);
const universal = require(`${projectNodeModulesDir}/angular2-universal`);

// Manually transpile the TS sources to a temp directory
const tsConfigPath = path.join(projectRoot, 'tsconfig.json');
const compilerOptions = JSON.parse(fs.readFileSync(tsConfigPath, 'utf-8'));

const tmpDir = fs.mkdtempSync('/tmp/cli-app-shell');
const parsedCompilerOpts = ts.convertCompilerOptionsFromJson(Object.assign({}, compilerOptions['compilerOptions'], {
module: 'commonjs',
outDir: tmpDir
}));
const tsProgram = ts.createProgram([appShellConfig], parsedCompilerOpts.options);
tsProgram.emit();

// Symlink temp directory node_modules to project's node_modules
fs.symlinkSync(path.join(projectRoot, '../node_modules/'), path.join(tmpDir, 'node_modules'), 'dir');

// Path to tmp-dir/main-app-shell.js
const pathToTranspiledConfig = path.resolve(tmpDir, path.relative(projectRoot, appShellConfig).replace(/\.ts$/, '.js'));

var platformRef = universal.platformUniversalDynamic();

var platformConfig = {
ngModule: require(pathToTranspiledConfig).Module,
document: fs.readFileSync(templatePath, 'utf-8'),
preboot: false,
baseUrl: '/',
requestUrl: '/',
originUrl: 'localhost:3000'
};


const zone = Zone.current.fork({
name: 'UNIVERSAL prerender',
properties: platformConfig
});
zone.run(() => (platformRef.serializeModule(platformConfig.ngModule, platformConfig))
.then((html) => {
process.stdout.write(html);
}, (err) => {
process.stderr.write(err);
}));
62 changes: 21 additions & 41 deletions packages/angular-cli/utilities/prerender-webpack-plugin.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// replace with the real thing when PR is merged
// https://github.com/angular/universal/pull/464
const path = require('path');
import { spawn } from 'child_process';

export interface IWebpackPrerender {
templatePath: string;
Expand All @@ -8,49 +8,29 @@ export interface IWebpackPrerender {
}

export class PrerenderWebpackPlugin {

private bootloader: any;
private cachedTemplate: string;

constructor(private options: IWebpackPrerender) {
// maintain your platform instance
this.bootloader = require(this.options.configPath).getBootloader();
}
constructor(private options: IWebpackPrerender) {}

apply(compiler: any) {
compiler.plugin('emit', (compilation: any, callback: Function) => {
if (compilation.assets.hasOwnProperty(this.options.templatePath)) {
// we need to cache the template file to be able to re-serialize it
// even when it is not being emitted
this.cachedTemplate = compilation.assets[this.options.templatePath].source();
}

if (this.cachedTemplate) {
this.decacheAppFiles();
require(this.options.configPath).serialize(this.bootloader, this.cachedTemplate)
.then((html: string) => {
compilation.assets[this.options.templatePath] = {
source: () => html,
size: () => html.length
};
callback();
});
} else {
let proc = spawn('node', [
`${path.resolve(__dirname, 'prerender-bootstrapper.js')}`,
this.options.appPath,
this.options.templatePath,
this.options.configPath],
{
cwd: this.options.appPath
});
proc.stderr.on('data', (e: any) => {
console.error('error in app shell', e.toString());
callback();
}
});
}

decacheAppFiles() {
// delete all app files from cache, but keep libs
// this is needed so that the config file can reimport up to date
// versions of the app files
delete require.cache[this.options.configPath];
Object.keys(require.cache)
.filter(key => key.startsWith(this.options.appPath))
.forEach(function (key) {
// console.log('===', key);
delete require.cache[key];
});
proc.stdout.on('data', (data: string | Buffer) => {
compilation.assets[path.relative(this.options.appPath, this.options.templatePath)] = {
source: () => data.toString(),
size: () => data.toString().length
};
callback();
});
});
}
};

0 comments on commit 6652ac0

Please sign in to comment.