feat(ssr): add ionic angular server (#18880)

This commit is contained in:
Adam Bradley 2019-08-06 12:24:42 -05:00 committed by GitHub
parent 713ea8adaa
commit 84e306c1a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 466 additions and 11616 deletions

View File

@ -91,6 +91,23 @@ jobs:
paths: paths:
- "*" - "*"
build-angular-server:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
command: npm install
working_directory: /tmp/workspace/packages/angular-server
- run:
command: npm run build.prod
working_directory: /tmp/workspace/packages/angular-server
- persist_to_workspace:
root: /tmp/workspace
paths:
- "*"
test-core-clean-build: test-core-clean-build:
<<: *defaults <<: *defaults
steps: steps:
@ -208,7 +225,11 @@ workflows:
- build-angular: - build-angular:
requires: [build-core] requires: [build-core]
- build-angular-server:
requires: [build-angular]
- test-angular-lint: - test-angular-lint:
requires: [build-angular] requires: [build-angular]
- test-angular-e2e: - test-angular-e2e:
requires: [build-angular] requires:
- build-angular
- build-angular-server

View File

@ -19,6 +19,10 @@
"type": "git", "type": "git",
"url": "https://github.com/ionic-team/ionic.git" "url": "https://github.com/ionic-team/ionic.git"
}, },
"bugs": {
"url": "https://github.com/ionic-team/ionic/issues"
},
"homepage": "https://ionicframework.com/",
"scripts": { "scripts": {
"build": "npm run clean && npm run build.core && npm run build.ng && npm run clean-generated", "build": "npm run clean && npm run build.core && npm run build.ng && npm run clean-generated",
"build.core": "node scripts/build-core.js", "build.core": "node scripts/build-core.js",
@ -38,7 +42,7 @@
"validate": "npm i && npm run lint && npm run test && npm run build" "validate": "npm i && npm run lint && npm run test && npm run build"
}, },
"module": "dist/fesm5.js", "module": "dist/fesm5.js",
"main": "dist/fesm5.js", "main": "dist/fesm5.cjs.js",
"types": "dist/core.d.ts", "types": "dist/core.d.ts",
"files": [ "files": [
"dist/", "dist/",
@ -82,8 +86,8 @@
"tsickle": "^0.34.0", "tsickle": "^0.34.0",
"tslint": "^5.12.1", "tslint": "^5.12.1",
"tslint-ionic-rules": "0.0.21", "tslint-ionic-rules": "0.0.21",
"typescript": "3.2.4", "typescript": "~3.2.2",
"zone.js": "^0.8.28" "zone.js": "~0.8.26"
}, },
"schematics": "./dist/schematics/collection.json" "schematics": "./dist/schematics/collection.json"
} }

View File

@ -1,12 +1,12 @@
const fs = require('fs-extra'); const fs = require('fs-extra');
const path = require('path'); const path = require('path');
const ROOT_DIR = path.join(__dirname, '..');
const cleanDirs = [ const cleanDirs = [
'dist' path.join(ROOT_DIR, 'dist')
]; ];
cleanDirs.forEach(dir => { cleanDirs.forEach(dir => {
const cleanDir = path.join(__dirname, '../', dir); fs.emptyDirSync(dir);
fs.removeSync(cleanDir);
}); });

View File

