SlideShare a Scribd company logo
@maciejtreder
@maciejtreder
Angular Schematics
Develop for developers
@maciejtreder
@maciejtreder
• Kraków, Poland
• Senior Software Development Engineer in Test
Akamai Technologies
• Angular passionate
• Open source contributor (founder of @ng-toolkit project)
• Articles author
@maciejtreder
• Cambridge, Massachusetts
• Content Delivery Network
• Over 240 00 servers deployed in more then 120 countries
• Serves 15%-30% of the Internet traffic
@maciejtreder
Innovation Begins With an Idea
• SEO friendly
• Works offline
• Cheap environment
- Angular Universal
- PWA
- Serverless
@maciejtreder
Do Not Reinvent the Wheel
• Angular CLI
• Angular Webpack starter (https://github.com/preboot/angular-webpack)
• Angular Universal starter (https://github.com/angular/universal-starter)
@maciejtreder
Yet Another Boilerplate…
• Progressive Web App
• Server-Side Rendering
• Hosted on AWS Lambda
• Uploaded to GitHub
• ~30 clones weekly
angular-universal-serverless-pwa
@maciejtreder
The Gray Eminence
Is GIT designed for hosting dev tools?
@esosanderelias
@maciejtreder
Schematics
@maciejtreder
Schematics
• Set of instructions (rules) consumed by the Angular CLI to manipulate the
file-system and perform NodeJS tasks
• Extensible - possible to combine multiple internal and external rules
• Atomic - “commit approach”/“all or nothing”
ng add/update/init/something
@maciejtreder
ng add @ng-toolkit/universal
@maciejtreder
package.json
{
"author": "Maciej Treder <contact@maciejtreder.com>",
"name": "@ng-toolkit/universal",
"main": "dist/index.js",
"version": "1.1.50",
"description": "Adds Angular Universal support for any Angular CLI project",
"repository": {
"type": "git",
"url": "git+https://github.com/maciejtreder/ng-toolkit.git"
},
"license": "MIT",
"schematics": "./collection.json",
"peerDependencies": {
},
"dependencies": {
},
"devDependencies": {
},
"publishConfig": {
"access": "public"
"schematics": "./collection.json",
@maciejtreder
collection.json
{
"$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
"schematics": {
"ng-add": {
"factory": "./schematics",
"description": "Update an application with server side rendering (Angular Universal)",
"schema": "./schema.json"
}
}
}
"factory": "./schematics",
"schema": "./schema.json"
@maciejtreder
schema.json{
"$schema": "http://json-schema.org/schema",
"id": "ng-toolkit universal",
"title": "Angular Application Options Schema",
"type": "object",
"properties": {
"directory": {
"description": "App root catalog",
"type": "string",
"default": "."
},
"http": {
"description": "Determines if you want to install TransferHttpCacheModule",
"type": "boolean",
"default": true
}
},
"required": []
ng add @ng-toolkit/universal —http false
@maciejtreder
schematics.ts
export default function index(options: any): Rule {
if (options.http) {
//true or nothing was passed (default value)
} else {
//false was passed
}
}
@maciejtreder
Tree
• Object which represents file system
• Supports CRUD operations and more:
• exists()
• getDir()
• visit()
• etc
@maciejtreder
Rule
• Set of instructions for the Angular CLI
• (tree: Tree, context: SchematicContext) => Tree | Observable<Tree> |
Rule | void
let rule: Rule = (tree: Tree) => {
tree.create('hello', 'world');
return tree;
}
krk-mps4m:angular-oslo mtreder$ ls
hello
krk-mps4m:angular-oslo mtreder$ cat hello
world
CLI
@maciejtreder
tree
Chaining
export default function index(options: any): Rule {
return chain([
rule1,
rule2,
rule3
])
}
rule1 rule2 rule3
@maciejtreder
Tree | Observable<Tree> | Rule |
void
export function performAdditionalAction(originalRule: Rule): Rule {
return (tree: Tree, context: SchematicContext) => {
originalRule.apply(tree, context)
.pipe(map(
(tree: Tree) => console.log(tree.exists('hello'))
)
);
}
}
@maciejtreder
export function applyAndLog(rule: Rule): Rule {
bugsnag.register('0b326fddc255310e516875c9874fed91');
return (tree: Tree, context: SchematicContext) => {
return (<Observable<Tree>> rule(tree, context))
.pipe(catchError((error: any) => {
let subject: Subject<Tree> = new Subject();
bugsnag.notify(error, (bugsnagError, response) => {
if (!bugsnagError && response === 'OK') {
console.log(`Stacktrace sent to tracking system.`);
}
subject.next(Tree.empty());
subject.complete();
});
return subject;
}));
}
}
@maciejtreder
@maciejtreder
ng update
{
"ng-update": {
"requirements": { "my-lib": "^5" },
"migrations": "./migrations/migration-collection.json"
}
} {
"schematics": {
"migration-01": { "version": "6", "factory": "./update-6" },
"migration-02": { "version": "6.2", "factory": "./update-6_2" },
"migration-03": { "version": "6.3", "factory": "./update-6_3" }
}
}
Updates one or multiple packages, its peer dependencies and the peer dependencies th
@maciejtreder
ng [what?] —collection
export default function(options: Schema): Rule {
const rule: Rule = chain([
externalSchematic('@schematics/angular', 'ng-new', options),
// other rules
]);
return rule;
}
Shadows default rules/schematics collection
• ng new —collection @ng-toolkit/init
• ng generate service —collection myCollection
@maciejtreder
Working with source-code
import * as ts from 'typescript';
export default function(options: any): Rule {
return (tree: Tree, context: SchematicContext) => {
const filePath = `${options.directory}/sourceFile.ts`;
const recorder = tree.beginUpdate(filePath);
let fileContent = getFileContent(tree, filePath);
let sourceFile: ts.SourceFile = ts.createSourceFile('temp.ts', fileContent, ts.ScriptTarget.Latest);
sourceFile.forEachChild(node => {
if (ts.isClassDeclaration(node)) {
node.members.forEach(node => {
if (ts.isConstructorDeclaration(node)) {
if (node.body) {
recorder.insertRight(node.body.pos + 1, 'console.log('constructor!');')
}
}
});
}
});
tree.commitUpdate(recorder);
const recorder = tree.beginUpdate(filePath);
let sourceFile: ts.SourceFile = ts.createSourceFile(
import * as ts from 'typescript';
recorder.insertRight(node.body.pos + 1, 'console.log('constructor!');')
tree.commitUpdate(recorder);
@maciejtreder
is…
• isImportDeclaration
• isVariableDeclaration
• isClassDeclaration
• isMethodDeclaration
• isStringLiteral
• isIfStatement
@maciejtreder
tree.
tree.create('path', 'content');
tree.exists('path')
tree.overwrite('path', 'new file content');
tree.getDir(`${options.directory}/src/environments`).visit( (path: Path) => {
if (path.endsWith('.ts')) {
addEntryToEnvironment(tree, path, 'line to be inserted');
}
});
const recorder = tree.beginUpdate(‘filePath’);
tree.commitUpdate(recorder);
@maciejtreder
Why should I use typescript?
Task:
change all ‘window’ occurences to ‘this.window’
Source code:export MyClass {
private message = 'Do not open window!';
console.log(window
.URL);
}
@maciejtreder
SchematicContext
export default function(options: any): Rule {
return (tree: Tree, context: SchematicContext) => {
context.addTask(new NodePackageInstallTask(options.directory));
return tree;
}
}
• NodePackageInstallTask
• NodePackageLinkTask
• RepositoryInitializerTask
• RunSchematicTask
• TslintFixTask
@maciejtreder
Testing
const collectionPath = path.join(__dirname, './collection.json');
describe('Universal', () => {
let appTree: UnitTestTree;
const schematicRunner = new SchematicTestRunner('@ng-toolkit/universal', collectionPath);
const appOptions: any = { name: 'foo', version: '7.0.0'};
beforeEach((done) => {
appTree = new UnitTestTree(Tree.empty());
schematicRunner.runExternalSchematicAsync(
'@schematics/angular',
'ng-new',
appOptions,
appTree
).subscribe(tree => {
appTree = tree
done();
});
});
@maciejtreder
Testing
const defaultOptions: any = {
project: 'foo',
disableBugsnag: true,
directory: '/foo'
};
it('Should add server build', (done) => {
schematicRunner.runSchematicAsync('ng-add', defaultOptions, appTree).subscribe(tree => {
const cliConfig = JSON.parse(getFileContent(tree, `${defaultOptions.directory}/angular.json`));
expect(cliConfig.projects.foo.architect.server).toBeDefined(`Can't find server build`);
done();
});
})
@maciejtreder
e2e
npm install -g verdaccio
verdaccio --config scripts/default.yaml >> verdacio_output &
npm set registry=http://localhost:4873/
echo "//localhost:4873/:_authToken="fooBar"" >> ~/.npmrc
@maciejtreder
e2e
npm install -g verdaccio
verdaccio --config scripts/default.yaml >> verdacio_output &
npm set registry=http://localhost:4873/
cp ~/.npmrc ~/.npmrc_original
echo "//localhost:4873/:_authToken="fooBar"" >> ~/.npmrc
@maciejtreder
e2e
cd dist
npm publish --registry http://localhost:4873
cd
ng new testApp
ng add @ng-toolkit/universal
npm set registry=https://registry.npmjs.org/
@maciejtreder
Use cases
@maciejtreder
No more boring readme!
Change long instructions to simple parameters
ng add @ng-toolkit/universal
• installs @ng-toolkit/universal package
• creates server configuration in angular.json
• adds NgtUniversalModule to your default app module
• adds TransferHttpCacheModule
• replaces all ocurences of window object with window wrapper
@maciejtreder
Corporate mess!
Anna
HYZ Corporation
Front-end team
Bob
@maciejtreder
Customize your codebase!
• install @xyz/forms
• add OurFormsModule to your app
• customize your code in 32123 files
• udpate @xyz/forms
• customize your code again!
• ng add @xyz/forms
• ng update @xyz/forms
VS
@maciejtreder

More Related Content

What's hot (20)

PPTX
Axis2 client memory leak
feng lee
 
PDF
Scripting GeoServer
Jared Erickson
 
PDF
Cassandra 3.0 Awesomeness
Jon Haddad
 
PDF
Python in the database
pybcn
 
PDF
Presto in Treasure Data (presented at db tech showcase Sapporo 2015)
Mitsunori Komatsu
 
PPTX
Cassandra 2.2 & 3.0
Victor Coustenoble
 
PDF
Cassandra 3.0
Robert Stupp
 
PDF
Painless Persistence in a Disconnected World
Christian Melchior
 
PDF
Webエンジニアから見たiOS5
Satoshi Asano
 
PPTX
MongoDB: tips, trick and hacks
Scott Hernandez
 
PDF
Spring data requery
Sunghyouk Bae
 
PDF
Effective testing for spark programs scala bay preview (pre-strata ny 2015)
Holden Karau
 
PDF
Realm: Building a mobile database
Christian Melchior
 
PPTX
ElasticSearch for .NET Developers
Ben van Mol
 
PDF
Enter the Snake Pit for Fast and Easy Spark
Jon Haddad
 
ODP
Agile web development Groovy Grails with Netbeans
Carol McDonald
 
PDF
Kotlin @ Coupang Backed - JetBrains Day seoul 2018
Sunghyouk Bae
 
PDF
React for Beginners
Derek Willian Stavis
 
PDF
Combine Spring Data Neo4j and Spring Boot to quickl
Neo4j
 
PPTX
Beyond parallelize and collect - Spark Summit East 2016
Holden Karau
 
Axis2 client memory leak
feng lee
 
Scripting GeoServer
Jared Erickson
 
Cassandra 3.0 Awesomeness
Jon Haddad
 
Python in the database
pybcn
 
Presto in Treasure Data (presented at db tech showcase Sapporo 2015)
Mitsunori Komatsu
 
Cassandra 2.2 & 3.0
Victor Coustenoble
 
Cassandra 3.0
Robert Stupp
 
Painless Persistence in a Disconnected World
Christian Melchior
 
Webエンジニアから見たiOS5
Satoshi Asano
 
MongoDB: tips, trick and hacks
Scott Hernandez
 
Spring data requery
Sunghyouk Bae
 
Effective testing for spark programs scala bay preview (pre-strata ny 2015)
Holden Karau
 
Realm: Building a mobile database
Christian Melchior
 
ElasticSearch for .NET Developers
Ben van Mol
 
Enter the Snake Pit for Fast and Easy Spark
Jon Haddad
 
Agile web development Groovy Grails with Netbeans
Carol McDonald
 
Kotlin @ Coupang Backed - JetBrains Day seoul 2018
Sunghyouk Bae
 
React for Beginners
Derek Willian Stavis
 
Combine Spring Data Neo4j and Spring Boot to quickl
Neo4j
 
Beyond parallelize and collect - Spark Summit East 2016
Holden Karau
 

Similar to JS Fest 2019/Autumn. Maciej Treder. Angular Schematics - Develop for developers (20)

PDF
A Gentle Introduction to Angular Schematics - Angular SF 2019
Matt Raible
 
PDF
Angular Schematics
Christoffer Noring
 
PDF
Use Angular Schematics to Simplify Your Life - Develop Denver 2019
Matt Raible
 
PDF
A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019
Matt Raible
 
PDF
Everything You Should Know About the New Angular CLI
Amadou Sall
 
PDF
Quick introduction to Angular 4 for AngularJS 1.5 developers
Paweł Żurowski
 
PDF
Beginner workshop to angularjs presentation at Google
Ari Lerner
 
PDF
From MEAN to the MERN Stack
Troy Miles
 
PDF
Basic overview of Angular
Aleksei Bulgak
 
PDF
"Objects validation and comparison using runtime types (io-ts)", Oleksandr Suhak
Fwdays
 
PDF
Tales of an open source library
500Tech
 
PDF
Angular Weekend
Troy Miles
 
PDF
Angular.js опыт использования, проблемы и решения
Olga Lavrentieva
 
PPTX
Angular CLI : HelloWorld
nikspatel007
 
PDF
Asynchronous single page applications without a line of HTML or Javascript, o...
Robert Schadek
 
PDF
Writing RESTful web services using Node.js
FDConf
 
PPTX
Ext Web Components - Dev Week 2019
Sandeep Adwankar
 
PDF
Angular JS2 Training Session #1
Paras Mendiratta
 
PPTX
Angular2
Oswald Campesato
 
PDF
Angular, the New Angular JS
Kenzan
 
A Gentle Introduction to Angular Schematics - Angular SF 2019
Matt Raible
 
Angular Schematics
Christoffer Noring
 
Use Angular Schematics to Simplify Your Life - Develop Denver 2019
Matt Raible
 
A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019
Matt Raible
 
Everything You Should Know About the New Angular CLI
Amadou Sall
 
Quick introduction to Angular 4 for AngularJS 1.5 developers
Paweł Żurowski
 
Beginner workshop to angularjs presentation at Google
Ari Lerner
 
From MEAN to the MERN Stack
Troy Miles
 
Basic overview of Angular
Aleksei Bulgak
 
"Objects validation and comparison using runtime types (io-ts)", Oleksandr Suhak
Fwdays
 
Tales of an open source library
500Tech
 
Angular Weekend
Troy Miles
 
Angular.js опыт использования, проблемы и решения
Olga Lavrentieva
 
Angular CLI : HelloWorld
nikspatel007
 
Asynchronous single page applications without a line of HTML or Javascript, o...
Robert Schadek
 
Writing RESTful web services using Node.js
FDConf
 
Ext Web Components - Dev Week 2019
Sandeep Adwankar
 
Angular JS2 Training Session #1
Paras Mendiratta
 
Angular, the New Angular JS
Kenzan
 
Ad

More from JSFestUA (20)

PDF
JS Fest 2019/Autumn. Роман Савіцький. Webcomponents & lit-element in production
JSFestUA
 
PDF
JS Fest 2019/Autumn. Erick Wendel. 10 secrets to improve Javascript Performance
JSFestUA
 
PDF
JS Fest 2019/Autumn. Alexandre Gomes. Embrace the "react fatigue"
JSFestUA
 
PDF
JS Fest 2019/Autumn. Anton Cherednikov. Choreographic or orchestral architect...
JSFestUA
 
PDF
JS Fest 2019/Autumn. Adam Leos. So why do you need to know Algorithms and Dat...
JSFestUA
 
PDF
JS Fest 2019/Autumn. Marko Letic. Saving the world with JavaScript: A Data Vi...
JSFestUA
 
PPTX
JS Fest 2019/Autumn. Александр Товмач. JAMstack
JSFestUA
 
PPTX
JS Fest 2019/Autumn. Влад Федосов. Technology agnostic microservices at SPA f...
JSFestUA
 
PPTX
JS Fest 2019/Autumn. Дмитрий Жарков. Blockchainize your SPA or Integrate Java...
JSFestUA
 
PPTX
JS Fest 2019/Autumn. Kyle Boss. A Tinder Love Story: Create a Wordpress Blog ...
JSFestUA
 
PPTX
JS Fest 2019/Autumn. Андрей Старовойт. Зачем нужен тип "true" в TypeScript?
JSFestUA
 
PPTX
JS Fest 2019/Autumn. Eyal Eizenberg. Tipping the Scale
JSFestUA
 
PDF
JS Fest 2019/Autumn. Sota Ohara. Сreate own server less CMS from scratch
JSFestUA
 
PPTX
JS Fest 2019/Autumn. Джордж Евтушенко. Как стать программистом, которого хотят
JSFestUA
 
PDF
JS Fest 2019/Autumn. Алексей Орленко. Node.js N-API for Rust
JSFestUA
 
PDF
JS Fest 2019/Autumn. Daniel Ostrovsky. Falling in love with decorators ES6/Ty...
JSFestUA
 
PPTX
JS Fest 2019/Autumn. Андрей Андрийко. Гексагональна архітектура в Nodejs проекті
JSFestUA
 
PPTX
JS Fest 2019/Autumn. Борис Могила. Svelte. Почему нам не нужно run-time ядро
JSFestUA
 
PPTX
JS Fest 2019/Autumn. Виталий Кухар. Сравнение кластеризации HTTP, TCP и UDP н...
JSFestUA
 
PDF
JS Fest 2019. Виктор Турский. 6 способов взломать твое JavaScript приложение
JSFestUA
 
JS Fest 2019/Autumn. Роман Савіцький. Webcomponents & lit-element in production
JSFestUA
 
JS Fest 2019/Autumn. Erick Wendel. 10 secrets to improve Javascript Performance
JSFestUA
 
JS Fest 2019/Autumn. Alexandre Gomes. Embrace the "react fatigue"
JSFestUA
 
JS Fest 2019/Autumn. Anton Cherednikov. Choreographic or orchestral architect...
JSFestUA
 
JS Fest 2019/Autumn. Adam Leos. So why do you need to know Algorithms and Dat...
JSFestUA
 
JS Fest 2019/Autumn. Marko Letic. Saving the world with JavaScript: A Data Vi...
JSFestUA
 
JS Fest 2019/Autumn. Александр Товмач. JAMstack
JSFestUA
 
JS Fest 2019/Autumn. Влад Федосов. Technology agnostic microservices at SPA f...
JSFestUA
 
JS Fest 2019/Autumn. Дмитрий Жарков. Blockchainize your SPA or Integrate Java...
JSFestUA
 
JS Fest 2019/Autumn. Kyle Boss. A Tinder Love Story: Create a Wordpress Blog ...
JSFestUA
 
JS Fest 2019/Autumn. Андрей Старовойт. Зачем нужен тип "true" в TypeScript?
JSFestUA
 
JS Fest 2019/Autumn. Eyal Eizenberg. Tipping the Scale
JSFestUA
 
JS Fest 2019/Autumn. Sota Ohara. Сreate own server less CMS from scratch
JSFestUA
 
JS Fest 2019/Autumn. Джордж Евтушенко. Как стать программистом, которого хотят
JSFestUA
 
JS Fest 2019/Autumn. Алексей Орленко. Node.js N-API for Rust
JSFestUA
 
JS Fest 2019/Autumn. Daniel Ostrovsky. Falling in love with decorators ES6/Ty...
JSFestUA
 
JS Fest 2019/Autumn. Андрей Андрийко. Гексагональна архітектура в Nodejs проекті
JSFestUA
 
JS Fest 2019/Autumn. Борис Могила. Svelte. Почему нам не нужно run-time ядро
JSFestUA
 
JS Fest 2019/Autumn. Виталий Кухар. Сравнение кластеризации HTTP, TCP и UDP н...
JSFestUA
 
JS Fest 2019. Виктор Турский. 6 способов взломать твое JavaScript приложение
JSFestUA
 
Ad

Recently uploaded (20)

PDF
Isharyanti-2025-Cross Language Communication in Indonesian Language
Neny Isharyanti
 
PPTX
HYDROCEPHALUS: NURSING MANAGEMENT .pptx
PRADEEP ABOTHU
 
PPTX
2025 Winter SWAYAM NPTEL & A Student.pptx
Utsav Yagnik
 
PPTX
Growth and development and milestones, factors
BHUVANESHWARI BADIGER
 
PDF
SSHS-2025-PKLP_Quarter-1-Dr.-Kerby-Alvarez.pdf
AishahSangcopan1
 
PPTX
SPINA BIFIDA: NURSING MANAGEMENT .pptx
PRADEEP ABOTHU
 
PDF
DIGESTION OF CARBOHYDRATES,PROTEINS,LIPIDS
raviralanaresh2
 
PDF
Knee Extensor Mechanism Injuries - Orthopedic Radiologic Imaging
Sean M. Fox
 
PDF
Chapter-V-DED-Entrepreneurship: Institutions Facilitating Entrepreneurship
Dayanand Huded
 
PDF
The-Ever-Evolving-World-of-Science (1).pdf/7TH CLASS CURIOSITY /1ST CHAPTER/B...
Sandeep Swamy
 
PDF
BÀI TẬP BỔ TRỢ TIẾNG ANH 8 - GLOBAL SUCCESS - CẢ NĂM - NĂM 2024 (VOCABULARY, ...
Nguyen Thanh Tu Collection
 
PPTX
grade 5 lesson matatag ENGLISH 5_Q1_PPT_WEEK4.pptx
SireQuinn
 
PDF
0725.WHITEPAPER-UNIQUEWAYSOFPROTOTYPINGANDUXNOW.pdf
Thomas GIRARD, MA, CDP
 
PDF
LAW OF CONTRACT (5 YEAR LLB & UNITARY LLB )- MODULE - 1.& 2 - LEARN THROUGH P...
APARNA T SHAIL KUMAR
 
PPSX
HEALTH ASSESSMENT (Community Health Nursing) - GNM 1st Year
Priyanshu Anand
 
PPTX
STAFF DEVELOPMENT AND WELFARE: MANAGEMENT
PRADEEP ABOTHU
 
PPTX
Unit 2 COMMERCIAL BANKING, Corporate banking.pptx
AnubalaSuresh1
 
PDF
Biological Bilingual Glossary Hindi and English Medium
World of Wisdom
 
PDF
Generative AI: it's STILL not a robot (CIJ Summer 2025)
Paul Bradshaw
 
PDF
CONCURSO DE POESIA “POETUFAS – PASSOS SUAVES PELO VERSO.pdf
Colégio Santa Teresinha
 
Isharyanti-2025-Cross Language Communication in Indonesian Language
Neny Isharyanti
 
HYDROCEPHALUS: NURSING MANAGEMENT .pptx
PRADEEP ABOTHU
 
2025 Winter SWAYAM NPTEL & A Student.pptx
Utsav Yagnik
 
Growth and development and milestones, factors
BHUVANESHWARI BADIGER
 
SSHS-2025-PKLP_Quarter-1-Dr.-Kerby-Alvarez.pdf
AishahSangcopan1
 
SPINA BIFIDA: NURSING MANAGEMENT .pptx
PRADEEP ABOTHU
 
DIGESTION OF CARBOHYDRATES,PROTEINS,LIPIDS
raviralanaresh2
 
Knee Extensor Mechanism Injuries - Orthopedic Radiologic Imaging
Sean M. Fox
 
Chapter-V-DED-Entrepreneurship: Institutions Facilitating Entrepreneurship
Dayanand Huded
 
The-Ever-Evolving-World-of-Science (1).pdf/7TH CLASS CURIOSITY /1ST CHAPTER/B...
Sandeep Swamy
 
BÀI TẬP BỔ TRỢ TIẾNG ANH 8 - GLOBAL SUCCESS - CẢ NĂM - NĂM 2024 (VOCABULARY, ...
Nguyen Thanh Tu Collection
 
grade 5 lesson matatag ENGLISH 5_Q1_PPT_WEEK4.pptx
SireQuinn
 
0725.WHITEPAPER-UNIQUEWAYSOFPROTOTYPINGANDUXNOW.pdf
Thomas GIRARD, MA, CDP
 
LAW OF CONTRACT (5 YEAR LLB & UNITARY LLB )- MODULE - 1.& 2 - LEARN THROUGH P...
APARNA T SHAIL KUMAR
 
HEALTH ASSESSMENT (Community Health Nursing) - GNM 1st Year
Priyanshu Anand
 
STAFF DEVELOPMENT AND WELFARE: MANAGEMENT
PRADEEP ABOTHU
 
Unit 2 COMMERCIAL BANKING, Corporate banking.pptx
AnubalaSuresh1
 
Biological Bilingual Glossary Hindi and English Medium
World of Wisdom
 
Generative AI: it's STILL not a robot (CIJ Summer 2025)
Paul Bradshaw
 
CONCURSO DE POESIA “POETUFAS – PASSOS SUAVES PELO VERSO.pdf
Colégio Santa Teresinha
 

JS Fest 2019/Autumn. Maciej Treder. Angular Schematics - Develop for developers

  • 3. @maciejtreder @maciejtreder • Kraków, Poland • Senior Software Development Engineer in Test Akamai Technologies • Angular passionate • Open source contributor (founder of @ng-toolkit project) • Articles author
  • 4. @maciejtreder • Cambridge, Massachusetts • Content Delivery Network • Over 240 00 servers deployed in more then 120 countries • Serves 15%-30% of the Internet traffic
  • 5. @maciejtreder Innovation Begins With an Idea • SEO friendly • Works offline • Cheap environment - Angular Universal - PWA - Serverless
  • 6. @maciejtreder Do Not Reinvent the Wheel • Angular CLI • Angular Webpack starter (https://github.com/preboot/angular-webpack) • Angular Universal starter (https://github.com/angular/universal-starter)
  • 7. @maciejtreder Yet Another Boilerplate… • Progressive Web App • Server-Side Rendering • Hosted on AWS Lambda • Uploaded to GitHub • ~30 clones weekly angular-universal-serverless-pwa
  • 8. @maciejtreder The Gray Eminence Is GIT designed for hosting dev tools? @esosanderelias
  • 10. @maciejtreder Schematics • Set of instructions (rules) consumed by the Angular CLI to manipulate the file-system and perform NodeJS tasks • Extensible - possible to combine multiple internal and external rules • Atomic - “commit approach”/“all or nothing” ng add/update/init/something
  • 12. @maciejtreder package.json { "author": "Maciej Treder <[email protected]>", "name": "@ng-toolkit/universal", "main": "dist/index.js", "version": "1.1.50", "description": "Adds Angular Universal support for any Angular CLI project", "repository": { "type": "git", "url": "git+https://github.com/maciejtreder/ng-toolkit.git" }, "license": "MIT", "schematics": "./collection.json", "peerDependencies": { }, "dependencies": { }, "devDependencies": { }, "publishConfig": { "access": "public" "schematics": "./collection.json",
  • 13. @maciejtreder collection.json { "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json", "schematics": { "ng-add": { "factory": "./schematics", "description": "Update an application with server side rendering (Angular Universal)", "schema": "./schema.json" } } } "factory": "./schematics", "schema": "./schema.json"
  • 14. @maciejtreder schema.json{ "$schema": "http://json-schema.org/schema", "id": "ng-toolkit universal", "title": "Angular Application Options Schema", "type": "object", "properties": { "directory": { "description": "App root catalog", "type": "string", "default": "." }, "http": { "description": "Determines if you want to install TransferHttpCacheModule", "type": "boolean", "default": true } }, "required": [] ng add @ng-toolkit/universal —http false
  • 15. @maciejtreder schematics.ts export default function index(options: any): Rule { if (options.http) { //true or nothing was passed (default value) } else { //false was passed } }
  • 16. @maciejtreder Tree • Object which represents file system • Supports CRUD operations and more: • exists() • getDir() • visit() • etc
  • 17. @maciejtreder Rule • Set of instructions for the Angular CLI • (tree: Tree, context: SchematicContext) => Tree | Observable<Tree> | Rule | void let rule: Rule = (tree: Tree) => { tree.create('hello', 'world'); return tree; } krk-mps4m:angular-oslo mtreder$ ls hello krk-mps4m:angular-oslo mtreder$ cat hello world CLI
  • 18. @maciejtreder tree Chaining export default function index(options: any): Rule { return chain([ rule1, rule2, rule3 ]) } rule1 rule2 rule3
  • 19. @maciejtreder Tree | Observable<Tree> | Rule | void export function performAdditionalAction(originalRule: Rule): Rule { return (tree: Tree, context: SchematicContext) => { originalRule.apply(tree, context) .pipe(map( (tree: Tree) => console.log(tree.exists('hello')) ) ); } }
  • 20. @maciejtreder export function applyAndLog(rule: Rule): Rule { bugsnag.register('0b326fddc255310e516875c9874fed91'); return (tree: Tree, context: SchematicContext) => { return (<Observable<Tree>> rule(tree, context)) .pipe(catchError((error: any) => { let subject: Subject<Tree> = new Subject(); bugsnag.notify(error, (bugsnagError, response) => { if (!bugsnagError && response === 'OK') { console.log(`Stacktrace sent to tracking system.`); } subject.next(Tree.empty()); subject.complete(); }); return subject; })); } }
  • 22. @maciejtreder ng update { "ng-update": { "requirements": { "my-lib": "^5" }, "migrations": "./migrations/migration-collection.json" } } { "schematics": { "migration-01": { "version": "6", "factory": "./update-6" }, "migration-02": { "version": "6.2", "factory": "./update-6_2" }, "migration-03": { "version": "6.3", "factory": "./update-6_3" } } } Updates one or multiple packages, its peer dependencies and the peer dependencies th
  • 23. @maciejtreder ng [what?] —collection export default function(options: Schema): Rule { const rule: Rule = chain([ externalSchematic('@schematics/angular', 'ng-new', options), // other rules ]); return rule; } Shadows default rules/schematics collection • ng new —collection @ng-toolkit/init • ng generate service —collection myCollection
  • 24. @maciejtreder Working with source-code import * as ts from 'typescript'; export default function(options: any): Rule { return (tree: Tree, context: SchematicContext) => { const filePath = `${options.directory}/sourceFile.ts`; const recorder = tree.beginUpdate(filePath); let fileContent = getFileContent(tree, filePath); let sourceFile: ts.SourceFile = ts.createSourceFile('temp.ts', fileContent, ts.ScriptTarget.Latest); sourceFile.forEachChild(node => { if (ts.isClassDeclaration(node)) { node.members.forEach(node => { if (ts.isConstructorDeclaration(node)) { if (node.body) { recorder.insertRight(node.body.pos + 1, 'console.log('constructor!');') } } }); } }); tree.commitUpdate(recorder); const recorder = tree.beginUpdate(filePath); let sourceFile: ts.SourceFile = ts.createSourceFile( import * as ts from 'typescript'; recorder.insertRight(node.body.pos + 1, 'console.log('constructor!');') tree.commitUpdate(recorder);
  • 25. @maciejtreder is… • isImportDeclaration • isVariableDeclaration • isClassDeclaration • isMethodDeclaration • isStringLiteral • isIfStatement
  • 26. @maciejtreder tree. tree.create('path', 'content'); tree.exists('path') tree.overwrite('path', 'new file content'); tree.getDir(`${options.directory}/src/environments`).visit( (path: Path) => { if (path.endsWith('.ts')) { addEntryToEnvironment(tree, path, 'line to be inserted'); } }); const recorder = tree.beginUpdate(‘filePath’); tree.commitUpdate(recorder);
  • 27. @maciejtreder Why should I use typescript? Task: change all ‘window’ occurences to ‘this.window’ Source code:export MyClass { private message = 'Do not open window!'; console.log(window .URL); }
  • 28. @maciejtreder SchematicContext export default function(options: any): Rule { return (tree: Tree, context: SchematicContext) => { context.addTask(new NodePackageInstallTask(options.directory)); return tree; } } • NodePackageInstallTask • NodePackageLinkTask • RepositoryInitializerTask • RunSchematicTask • TslintFixTask
  • 29. @maciejtreder Testing const collectionPath = path.join(__dirname, './collection.json'); describe('Universal', () => { let appTree: UnitTestTree; const schematicRunner = new SchematicTestRunner('@ng-toolkit/universal', collectionPath); const appOptions: any = { name: 'foo', version: '7.0.0'}; beforeEach((done) => { appTree = new UnitTestTree(Tree.empty()); schematicRunner.runExternalSchematicAsync( '@schematics/angular', 'ng-new', appOptions, appTree ).subscribe(tree => { appTree = tree done(); }); });
  • 30. @maciejtreder Testing const defaultOptions: any = { project: 'foo', disableBugsnag: true, directory: '/foo' }; it('Should add server build', (done) => { schematicRunner.runSchematicAsync('ng-add', defaultOptions, appTree).subscribe(tree => { const cliConfig = JSON.parse(getFileContent(tree, `${defaultOptions.directory}/angular.json`)); expect(cliConfig.projects.foo.architect.server).toBeDefined(`Can't find server build`); done(); }); })
  • 31. @maciejtreder e2e npm install -g verdaccio verdaccio --config scripts/default.yaml >> verdacio_output & npm set registry=http://localhost:4873/ echo "//localhost:4873/:_authToken="fooBar"" >> ~/.npmrc
  • 32. @maciejtreder e2e npm install -g verdaccio verdaccio --config scripts/default.yaml >> verdacio_output & npm set registry=http://localhost:4873/ cp ~/.npmrc ~/.npmrc_original echo "//localhost:4873/:_authToken="fooBar"" >> ~/.npmrc
  • 33. @maciejtreder e2e cd dist npm publish --registry http://localhost:4873 cd ng new testApp ng add @ng-toolkit/universal npm set registry=https://registry.npmjs.org/
  • 35. @maciejtreder No more boring readme! Change long instructions to simple parameters ng add @ng-toolkit/universal • installs @ng-toolkit/universal package • creates server configuration in angular.json • adds NgtUniversalModule to your default app module • adds TransferHttpCacheModule • replaces all ocurences of window object with window wrapper
  • 37. @maciejtreder Customize your codebase! • install @xyz/forms • add OurFormsModule to your app • customize your code in 32123 files • udpate @xyz/forms • customize your code again! • ng add @xyz/forms • ng update @xyz/forms VS

Editor's Notes

  • #12: kreska od npm do angular + info,ze będzie coś robic
  • #16: zmienić tytuł
  • #18: dopisać CLI do obrazka
  • #21: zmienić nazwę zmiennej errorów wewn.
  • #25: dodać slajd window -> this.window private someVar = „do not ocen the widnow”;
  • #29: sprawdzić interfejs potrzebny do napisania własnego taska
  • #32: verdaccio na dol
  • #34: cd testApp