SlideShare ist ein Scribd-Unternehmen logo
1 von 38
@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

Weitere ähnliche Inhalte

Was ist angesagt?

Axis2 client memory leak
Axis2 client memory leakAxis2 client memory leak
Axis2 client memory leak
feng lee
 
MongoDB: tips, trick and hacks
MongoDB: tips, trick and hacksMongoDB: tips, trick and hacks
MongoDB: tips, trick and hacks
Scott Hernandez
 
Agile web development Groovy Grails with Netbeans
Agile web development Groovy Grails with NetbeansAgile web development Groovy Grails with Netbeans
Agile web development Groovy Grails with Netbeans
Carol McDonald
 

Was ist angesagt? (20)

Axis2 client memory leak
Axis2 client memory leakAxis2 client memory leak
Axis2 client memory leak
 
Scripting GeoServer
Scripting GeoServerScripting GeoServer
Scripting GeoServer
 
Cassandra 3.0 Awesomeness
Cassandra 3.0 AwesomenessCassandra 3.0 Awesomeness
Cassandra 3.0 Awesomeness
 
Python in the database
Python in the databasePython in the database
Python in the database
 
Presto in Treasure Data (presented at db tech showcase Sapporo 2015)
Presto in Treasure Data (presented at db tech showcase Sapporo 2015)Presto in Treasure Data (presented at db tech showcase Sapporo 2015)
Presto in Treasure Data (presented at db tech showcase Sapporo 2015)
 
Cassandra 2.2 & 3.0
Cassandra 2.2 & 3.0Cassandra 2.2 & 3.0
Cassandra 2.2 & 3.0
 
Cassandra 3.0
Cassandra 3.0Cassandra 3.0
Cassandra 3.0
 
Painless Persistence in a Disconnected World
Painless Persistence in a Disconnected WorldPainless Persistence in a Disconnected World
Painless Persistence in a Disconnected World
 
Webエンジニアから見たiOS5
Webエンジニアから見たiOS5Webエンジニアから見たiOS5
Webエンジニアから見たiOS5
 
MongoDB: tips, trick and hacks
MongoDB: tips, trick and hacksMongoDB: tips, trick and hacks
MongoDB: tips, trick and hacks
 
Spring data requery
Spring data requerySpring data requery
Spring data requery
 
Effective testing for spark programs scala bay preview (pre-strata ny 2015)
Effective testing for spark programs scala bay preview (pre-strata ny 2015)Effective testing for spark programs scala bay preview (pre-strata ny 2015)
Effective testing for spark programs scala bay preview (pre-strata ny 2015)
 
Realm: Building a mobile database
Realm: Building a mobile databaseRealm: Building a mobile database
Realm: Building a mobile database
 
ElasticSearch for .NET Developers
ElasticSearch for .NET DevelopersElasticSearch for .NET Developers
ElasticSearch for .NET Developers
 
Enter the Snake Pit for Fast and Easy Spark
Enter the Snake Pit for Fast and Easy SparkEnter the Snake Pit for Fast and Easy Spark
Enter the Snake Pit for Fast and Easy Spark
 
Agile web development Groovy Grails with Netbeans
Agile web development Groovy Grails with NetbeansAgile web development Groovy Grails with Netbeans
Agile web development Groovy Grails with Netbeans
 
Kotlin @ Coupang Backed - JetBrains Day seoul 2018
Kotlin @ Coupang Backed - JetBrains Day seoul 2018Kotlin @ Coupang Backed - JetBrains Day seoul 2018
Kotlin @ Coupang Backed - JetBrains Day seoul 2018
 
React for Beginners
React for BeginnersReact for Beginners
React for Beginners
 
Combine Spring Data Neo4j and Spring Boot to quickl
Combine Spring Data Neo4j and Spring Boot to quicklCombine Spring Data Neo4j and Spring Boot to quickl
Combine Spring Data Neo4j and Spring Boot to quickl
 
Beyond parallelize and collect - Spark Summit East 2016
Beyond parallelize and collect - Spark Summit East 2016Beyond parallelize and collect - Spark Summit East 2016
Beyond parallelize and collect - Spark Summit East 2016
 

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

Ähnlich wie JS Fest 2019/Autumn. Maciej Treder. Angular Schematics - Develop for developers (20)

Bye bye $GLOBALS['TYPO3_DB']
Bye bye $GLOBALS['TYPO3_DB']Bye bye $GLOBALS['TYPO3_DB']
Bye bye $GLOBALS['TYPO3_DB']
 