@ -2,10 +2,12 @@ import resolve from 'rollup-plugin-node-resolve';
export default { export default {
input: 'build/es2015/core.js', input: 'build/es2015/core.js',
output: { output: [
file: 'dist/fesm2015.js', {
format: 'es' file: 'dist/fesm2015.js',
}, format: 'es'
}
],
external: (id) => { external: (id) => {
// anything else is external // anything else is external
// Windows: C:\xxxxxx\xxx // Windows: C:\xxxxxx\xxx

View File

@ -4,6 +4,15 @@ const newConfig = {
...config, ...config,
input: 'build/es5/core.js', input: 'build/es5/core.js',
}; };
newConfig.output.file = 'dist/fesm5.js'; newConfig.output = [
{
file: 'dist/fesm5.js',
format: 'es'
},
{
file: 'dist/fesm5.cjs.js',
format: 'cjs'
}
];
export { newConfig as default }; export { newConfig as default };

View File

@ -0,0 +1 @@
package-lock=false

View File

@ -13,11 +13,11 @@
"build": { "build": {
"builder": "@angular-devkit/build-angular:browser", "builder": "@angular-devkit/build-angular:browser",
"options": { "options": {
"outputPath": "dist/test-app", "outputPath": "dist/browser",
"index": "src/index.html", "index": "src/index.html",
"main": "src/main.ts", "main": "src/main.ts",
"polyfills": "src/polyfills.ts", "polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.app.json", "tsConfig": "tsconfig.app.json",
"assets": [ "assets": [
"src/favicon.ico", "src/favicon.ico",
{ {
@ -31,9 +31,7 @@
"output": "./svg" "output": "./svg"
} }
], ],
"styles": [ "styles": ["src/styles.css"],
"src/styles.css"
],
"scripts": [] "scripts": []
}, },
"configurations": { "configurations": {
@ -86,37 +84,13 @@
"options": { "options": {
"main": "src/test.ts", "main": "src/test.ts",
"polyfills": "src/polyfills.ts", "polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json", "tsConfig": "tsconfig.spec.json",
"karmaConfig": "src/karma.conf.js", "karmaConfig": "karma.conf.js",
"styles": [ "styles": ["src/styles.css"],
"src/styles.css"
],
"scripts": [], "scripts": [],
"assets": [ "assets": ["src/favicon.ico", "src/assets"]
"src/favicon.ico",
"src/assets"
]
} }
}, },
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
},
"test-app-e2e": {
"root": "e2e/",
"projectType": "application",
"prefix": "",
"architect": {
"e2e": { "e2e": {
"builder": "@angular-devkit/build-angular:protractor", "builder": "@angular-devkit/build-angular:protractor",
"options": { "options": {
@ -126,20 +100,39 @@
"configurations": { "configurations": {
"production": { "production": {
"devServerTarget": "test-app:serve:production" "devServerTarget": "test-app:serve:production"
},
"ci": {
"devServerTarget": "test-app:serve:ci"
} }
} }
}, },
"lint": { "lint": {
"builder": "@angular-devkit/build-angular:tslint", "builder": "@angular-devkit/build-angular:tslint",
"options": { "options": {
"tsConfig": "e2e/tsconfig.e2e.json", "tsConfig": ["tsconfig.app.json", "tsconfig.spec.json"],
"exclude": [ "exclude": ["**/node_modules/**"]
"**/node_modules/**" }
] },
"server": {
"builder": "@angular-devkit/build-angular:server",
"options": {
"outputPath": "dist/server",
"main": "src/main.server.ts",
"tsConfig": "tsconfig.server.json"
},
"configurations": {
"production": {
"fileReplacements": [
{
"src": "src/environments/environment.ts",
"replaceWith": "src/environments/environment.prod.ts"
}
]
}
} }
} }
} }
} }
}, },
"defaultProject": "test-app" "defaultProject": "test-app"
} }

View File

@ -0,0 +1,12 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# You can see what browsers were selected by your queries by running:
# npx browserslist
> 0.5%
last 2 versions
Firefox ESR
not dead
not IE 9-11 # For IE 9-11 support, remove 'not'.

View File

