SlideShare uma empresa Scribd logo
1 de 67
Baixar para ler offline
Lean	React	-
Patterns	for	High	Performance
Devon	Bernard
VP	of	Engineering	@	Enlitic
What	if	all	websites	had
airplane	mode
ReactJS
Why?
1. Increases	developer	productivity
• Separation	of	concerns	between	state	and	DOM
• More	modular	and	isolates	business	logic	by	component	(not	by	page)
2. Faster	and	smoother	rendering	of	page	elements
React	+	Redux	Lifecycle
Redux
Persisting	State
Why
• Smoother	UX
• Less	network	requests
How
• Redux	store	is	only	in-memory,	disappears	on	page	refresh/close
• Use	localStorage
Persisting	State	(2)
export const saveState = (state) => {
try {
const serializedState = JSON.stringify(state);
localStorage.setItem('state', serializedState);
localStorage.setItem('updatedAt', (new Date).getTime());
} catch (err) {
// Ignore write errors.
}
}
export const loadState = () => {
try {
const serializedState = localStorage.getItem('state');
if (serializedState === null) {
return undefined;
}
return JSON.parse(serializedState);
}
};
localStorage.js localStorage.js
Persisting	State	(3)
import { loadState, saveState } from './localStorage';
// import throttle from 'lodash/throttle';
const middleware = applyMiddleware(promise(), thunk, loadState);
const store = createStore(reducers, middleware);
store.subscribe(() => {
const currentTime = (new Date).getTime();
const updateTime = localStorage.getItem('updatedAt');
const { reducerA, reducerB } = store.getState();
if (currentTime - updateTime > 10000) {
saveState({ reducerA, reducerB });
}
});
store.js
const libraries = [
{
id: 1,
city: 'New York'
},
{
id: 2,
city: 'San Francisco'
}
];
const libraries = [
{
id: 1, city: 'New York',
books: [
{
id: 1, title: 'Moby Dick',
author: 'Herman Melville'
}, {
id: 2, title: 'The Odyssey',
author: 'Homer'
}
]
}, {
id: 2, city: 'San Francisco',
books: [
{
id: 2, title: 'The Odyssey',
author: 'Homer'
} ...
]
} ...];
const libraries = [
{
id: 1, city: 'New York',
books: [
{
id: 1, title: 'Moby Dick',
author: {name: 'Herman Melville’, ...}
}, {
id: 2, title: 'The Odyssey',
author: {name: 'Homer’, ...}
}
]
}, {
id: 2, city: 'San Francisco',
books: [
{
id: 2, title: 'The Odyssey',
author: {name: 'Homer’, ...}
},...
]
} ...];
const libraries = [
{
id:1, city: 'New York',
books: [1, 2]
}, {
id: 2, city: 'San Francisco',
books: [2,3]
}
];
const books = [
{ id: 1, title: 'Moby Dick', author: 1 },
{ id: 2, title: 'The Odyssey', author: 2}
];
const authors = [
{ id: 1, name: 'Herman Melville', ...},
{ id: 2, name: 'Homer', ...}
];
const libraries = {
1: { city: 'New York', books: [1,2] },
2: { city: 'San Francisco', books: [2,3] }
};
const books {
1: { title: 'Moby Dick', author: 1 },
2: { title: 'The Odyssey', author: 2 }
};
const authors = {
1: { name: 'Herman Melville', ...},
2: { name: 'Homer', ...}
};
Normalized	State
Why
• Faster	queries
• Less	data	redundancy
• More	flexible	entity	access
• Easier	to	test	&	debug
How
1. Flatten	reducers
2. Separate	reducer	entities	(ideally	to	their	own	reducer)
3. Use	objects	with	ids	for	keys	instead	of	a	list
Normalized	State	(2)
https://github.com/paularmstrong/normalizr
{
”id": "123",
"author": {
"id": "1",
”name": "Paul"
},
"title": "My awesome blog post",
"comments": [
{
"id": "324",
"commenter": {
"id": "2",
"name": "Nicole"
}
}
]
}
+
import { normalize, schema }
from 'normalizr';
const user = new schema.Entity(
'users');
const comment = new schema.Entity(
'comments', {
commenter: user
});
const article = new schema.Entity(
'articles', {
author: user,
comments: [ comment ]
});
const normalizedData = normalize(
originalData, article);
{
result: "123",
entities: {
"articles": {
"123": {
id: "123",
author: "1",
title: "My awesome blog post",
comments: [ "324" ]
}
},
"users": {
"1": { "id": "1", "name": "Paul" },
"2": { "id": "2", "name": "Nicole" }
},
"comments": {
"324": { id: "324", "commenter": "2" }
}}}
=>
Pure	Reducers
Why
• Easier	to	debug
• Easier	to	test
How
• Cannot	depend	on	hidden	or	external	state
• Only	use	the	passed	parameters
• Does	NOT	have	side	effects
• E.g.	overriding	parameters
Redux	Dev	Tools
Redux	Dev	tools	(2)
Redux	Dev	tools	(3)
Components
Data	Heavy	Pages
Data	Heavy	Pages
2-4	seconds	later…
!
Data	Heavy	Pages
2-4	seconds	later…
!
Why?	Blockers.
class Dashboard extends Component {
render() {
const { stats } = this.props;
if (!stats) {
return null;
}
return (
<div>
<StatWidget stats={stats.twitter} />
<StatWidget stats={stats.facebook} />
<StatWidget stats={stats.google} />
<StatWidget stats={stats.linkedin} />
<StatWidget stats={stats.email} />
</div>
)
}
}
Not	Only	Slow,	But	Dangerous	Too
X
Not	Only	Slow,	But	Dangerous	Too
Unblocking
class Dashboard extends Component {
render() {
const { stats } = this.props;
//if (!stats) {
// return null;
//}
return (
<div>
{ stats.twitter && <StatWidget stats={stats.twitter} /> }
{ stats.facebook && <StatWidget stats={stats.facebook} /> }
{ stats.google && <StatWidget stats={stats.google} /> }
{ stats.linkedin && <StatWidget stats={stats.linkedin} /> }
{ stats.email && <StatWidget stats={stats.email} /> }
</div>
)
}
}
…better
…better
…better
…better
X X
Component	Skeletons
Component	Skeletons	(2)
class Dashboard extends Component {
render() {
const { stats } = this.props;
return (
<div>
<StatWidget stats={stats.twitter || undefined} />
<StatWidget stats={stats.facebook || undefined} />
<StatWidget stats={stats.google || undefined} />
<StatWidget stats={stats.linkedin || undefined} />
<StatWidget stats={stats.email || undefined} />
</div>
)
}
}
dashboard.js
Component	Skeletons	(3)
class StatWidget extends Component {
render() {
const { stats:info } = this.props;
return (
<div>
<div className="widget-header">
{info.title}
</div>
<div className="widget-body">
{ info.icon &&
<img src={info.icon} /> }
<div className="widget-text">
{ info.followers }
</div>
</div>
</div>
)
}
}
statWidget.js
StatWidget.propTypes = {
stats: PropTypes.object
}
StatWidget.defaultProps = {
stats: {
title: 'Loading widget',
followers: ’’,
icon: 'img/spinner.gif'
}
}
statWidget.js
…best
…best
…best
…best
Component	Lifecycle
shouldComponentUpdate?
Tracking	Repaints
Chrome	Render	Tools
Chrome	Render	Tools	(2)
Method	Binding
^^	Uncaught	TypeError:	Cannot	read	
property	'setColor'	of	null
class X extends Component {
setupDrawing() {
// Some logic
this.setColor();
// More logic
}
setColor() { ... }
render() {
return (
<button
type="button"
onClick={this.setupDrawing}
/>
)
}
}
Issue
Callbacks	and	event	handlers	are	passing	a	
different	scope	and	‘this’	to	your	component	
methods
Method	Binding	(2)
class X extends Component {
setupDrawing() {
this.setColor();
}
render() {
return (
<button
type="button"
onClick={this.setupDrawing.bind(this)}
/>
)
}
}
Method	1	(Inline	Binding)
Method	Binding	(3)
class X extends Component {
setupDrawing = () => {
this.setColor();
}
render() {
return (
<button
type="button"
onClick={this.setupDrawing}
/>
)
}
}
Method	2	(Fat	Arrow	Syntax)
Method	Binding	(4)
class X extends Component {
constructor(props) {
super(props);
this.setupDrawing = this.setupDrawing.bind(this);
}
setupDrawing() {
this.setColor();
}
render() {
return (
<button
type="button"
onClick={this.setupDrawing}
/>
)
}
}
Method	3	(Constructor)
Actions
ActionTypes
store.dispatch({
type: ”EDIT_TASK":,
payload: {}
});
actions.js
reducers.js
switch (action.type) {
case ”EDIT_TASK_PENDING":
case "EDIT_TASK_FULFILLED":
case ”EDIT_TASK_REJECTED":
}
ActionTypes (2)
const THUNK_TYPES = ['EDIT_TASK']; // network actions
const ACTION_TYPES = ['CLEAR_TASK']; // local actions
// Combine all local and network actions
class ActionTypes {
constructor() {
THUNK_TYPES.forEach((action) => {
this[action] = action;
this[`${action}_PENDING`] = `${action}_PENDING`;
this[`${action}_REJECTED`] = `${action}_REJECTED`;
this[`${action}_FULFILLED`] = `${action}_FULFILLED`;
});
ACTION_TYPES.forEach((action) => {
this[action] = action;
});
}
};
const actionTypes = new ActionTypes();
export default actionTypes;
store.dispatch({
type: ActionTypes.EDIT_TASK,
payload: {}
});
actions.js
reducers.js
switch (action.type) {
case ActionTypes.EDIT_TASK_PENDING:
case ActionTypes.EDIT_TASK_FULFILLED:
case ActionTypes.EDIT_TASK_REJECTED:
}
ActionTypes (3)
store.dispatch({
type: ActionTypes.tasks.edit,
payload: {}
});
actions.js
reducers.js
switch (action.type) {
case ActionTypes.tasks.edit.pending:
case ActionTypes.tasks.edit.fulfilled:
case ActionTypes.tasks.edit.rejected:
}
0
1
2
3
start end
Thread
Time
Action	Chains	/	Promises
Action	A Action	B Action	C Action	D Action	E
Synchronous	Actions
0
1
2
3
start end
Thread
Time
Action	A
Action	B
Action	C
Fully	Asynchronous	Actions
Action	Chains	/	Promises	(2)
0
1
2
3
start end
Thread
Time
Partially	Asynchronous	Actions	(	.all(),	.any()	)
Action	Chains	/	Promises	(3)
Action	A
Action	B
Action	C
store.getState()
What
Useful	for	exposing	store	state	to	any	
part	of	your	application
Why
We	want	to	keep	our	reducers	pure,	so	
we	enable	action	creators	to	pass	all	
required	parameters
export function loadTaskQuestions(taskID) {
store.dispatch({
type: ActionTypes.LOAD_TASK_QUESTIONS,
payload: axiosInstance.get(`/task_questions/${taskID}`)
}).then(() => {
const currentTask = store.getState().currentTask;
if (currentTask.status === 'done') {
loadTaskAnswers(currentTask.id);
} else {
populateTaskAnswers();
}
});
}
actions.js
General
Environment	Files
REACT_APP_API_HOST='https://staging.myapp.com'
REACT_APP_API_HOST='http://localhost:5000'
.env
.env.local
const axiosInstance = axios.create({
baseURL: process.env.REACT_APP_API_HOST,
withCredentials: true
});
actions.js
Route	Wrappers
<Route path="/" component={Home} />
<Route path="/login" component={Login} />
<EnsureLoggedInContainer>
<Route path="/profile" component={Profile} />
<Route path="/settings" component={Settings} />
</EnsureLoggedInContainer>
router.js
Route	Wrappers
class EnsureLoggedInContainer extends Component {
componentDidMount() {
if (!this.props.session.userID) {
const userID = localStorage.getItem('user-id');
if (userID) {
Actions.setUserID(parseInt(userID, 10));
} else {
this.props.history.push('/login');
}
}
}
render() {
if (this.props.session.userID) {
return this.props.children;
}
return null;
}
}
ensureLoggedInContainer.js
Offline	First	– Web	Workers
Javascript that	runs	in	the	background	that	can	be	used	for	hijacking	network	requests	and	caching	source	code
var staticCacheName = ’my-app-v1';
self.addEventListener('install', (event) => {
self.skipWaiting();
event.waitUntil(
caches.open(staticCacheName)
.then((cache) => {
return cache.addAll([
'./',
'js/bundle.min.js',
'css/main.css',
'imgs/CaltrainMap.png'
]);
})
);
});
webworker.js
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('./sw.min.js')
}
index.js
Offline	First	– IndexedDB Promised
Like	localStorage,	but	able	to	store	larger	volumes	of	data	and	has	an	asynchronous	API.
let dbPromise = idb.open(’app-db', 1, function(upgradeDb) {
switch(upgradeDb.oldVersion) {
case 0:
let lineStore = upgradeDb.createObjectStore('lines');
}
});
class DB {
constructor() {}
storeLine(line) {
dbPromise.then((db) => {
let tx = db.transaction('lines', 'readwrite');
let lineStore = tx.objectStore('lines');
lineStore.put(line, line.Id);
return tx.complete;
});
}
}
idbController.js
Guess	that	utility!
• Get	your	entire	team	to	use	the	same	coding	standard
• Prevent	developers	from	shipping	un-optimized	code
• Educate	your	team	about	best	practices	and	how	to	improve	their	code
• 100%	free
ESLint
$ npm run lint
/ProjectsX/client/src/js/reducers/index.js
125:9 error Identifier 'some_random_var' is not in camel case
camelcase
125:9 warning 'some_random_var' is assigned a value but never used
no-unused-vars
134:7 error for..in loops iterate over the entire prototype chain, which is virtually never
what you want. Use Object.{keys,values,entries}, and iterate over the resulting array
no-restricted-syntax
✖ 3 problems (2 errors, 1 warning)
ESLint (2)
https://eslint.org/docs/rules/no-unused-vars
ESLint
https://github.com/airbnb/javascript
$ npm install --save-dev eslint eslint-config-airbnb eslint-plugin-jsx-a11y eslint-plugin-react
module.exports = {
"parser": "babel-eslint",
"extends": "airbnb",
"plugins": [
"react",
"jsx-a11y”
],
"rules": {}
};
.eslintrc
Devon	Bernard
VP	of	Engineering	@	Enlitic
" devon@enlitic.com	
# @devonwbernard
Thank	you!
Any	questions?

Mais conteúdo relacionado

Mais procurados

Morphia: Simplifying Persistence for Java and MongoDB
Morphia:  Simplifying Persistence for Java and MongoDBMorphia:  Simplifying Persistence for Java and MongoDB
Morphia: Simplifying Persistence for Java and MongoDB
Jeff Yemin
 

Mais procurados (20)

Testing Backbone applications with Jasmine
Testing Backbone applications with JasmineTesting Backbone applications with Jasmine
Testing Backbone applications with Jasmine
 
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New Tricks
 
My app is secure... I think
My app is secure... I thinkMy app is secure... I think
My app is secure... I think
 
Webinar: MongoDB Persistence with Java and Morphia
Webinar: MongoDB Persistence with Java and MorphiaWebinar: MongoDB Persistence with Java and Morphia
Webinar: MongoDB Persistence with Java and Morphia
 
Beyond PHP - it's not (just) about the code
Beyond PHP - it's not (just) about the codeBeyond PHP - it's not (just) about the code
Beyond PHP - it's not (just) about the code
 
Morphia: Simplifying Persistence for Java and MongoDB
Morphia:  Simplifying Persistence for Java and MongoDBMorphia:  Simplifying Persistence for Java and MongoDB
Morphia: Simplifying Persistence for Java and MongoDB
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
 
Class-based views with Django
Class-based views with DjangoClass-based views with Django
Class-based views with Django
 
Object Oriented Exploitation: New techniques in Windows mitigation bypass
Object Oriented Exploitation: New techniques in Windows mitigation bypassObject Oriented Exploitation: New techniques in Windows mitigation bypass
Object Oriented Exploitation: New techniques in Windows mitigation bypass
 
greenDAO
greenDAOgreenDAO
greenDAO
 
MySQL in Go - Golang NE July 2015
MySQL in Go - Golang NE July 2015MySQL in Go - Golang NE July 2015
MySQL in Go - Golang NE July 2015
 
How to Use JSON in MySQL Wrong
How to Use JSON in MySQL WrongHow to Use JSON in MySQL Wrong
How to Use JSON in MySQL Wrong
 
Zabbix LLD from a C Module by Jan-Piet Mens
Zabbix LLD from a C Module by Jan-Piet MensZabbix LLD from a C Module by Jan-Piet Mens
Zabbix LLD from a C Module by Jan-Piet Mens
 
Entity Framework Core & Micro-Orms with Asp.Net Core
Entity Framework Core & Micro-Orms with Asp.Net CoreEntity Framework Core & Micro-Orms with Asp.Net Core
Entity Framework Core & Micro-Orms with Asp.Net Core
 
java
javajava
java
 
Beyond php it's not (just) about the code
Beyond php   it's not (just) about the codeBeyond php   it's not (just) about the code
Beyond php it's not (just) about the code
 
Ten useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesTen useful JavaScript tips & best practices
Ten useful JavaScript tips & best practices
 
React for Beginners
React for BeginnersReact for Beginners
React for Beginners
 
#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기
 
Getting started with Elasticsearch and .NET
Getting started with Elasticsearch and .NETGetting started with Elasticsearch and .NET
Getting started with Elasticsearch and .NET
 

Semelhante a Lean React - Patterns for High Performance [ploneconf2017]

#NewMeetup Performance
#NewMeetup Performance#NewMeetup Performance
#NewMeetup Performance
Justin Cataldo
 
! Modernizr v2.0.6 httpwww.modernizr.com Copyri.docx
!  Modernizr v2.0.6  httpwww.modernizr.com   Copyri.docx!  Modernizr v2.0.6  httpwww.modernizr.com   Copyri.docx
! Modernizr v2.0.6 httpwww.modernizr.com Copyri.docx
MARRY7
 
Cristiano Betta (Betta Works) - Lightweight Libraries with Rollup, Riot and R...
Cristiano Betta (Betta Works) - Lightweight Libraries with Rollup, Riot and R...Cristiano Betta (Betta Works) - Lightweight Libraries with Rollup, Riot and R...
Cristiano Betta (Betta Works) - Lightweight Libraries with Rollup, Riot and R...
Techsylvania
 
Superficial mongo db
Superficial mongo dbSuperficial mongo db
Superficial mongo db
DaeMyung Kang
 

Semelhante a Lean React - Patterns for High Performance [ploneconf2017] (20)

SenchaCon 2016: Ext JS + React: A Match Made in UX Heaven - Mark Brocato
SenchaCon 2016: Ext JS + React: A Match Made in UX Heaven - Mark BrocatoSenchaCon 2016: Ext JS + React: A Match Made in UX Heaven - Mark Brocato
SenchaCon 2016: Ext JS + React: A Match Made in UX Heaven - Mark Brocato
 
Modern frontend development with VueJs
Modern frontend development with VueJsModern frontend development with VueJs
Modern frontend development with VueJs
 
Full Stack Toronto - the 3R Stack
Full Stack Toronto - the 3R StackFull Stack Toronto - the 3R Stack
Full Stack Toronto - the 3R Stack
 
#NewMeetup Performance
#NewMeetup Performance#NewMeetup Performance
#NewMeetup Performance
 
Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejs
 
Selectors and normalizing state shape
Selectors and normalizing state shapeSelectors and normalizing state shape
Selectors and normalizing state shape
 
! Modernizr v2.0.6 httpwww.modernizr.com Copyri.docx
!  Modernizr v2.0.6  httpwww.modernizr.com   Copyri.docx!  Modernizr v2.0.6  httpwww.modernizr.com   Copyri.docx
! Modernizr v2.0.6 httpwww.modernizr.com Copyri.docx
 
React + Redux Introduction
React + Redux IntroductionReact + Redux Introduction
React + Redux Introduction
 
Boost Development With Java EE7 On EAP7 (Demitris Andreadis)
Boost Development With Java EE7 On EAP7 (Demitris Andreadis)Boost Development With Java EE7 On EAP7 (Demitris Andreadis)
Boost Development With Java EE7 On EAP7 (Demitris Andreadis)
 
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and MingRapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
 
React js
React jsReact js
React js
 
前端概述
前端概述前端概述
前端概述
 
Event Sourcing - what could go wrong - Devoxx BE
Event Sourcing - what could go wrong - Devoxx BEEvent Sourcing - what could go wrong - Devoxx BE
Event Sourcing - what could go wrong - Devoxx BE
 
Javascript Application Architecture with Backbone.JS
Javascript Application Architecture with Backbone.JSJavascript Application Architecture with Backbone.JS
Javascript Application Architecture with Backbone.JS
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCBackbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVC
 
Cristiano Betta (Betta Works) - Lightweight Libraries with Rollup, Riot and R...
Cristiano Betta (Betta Works) - Lightweight Libraries with Rollup, Riot and R...Cristiano Betta (Betta Works) - Lightweight Libraries with Rollup, Riot and R...
Cristiano Betta (Betta Works) - Lightweight Libraries with Rollup, Riot and R...
 
Superficial mongo db
Superficial mongo dbSuperficial mongo db
Superficial mongo db
 
Introduction to React and MobX
Introduction to React and MobXIntroduction to React and MobX
Introduction to React and MobX
 
How to React Native
How to React NativeHow to React Native
How to React Native
 
jQuery
jQueryjQuery
jQuery
 

Último

TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
mohitmore19
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
VictorSzoltysek
 

Último (20)

TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdf
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 

Lean React - Patterns for High Performance [ploneconf2017]