DjangoCon 2010 Scaling Disqus
DjangoCon 2010 Scaling DisqusDjangoCon 2010 Scaling Disqus
DjangoCon 2010 Scaling Disqus
 
Go Web Development
Go Web DevelopmentGo Web Development
Go Web Development
 
Cassandra Day NY 2014: Getting Started with the DataStax C# Driver
Cassandra Day NY 2014: Getting Started with the DataStax C# DriverCassandra Day NY 2014: Getting Started with the DataStax C# Driver
Cassandra Day NY 2014: Getting Started with the DataStax C# Driver
 
Staying Sane with Drupal NEPHP
Staying Sane with Drupal NEPHPStaying Sane with Drupal NEPHP
Staying Sane with Drupal NEPHP
 
Linq
LinqLinq
Linq
 
Kerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-Malla
Kerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-MallaKerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-Malla
Kerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-Malla
 
Introduction to laravel framework
Introduction to laravel frameworkIntroduction to laravel framework
Introduction to laravel framework
 
Node azure
Node azureNode azure
Node azure
 
Running Airflow Workflows as ETL Processes on Hadoop
Running Airflow Workflows as ETL Processes on HadoopRunning Airflow Workflows as ETL Processes on Hadoop
Running Airflow Workflows as ETL Processes on Hadoop
 
Angular2 inter3
Angular2 inter3Angular2 inter3
Angular2 inter3
 
Kubernetes上で動作する機械学習モジュールの配信&管理基盤Rekcurd について
Kubernetes上で動作する機械学習モジュールの配信&管理基盤Rekcurd についてKubernetes上で動作する機械学習モジュールの配信&管理基盤Rekcurd について
Kubernetes上で動作する機械学習モジュールの配信&管理基盤Rekcurd について
 
HashiCorp Vault Plugin Infrastructure
HashiCorp Vault Plugin InfrastructureHashiCorp Vault Plugin Infrastructure
HashiCorp Vault Plugin Infrastructure
 
Kerberizing spark. Spark Summit east
Kerberizing spark. Spark Summit eastKerberizing spark. Spark Summit east
Kerberizing spark. Spark Summit east
 
Cassandra Summit 2014: Highly Scalable Web Application in the Cloud with Cass...
Cassandra Summit 2014: Highly Scalable Web Application in the Cloud with Cass...Cassandra Summit 2014: Highly Scalable Web Application in the Cloud with Cass...
Cassandra Summit 2014: Highly Scalable Web Application in the Cloud with Cass...
 
TechDays 2016 - Developing websites using asp.net core mvc6 and entity framew...
TechDays 2016 - Developing websites using asp.net core mvc6 and entity framew...TechDays 2016 - Developing websites using asp.net core mvc6 and entity framew...
TechDays 2016 - Developing websites using asp.net core mvc6 and entity framew...
 
Boost Your Neo4j with User-Defined Procedures
Boost Your Neo4j with User-Defined ProceduresBoost Your Neo4j with User-Defined Procedures
Boost Your Neo4j with User-Defined Procedures
 
LA Ember.js Meetup, Jan 2017
LA Ember.js Meetup, Jan 2017LA Ember.js Meetup, Jan 2017
LA Ember.js Meetup, Jan 2017
 
Wider than rails
Wider than railsWider than rails
Wider than rails
 
React inter3
React inter3React inter3
React inter3
 

Mehr von JSFestUA

Mehr von JSFestUA (20)

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

Kürzlich hochgeladen

Spellings Wk 3 English CAPS CARES Please Practise
Spellings Wk 3 English CAPS CARES Please PractiseSpellings Wk 3 English CAPS CARES Please Practise
Spellings Wk 3 English CAPS CARES Please Practise
AnaAcapella
 
Salient Features of India constitution especially power and functions
Salient Features of India constitution especially power and functionsSalient Features of India constitution especially power and functions
Salient Features of India constitution especially power and functions
KarakKing
 

Kürzlich hochgeladen (20)

Towards a code of practice for AI in AT.pptx
Towards a code of practice for AI in AT.pptxTowards a code of practice for AI in AT.pptx
Towards a code of practice for AI in AT.pptx
 
Single or Multiple melodic lines structure
Single or Multiple melodic lines structureSingle or Multiple melodic lines structure
Single or Multiple melodic lines structure
 
Introduction to Nonprofit Accounting: The Basics
Introduction to Nonprofit Accounting: The BasicsIntroduction to Nonprofit Accounting: The Basics
Introduction to Nonprofit Accounting: The Basics
 
Dyslexia AI Workshop for Slideshare.pptx
Dyslexia AI Workshop for Slideshare.pptxDyslexia AI Workshop for Slideshare.pptx
Dyslexia AI Workshop for Slideshare.pptx
 