@ -1,19 +1,22 @@
// @ts-check
// Protractor configuration file, see link for more information // Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts // https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require('jasmine-spec-reporter'); const { SpecReporter } = require('jasmine-spec-reporter');
/**
* @type { import("protractor").Config }
*/
exports.config = { exports.config = {
allScriptsTimeout: 11000, allScriptsTimeout: 11000,
specs: [ specs: [
'./**/*.e2e-spec.ts' './src/**/*.e2e-spec.ts'
], ],
capabilities: { capabilities: {
browserName: 'chrome', 'browserName': 'chrome'
},
chromeOptions: { chromeOptions: {
args: [ "--headless", "--disable-gpu", "--window-size=400,1000", "--start-maximized" ] args: [ "--headless", "--disable-gpu", "--window-size=400,1000", "--start-maximized" ]
}
}, },
directConnect: true, directConnect: true,
baseUrl: 'http://localhost:4200/', baseUrl: 'http://localhost:4200/',
@ -25,8 +28,8 @@ exports.config = {
}, },
onPrepare() { onPrepare() {
require('ts-node').register({ require('ts-node').register({
project: require('path').join(__dirname, './tsconfig.e2e.json') project: require('path').join(__dirname, './tsconfig.json')
}); });
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
} }
}; };

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,22 @@
{ {
"name": "test-app", "name": "ionic-angular-test-app",
"version": "0.0.0", "version": "0.0.0",
"private": true,
"scripts": { "scripts": {
"ng": "ng", "ng": "ng",
"start": "npm run sync && ng serve", "start": "npm run sync && ng serve",
"sync:build": "sh scripts/build-ionic.sh", "sync:build": "sh scripts/build-ionic.sh",
"sync": "sh scripts/sync.sh", "sync": "sh scripts/sync.sh",
"build": "ng build --prod --no-progress", "build": "npm run sync && ng build --prod --no-progress",
"test": "ng e2e --prod", "test": "ng e2e --prod",
"test.dev": "npm run sync && ng e2e", "test.dev": "npm run sync && ng e2e",
"lint": "ng lint" "lint": "ng lint",
"postinstall": "npm run sync",
"compile:server": "webpack --config webpack.server.config.js --progress --colors",
"serve:ssr": "node dist/server",
"build:ssr": "npm run build:client-and-server-bundles && npm run compile:server",
"build:client-and-server-bundles": "npm run build && ng run test-app:server:production"
}, },
"private": true,
"dependencies": { "dependencies": {
"@angular/animations": "~8.2.0", "@angular/animations": "~8.2.0",
"@angular/common": "~8.2.0", "@angular/common": "~8.2.0",
@ -20,21 +25,27 @@
"@angular/forms": "~8.2.0", "@angular/forms": "~8.2.0",
"@angular/platform-browser": "~8.2.0", "@angular/platform-browser": "~8.2.0",
"@angular/platform-browser-dynamic": "~8.2.0", "@angular/platform-browser-dynamic": "~8.2.0",
"@angular/platform-server": "~8.2.0",
"@angular/router": "~8.2.0", "@angular/router": "~8.2.0",
"@ionic/angular": "^4.7.0", "@ionic/angular": "^4.7.0",
"@ionic/angular-server": "^0.0.2",
"@nguniversal/express-engine": "~8.1.1",
"@nguniversal/module-map-ngfactory-loader": "~8.1.1",
"core-js": "^2.6.2", "core-js": "^2.6.2",
"rxjs": "^6.4.0", "express": "^4.15.2",
"rxjs": "~6.5.2",
"tslib": "^1.9.0", "tslib": "^1.9.0",
"zone.js": "~0.10.0" "zone.js": "~0.10.0"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "^0.802.0", "@angular-devkit/build-angular": "~0.802.0",
"@angular/cli": "~8.2.0", "@angular/cli": "~8.2.0",
"@angular/compiler-cli": "~8.2.0", "@angular/compiler-cli": "~8.2.0",
"@angular/language-service": "~8.2.0", "@angular/language-service": "~8.2.0",
"@types/jasmine": "~3.3.16", "@types/jasmine": "~3.3.16",
"@types/jasminewd2": "~2.0.3", "@types/jasminewd2": "~2.0.3",
"@types/node": "~12.6.8", "@types/node": "~12.6.8",
"codelyzer": "^5.0.1",
"jasmine-core": "~2.99.1", "jasmine-core": "~2.99.1",
"jasmine-spec-reporter": "~4.2.1", "jasmine-spec-reporter": "~4.2.1",
"karma": "~4.2.0", "karma": "~4.2.0",
@ -43,8 +54,10 @@
"karma-jasmine": "~2.0.1", "karma-jasmine": "~2.0.1",
"karma-jasmine-html-reporter": "^1.4.2", "karma-jasmine-html-reporter": "^1.4.2",
"protractor": "~5.4.2", "protractor": "~5.4.2",
"ts-loader": "^5.2.0",
"ts-node": "~8.3.0", "ts-node": "~8.3.0",
"tslint": "~5.18.0", "tslint": "~5.18.0",
"typescript": "~3.4.0" "typescript": "~3.5.3",
"webpack-cli": "^3.1.0"
} }
} }

View File

@ -10,6 +10,14 @@ popd
pushd angular pushd angular
npm link @ionic/core npm link @ionic/core
npm run build npm run build
npm link
popd
# Build angular-server
pushd packages/angular-server
npm link @ionic/core
npm link @ionic/angular
npm run build
popd popd
popd popd

View File

@ -1,15 +1,25 @@
# Copy angular dist # Copy angular dist
rm -rf node_modules/@ionic/angular/dist rm -rf node_modules/@ionic/angular
mkdir node_modules/@ionic/angular
cp -a ../../dist node_modules/@ionic/angular/dist cp -a ../../dist node_modules/@ionic/angular/dist
cp -a ../../css node_modules/@ionic/angular/css
cp -a ../../package.json node_modules/@ionic/angular/package.json cp -a ../../package.json node_modules/@ionic/angular/package.json
# Copy core dist # Copy angular server
rm -rf node_modules/@ionic/core/dist rm -rf node_modules/@ionic/angular-server
rm -rf node_modules/@ionic/core/loader mkdir node_modules/@ionic/angular-server
cp -a ../../../packages/angular-server/dist node_modules/@ionic/angular-server/dist
cp -a ../../../packages/angular-server/package.json node_modules/@ionic/angular-server/package.json
# # Copy core dist
rm -rf node_modules/@ionic/core
mkdir node_modules/@ionic/core
cp -a ../../../core/css node_modules/@ionic/core/css
cp -a ../../../core/dist node_modules/@ionic/core/dist cp -a ../../../core/dist node_modules/@ionic/core/dist
cp -a ../../../core/hydrate node_modules/@ionic/core/hydrate
cp -a ../../../core/loader node_modules/@ionic/core/loader cp -a ../../../core/loader node_modules/@ionic/core/loader
cp -a ../../../core/package.json node_modules/@ionic/core/package.json cp -a ../../../core/package.json node_modules/@ionic/core/package.json
# Copy ionicons # # Copy ionicons
rm -rf node_modules/ionicons rm -rf node_modules/ionicons
cp -a ../../../core/node_modules/ionicons node_modules/ionicons cp -a ../../../core/node_modules/ionicons node_modules/ionicons

View File

