├── .angular-cli.json ├── .editorconfig ├── .gitignore ├── README.md ├── app1.server.ts ├── app2.server.ts ├── e2e ├── app1 │ ├── app.e2e-spec.ts │ ├── app.po.ts │ └── tsconfig.e2e.json └── app2 │ ├── app.e2e-spec.ts │ ├── app.po.ts │ └── tsconfig.e2e.json ├── karma.conf.js ├── package-lock.json ├── package.json ├── protractor.conf.js ├── scripts ├── update.js ├── verify.js └── versions │ └── 1.3.2.json ├── src ├── app1.test.ts ├── app1 │ ├── app │ │ ├── app.component.css │ │ ├── app.component.html │ │ ├── app.component.ts │ │ ├── app.module.ts │ │ ├── app.server.module.ts │ │ └── views │ │ │ └── default │ │ │ ├── default.component.css │ │ │ ├── default.component.html │ │ │ ├── default.component.spec.ts │ │ │ ├── default.component.ts │ │ │ └── default.module.ts │ ├── assets │ │ └── .gitkeep │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── favicon.ico │ ├── index.html │ ├── main.server.ts │ ├── main.ts │ └── styles.scss ├── app2.test.ts ├── app2 │ ├── app │ │ ├── app.component.css │ │ ├── app.component.html │ │ ├── app.component.ts │ │ ├── app.module.ts │ │ ├── app.server.module.ts │ │ └── views │ │ │ └── default │ │ │ ├── default.component.css │ │ │ ├── default.component.html │ │ │ ├── default.component.spec.ts │ │ │ ├── default.component.ts │ │ │ └── default.module.ts │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── favicon.ico │ ├── index.html │ ├── main.server.ts │ ├── main.ts │ └── styles.scss ├── shared │ ├── assets │ │ └── .gitkeep │ ├── components │ │ ├── angular-cli │ │ │ ├── angular-cli.css │ │ │ ├── angular-cli.html │ │ │ ├── angular-cli.module.ts │ │ │ ├── angular-cli.spec.ts │ │ │ └── angular-cli.ts │ │ ├── example1 │ │ │ ├── example1.css │ │ │ ├── example1.html │ │ │ ├── example1.module.ts │ │ │ ├── example1.spec.ts │ │ │ └── example1.ts │ │ └── example2 │ │ │ ├── example2.css │ │ │ ├── example2.html │ │ │ ├── example2.module.ts │ │ │ ├── example2.spec.ts │ │ │ └── example2.ts │ ├── other │ │ ├── polyfills.ts │ │ └── styles.scss │ └── package.json ├── test.ts ├── tsconfig.app1.json ├── tsconfig.app1.server.json ├── tsconfig.app2.json ├── tsconfig.app2.server.json ├── tsconfig.spec.json └── typings.d.ts ├── tsconfig.json ├── tslint.json ├── webpack.app1.server.config.js └── webpack.app2.server.config.js /.angular-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "project": { 4 | "name": "angular-cli-library" 5 | }, 6 | "apps": [ 7 | { 8 | "name": "app1-browser", 9 | "root": "src", 10 | "outDir": "dist/app1-browser", 11 | "assets": [ 12 | { "glob": "**/*", "input": "app1/assets/", "output": "./assets/" }, 13 | { "glob": "favicon.ico", "input": "app1/", "output": "./" }, 14 | { "glob": "**/*", "input": "shared/assets", "output": "./assets/" } 15 | ], 16 | "index": "app1/index.html", 17 | "deployUrl": "./", 18 | "platform": "browser", 19 | "main": "app1/main.ts", 20 | "polyfills": "shared/other/polyfills.ts", 21 | "test": "app1.test.ts", 22 | "tsconfig": "tsconfig.app1.json", 23 | "testTsconfig": "tsconfig.spec.json", 24 | "prefix": "app1", 25 | "styles": [ 26 | "app1/styles.scss", 27 | "shared/other/styles.scss" 28 | ], 29 | "scripts": [], 30 | "environmentSource": "app1/environments/environment.ts", 31 | "environments": { 32 | "dev": "app1/environments/environment.ts", 33 | "prod": "app1/environments/environment.prod.ts" 34 | } 35 | },{ 36 | "name": "app1-server", 37 | "root": "src", 38 | "outDir": "dist/app1-server", 39 | "assets": [ 40 | { "glob": "**/*", "input": "app1/assets/", "output": "./assets/" }, 41 | { "glob": "favicon.ico", "input": "app1/", "output": "./" }, 42 | { "glob": "**/*", "input": "shared/assets", "output": "./assets/" } 43 | ], 44 | "index": "app1/index.html", 45 | "deployUrl": "./", 46 | "platform": "server", 47 | "main": "app1/main.server.ts", 48 | "test": "app1.test.ts", 49 | "tsconfig": "tsconfig.app1.server.json", 50 | "testTsconfig": "tsconfig.spec.json", 51 | "prefix": "app1", 52 | "styles": [ 53 | "app1/styles.scss", 54 | "shared/other/styles.scss" 55 | ], 56 | "scripts": [], 57 | "environmentSource": "app1/environments/environment.ts", 58 | "environments": { 59 | "dev": "app1/environments/environment.ts", 60 | "prod": "app1/environments/environment.prod.ts" 61 | } 62 | }, 63 | { 64 | "name": "app2-browser", 65 | "root": "src", 66 | "outDir": "dist/app2-browser", 67 | "assets": [ 68 | { "glob": "**/*", "input": "app2/assets/", "output": "./assets/" }, 69 | { "glob": "favicon.ico", "input": "app2/", "output": "./" }, 70 | { "glob": "**/*", "input": "../node_modules/angular-cli-library/assets", "output": "./assets/" } 71 | ], 72 | "index": "app2/index.html", 73 | "deployUrl": "./", 74 | "platform": "browser", 75 | "main": "app2/main.ts", 76 | "polyfills": "../node_modules/angular-cli-library/other/polyfills.ts", 77 | "test": "app2.test.ts", 78 | "tsconfig": "tsconfig.app2.json", 79 | "testTsconfig": "tsconfig.spec.json", 80 | "prefix": "app2", 81 | "styles": [ 82 | "app2/styles.scss", 83 | "../node_modules/angular-cli-library/other/styles.scss" 84 | ], 85 | "scripts": [], 86 | "environmentSource": "app2/environments/environment.ts", 87 | "environments": { 88 | "dev": "app2/environments/environment.ts", 89 | "prod": "app2/environments/environment.prod.ts" 90 | } 91 | },{ 92 | "name": "app2-server", 93 | "root": "src", 94 | "outDir": "dist/app2-server", 95 | "assets": [ 96 | { "glob": "**/*", "input": "app2/assets/", "output": "./assets/" }, 97 | { "glob": "favicon.ico", "input": "app2/", "output": "./" }, 98 | { "glob": "**/*", "input": "../node_modules/angular-cli-library/assets", "output": "./assets/" } 99 | ], 100 | "index": "app2/index.html", 101 | "deployUrl": "./", 102 | "platform": "server", 103 | "main": "app2/main.server.ts", 104 | "test": "app2.test.ts", 105 | "tsconfig": "tsconfig.app2.server.json", 106 | "testTsconfig": "tsconfig.spec.json", 107 | "prefix": "app2", 108 | "styles": [ 109 | "app2/styles.scss", 110 | "../node_modules/angular-cli-library/other/styles.scss" 111 | ], 112 | "scripts": [], 113 | "environmentSource": "app2/environments/environment.ts", 114 | "environments": { 115 | "dev": "app2/environments/environment.ts", 116 | "prod": "app2/environments/environment.prod.ts" 117 | } 118 | } 119 | ], 120 | "e2e": { 121 | "protractor": { 122 | "config": "./protractor.conf.js" 123 | } 124 | }, 125 | "lint": [ 126 | { 127 | "project": "src/tsconfig.app.json", 128 | "exclude": "**/node_modules/**" 129 | }, 130 | { 131 | "project": "src/tsconfig.spec.json", 132 | "exclude": "**/node_modules/**" 133 | }, 134 | { 135 | "project": "e2e/tsconfig.e2e.json", 136 | "exclude": "**/node_modules/**" 137 | } 138 | ], 139 | "test": { 140 | "karma": { 141 | "config": "./karma.conf.js" 142 | } 143 | }, 144 | "defaults": { 145 | "styleExt": "css", 146 | "component": {} 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | /node_modules 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | .c9/ 16 | *.launch 17 | .settings/ 18 | *.sublime-workspace 19 | 20 | # IDE - VSCode 21 | .vscode/* 22 | !.vscode/settings.json 23 | !.vscode/tasks.json 24 | !.vscode/launch.json 25 | !.vscode/extensions.json 26 | 27 | # misc 28 | /.sass-cache 29 | /connect.lock 30 | /coverage 31 | /libpeerconnection.log 32 | npm-debug.log 33 | testem.log 34 | /typings 35 | yarn-error.log 36 | 37 | # e2e 38 | /e2e/*.js 39 | /e2e/*.map 40 | 41 | # System Files 42 | .DS_Store 43 | Thumbs.db 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular CLI with Library support (1.5.4) 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli). It is an extended version of a new app generated with ng new. It adds Library support for multiple apps in a mono-repo. 4 | 5 | This starter is a result of many workarounds in order to make angular-cli work with a shared library of components/services/modules etc. 6 | 7 | Currently supports: 8 | 9 | * Library can be published and imported from npm registry (supports lazy loading and aot, Example2) 10 | * Serving multiple apps at the same time 11 | * Production build of multiple apps (with AOT) 12 | * Shared Library of components/modules ( can be shared between each app with `@shared/` ) 13 | * Shared assets folder and polyfills. ( can be shared between each app ) 14 | * Shared SCSS. ( can be shared between each app ) 15 | * lazy loading of Shared modules 16 | * Shared modules can lazy load other Shared modules ( with/without routes ) 17 | * Unit tests for each app 18 | * E2E tests for each app 19 | * Custom commands to make your life easier 20 | * Universal Integration for multiple apps (need to install webpack for local serve `npm install -g webpack`) 21 | 22 | and everything else you would normally be able to do with an app generated with ng new. 23 | 24 | Feel free to ask questions, provide feedback, submit ideas, requests or create an issue. 25 | 26 | Star and support this project if you like it, to help it stay alive and maybe even be added as a boilerplate/starter to angular-cli (e.x. ng new app-name --template library). 27 | 28 | ## Versioning 29 | 30 | Versioning of this project will follow the same with Angular-cli. There will be a separate branch that will be working for each version (starting with 1.2.7) 31 | 32 | ## How to use this Starter 33 | 34 | Just git clone this repo and start using it (run `npm install` after). The result would be the same if you had created a new app with Angular-CLI (ng new) having made all the necessary changes so that you can use multiple apps with a shared Library of components and have extra functionality. 35 | 36 | ## Examples 37 | 38 | The repo also includes examples of some use cases to help you out: 39 | 40 | 0. AngularCLI: `AngularCLI` module is lazy loaded from the shared Libary (@shared) as a component/module of the default view/route. 41 | 1. Example1: In example 1 `Example1` module is lazy loaded from the shared Libary (@shared) as a view/route. 42 | 2. Example2: In example 2, the lazy loaded shared module `Example1` lazy loads another shared module `Example2`. Also `AngularCLI` module is lazily loaded and imported from the angular-cli-library (npm registry) 43 | 44 | ## Commands 45 | 46 | #### Development server 47 | 48 | * Run `npm run app1` to serve app1 (runs `ng serve --app app1 --port 4200`) 49 | * Run `npm run app2` to serve app2 etc. (runs `ng serve --app app2 --port 4201`) 50 | 51 | Names can change if you want (package.json). You can have multiple apps running in your browser as each app is launched on a different port. Navigate to `http://localhost:4200/` or `http://localhost:4201/` for example. Each app will automatically reload if you change any of the source files (if you edit your shared library both apps will reload if they are using it). 52 | 53 | #### Library 54 | 55 | * Run `npm run library:publish` to publish your library to npm registry. It is the same as running `npm publish` in `src/shared` folder. 56 | 57 | #### Build 58 | 59 | * Run `npm run app1:build` to build app1. (runs `ng build --app app1 --prod --build-optimizer`) 60 | * Run `npm run app2:build` to build app2 etc. (runs `ng build --app app2 --prod --build-optimizer`) 61 | 62 | The build artifacts will be stored in the `dist/app1` or `dist/app2` directory. All builds are for production ( --prod ). 63 | 64 | #### Code scaffolding 65 | 66 | Run `ng generate component component-name` to generate a new component. To add a component to app1 specify app.module as in the following example: `ng g component default --module ../app.module.ts`. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 67 | 68 | #### Running unit tests 69 | 70 | * Run `npm run app1:test` to run *.spec.ts tests in app1 folder. (runs `ng test --app app1`) 71 | * Run `npm run app2:test` to run *.spec.ts tests in app2 folder. (runs `ng test --app app2`) 72 | 73 | #### Running end-to-end tests 74 | 75 | * Run `npm run app1:e2e` to run e2e tests from e2e/app1 folder. (runs `ng e2e --app app1`) 76 | * Run `npm run app2:e2e` to run e2e tests from e2e/app2 folder. (runs `ng e2e --app app2`) 77 | 78 | #### Further help 79 | 80 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). 81 | -------------------------------------------------------------------------------- /app1.server.ts: -------------------------------------------------------------------------------- 1 | // These are important and needed before anything else 2 | import 'zone.js/dist/zone-node'; 3 | import 'reflect-metadata'; 4 | 5 | import { renderModuleFactory } from '@angular/platform-server'; 6 | import { enableProdMode } from '@angular/core'; 7 | 8 | import * as express from 'express'; 9 | import { join } from 'path'; 10 | import { readFileSync } from 'fs'; 11 | 12 | // Faster server renders w/ Prod mode (dev mode never needed) 13 | enableProdMode(); 14 | 15 | // Express server 16 | const app = express(); 17 | 18 | const PORT = process.env.PORT || 4000; 19 | const DIST_FOLDER = join(process.cwd(), './dist'); 20 | 21 | // Our index.html we'll use as our template 22 | const template = readFileSync(join(DIST_FOLDER, 'app1-browser', 'index.html')).toString(); 23 | 24 | // * NOTE :: leave this as require() since this file is built Dynamically from webpack 25 | const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/app1-server/main.bundle'); 26 | 27 | const { provideModuleMap } = require('@nguniversal/module-map-ngfactory-loader'); 28 | 29 | app.engine('html', (_, options, callback) => { 30 | renderModuleFactory(AppServerModuleNgFactory, { 31 | // Our index.html 32 | document: template, 33 | url: options.req.url, 34 | // DI so that we can get lazy-loading to work differently (since we need it to just instantly render it) 35 | extraProviders: [ 36 | provideModuleMap(LAZY_MODULE_MAP) 37 | ] 38 | }).then(html => { 39 | callback(null, html); 40 | }); 41 | }); 42 | 43 | app.set('view engine', 'html'); 44 | app.set('views', join(DIST_FOLDER, 'app1-browser')); 45 | 46 | // Server static files from /browser 47 | app.get('*.*', express.static(join(DIST_FOLDER, 'app1-browser'))); 48 | 49 | // All regular routes use the Universal engine 50 | app.get('*', (req, res) => { 51 | res.render(join(DIST_FOLDER, 'app1-browser', 'index.html'), { req }); 52 | }); 53 | 54 | // Start up the Node server 55 | app.listen(PORT, () => { 56 | console.log(`Node server listening on http://localhost:${PORT}`); 57 | }); -------------------------------------------------------------------------------- /app2.server.ts: -------------------------------------------------------------------------------- 1 | // These are important and needed before anything else 2 | import 'zone.js/dist/zone-node'; 3 | import 'reflect-metadata'; 4 | 5 | import { renderModuleFactory } from '@angular/platform-server'; 6 | import { enableProdMode } from '@angular/core'; 7 | 8 | import * as express from 'express'; 9 | import { join } from 'path'; 10 | import { readFileSync } from 'fs'; 11 | 12 | // Faster server renders w/ Prod mode (dev mode never needed) 13 | enableProdMode(); 14 | 15 | // Express server 16 | const app = express(); 17 | 18 | const PORT = process.env.PORT || 4000; 19 | const DIST_FOLDER = join(process.cwd(), './dist'); 20 | 21 | // Our index.html we'll use as our template 22 | const template = readFileSync(join(DIST_FOLDER, 'app2-browser', 'index.html')).toString(); 23 | 24 | // * NOTE :: leave this as require() since this file is built Dynamically from webpack 25 | const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/app2-server/main.bundle'); 26 | 27 | const { provideModuleMap } = require('@nguniversal/module-map-ngfactory-loader'); 28 | 29 | app.engine('html', (_, options, callback) => { 30 | renderModuleFactory(AppServerModuleNgFactory, { 31 | // Our index.html 32 | document: template, 33 | url: options.req.url, 34 | // DI so that we can get lazy-loading to work differently (since we need it to just instantly render it) 35 | extraProviders: [ 36 | provideModuleMap(LAZY_MODULE_MAP) 37 | ] 38 | }).then(html => { 39 | callback(null, html); 40 | }); 41 | }); 42 | 43 | app.set('view engine', 'html'); 44 | app.set('views', join(DIST_FOLDER, 'app2-browser')); 45 | 46 | // Server static files from /browser 47 | app.get('*.*', express.static(join(DIST_FOLDER, 'app2-browser'))); 48 | 49 | // All regular routes use the Universal engine 50 | app.get('*', (req, res) => { 51 | res.render(join(DIST_FOLDER, 'app2-browser', 'index.html'), { req }); 52 | }); 53 | 54 | // Start up the Node server 55 | app.listen(PORT, () => { 56 | console.log(`Node server listening on http://localhost:${PORT}`); 57 | }); -------------------------------------------------------------------------------- /e2e/app1/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { AngularCliLibraryPage } from './app.po'; 2 | 3 | describe('App1 ', () => { 4 | let page: AngularCliLibraryPage; 5 | 6 | beforeEach(() => { 7 | page = new AngularCliLibraryPage(); 8 | }); 9 | 10 | it('should display welcome message', () => { 11 | page.navigateTo(); 12 | expect(page.getParagraphText()).toEqual('Welcome to an extended version of a new app generated with ng new! This example uses a shared component/module between multiple apps!!'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /e2e/app1/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class AngularCliLibraryPage { 4 | navigateTo() { 5 | return browser.get('/'); 6 | } 7 | 8 | getParagraphText() { 9 | return element(by.css('app-root h1')).getText(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/app1/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/e2e", 5 | "baseUrl": ".", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": [ 9 | "jasmine", 10 | "jasminewd2", 11 | "node" 12 | ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /e2e/app2/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { AngularCliLibraryPage } from './app.po'; 2 | 3 | describe('App2 ', () => { 4 | let page: AngularCliLibraryPage; 5 | 6 | beforeEach(() => { 7 | page = new AngularCliLibraryPage(); 8 | }); 9 | 10 | it('should display welcome message', () => { 11 | page.navigateTo(); 12 | expect(page.getParagraphText()).toEqual('Welcome to an extended version of a new app generated with ng new! This example uses a shared component/module between multiple apps!!'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /e2e/app2/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class AngularCliLibraryPage { 4 | navigateTo() { 5 | return browser.get('/'); 6 | } 7 | 8 | getParagraphText() { 9 | return element(by.css('app-root h1')).getText(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/app2/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/e2e", 5 | "baseUrl": ".", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": [ 9 | "jasmine", 10 | "jasminewd2", 11 | "node" 12 | ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/0.13/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular/cli'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular/cli/plugins/karma') 14 | ], 15 | client:{ 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | reports: [ 'html', 'lcovonly' ], 20 | fixWebpackSourcePaths: true 21 | }, 22 | angularCli: { 23 | environment: 'dev' 24 | }, 25 | reporters: ['progress', 'kjhtml'], 26 | port: 9876, 27 | colors: true, 28 | logLevel: config.LOG_INFO, 29 | autoWatch: true, 30 | browsers: ['Chrome'], 31 | singleRun: false 32 | }); 33 | }; 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-cli-library", 3 | "version": "1.5.4", 4 | "license": "MIT", 5 | "scripts": { 6 | "ng": "ng", 7 | "start": "ng serve", 8 | "build": "ng build", 9 | "test": "ng test", 10 | "lint": "ng lint", 11 | "e2e": "ng e2e", 12 | "library:publish": "npm publish src/shared", 13 | "update": "node scripts/update.js", 14 | "verify": "node scripts/verify.js", 15 | "app1": "ng serve --app app1-browser --port 4200", 16 | "app2": "ng serve --app app2-browser --port 4201", 17 | "app1:build": "ng build --app app1-browser --prod --build-optimizer", 18 | "app2:build": "ng build --app app2-browser --prod --build-optimizer", 19 | "app1:ssr": "npm run app1:build && npm run app1:ssr:build && webpack --config webpack.app1.server.config.js --progress --colors && node dist/app1-server/server.js", 20 | "app2:ssr": "npm run app2:build && npm run app2:ssr:build && webpack --config webpack.app2.server.config.js --progress --colors && node dist/app2-server/server.js", 21 | "app1:ssr:build": "ng build --app app1-server --prod --output-hashing=false", 22 | "app2:ssr:build": "ng build --app app2-server --prod --output-hashing=false", 23 | "app1:test": "ng test --app app1", 24 | "app2:test": "ng test --app app2", 25 | "app1:e2e": "ng e2e --app app1", 26 | "app2:e2e": "ng e2e --app app2" 27 | }, 28 | "private": true, 29 | "dependencies": { 30 | "@angular/animations": "5.0.3", 31 | "@angular/common": "5.0.3", 32 | "@angular/compiler": "5.0.3", 33 | "@angular/core": "5.0.3", 34 | "@angular/forms": "5.0.3", 35 | "@angular/http": "5.0.3", 36 | "@angular/platform-browser": "5.0.3", 37 | "@angular/platform-browser-dynamic": "5.0.3", 38 | "@angular/platform-server": "5.0.3", 39 | "@angular/router": "5.0.3", 40 | "@nguniversal/module-map-ngfactory-loader": "5.0.0-beta.5", 41 | "angular-cli-library": "1.3.2", 42 | "core-js": "2.5.1", 43 | "rxjs": "5.5.2", 44 | "ts-loader": "3.1.1", 45 | "@types/node": "8.0.53", 46 | "zone.js": "0.8.18" 47 | }, 48 | "devDependencies": { 49 | "@angular/cli": "1.5.4", 50 | "@angular/compiler-cli": "5.0.3", 51 | "@angular/language-service": "5.0.3", 52 | "@types/jasmine": "2.8.2", 53 | "@types/jasminewd2": "2.0.3", 54 | "@types/node": "8.0.53", 55 | "codelyzer": "4.0.1", 56 | "jasmine-core": "2.8.0", 57 | "jasmine-spec-reporter": "4.2.1", 58 | "karma": "1.7.1", 59 | "karma-chrome-launcher": "2.2.0", 60 | "karma-cli": "1.0.1", 61 | "karma-coverage-istanbul-reporter": "1.3.0", 62 | "karma-jasmine": "1.1.0", 63 | "karma-jasmine-html-reporter": "0.2.2", 64 | "protractor": "5.2.0", 65 | "ts-node": "3.3.0", 66 | "tslint": "5.8.0", 67 | "typescript": "2.4.2" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /protractor.conf.js: -------------------------------------------------------------------------------- 1 | // Protractor configuration file, see link for more information 2 | // https://github.com/angular/protractor/blob/master/lib/config.ts 3 | 4 | const { SpecReporter } = require('jasmine-spec-reporter'); 5 | 6 | var argv = require('minimist')(process.argv.slice(2)); 7 | var path = './e2e/'; 8 | if(argv.app){ 9 | path += argv.app; 10 | } 11 | 12 | exports.config = { 13 | allScriptsTimeout: 11000, 14 | specs: [ 15 | path + '/**/*.e2e-spec.ts' 16 | ], 17 | capabilities: { 18 | 'browserName': 'chrome' 19 | }, 20 | directConnect: true, 21 | baseUrl: 'http://localhost:4200/', 22 | framework: 'jasmine', 23 | jasmineNodeOpts: { 24 | showColors: true, 25 | defaultTimeoutInterval: 30000, 26 | print: function() {} 27 | }, 28 | onPrepare() { 29 | console.log(path); 30 | require('ts-node').register({ 31 | project: path + '/tsconfig.e2e.json' 32 | }); 33 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /scripts/update.js: -------------------------------------------------------------------------------- 1 | 2 | var latest_version = '1.3.2' 3 | 4 | var readline = require('readline'); 5 | 6 | var rl = readline.createInterface({ 7 | input: process.stdin, 8 | output: process.stdout 9 | }); 10 | console.log('Latest version is:' + latest_version); 11 | rl.question('Upgrade to latest version? (y/n) ', function(answer) { 12 | if(answer == 'y' || answer == 'Y'){ 13 | console.log('Updating project to latest version...'); 14 | } else { 15 | 16 | } 17 | rl.close(); 18 | }); -------------------------------------------------------------------------------- /scripts/verify.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nekkon/angular-cli-library/c61f240ba6b241fa652fab904580d75b3c7985e1/scripts/verify.js -------------------------------------------------------------------------------- /scripts/versions/1.3.2.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nekkon/angular-cli-library/c61f240ba6b241fa652fab904580d75b3c7985e1/scripts/versions/1.3.2.json -------------------------------------------------------------------------------- /src/app1.test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/long-stack-trace-zone'; 4 | import 'zone.js/dist/proxy.js'; 5 | import 'zone.js/dist/sync-test'; 6 | import 'zone.js/dist/jasmine-patch'; 7 | import 'zone.js/dist/async-test'; 8 | import 'zone.js/dist/fake-async-test'; 9 | import { getTestBed } from '@angular/core/testing'; 10 | import { 11 | BrowserDynamicTestingModule, 12 | platformBrowserDynamicTesting 13 | } from '@angular/platform-browser-dynamic/testing'; 14 | 15 | // Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. 16 | declare const __karma__: any; 17 | declare const require: any; 18 | 19 | // Prevent Karma from running prematurely. 20 | __karma__.loaded = function () {}; 21 | 22 | // First, initialize the Angular testing environment. 23 | getTestBed().initTestEnvironment( 24 | BrowserDynamicTestingModule, 25 | platformBrowserDynamicTesting() 26 | ); 27 | // Then we find all the tests. 28 | const context = require.context('./app1', true, /\.spec\.ts$/); 29 | // And load the modules. 30 | context.keys().map(context); 31 | // Finally, start Karma to run the tests. 32 | __karma__.start(); 33 | -------------------------------------------------------------------------------- /src/app1/app/app.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nekkon/angular-cli-library/c61f240ba6b241fa652fab904580d75b3c7985e1/src/app1/app/app.component.css -------------------------------------------------------------------------------- /src/app1/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/app1/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.css'] 7 | }) 8 | export class AppComponent { 9 | title = 'app'; 10 | } 11 | -------------------------------------------------------------------------------- /src/app1/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { NgModule } from '@angular/core'; 4 | 5 | import { AppComponent } from './app.component'; 6 | 7 | @NgModule({ 8 | declarations: [ 9 | AppComponent 10 | ], 11 | imports: [ 12 | BrowserModule.withServerTransition({appId: 'app1'}), 13 | RouterModule.forRoot([ 14 | { path: '', loadChildren:'./views/default/default.module#DefaultModule'}, 15 | { path: 'example1', loadChildren:'@shared/components/example1/example1.module#Example1Module'}, 16 | ]) 17 | ], 18 | providers: [], 19 | bootstrap: [AppComponent] 20 | }) 21 | export class AppModule { } 22 | -------------------------------------------------------------------------------- /src/app1/app/app.server.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { ServerModule } from '@angular/platform-server'; 3 | 4 | import { AppModule } from './app.module'; 5 | import { AppComponent } from './app.component'; 6 | import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader'; 7 | 8 | @NgModule({ 9 | imports: [ 10 | // The AppServerModule should import your AppModule followed 11 | // by the ServerModule from @angular/platform-server. 12 | AppModule, 13 | ServerModule, 14 | ModuleMapLoaderModule 15 | ], 16 | // Since the bootstrapped component is not inherited from your 17 | // imported AppModule, it needs to be repeated here. 18 | bootstrap: [AppComponent] 19 | }) 20 | export class AppServerModule {} -------------------------------------------------------------------------------- /src/app1/app/views/default/default.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nekkon/angular-cli-library/c61f240ba6b241fa652fab904580d75b3c7985e1/src/app1/app/views/default/default.component.css -------------------------------------------------------------------------------- /src/app1/app/views/default/default.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/app1/app/views/default/default.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { AngularCLIModule } from '@shared/components/angular-cli/angular-cli.module'; 2 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 3 | 4 | import { DefaultComponent } from './default.component'; 5 | 6 | describe('Default view of app1 ', () => { 7 | let component: DefaultComponent; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(() => { 11 | TestBed.configureTestingModule({ 12 | imports: [AngularCLIModule], 13 | declarations: [ DefaultComponent ] 14 | }) 15 | .compileComponents(); 16 | 17 | fixture = TestBed.createComponent(DefaultComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should be created', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app1/app/views/default/default.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app1-default', 5 | templateUrl: './default.component.html', 6 | styleUrls: ['./default.component.css'] 7 | }) 8 | export class DefaultComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app1/app/views/default/default.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { CommonModule } from '@angular/common'; 3 | import { NgModule } from '@angular/core'; 4 | 5 | import { DefaultComponent } from './default.component'; 6 | import { AngularCLIModule } from "@shared/components/angular-cli/angular-cli.module"; 7 | 8 | @NgModule({ 9 | declarations: [ 10 | DefaultComponent 11 | ], 12 | imports: [ 13 | CommonModule, 14 | AngularCLIModule, 15 | RouterModule.forChild([ 16 | { path: '', component:DefaultComponent}, 17 | ]) 18 | ] 19 | }) 20 | export class DefaultModule { } 21 | -------------------------------------------------------------------------------- /src/app1/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nekkon/angular-cli-library/c61f240ba6b241fa652fab904580d75b3c7985e1/src/app1/assets/.gitkeep -------------------------------------------------------------------------------- /src/app1/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /src/app1/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // The file contents for the current environment will overwrite these during build. 2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do 3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead. 4 | // The list of which env maps to which file can be found in `.angular-cli.json`. 5 | 6 | export const environment = { 7 | production: false 8 | }; 9 | -------------------------------------------------------------------------------- /src/app1/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nekkon/angular-cli-library/c61f240ba6b241fa652fab904580d75b3c7985e1/src/app1/favicon.ico -------------------------------------------------------------------------------- /src/app1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular CLI with Library (app1) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/app1/main.server.ts: -------------------------------------------------------------------------------- 1 | export { AppServerModule } from './app/app.server.module'; -------------------------------------------------------------------------------- /src/app1/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule); 12 | -------------------------------------------------------------------------------- /src/app1/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /src/app2.test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/long-stack-trace-zone'; 4 | import 'zone.js/dist/proxy.js'; 5 | import 'zone.js/dist/sync-test'; 6 | import 'zone.js/dist/jasmine-patch'; 7 | import 'zone.js/dist/async-test'; 8 | import 'zone.js/dist/fake-async-test'; 9 | import { getTestBed } from '@angular/core/testing'; 10 | import { 11 | BrowserDynamicTestingModule, 12 | platformBrowserDynamicTesting 13 | } from '@angular/platform-browser-dynamic/testing'; 14 | 15 | // Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. 16 | declare const __karma__: any; 17 | declare const require: any; 18 | 19 | // Prevent Karma from running prematurely. 20 | __karma__.loaded = function () {}; 21 | 22 | // First, initialize the Angular testing environment. 23 | getTestBed().initTestEnvironment( 24 | BrowserDynamicTestingModule, 25 | platformBrowserDynamicTesting() 26 | ); 27 | // Then we find all the tests. 28 | const context = require.context('./app2', true, /\.spec\.ts$/); 29 | // And load the modules. 30 | context.keys().map(context); 31 | // Finally, start Karma to run the tests. 32 | __karma__.start(); 33 | -------------------------------------------------------------------------------- /src/app2/app/app.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nekkon/angular-cli-library/c61f240ba6b241fa652fab904580d75b3c7985e1/src/app2/app/app.component.css -------------------------------------------------------------------------------- /src/app2/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/app2/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.css'] 7 | }) 8 | export class AppComponent { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/app2/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { NgModule } from '@angular/core'; 4 | 5 | import { AppComponent } from './app.component'; 6 | 7 | @NgModule({ 8 | declarations: [ 9 | AppComponent 10 | ], 11 | imports: [ 12 | BrowserModule.withServerTransition({appId: 'app2'}), 13 | RouterModule.forRoot([ 14 | { path: '', loadChildren:'./views/default/default.module#DefaultModule'}, 15 | { path: 'example1', loadChildren:'@angular-cli-library/components/example1/example1.module#Example1Module'}, 16 | ]) 17 | ], 18 | providers: [], 19 | bootstrap: [AppComponent] 20 | }) 21 | export class AppModule { } 22 | -------------------------------------------------------------------------------- /src/app2/app/app.server.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { ServerModule } from '@angular/platform-server'; 3 | 4 | import { AppModule } from './app.module'; 5 | import { AppComponent } from './app.component'; 6 | import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader'; 7 | 8 | @NgModule({ 9 | imports: [ 10 | // The AppServerModule should import your AppModule followed 11 | // by the ServerModule from @angular/platform-server. 12 | AppModule, 13 | ServerModule, 14 | ModuleMapLoaderModule 15 | ], 16 | // Since the bootstrapped component is not inherited from your 17 | // imported AppModule, it needs to be repeated here. 18 | bootstrap: [AppComponent] 19 | }) 20 | export class AppServerModule {} -------------------------------------------------------------------------------- /src/app2/app/views/default/default.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nekkon/angular-cli-library/c61f240ba6b241fa652fab904580d75b3c7985e1/src/app2/app/views/default/default.component.css -------------------------------------------------------------------------------- /src/app2/app/views/default/default.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/app2/app/views/default/default.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { AngularCLIModule } from '@shared/components/angular-cli/angular-cli.module'; 2 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 3 | 4 | import { DefaultComponent } from './default.component'; 5 | 6 | describe('Default view of app2 ', () => { 7 | let component: DefaultComponent; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(() => { 11 | TestBed.configureTestingModule({ 12 | imports: [AngularCLIModule], 13 | declarations: [ DefaultComponent ] 14 | }) 15 | .compileComponents(); 16 | 17 | fixture = TestBed.createComponent(DefaultComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should be created', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app2/app/views/default/default.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app2-default', 5 | templateUrl: './default.component.html', 6 | styleUrls: ['./default.component.css'] 7 | }) 8 | export class DefaultComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app2/app/views/default/default.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | import { AngularCLIModule } from "@angular-cli-library/components/angular-cli/angular-cli.module"; 4 | import { DefaultComponent } from './default.component'; 5 | import { RouterModule } from '@angular/router'; 6 | 7 | @NgModule({ 8 | declarations:[DefaultComponent], 9 | imports: [ 10 | CommonModule, 11 | AngularCLIModule, 12 | RouterModule.forChild([ 13 | { path: '', component:DefaultComponent}, 14 | ]) 15 | ] 16 | }) 17 | export class DefaultModule { } 18 | -------------------------------------------------------------------------------- /src/app2/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /src/app2/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // The file contents for the current environment will overwrite these during build. 2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do 3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead. 4 | // The list of which env maps to which file can be found in `.angular-cli.json`. 5 | 6 | export const environment = { 7 | production: false 8 | }; 9 | -------------------------------------------------------------------------------- /src/app2/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nekkon/angular-cli-library/c61f240ba6b241fa652fab904580d75b3c7985e1/src/app2/favicon.ico -------------------------------------------------------------------------------- /src/app2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular CLI with Library (app2) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/app2/main.server.ts: -------------------------------------------------------------------------------- 1 | export { AppServerModule } from './app/app.server.module'; -------------------------------------------------------------------------------- /src/app2/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule); 12 | -------------------------------------------------------------------------------- /src/app2/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /src/shared/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nekkon/angular-cli-library/c61f240ba6b241fa652fab904580d75b3c7985e1/src/shared/assets/.gitkeep -------------------------------------------------------------------------------- /src/shared/components/angular-cli/angular-cli.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nekkon/angular-cli-library/c61f240ba6b241fa652fab904580d75b3c7985e1/src/shared/components/angular-cli/angular-cli.css -------------------------------------------------------------------------------- /src/shared/components/angular-cli/angular-cli.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | Example1 4 | Example2 5 |
6 |
7 |

8 | Welcome to {{ title }}!! 9 |

10 | 11 |
12 |

Here are some links to help you start:

13 | -------------------------------------------------------------------------------- /src/shared/components/angular-cli/angular-cli.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | 4 | import { AngularCLI } from './angular-cli'; 5 | 6 | @NgModule({ 7 | declarations: [ 8 | AngularCLI 9 | ], 10 | entryComponents:[ 11 | AngularCLI 12 | ], 13 | imports: [ 14 | CommonModule 15 | ], 16 | exports:[ 17 | AngularCLI 18 | ] 19 | }) 20 | export class AngularCLIModule { } 21 | -------------------------------------------------------------------------------- /src/shared/components/angular-cli/angular-cli.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { AngularCLI } from './angular-cli'; 4 | 5 | describe('Shared Angular CLI component/module', () => { 6 | let component: AngularCLI; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ AngularCLI ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AngularCLI); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should be created', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/shared/components/angular-cli/angular-cli.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'angular-cli', 5 | templateUrl: './angular-cli.html', 6 | styleUrls: ['./angular-cli.css'] 7 | }) 8 | export class AngularCLI implements OnInit { 9 | title = 'an extended version of a new app generated with ng new with Library suppport for multiple apps!' 10 | 11 | constructor() { } 12 | 13 | ngOnInit() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/shared/components/example1/example1.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nekkon/angular-cli-library/c61f240ba6b241fa652fab904580d75b3c7985e1/src/shared/components/example1/example1.css -------------------------------------------------------------------------------- /src/shared/components/example1/example1.html: -------------------------------------------------------------------------------- 1 |
2 | {{title}} 3 |
4 |
5 | Home 6 | Example2 7 |
-------------------------------------------------------------------------------- /src/shared/components/example1/example1.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { Example1Component } from './example1'; 3 | import { CommonModule } from '@angular/common'; 4 | import { NgModule } from '@angular/core'; 5 | 6 | 7 | @NgModule({ 8 | declarations: [ 9 | Example1Component, 10 | ], 11 | imports: [ 12 | CommonModule, 13 | RouterModule.forChild([ 14 | { path: '', component:Example1Component}, 15 | { path: 'example2', loadChildren:'../example2/example2.module#Example2Module'}, 16 | ]) 17 | ], 18 | exports:[ 19 | Example1Component 20 | ] 21 | }) 22 | export class Example1Module { } 23 | -------------------------------------------------------------------------------- /src/shared/components/example1/example1.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { AngularCLI } from './angular-cli'; 4 | 5 | describe('Shared Angular CLI component/module', () => { 6 | let component: AngularCLI; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ AngularCLI ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AngularCLI); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should be created', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/shared/components/example1/example1.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'example1', 5 | templateUrl: './example1.html', 6 | styleUrls: ['./example1.css'] 7 | }) 8 | export class Example1Component implements OnInit { 9 | title = 'Example1: This component/module was lazy loaded from a Shared Library'; 10 | 11 | constructor() { } 12 | 13 | ngOnInit() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/shared/components/example2/example2.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nekkon/angular-cli-library/c61f240ba6b241fa652fab904580d75b3c7985e1/src/shared/components/example2/example2.css -------------------------------------------------------------------------------- /src/shared/components/example2/example2.html: -------------------------------------------------------------------------------- 1 |
2 | {{title}} 3 |
4 |
5 | Home 6 | Example1 7 |
-------------------------------------------------------------------------------- /src/shared/components/example2/example2.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { CommonModule } from '@angular/common'; 3 | import { NgModule } from '@angular/core'; 4 | import { Example2Component } from "./example2"; 5 | 6 | @NgModule({ 7 | declarations: [ 8 | Example2Component 9 | ], 10 | imports: [ 11 | CommonModule, 12 | RouterModule.forChild([ 13 | { path: '', component:Example2Component } 14 | ]) 15 | ], 16 | exports:[ 17 | Example2Component 18 | ] 19 | }) 20 | export class Example2Module { } 21 | -------------------------------------------------------------------------------- /src/shared/components/example2/example2.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { AngularCLI } from './angular-cli'; 4 | 5 | describe('Shared Angular CLI component/module', () => { 6 | let component: AngularCLI; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ AngularCLI ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AngularCLI); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should be created', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/shared/components/example2/example2.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'example2', 5 | templateUrl: './example2.html', 6 | styleUrls: ['./example2.css'] 7 | }) 8 | export class Example2Component implements OnInit { 9 | title = 'Example2: This Shared module/component was lazily loaded from another Shared lazy loaded module/component!'; 10 | 11 | constructor() { } 12 | 13 | ngOnInit() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/shared/other/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/ 22 | // import 'core-js/es6/symbol'; 23 | // import 'core-js/es6/object'; 24 | // import 'core-js/es6/function'; 25 | // import 'core-js/es6/parse-int'; 26 | // import 'core-js/es6/parse-float'; 27 | // import 'core-js/es6/number'; 28 | // import 'core-js/es6/math'; 29 | // import 'core-js/es6/string'; 30 | // import 'core-js/es6/date'; 31 | // import 'core-js/es6/array'; 32 | // import 'core-js/es6/regexp'; 33 | // import 'core-js/es6/map'; 34 | // import 'core-js/es6/weak-map'; 35 | // import 'core-js/es6/set'; 36 | 37 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 38 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 39 | 40 | /** Evergreen browsers require these. **/ 41 | import 'core-js/es6/reflect'; 42 | import 'core-js/es7/reflect'; 43 | 44 | 45 | /** 46 | * Required to support Web Animations `@angular/animation`. 47 | * Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation 48 | **/ 49 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 50 | 51 | 52 | 53 | /*************************************************************************************************** 54 | * Zone JS is required by Angular itself. 55 | */ 56 | import 'zone.js/dist/zone'; // Included with Angular CLI. 57 | 58 | 59 | 60 | /*************************************************************************************************** 61 | * APPLICATION IMPORTS 62 | */ 63 | 64 | /** 65 | * Date, currency, decimal and percent pipes. 66 | * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10 67 | */ 68 | // import 'intl'; // Run `npm install --save intl`. 69 | /** 70 | * Need to import at least one locale-data with intl. 71 | */ 72 | // import 'intl/locale-data/jsonp/en'; 73 | -------------------------------------------------------------------------------- /src/shared/other/styles.scss: -------------------------------------------------------------------------------- 1 | /* Styles in this file can be shared between apps */ 2 | -------------------------------------------------------------------------------- /src/shared/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-cli-library", 3 | "version": "1.3.2", 4 | "description": "npm package showcasing angular-cli-library by nekkon", 5 | "main": "index.ts", 6 | "scripts": { 7 | "test": "ng test" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/nekkon/angular-cli-library.git" 12 | }, 13 | "keywords": [ 14 | "angular-cli", 15 | "angular", 16 | "typescript", 17 | "library", 18 | "mono-repo", 19 | "multiple-apps" 20 | ], 21 | "author": "nekkon", 22 | "license": "MIT", 23 | "bugs": { 24 | "url": "https://github.com/nekkon/angular-cli-library/issues" 25 | }, 26 | "homepage": "https://github.com/nekkon/angular-cli-library#readme" 27 | } 28 | -------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/long-stack-trace-zone'; 4 | import 'zone.js/dist/proxy.js'; 5 | import 'zone.js/dist/sync-test'; 6 | import 'zone.js/dist/jasmine-patch'; 7 | import 'zone.js/dist/async-test'; 8 | import 'zone.js/dist/fake-async-test'; 9 | import { getTestBed } from '@angular/core/testing'; 10 | import { 11 | BrowserDynamicTestingModule, 12 | platformBrowserDynamicTesting 13 | } from '@angular/platform-browser-dynamic/testing'; 14 | 15 | // Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. 16 | declare const __karma__: any; 17 | declare const require: any; 18 | 19 | // Prevent Karma from running prematurely. 20 | __karma__.loaded = function () {}; 21 | 22 | // First, initialize the Angular testing environment. 23 | getTestBed().initTestEnvironment( 24 | BrowserDynamicTestingModule, 25 | platformBrowserDynamicTesting() 26 | ); 27 | // Then we find all the tests. 28 | const context = require.context('./', true, /\.spec\.ts$/); 29 | // And load the modules. 30 | context.keys().map(context); 31 | // Finally, start Karma to run the tests. 32 | __karma__.start(); 33 | -------------------------------------------------------------------------------- /src/tsconfig.app1.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "paths": { 5 | "@shared/*": ["shared/*"] 6 | }, 7 | "outDir": "../out-tsc/app", 8 | "baseUrl": ".", 9 | "module": "es2015", 10 | "types": [] 11 | }, 12 | "include": [ 13 | "app1/**/*", 14 | "shared/**/*" 15 | ], 16 | "exclude":[ 17 | "**/*.spec.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /src/tsconfig.app1.server.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "paths": { 5 | "@shared/*": ["shared/*"] 6 | }, 7 | "outDir": "../out-tsc/app", 8 | "baseUrl": ".", 9 | "module": "commonjs" 10 | }, 11 | "include": [ 12 | "app1/**/*", 13 | "shared/**/*" 14 | ], 15 | "exclude":[ 16 | "**/*.spec.ts" 17 | ], 18 | "angularCompilerOptions": { 19 | "entryModule": "app1/app/app.server.module#AppServerModule" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/tsconfig.app2.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "paths": { 5 | "@angular-cli-library/*": ["../node_modules/angular-cli-library/*"] 6 | }, 7 | "outDir": "../out-tsc/app", 8 | "baseUrl": ".", 9 | "module": "es2015", 10 | "types": [] 11 | }, 12 | "include": [ 13 | "app2/**/*", 14 | "../node_modules/angular-cli-library/**/*" 15 | ], 16 | "exclude":[ 17 | "../**/*.spec.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /src/tsconfig.app2.server.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "paths": { 5 | "@angular-cli-library/*": ["../node_modules/angular-cli-library/*"] 6 | }, 7 | "outDir": "../out-tsc/app", 8 | "baseUrl": ".", 9 | "module": "commonjs", 10 | "types": [] 11 | }, 12 | "include": [ 13 | "app2/**/*", 14 | "../node_modules/angular-cli-library/**/*" 15 | ], 16 | "exclude":[ 17 | "../**/*.spec.ts" 18 | ], 19 | "angularCompilerOptions": { 20 | "entryModule": "app2/app/app.server.module#AppServerModule" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "paths": { 5 | "@shared/*": ["shared/*"] 6 | }, 7 | "outDir": "../out-tsc/app", 8 | "baseUrl": ".", 9 | "module": "es2015", 10 | "types": ["jasmine"] 11 | }, 12 | "include": [ 13 | "**/*.spec.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/typings.d.ts: -------------------------------------------------------------------------------- 1 | /* SystemJS module definition */ 2 | declare var module: NodeModule; 3 | interface NodeModule { 4 | id: string; 5 | } 6 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "paths": { 5 | "@shared/*": ["src/shared/*"] 6 | }, 7 | "outDir": "./dist/out-tsc", 8 | "baseUrl": ".", 9 | "sourceMap": true, 10 | "declaration": false, 11 | "moduleResolution": "node", 12 | "emitDecoratorMetadata": true, 13 | "experimentalDecorators": true, 14 | "target": "es5", 15 | "typeRoots": [ 16 | "node_modules/@types" 17 | ], 18 | "lib": [ 19 | "es2017", 20 | "dom" 21 | ] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "arrow-return-shorthand": true, 7 | "callable-types": true, 8 | "class-name": true, 9 | "comment-format": [ 10 | true, 11 | "check-space" 12 | ], 13 | "curly": true, 14 | "eofline": true, 15 | "forin": true, 16 | "import-blacklist": [ 17 | true, 18 | "rxjs" 19 | ], 20 | "import-spacing": true, 21 | "indent": [ 22 | true, 23 | "spaces" 24 | ], 25 | "interface-over-type-literal": true, 26 | "label-position": true, 27 | "max-line-length": [ 28 | true, 29 | 140 30 | ], 31 | "member-access": false, 32 | "member-ordering": [ 33 | true, 34 | { 35 | "order": [ 36 | "static-field", 37 | "instance-field", 38 | "static-method", 39 | "instance-method" 40 | ] 41 | } 42 | ], 43 | "no-arg": true, 44 | "no-bitwise": true, 45 | "no-console": [ 46 | true, 47 | "debug", 48 | "info", 49 | "time", 50 | "timeEnd", 51 | "trace" 52 | ], 53 | "no-construct": true, 54 | "no-debugger": true, 55 | "no-duplicate-super": true, 56 | "no-empty": false, 57 | "no-empty-interface": true, 58 | "no-eval": true, 59 | "no-inferrable-types": [ 60 | true, 61 | "ignore-params" 62 | ], 63 | "no-misused-new": true, 64 | "no-non-null-assertion": true, 65 | "no-shadowed-variable": true, 66 | "no-string-literal": false, 67 | "no-string-throw": true, 68 | "no-switch-case-fall-through": true, 69 | "no-trailing-whitespace": true, 70 | "no-unnecessary-initializer": true, 71 | "no-unused-expression": true, 72 | "no-use-before-declare": true, 73 | "no-var-keyword": true, 74 | "object-literal-sort-keys": false, 75 | "one-line": [ 76 | true, 77 | "check-open-brace", 78 | "check-catch", 79 | "check-else", 80 | "check-whitespace" 81 | ], 82 | "prefer-const": true, 83 | "quotemark": [ 84 | true, 85 | "single" 86 | ], 87 | "radix": true, 88 | "semicolon": [ 89 | true, 90 | "always" 91 | ], 92 | "triple-equals": [ 93 | true, 94 | "allow-null-check" 95 | ], 96 | "typedef-whitespace": [ 97 | true, 98 | { 99 | "call-signature": "nospace", 100 | "index-signature": "nospace", 101 | "parameter": "nospace", 102 | "property-declaration": "nospace", 103 | "variable-declaration": "nospace" 104 | } 105 | ], 106 | "typeof-compare": true, 107 | "unified-signatures": true, 108 | "variable-name": false, 109 | "whitespace": [ 110 | true, 111 | "check-branch", 112 | "check-decl", 113 | "check-operator", 114 | "check-separator", 115 | "check-type" 116 | ], 117 | "directive-selector": [ 118 | true, 119 | "attribute", 120 | "app", 121 | "camelCase" 122 | ], 123 | "component-selector": [ 124 | true, 125 | "element", 126 | "app", 127 | "kebab-case" 128 | ], 129 | "use-input-property-decorator": true, 130 | "use-output-property-decorator": true, 131 | "use-host-property-decorator": true, 132 | "no-input-rename": true, 133 | "no-output-rename": true, 134 | "use-life-cycle-interface": true, 135 | "use-pipe-transform-interface": true, 136 | "component-class-suffix": true, 137 | "directive-class-suffix": true, 138 | "no-access-missing-member": true, 139 | "templates-use-public": true, 140 | "invoke-injectable": true 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /webpack.app1.server.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | 4 | module.exports = { 5 | entry: { server: './app1.server.ts' }, 6 | resolve: { extensions: ['.js', '.ts'] }, 7 | target: 'node', 8 | // this makes sure we include node_modules and other 3rd party libraries 9 | externals: [/(node_modules|main\..*\.js)/], 10 | output: { 11 | path: path.join(__dirname, './dist/app1-server'), 12 | filename: '[name].js' 13 | }, 14 | module: { 15 | rules: [ 16 | { 17 | test: /\.ts$/, 18 | loader: 'ts-loader?configFile=src/tsconfig.app1.server.json' 19 | } 20 | ] 21 | }, 22 | plugins: [ 23 | // Temporary Fix for issue: https://github.com/angular/angular/issues/11580 24 | // for "WARNING Critical dependency: the request of a dependency is an expression" 25 | new webpack.ContextReplacementPlugin( 26 | /(.+)?angular(\\|\/)core(.+)?/, 27 | path.join(__dirname, './src/app1'), // location of your src 28 | {} // a map of your routes 29 | ), 30 | new webpack.ContextReplacementPlugin( 31 | /(.+)?express(\\|\/)(.+)?/, 32 | path.join(__dirname, './src/app1'), 33 | {} 34 | ) 35 | ] 36 | } -------------------------------------------------------------------------------- /webpack.app2.server.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | 4 | module.exports = { 5 | entry: { server: './app2.server.ts' }, 6 | resolve: { extensions: ['.js', '.ts'] }, 7 | target: 'node', 8 | // this makes sure we include node_modules and other 3rd party libraries 9 | externals: [/(node_modules|main\..*\.js)/], 10 | output: { 11 | path: path.join(__dirname, './dist/app1-server'), 12 | filename: '[name].js' 13 | }, 14 | module: { 15 | rules: [ 16 | { 17 | test: /\.ts$/, 18 | loader: 'ts-loader?configFile=src/tsconfig.app1.server.json' 19 | } 20 | ] 21 | }, 22 | plugins: [ 23 | // Temporary Fix for issue: https://github.com/angular/angular/issues/11580 24 | // for "WARNING Critical dependency: the request of a dependency is an expression" 25 | new webpack.ContextReplacementPlugin( 26 | /(.+)?angular(\\|\/)core(.+)?/, 27 | path.join(__dirname, './src/app1'), // location of your src 28 | {} // a map of your routes 29 | ), 30 | new webpack.ContextReplacementPlugin( 31 | /(.+)?express(\\|\/)(.+)?/, 32 | path.join(__dirname, './src/app1'), 33 | {} 34 | ) 35 | ] 36 | } --------------------------------------------------------------------------------