Unit-IV- Pharma. Marketing Channels.pptx
Unit-IV- Pharma. Marketing Channels.pptxUnit-IV- Pharma. Marketing Channels.pptx
Unit-IV- Pharma. Marketing Channels.pptx
 
Application orientated numerical on hev.ppt
Application orientated numerical on hev.pptApplication orientated numerical on hev.ppt
Application orientated numerical on hev.ppt
 
This PowerPoint helps students to consider the concept of infinity.
This PowerPoint helps students to consider the concept of infinity.This PowerPoint helps students to consider the concept of infinity.
This PowerPoint helps students to consider the concept of infinity.
 
Food safety_Challenges food safety laboratories_.pdf
Food safety_Challenges food safety laboratories_.pdfFood safety_Challenges food safety laboratories_.pdf
Food safety_Challenges food safety laboratories_.pdf
 
Accessible Digital Futures project (20/03/2024)
Accessible Digital Futures project (20/03/2024)Accessible Digital Futures project (20/03/2024)
Accessible Digital Futures project (20/03/2024)
 
ICT role in 21st century education and it's challenges.
ICT role in 21st century education and it's challenges.ICT role in 21st century education and it's challenges.
ICT role in 21st century education and it's challenges.
 
TỔNG ÔN TẬP THI VÀO LỚP 10 MÔN TIẾNG ANH NĂM HỌC 2023 - 2024 CÓ ĐÁP ÁN (NGỮ Â...
TỔNG ÔN TẬP THI VÀO LỚP 10 MÔN TIẾNG ANH NĂM HỌC 2023 - 2024 CÓ ĐÁP ÁN (NGỮ Â...TỔNG ÔN TẬP THI VÀO LỚP 10 MÔN TIẾNG ANH NĂM HỌC 2023 - 2024 CÓ ĐÁP ÁN (NGỮ Â...
TỔNG ÔN TẬP THI VÀO LỚP 10 MÔN TIẾNG ANH NĂM HỌC 2023 - 2024 CÓ ĐÁP ÁN (NGỮ Â...
 
Python Notes for mca i year students osmania university.docx
Python Notes for mca i year students osmania university.docxPython Notes for mca i year students osmania university.docx
Python Notes for mca i year students osmania university.docx
 
Spellings Wk 3 English CAPS CARES Please Practise
Spellings Wk 3 English CAPS CARES Please PractiseSpellings Wk 3 English CAPS CARES Please Practise
Spellings Wk 3 English CAPS CARES Please Practise
 
Salient Features of India constitution especially power and functions
Salient Features of India constitution especially power and functionsSalient Features of India constitution especially power and functions
Salient Features of India constitution especially power and functions
 
SKILL OF INTRODUCING THE LESSON MICRO SKILLS.pptx
SKILL OF INTRODUCING THE LESSON MICRO SKILLS.pptxSKILL OF INTRODUCING THE LESSON MICRO SKILLS.pptx
SKILL OF INTRODUCING THE LESSON MICRO SKILLS.pptx
 
Making communications land - Are they received and understood as intended? we...
Making communications land - Are they received and understood as intended? we...Making communications land - Are they received and understood as intended? we...
Making communications land - Are they received and understood as intended? we...
 
SOC 101 Demonstration of Learning Presentation
SOC 101 Demonstration of Learning PresentationSOC 101 Demonstration of Learning Presentation
SOC 101 Demonstration of Learning Presentation
 
Fostering Friendships - Enhancing Social Bonds in the Classroom
Fostering Friendships - Enhancing Social Bonds  in the ClassroomFostering Friendships - Enhancing Social Bonds  in the Classroom
Fostering Friendships - Enhancing Social Bonds in the Classroom
 
Sociology 101 Demonstration of Learning Exhibit
Sociology 101 Demonstration of Learning ExhibitSociology 101 Demonstration of Learning Exhibit
Sociology 101 Demonstration of Learning Exhibit
 
Understanding Accommodations and Modifications
Understanding  Accommodations and ModificationsUnderstanding  Accommodations and Modifications
Understanding Accommodations and Modifications
 

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 <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",
  • 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

Hinweis der Redaktion

  1. kreska od npm do angular + info,ze będzie coś robic
  2. zmienić tytuł
  3. dopisać CLI do obrazka
  4. zmienić nazwę zmiennej errorów wewn.
  5. dodać slajd window -> this.window private someVar = „do not ocen the widnow”;
  6. sprawdzić interfejs potrzebny do napisania własnego taska
  7. verdaccio na dol
  8. cd testApp