@ -0,0 +1,58 @@
/**
* *** NOTE ON IMPORTING FROM ANGULAR AND NGUNIVERSAL IN THIS FILE ***
*
* If your application uses third-party dependencies, you'll need to
* either use Webpack or the Angular CLI's `bundleDependencies` feature
* in order to adequately package them for use on the server without a
* node_modules directory.
*
* However, due to the nature of the CLI's `bundleDependencies`, importing
* Angular in this file will create a different instance of Angular than
* the version in the compiled application code. This leads to unavoidable
* conflicts. Therefore, please do not explicitly import from @angular or
* @nguniversal in this file. You can export any needed resources
* from your application's main.server.ts file, as seen below with the
* import for `ngExpressEngine`.
*/
import 'zone.js/dist/zone-node';
import * as express from 'express';
import {join} from 'path';
// Express server
const app = express();
const PORT = process.env.PORT || 4000;
const DIST_FOLDER = join(process.cwd(), 'dist/browser');
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const {AppServerModuleNgFactory, LAZY_MODULE_MAP, ngExpressEngine, provideModuleMap} = require('./dist/server/main');
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP)
]
}));
app.set('view engine', 'html');
app.set('views', DIST_FOLDER);
// Example Express Rest API endpoints
// app.get('/api/**', (req, res) => { });
// Serve static files from /browser
app.get('*.*', express.static(DIST_FOLDER, {
maxAge: '1y'
}));
// All regular routes use the Universal engine
app.get('*', (req, res) => {
res.render('index', { req });
});
// Start up the Node server
app.listen(PORT, () => {
console.log(`Node Express server listening on http://localhost:${PORT}`);
});

View File

@ -47,7 +47,7 @@ const routes: Routes = [
}, },
{ {
path: 'tabs', path: 'tabs',
loadChildren: './tabs/tabs.module#TabsPageModule' loadChildren: () => import('./tabs/tabs.module').then(m => m.TabsPageModule)
}, },
{ {
path: 'nested-outlet', path: 'nested-outlet',

View File

@ -59,7 +59,7 @@ import { AlertComponent } from './alert/alert.component';
AlertComponent AlertComponent
], ],
imports: [ imports: [
BrowserModule, BrowserModule.withServerTransition({ appId: 'serverApp' }),
AppRoutingModule, AppRoutingModule,
FormsModule, FormsModule,
ReactiveFormsModule, ReactiveFormsModule,

View File

@ -0,0 +1,19 @@
import { NgModule } from '@angular/core';
import { ServerModule } from '@angular/platform-server';
import { IonicServerModule } from '@ionic/angular-server';
import { AppModule } from './app.module';
import { AppComponent } from './app.component';
import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader';
@NgModule({
imports: [
AppModule,
ServerModule,
ModuleMapLoaderModule,
IonicServerModule
],
bootstrap: [AppComponent],
})
export class AppServerModule {}

View File

@ -20,7 +20,9 @@ export class FormComponent {
input2: ['Default Value'], input2: ['Default Value'],
checkbox: [false], checkbox: [false],
range: [5, Validators.min(10)], range: [5, Validators.min(10)],
}, {updateOn: window.location.hash === '#blur' ? 'blur' : 'change'}); }, {
updateOn: typeof (window as any) !== 'undefined' && window.location.hash === '#blur' ? 'blur' : 'change'
});
} }
onSubmit(_ev) { onSubmit(_ev) {

View File

@ -1,4 +1,4 @@
import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core'; import { AfterViewInit, Component, ViewChild } from '@angular/core';
import { IonSlides } from '@ionic/angular'; import { IonSlides } from '@ionic/angular';
@Component({ @Component({
@ -6,7 +6,7 @@ import { IonSlides } from '@ionic/angular';
templateUrl: './slides.component.html', templateUrl: './slides.component.html',
}) })
export class SlidesComponent implements AfterViewInit { export class SlidesComponent implements AfterViewInit {
@ViewChild(IonSlides, {static: true}) slides: IonSlides; @ViewChild(IonSlides, { static: true }) slides: IonSlides;
slideIndex = 0; slideIndex = 0;
slideIndex2 = 0; slideIndex2 = 0;

View File

@ -39,7 +39,7 @@ const routes: Routes = [
}, },
{ {
path: 'lazy', path: 'lazy',
loadChildren: '../tabs-lazy/tabs-lazy.module#TabsLazyModule' loadChildren: () => import('../tabs-lazy/tabs-lazy.module').then(m => m.TabsLazyModule)
} }
] ]
} }

View File

@ -7,11 +7,11 @@ import { IonTabs, IonButton, IonSlides, IonSlide } from '@ionic/angular';
}) })
export class ViewChildComponent implements AfterViewInit { export class ViewChildComponent implements AfterViewInit {
@ViewChild(IonSlides, {static: true}) slides: IonSlides; @ViewChild(IonSlides, { static: true }) slides: IonSlides;
@ViewChild(IonButton, {static: true}) button: IonButton; @ViewChild(IonButton, { static: true }) button: IonButton;
@ViewChild(IonTabs, {static: true}) tabs: IonTabs; @ViewChild(IonTabs, { static: true }) tabs: IonTabs;
@ViewChild('div', {static: true}) div: ElementRef; @ViewChild('div', { static: true }) div: ElementRef;
@ViewChild('slide', {static: true}) slide: IonSlide; @ViewChild('slide', { static: true }) slide: IonSlide;
ngAfterViewInit() { ngAfterViewInit() {
const loaded = !!(this.slides && this.button && this.tabs && this.div && this.slide); const loaded = !!(this.slides && this.button && this.tabs && this.div && this.slide);

View File

@ -8,7 +8,7 @@ import { IonVirtualScroll } from '@ionic/angular';
}) })
export class VirtualScrollComponent { export class VirtualScrollComponent {
@ViewChild(IonVirtualScroll, {static: true}) virtualScroll: IonVirtualScroll; @ViewChild(IonVirtualScroll, { static: true }) virtualScroll: IonVirtualScroll;
items = Array.from({length: 100}, (_, i) => ({ name: `${i}`, checked: true})); items = Array.from({length: 100}, (_, i) => ({ name: `${i}`, checked: true}));

View File

@ -1,10 +0,0 @@
# This file is currently used by autoprefixer to adjust CSS to support the below specified browsers
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
#
# For IE 9-11 support, please remove 'not' from the last line of the file and adjust as needed
> 0.5%
last 2 versions
not dead
not IE 9-11

View File

@ -0,0 +1,11 @@
import { enableProdMode } from '@angular/core';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
export { AppServerModule } from './app/app.server.module';
export { ngExpressEngine } from '@nguniversal/express-engine';
export { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';

View File

@ -8,5 +8,8 @@ if (environment.production) {
enableProdMode(); enableProdMode();
} }
platformBrowserDynamic().bootstrapModule(AppModule) document.addEventListener('DOMContentLoaded', () => {
.catch(err => console.error(err)); platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch(err => console.error(err));
});

View File

@ -18,57 +18,40 @@
* BROWSER POLYFILLS * BROWSER POLYFILLS
*/ */
/** IE9, IE10 and IE11 requires all of the following polyfills. **/
// import 'core-js/es6/symbol';
// import 'core-js/es6/object';
// import 'core-js/es6/function';
// import 'core-js/es6/parse-int';
// import 'core-js/es6/parse-float';
// import 'core-js/es6/number';
// import 'core-js/es6/math';
// import 'core-js/es6/string';
// import 'core-js/es6/date';
// import 'core-js/es6/array';
// import 'core-js/es6/regexp';
// import 'core-js/es6/map';
// import 'core-js/es6/weak-map';
// import 'core-js/es6/set';
/**
* If the application will be indexed by Google Search, the following is required.
* Googlebot uses a renderer based on Chrome 41.
* https://developers.google.com/search/docs/guides/rendering
**/
// import 'core-js/es6/array';
/** IE10 and IE11 requires the following for NgClass support on SVG elements */ /** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js'; // Run `npm install --save classlist.js`. // import 'classlist.js'; // Run `npm install --save classlist.js`.
/** IE10 and IE11 requires the following for the Reflect API. */
// import 'core-js/es6/reflect';
/** /**
* Web Animations `@angular/platform-browser/animations` * Web Animations `@angular/platform-browser/animations`
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
**/ */
// import 'web-animations-js'; // Run `npm install --save web-animations-js`. // import 'web-animations-js'; // Run `npm install --save web-animations-js`.
/** /**
* By default, zone.js will patch all possible macroTask and DomEvents * By default, zone.js will patch all possible macroTask and DomEvents
* user can disable parts of macroTask/DomEvents patch by setting following flags * user can disable parts of macroTask/DomEvents patch by setting following flags
* because those flags need to be set before `zone.js` being loaded, and webpack
* will put import in the top of bundle, so user need to create a separate file
* in this directory (for example: zone-flags.ts), and put the following flags
* into that file, and then add the following code before importing zone.js.
* import './zone-flags.ts';
*
* The flags allowed in zone-flags.ts are listed here.
*
* The following flags will work for all browsers.
*
* (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
* (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
*
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
* with the following flag, it will bypass `zone.js` patch for IE/Edge
*
* (window as any).__Zone_enable_cross_context_check = true;
*
*/ */
// (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
// (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
// (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
/*
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
* with the following flag, it will bypass `zone.js` patch for IE/Edge
*/
// (window as any).__Zone_enable_cross_context_check = true;
/*************************************************************************************************** /***************************************************************************************************
* Zone JS is required by default for Angular itself. * Zone JS is required by default for Angular itself.
*/ */

View File

@ -1,15 +0,0 @@
{
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"strictMetadataEmit" : true
},
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"types": []
},
"exclude": [
"test.ts",
"**/*.spec.ts"
]
}

View File

@ -1,18 +0,0 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/spec",
"types": [
"jasmine",
"node"
]
},
"files": [
"test.ts",
"polyfills.ts"
],
"include": [
"**/*.spec.ts",
"**/*.d.ts"
]
}

View File

@ -1,17 +0,0 @@
{
"extends": "../tslint.json",
"rules": {
"directive-selector": [
true,
"attribute",
"app",
"camelCase"
],
"component-selector": [
true,
"element",
"app",
"kebab-case"
]
}
}

View File

@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app"
},
"include": ["src/**/*.ts"],
"exclude": ["src/test.ts", "src/**/*.spec.ts"]
}

View File

@ -1,16 +1,13 @@
{ {
"compileOnSave": false, "compileOnSave": false,
"compilerOptions": { "compilerOptions": {
"baseUrl": "./", "importHelpers": true,
"outDir": "./dist/out-tsc", "outDir": "./dist/out-tsc",
"sourceMap": true, "sourceMap": true,
"declaration": false, "declaration": false,
"module": "es2015",
"moduleResolution": "node", "moduleResolution": "node",
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"importHelpers": true,
"target": "es2015",
"typeRoots": [ "typeRoots": [
"node_modules/@types" "node_modules/@types"
], ],

View File

@ -0,0 +1,9 @@
{
"extends": "./tsconfig.app.json",
"compilerOptions": {
"outDir": "../out-tsc/app-server"
},
"angularCompilerOptions": {
"entryModule": "./src/app/app.server.module#AppServerModule"
}
}

View File

@ -0,0 +1,19 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": [
"jasmine",
"node"
]
},
"files": [
"src/test.ts",
"src/zone-flags.ts",
"src/polyfills.ts"
],
"include": [
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}

View File

@ -1,36 +1,16 @@
{ {
"rulesDirectory": [ "extends": "tslint:recommended",
"node_modules/codelyzer" "rulesDirectory": ["codelyzer"],
],
"rules": { "rules": {
"arrow-return-shorthand": true, "array-type": false,
"callable-types": true, "arrow-parens": false,
"class-name": true,
"comment-format": [
true,
"check-space"
],
"curly": true,
"deprecation": { "deprecation": {
"severity": "warn" "severity": "warn"
}, },
"eofline": true, "import-blacklist": [true, "rxjs/Rx"],
"forin": true, "interface-name": false,
"import-blacklist": [ "max-classes-per-file": false,
true, "max-line-length": [true, 140],
"rxjs/Rx"
],
"import-spacing": true,
"indent": [
true,
"spaces"
],
"interface-over-type-literal": true,
"label-position": true,
"max-line-length": [
true,
140
],
"member-access": false, "member-access": false,
"member-ordering": [ "member-ordering": [
true, true,
@ -43,89 +23,32 @@
] ]
} }
], ],
"no-arg": true, "no-consecutive-blank-lines": false,
"no-bitwise": true, "no-console": [true, "debug", "info", "time", "timeEnd", "trace"],
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-construct": true,
"no-debugger": true,
"no-duplicate-super": true,
"no-empty": false, "no-empty": false,
"no-empty-interface": true, "no-inferrable-types": [true, "ignore-params"],
"no-eval": true,
"no-inferrable-types": [
true,
"ignore-params"
],
"no-misused-new": true,
"no-non-null-assertion": true, "no-non-null-assertion": true,
"no-redundant-jsdoc": true, "no-redundant-jsdoc": true,
"no-shadowed-variable": true,
"no-string-literal": false,
"no-string-throw": true,
"no-switch-case-fall-through": true, "no-switch-case-fall-through": true,
"no-trailing-whitespace": true,
"no-unnecessary-initializer": true,
"no-unused-expression": true,
"no-use-before-declare": true, "no-use-before-declare": true,
"no-var-keyword": true, "no-var-requires": false,
"object-literal-key-quotes": [true, "as-needed"],
"object-literal-sort-keys": false, "object-literal-sort-keys": false,
"one-line": [ "ordered-imports": false,
true, "quotemark": [true, "single"],
"check-open-brace", "trailing-comma": false,
"check-catch",
"check-else",
"check-whitespace"
],
"prefer-const": true,
"quotemark": [
true,
"single"
],
"radix": true,
"semicolon": [
true,
"always"
],
"triple-equals": [
true,
"allow-null-check"
],
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
}
],
"unified-signatures": true,
"variable-name": false,
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
],
"no-output-on-prefix": true, "no-output-on-prefix": true,
"use-input-property-decorator": true, "no-inputs-metadata-property": true,
"use-output-property-decorator": true, "no-inputs-metadata-property": true,
"use-host-property-decorator": true, "no-host-metadata-property": true,
"no-input-rename": true, "no-input-rename": true,
"no-output-rename": true, "no-output-rename": true,
"use-life-cycle-interface": true, "use-lifecycle-interface": true,
"use-pipe-transform-interface": true, "use-pipe-transform-interface": true,
"component-class-suffix": true, "one-variable-per-declaration": false,
"directive-class-suffix": true "component-class-suffix": [true, "Page", "Component"],
"directive-class-suffix": true,
"directive-selector": [true, "attribute", "app", "camelCase"],
"component-selector": [true, "element", "app", "page", "kebab-case"]
} }
} }

View File

@ -0,0 +1,53 @@
// Work around for https://github.com/angular/angular-cli/issues/7200
const path = require('path');
const webpack = require('webpack');
module.exports = {
mode: 'none',
entry: {
// This is our Express server for Dynamic universal
server: './server.ts'
},
externals: {
'./dist/server/main': 'require("./server/main")'
},
target: 'node',
resolve: {
mainFields: ['module', 'main'],
extensions: ['.ts', '.js']
},
optimization: {
minimize: false
},
output: {
// Puts the output at the root of the dist folder
path: path.join(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [
{ test: /\.ts$/, loader: 'ts-loader' },
{
// Mark files inside `@angular/core` as using SystemJS style dynamic imports.
// Removing this will cause deprecation warnings to appear.
test: /(\\|\/)@angular(\\|\/)core(\\|\/).+\.js$/,
parser: { system: true },
},
]
},
plugins: [
new webpack.ContextReplacementPlugin(
// fixes WARNING Critical dependency: the request of a dependency is an expression
/(.+)?angular(\\|\/)core(.+)?/,
path.join(__dirname, 'src'), // location of your src
{} // a map of your routes
),
new webpack.ContextReplacementPlugin(
// fixes WARNING Critical dependency: the request of a dependency is an expression
/(.+)?express(\\|\/)(.+)?/,
path.join(__dirname, 'src'),
{}
)
]
};

View File

@ -29,7 +29,16 @@
"importHelpers": true, "importHelpers": true,
"rootDir": "src", "rootDir": "src",
"strictPropertyInitialization": false, "strictPropertyInitialization": false,
"target": "es2015" "target": "es2015",
"baseUrl": ".",
"paths": {
"@ionic/core/hydrate": [
"../core/hydrate"
],
"@ionic/core": [
"../core"
]
}
}, },
"exclude": ["node_modules", "src/schematics"], "exclude": ["node_modules", "src/schematics"],
"files": ["src/index.ts"] "files": ["src/index.ts"]

View File

@ -34,7 +34,7 @@
"tslib": "^1.10.0" "tslib": "^1.10.0"
}, },
"devDependencies": { "devDependencies": {
"@stencil/core": "1.2.1", "@stencil/core": "1.2.3",
"@stencil/sass": "1.0.0", "@stencil/sass": "1.0.0",
"@types/jest": "24.0.13", "@types/jest": "24.0.13",
"@types/node": "10.12.18", "@types/node": "10.12.18",
@ -62,13 +62,14 @@
"tslint-react": "^3.6.0" "tslint-react": "^3.6.0"
}, },
"scripts": { "scripts": {
"build": "npm run clean && npm run build.css && npm run build.vendor && stencil build --docs", "build": "npm run clean && npm run build.css && npm run build.vendor && stencil build --docs && npm run cdnloader",
"build.vendor": "rollup --config ./scripts/swiper.rollup.config.js", "build.vendor": "rollup --config ./scripts/swiper.rollup.config.js",
"build.css": "npm run css.sass && npm run css.minify", "build.css": "npm run css.sass && npm run css.minify",
"build.debug": "npm run clean && stencil build --debug", "build.debug": "npm run clean && stencil build --debug",
"build.docs.json": "stencil build --docs-json dist/docs.json", "build.docs.json": "stencil build --docs-json dist/docs.json",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s", "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
"clean": "node scripts/clean.js", "clean": "node scripts/clean.js",
"cdnloader": "node scripts/copy-cdn-loader.js",
"css.minify": "cleancss -O2 -o ./css/ionic.bundle.css ./css/ionic.bundle.css", "css.minify": "cleancss -O2 -o ./css/ionic.bundle.css ./css/ionic.bundle.css",
"css.sass": "sass src/css:./css", "css.sass": "sass src/css:./css",
"lint": "npm run lint.ts && npm run lint.sass", "lint": "npm run lint.ts && npm run lint.sass",
@ -99,7 +100,7 @@
"bugs": { "bugs": {
"url": "https://github.com/ionic-team/ionic/issues" "url": "https://github.com/ionic-team/ionic/issues"
}, },
"homepage": "https://github.com/ionic-team/ionic#readme", "homepage": "https://ionicframework.com/",
"jest": { "jest": {
"preset": "@stencil/core/testing" "preset": "@stencil/core/testing"
} }

View File

@ -1,24 +1,30 @@
module.exports.applyPolyfills = function() { return Promise.resolve() };
module.exports.defineCustomElements = function(_, opts = {}) {
return new Promise((resolve, reject) => {
const doc = document;
const mod = doc.createElement('script');
mod.setAttribute('type', 'module');
mod['data-opts'] = opts;
mod.src = '__CDN_LOADER_URL__/dist/ionic/ionic.esm.js';
const legacy = doc.createElement('script'); exports.applyPolyfills = function() { return Promise.resolve() };
legacy.setAttribute('nomodule', '');
legacy['data-opts'] = opts;
legacy.src = '__CDN_LOADER_URL__/dist/ionic/ionic.js';
mod.onload = resolve; exports.defineCustomElements = function(_, opts) {
mod.onerror = reject; return new Promise(function(resolve, reject) {
if (typeof document !== 'undefined') {
opts = opts || {};
var mod = document.createElement('script');
mod.setAttribute('type', 'module');
mod['data-opts'] = opts;
mod.src = '__CDN_LOADER_URL__/dist/ionic/ionic.esm.js';
legacy.onload = resolve; var legacy = document.createElement('script');
legacy.onerror = reject; legacy.setAttribute('nomodule', '');
legacy['data-opts'] = opts;
legacy.src = '__CDN_LOADER_URL__/dist/ionic/ionic.js';
doc.head.appendChild(mod); mod.onload = resolve;
doc.head.appendChild(legacy); mod.onerror = reject;
legacy.onload = resolve;
legacy.onerror = reject;
document.head.appendChild(mod);
document.head.appendChild(legacy);
} else {
resolve();
}
}); });
} }

View File

@ -6,10 +6,12 @@
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const version = process.argv[2]; let version = process.argv[2];
if (!version) { if (version) {
throw new Error('version arg missing'); version = '@' + version;
} else {
version = '';
} }
const srcPath = path.join(__dirname, 'cdn-loader.js'); const srcPath = path.join(__dirname, 'cdn-loader.js');
@ -19,7 +21,7 @@ let scriptContent = fs.readFileSync(srcPath, 'utf-8');
scriptContent = scriptContent.replace( scriptContent = scriptContent.replace(
/__CDN_LOADER_URL__/g, /__CDN_LOADER_URL__/g,
'https://cdn.jsdelivr.net/npm/@ionic/core@' + version 'https://cdn.jsdelivr.net/npm/@ionic/core' + version
); );
fs.writeFileSync(path.join(__dirname, '..', 'loader', 'cdn.js'), scriptContent); fs.writeFileSync(path.join(__dirname, '..', 'loader', 'cdn.js'), scriptContent);

View File

@ -15,5 +15,5 @@
"bugs": { "bugs": {
"url": "https://github.com/ionic-team/ionic-docs/issues" "url": "https://github.com/ionic-team/ionic-docs/issues"
}, },
"homepage": "https://github.com/ionic-team/ionic-docs#readme" "homepage": "https://ionicframework.com/docs"
} }

View File

@ -1,7 +1,25 @@
{ {
"name": "@ionic/angular-server", "name": "@ionic/angular-server",
"version": "0.0.2",
"description": "Angular SSR Module for Ionic", "description": "Angular SSR Module for Ionic",
"version": "0.0.0", "keywords": [
"ionic",
"angular",
"universal",
"ssr",
"prerender",
"serverside"
],
"author": "Ionic Team",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/ionic-team/ionic.git"
},
"bugs": {
"url": "https://github.com/ionic-team/ionic/issues"
},
"homepage": "https://ionicframework.com/",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",
"files": [ "files": [
@ -13,24 +31,24 @@
"clean": "rm -rf ./dist" "clean": "rm -rf ./dist"
}, },
"peerDependencies": { "peerDependencies": {
"@angular-devkit/core": "~8.0.0", "@angular-devkit/core": "^8.0.0",
"@angular/common": "~8.0.0", "@angular/common": "^8.0.0",
"@angular/core": "~8.0.0", "@angular/core": "^8.0.0",
"@angular/platform-server": "~8.0.0", "@angular/platform-server": "^8.0.0",
"@ionic/core": "*", "@ionic/core": "*",
"rxjs": ">=6.2.0", "rxjs": ">=6.2.0",
"zone.js": ">=0.8.26" "zone.js": ">=0.8.26"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/core": "~8.0.0", "@angular-devkit/core": "^8.0.0",
"@angular/animations": "~8.0.0", "@angular/animations": "^8.0.0",
"@angular/common": "~8.0.0", "@angular/common": "^8.0.0",
"@angular/compiler": "~8.0.0", "@angular/compiler": "^8.0.0",
"@angular/compiler-cli": "~8.0.0", "@angular/compiler-cli": "^8.0.0",
"@angular/core": "~8.0.0", "@angular/core": "^8.0.0",
"@angular/platform-browser": "~8.0.0", "@angular/platform-browser": "^8.0.0",
"@angular/platform-server": "~8.0.0", "@angular/platform-server": "^8.0.0",
"@angular/router": "~8.0.0", "@angular/router": "^8.0.0",
"rxjs": "^6.4.0", "rxjs": "^6.4.0",
"tsickle": "^0.34.0", "tsickle": "^0.34.0",
"typescript": "~3.4.3", "typescript": "~3.4.3",

View File

@ -1,6 +1,7 @@
{ {
"extends": "../../tsconfig", "extends": "../../tsconfig",
"compilerOptions": { "compilerOptions": {
"module": "CommonJS",
"rootDir": "src", "rootDir": "src",
"outDir": "dist" "outDir": "dist"
}, },