{ "insights-release-the-kraken-how-paypal-is-being-revolutionised-by-node-js-and-lean-ux": { "href": "https://nearform.com/insights/release-the-kraken-how-paypal-is-being-revolutionised-by-node-js-and-lean-ux", "postType": "blog", "slug": "insights-release-the-kraken-how-paypal-is-being-revolutionised-by-node-js-and-lean-ux", "date": "2013-11-05", "title": "Release the Kraken: How PayPal is being revolutionised by Node.js and Lean-UX", "authors": [], "content": [ "Paypal's productivity increased exponentially with the adoption of Node.js\n\nAt the beginning of September 2013, we had the pleasure of hearing Bill Scott from PayPal talk about the revolution that is happening there through the use of Node.js and Lean-UX practices.\n\nBill arrived at PayPal in 2011 to a risk-averse, “not invented here” culture where long shelf life was the norm.\n\nThings were so slow, in fact, that in 2011 even a simple content copy change could take as much as 6 weeks to change on the PayPal site.\n\nDue to the slow release cycle times, the door had been left open for new entrants like Stripe and Square to enter the payments market.\n\nOne of the root problems was that all the technology in PayPal was tangled up and not suited for rapid experimentation and build/measure/learn.\n\nThe existing stack was Java through and through. You didn’t write HTML, CSS or JavaScript – you wrote CSS in Java, you wrote HTML in Java and you wrote JavaScript in Java.\n\nLater the stack was changed to be more reasonable (JSP for templating). But even in that state the stack was not conducive to prototyping, and most of the UI bits lived on the server.\n\nUnder Bill Scott, some sharp folks joined from Netflix and Yahoo, and in early 2012 they began to flesh out a UI layer that could support rapid experimentation.\n\nIn April 2012, David Marcus became president of PayPal and Bill was given a small team and a project to re-invent checkout.\n\nDavid is a startup person and gave them 6 weeks to launch a new checkout system (bear in mind that checkout is a system that generates $3.5 Billion revenue for PayPal).\n\nIt wasn’t possible to get Node.js production ready within 6 weeks as a large number of PayPal’s subsystems needed to be integrated into the Node.js system so Node.js was initially used as a rapid prototyping framework.\n\nJava and Node.js in Parallel\n\nDavid had a number of features in mind for the initial system, and he drew some mockups.\n\nWith Node.js, Bootstrap and other open source technology, it was possible to get the flow working in 3 days. This LeanUX project was called Hermes: God of Mobile (mobility), God of Agility (lean) and God of Commerce (checkout).\n\nThe team adopted a whiteboard-to-code build-measure-learn prototyping cycle where the concept becomes a living spec, or as Bill dubbed it, ‘a vicious cycle of goodness was embarked upon’.\n\nEvery week, the team went from code to usability test and feedback, where they built, got feedback and learning and then implemented what they learned.\n\nBill’s team did this for 8 weeks, while the Java application team had started to spin up the application controller layer and were able to get it up and running simultaneously.\n\nIn the meantime, most of the initial experience was already written in Node.js.\n\nFocus on re-use (running two horses)\n\nThe strategy was to try to use the legacy systems already in existence in PayPal – but to do this from Node.js.\n\nThese are the steps involved in implementing a game-changing program inside PayPal:\n\nStep 1: Utilize an Open Source Stack (use tools that lots of people use)\n\nExpress, Connect, Require.js, bring in JavaScript templating and other open source UI Goodness.\n\nStep 2: Bootstrap with Bootstrap\n\nUsed Bootstrap to enable developers to create a newly branded frontend in a few hours, enabling sketch to code.\n\nStep 3: Use JavaScript Templating\n\nJavaScript Templating can be run in the client browser or server on the production stack.\n\nStep 4: Make UI Bits portable to legacy\n\nIt was possible to take the Dust Templates and use them on top of the old Java-Stack (this meant that quick results were possible from the frontend work that was being done).\n\nThis allowed the team to drag and drop the UI bits from the prototyping stack (Node) to the production stack (Java), with Rhino (JavaScript for Java VM) enabling stack parity between the two. Project Delorean (named after the car in Back to the Future):\n\nAs PayPal still has a number of experiences running on top of an XML/C++ stack in production, they were able to insert V8 into the C++ stack.\n\nJust like with Rhino, this allowed them to create Dust templates and run these JavaScript templates on the legacy C++ stack.\n\nJavaScript templating gave a clean way to cover across 3 stacks at once – Node.js prototype, Java Legacy and C++ Legacy – and provided a graceful way to nibble away at the old stacks, producing results all the way along.\n\nStep 5: Make it easy to understand and easy to experiment\n\nBuilding totally on open source stack enabled new hires to start and grasp what was going on within a few hours. Contrast this with the custom Java Spring framework where it took a 20-day training course just to become proficient in that environment.\n\nA key goal was hiding all the complexity of PayPal from developers and allowing them to just get stuff done without over-complicating things, plus creating an environment where it’s possible to embrace learning and experimentation.\n\nThis makes it easy to experiment with minimal investment. In other words, make it cheap and frictionless to experiment.\n\nStep 6: Bring Node to Production:\n\nIn order to do this, it was necessary to enable all of the standard PayPal services – without looking like PayPal. In other words, do it in a friendly NPM way, and simplify creating an app in a few minutes with all of the PayPal services.\n\nOne Language to Rule them all\n\nBringing Node.js into PayPal removed the barriers between the layers in the software organization, Node.js and JavaScript all the way up from just above the services layer to the frontend layer, meaning you need fewer engineers.\n\nIn one project there were initially 25-30 Java engineers required to build a simple controller layer.\n\nLater this was simplified to a smaller team. But in parallel, the Node.js team did it with just 1-2 node engineers!\n\nDeveloper Love\n\nPayPal got it down to the level where developers could build an initial deployable app in a few minutes, while integrated with all the PayPal services.\n\nBill’s team (along with other key partners in PayPal) made the environment developer-friendly internally to the point where adoption teams that had been in PayPal in the past to help with the adoption of Java Stack were no longer necessary.\n\nThe Node.js stack was user-friendly to the point where they had removed all the bespoke complexity and scariness out of their toolset.\n\nOnce Node.js made it into PayPal, they had to almost have an anti-adoption team to slow things down.\n\nFrictionless\n\nTo get people up and running, there are JavaScript classes, a nice set of GitHub internal docs and Yeoman scripts to produce flavours of apps.\n\nA simple app that connects to authentication, account services, experimentation, logging and other services can be finished in 10-15 minutes.\n\nOnce engineers have gone through this experience, they become believers and in turn evangelists for Node.\n\nStep 7: Node.js Wins\n\nOne stack to rule them; all the new applications in PayPal are now being built using Node.js. This makes the prototyping and production stacks one and the same.\n\nStep 8: Release Modules to Open Source:\n\nA core express module (Kraken), i18n: managing content at scale, security, app lifecycle middleware, and bootstrap capability.\n\nSummary:\n\nHeadcount: Node.js. Typically they are seeing anywhere from 1⁄3 to 1/10 the number of developers needed on the new stack vs the old stack. Performance: In one set of Load & Performance tests done on the same app built on both the Java stack vs the Node stack showed a 10x throughput in scale. All in on Node.js: all the new applications in PayPal are now being built using Node.js Lines of code: In general they have seen code size shrink by a factor of 3-5 by moving from the Java stack to the Node stack.\n\nEven the number of files shrunk by a similar factor.\n\nFor more information on the modules and frameworks PayPal is moving to open source check out the kraken homepage .\n\nKraken-js\n\nThe framework that started it all. This is the glue that holds everything together.\n\nKraken-js is built on top of the tried and true Express web app framework, and further streamlines it.\n\nIt gives you a clean web app structure that will induce developers to write neat, well-organized code.\n\nWhen used in combination with the other modules, it makes it easy to set up robust applications.\n\nTo make things even easier for adopters, we are also providing a Yeoman generator for Kraken apps. By simply typing `yo kraken` you will have a ready-to-run basic application.\n\nKraken Suite Modules\nLusca\n\nOut-of-the-box application security.\n\nLusca is middleware that can be deployed over Express, and configured to plug common attack vectors.\n\nWhen used, it will:\n\nEnable Cross Site Request Forgery (CSRF) headers\nEnable Content Security Policy (CSP) headers\nEnable X-FRAME-OPTIONS headers to help prevent Clickjacking\nEnable Platform for Privacy Preferences Project (P3P) headers\nAdaro\n\nA DustJS template rendering plugin for Express.\n\nIt is based on LinkedIn’s fork of DustJS, and includes DustJS-helpers by default.\n\nMakara\n\nAn internationalization/localization support module.\n\nIt allows for loading content bundles based on a context (eg: a user connecting from the US would receive the en_US content bundle, while a Spanish user would receive the es_ES one ).\n\nThe loaded bundles can then be used to decorate DustJS templates.\n\nKappa\n\nOne of the main challenges faced by the enterprise is the need to deploy private modules in an efficient manner.\n\nExisting solutions often entail replicating the public npm registry in its entirety, in order to deploy a few packages privately.\n\nKappa is a smart npm proxy that allows public and private npm packages to be fetched from the right place. This means that companies can have a private npm server that only holds their modules.\n\nWhen a project requires either private or public modules, Kappa will transparently deliver them. In addition, it will soon support licensing checks, blacklisting, statistics, and more!\n\nIn addition to the headliner Kraken Suite modules, they are releasing the following supporting utilities:\nshortstop\n\nSometimes JSON just isn’t enough for configuration needs. Occasionally it would be nice to use arbitrary types as values, but JSON is necessarily a subset of all available JS types. shortstop enables the use of protocols and handlers to enable identification and special handling of json values.\n\nfindATag\n\nA string tokenizer, configured to recognize a particular pattern: {@[A-Za-z._] [attrs...]/}.\n\nspud\n\nA content bundle transcoder. It will convert to and from different formats, including .properties, .json, .4cb, etc.\n\nexpress-enrouten\n\nRoute configuration middleware for expressjs. This module changes where/how express loads its routing, making for more organized applications.\n\nkraken-webtools\n\nA collection of Development-time tools for Kraken applications.\n\nNeed help developing Node.js applications for your business? NearForm are experts in Node.js development . Contact us today to find out more!\n\nJoin the Digital Advantage Insider for more great content and exclusive offers. Antonella Lombardi" ], "categories": { "primary": "backend", "others": [ "frontend", "product" ] }, "verticals": { "primary": "finance", "others": [] } }, "digital-community-05-08-anchors-buttons-and-accessibility": { "href": "https://nearform.com/digital-community/05/08/anchors-buttons-and-accessibility", "postType": "blog", "slug": "digital-community-05-08-anchors-buttons-and-accessibility", "date": "2014-05-08", "title": "Anchors, Buttons, and Accessibility", "authors": [ "ALEX LANDE" ], "content": [ "Accessibility is a foundational feature of the web. It is a direct reflection of a key tenet of the platform: the free and universal sharing of knowledge, unfettered by language, location, or disability. This is why it’s disappointing that accessibility is so often (and so easily) overlooked.\n\nTo build an accessible website or application, it’s best to start with the foundations: semantic markup. Using the correct markup is an easy win as it does the vast majority of the accessibility work for you. As rich client-side JavaScript applications have grown in popularity, a particular markup misuse has become common: .\n\nWhat’s wrong with href=\"#\"?\n\nIf you’re not familiar with this pattern, take a look at the source of your favorite web app, and weep. There are some other similar examples like , , and .\n\nHTML anchor elements in this form don’t do what anchors do: act as a link. (While anchors can act as placeholder links or target link destinations, these uses are much less common.) These links are actually working as user interface controls— clicking on them affects the UI in some way, rather than taking the user to a destination.\n\nThe thing is, we already have an HTML element specifically meant for controlling a user interface:
, since we learned that position:fixed cannot be trusted. Both components require certain user data to be passed into the component to work. This data is returned from an API endpoint called /user/
process.on('uncaughtException', (err) => {\n console.log(`Error: ${err.message}`)\n})
const file = fs.createReadStream('non-existent-file.md')\nfile.pipe(process.stdout)\ntextCopy to clipboard\n\nRunning this code will output Error: ENOENT: no such file or directory, open 'non-existent-file.md' . This is because fs.createReadStream returns a stream.ReadStream instance. In turn, stream.ReadStream is an instance of events.EventEmitter , therefore uncaughtException is emitted.\n\nInternally to Node, when there's a fatal exception V8 calls an onMessage callback function in the C++ layer. This function is provided in src/node.cc and calls another C++ function ( FatalException ), which in turn calls a JavaScript function ( process._fatalException ) that is created in lib/internal/boostrap_node.js , which finally calls process.emit('uncaughtException') when the error goes unhandled.\n\nThrown errors are also emitted because of integration between EventEmitter and V8:\n\nconst fs = require('fs')
process.on('uncaughtException', (err) => {\n console.log(`Error: ${err.message}`)\n})
const file = fs.createReadStream('non-existent-file.md')\nfile.pipe(process.stdout)
const err = new Error('Random error')\nthrow err\ntextCopy to clipboard\n\nCurrently, Node.js gives unhandled promise rejections a little more leeway. If a rejection happens and there's no .reject(fn) handler, the runtime prints this error to the console without crashing:\n\n(node:10044) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.\ntextCopy to clipboard\n\nIn order to use promises successfully, a rejection handler ( .catch(handleFn) ) should always be used, and should always be attached synchronously.\n\nThe Importance of Handling Rejections\n\nOftentimes any extra logic for handling errors in an application is seen as unnecessary, but properly dealing with exceptions is crucial for any application's security, efficiency, and performance. Many asynchronous operations leave file descriptors lying around or use a significant amount of RAM, and it's important to clean up when they fail in order to avoid memory leaks and other denial-of-service situations.\n\nTake this example server:\n\nconst http = require('http')
const server = http.createServer(handler)\nserver.listen(3000)
const queue = [];
function handler(req, res) {\n const url = req.url
generateBuffer(url, res)\n .then((reply) => {\n // Use a buffer and clean it up\n queue.pop()\n })\n // No rejection handler
res.end('OK')\n}
function generateBuffer(url) {\n // Create a buffer 1 GB in size\n queue.push(Buffer.alloc(1073741824, 1));
if (url === '/') {\n return Promise.resolve()\n }
const err = new Error(`Rule for ${url} not found`)\n return Promise.reject(err)\n}\ntextCopy to clipboard\n\nIf this server receives a request for / , it will respond and clean up the buffer as expected. For all other requests, two things are noted:\n\nThere will be a warning in the console: (node:32236) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: Rule for /blog not found\nThe requests don't clean up after themselves, so more and more RAM is used. Unless the path is /, generateReply() returns Promise.reject(...) and the request handler has no .catch(...) so clean up is never performed.\n\nThe behaviour can be reproduced by testing the server with ApacheBench ( ab ):\n\nab -n 400 https://localhost:3000/crash\ntextCopy to clipboard\n\nIn order to fix these kinds of errors, add a .catch() call to the promise and handle the rejection:\n\nfunction handler(req, res) {\n const url = req.url
generateBuffer(url, res)\n .then((reply) => {\n // Use a buffer and clean it up\n queue.pop()\n res.end('OK')\n })\n .catch((error) => {\n // Clean up the buffer and handle the error\n queue.pop()\n res.statusCode = 500\n res.end(error.message)\n })\n}\ntextCopy to clipboard\nFuture-Proofing using make-promises-safe\n\nNode.js versions 6 and 8 will continue to chug along following an unhandled promise rejection. In future versions, unhandled rejections will cause the Node.js process to terminate, as per DEP0018 .\n\nThe best way to ensure that an application is future-proofed is to emulate Node.js's future behaviour today. Matteo Collina's make-promises-safe module binds an event listener to the global uncaughtRejection event, causing any unhandled promise rejections to terminate the Node.js process. This is crucial because even when a developer knows to always use .catch() , it is easy to forget to add it every time a promise is used.\n\nInstalling make-promises-safe\n\nTo install the module, use npm install make-promises-safe --save , which will also make it a dependency of the project.\n\nUsage\n\nUsing make-promises-safe is as simple as requiring it in the application's entry script.\n\nrequire('make-promises-safe')\ntextCopy to clipboard\n\nThe application's code, along with any external modules, will be bound to this new behaviour. To test how the application fares with this behaviour, consider running unit tests; any new regressions most likely point toward promises without any catch() handler.\n\nConclusion\n\nNode.js is moving towards treating unhandled promise rejections similarly to uncaughtException errors in the future. Soon, Node's behaviour will be to terminate with a stack trace whenever an unhandled promise rejection occurs. Using the make-promises-safe module, developers can use that behaviour today. This promotes best practices by requiring unfulfilled promises to be handled with .catch() .\n\nPromises are number 8 on our list of features in our article about the top 10 features, drivers, mistakes and tricks of Node.js ."
],
"categories": {
"primary": "backend",
"others": [
"devops"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"insights-the-nearform-design-sprint-handbook": {
"href": "https://nearform.com/insights/the-nearform-design-sprint-handbook",
"postType": "blog",
"slug": "insights-the-nearform-design-sprint-handbook",
"date": "2017-11-30",
"title": "Given how expensive software development is, the biggest cost saving in any of our engagements is to write as little software as possible!",
"authors": [],
"content": [
"Design Sprint\nAt NearForm, design and design thinking are fundamental to how we deliver solutions. However, it cannot be overstated how important design is to any solution before development even begins. Given how expensive software development is, the biggest cost saving in any of our engagements is to write as little software as possible!\n\nPioneered by Google Ventures, Design Sprints are described as:\n\n“a five-day process for answering critical business questions through design, prototyping, and testing ideas with customers. Developed at GV, it's a greatest hits of business strategy, innovation, behaviour science, design thinking, and more packaged into a battle-tested process that any team can use.”\n\nHow do we achieve this? There are several ways; but over the last year, we've had a lot of success running Design Sprints, so much so that today we are very proud to announce the publication of the NearForm Design Sprint Handbook (no longer available) — the ultimate guide to how we run Design Sprints at NearForm.\n\nSo, what are the business benefits you get when you engage with NearForm to do a Design Sprint? We have run Design Sprints for both new solutions and also for improving existing solutions, but ultimately its main benefit is the ability to test ideas in a risk-free environment in a low-cost fashion — it's an incredibly powerful process.\n\nThe other business benefits you can gain are:\n\nStakeholder alignment. Design Sprints are amazingly good for resolving team conflicts around solution disputes. We encourage equal participation from many areas of the business. This fosters mutual respect, motivates the wider team and builds momentum and support behind the solution.\n\nTime-boxed decision making and problem-solving. The 5-day process forces stakeholders to make decisions quickly. It is simply not possible to wait weeks for a decision on something. This is fantastic for pushing through blockers and it accelerates the thinking around the solution.\n\nFocus on the user. Prototyping and user testing are the cornerstones of design thinking and are the ultimate focus of the Design Sprint during the week. We have found that having real users test the prototypes humanizes the problem and naturally makes the stakeholders empathise with the end user.\n\nA Design Sprint is not your entire design phase compressed in the span of a week. It is, however, an excellent way to get from idea to tangible concept in a week. This is why at nearForm we use Design Sprints a lot to kick-start a new engagement. It does not solve all problems, but we find it very effective for finding the north star that the solution will follow from there. Also, it's perfectly fine if the outcome of a Design Sprint is a decision not to proceed with the solution any further - when that's the case the business is very happy with the amount of money it has saved by not continuing.\n\nThis is the first of several posts about how we succeed with solution delivery in NearForm. In our next post, we'll talk about what happens post–Design Sprint and discuss the processes and tools we use to get you from prototype to Minimal Viable Product (MVP) launch in a three-month timeframe.\n\nIf you would like to talk to us specifically about Design at nearForm or need help in running a Design Sprint, please contact us at info@nearform.com.\n\nHuge thanks to our dedicated design team for putting this handbook together, in particular, Joy Burke and Antoine Marin."
],
"categories": {
"primary": "design",
"others": [
"product"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"insights-reaching-ludicrous-speed-with-fastify": {
"href": "https://nearform.com/insights/reaching-ludicrous-speed-with-fastify",
"postType": "blog",
"slug": "insights-reaching-ludicrous-speed-with-fastify",
"date": "2017-12-13",
"title": "In this post we're going to take a look at Fastify, a high-performance HTTP framework for Node.js",
"authors": [],
"content": [
"In this post, we're going to take a look at Fastify, a high-performance HTTP framework for Node.js written by Matteo Collina and Tomas Della Vedova . Correction: an earlier version of this article was published with diagrams that reported incorrect benchmark results. The benchmarks had been run with 10 connections instead of 100 and included data for an older version of hapi. These issues have been corrected in the current version of the article. See fastify/benchmarks#39 and fastify/fastify#545 .\n\nBenchmarking Web Frameworks\n\nTo better understand where different frameworks stand in terms of performance, we'll begin with some load testing. Fastify provides a number of basic benchmarks for different frameworks, and different configurations.\n\nWe're going to see how Fastify stacks up to some of the most popular frameworks in use today: Express , hapi , Restify , and Koa .\n\nEach server is set up with one route, GET / . The route handler serialises the object { hello: 'world' } and sends it to the client as JSON.\n\nOur baseline will be a simple http.Server instance without any router. We're using the default router for each framework, but as Koa doesn't supply a router by default, we're using koa-router .\n\nTo conduct the benchmark, we're going to use Autocannon with command-line options autocannon -c 100 -d 40 -p 10 .\n\n-c 100 indicates we want to have 100 concurrent connections\n-d 40 indicates we want the benchmark to run for forty seconds\n-p 10 indicates we want to share one socket connection for every ten requests (HTTP pipelining)\n\nWe're repeating the Autocannon command and taking the second average as our result. The first time we invoke autocannon , V8 (the JavaScript engine behind Node) performs optimisations to maximise runtime performance. Using the second result for comparison gives us a more realistic idea of performance. (All the benchmarks in this post were run on an Amazon EC2 m4.xlarge instance, with an Intel Xeon E5-2686 v4 @ 2.30GHz (4 cores, 8 threads) and 16GiB RAM. We used Node 8.4.0, and the actual code for the tests lives in https://github.com/fastify/benchmarks.)\n\nReaching Ludicrous Speed\n\nThe benchmarks above demonstrate a very simple use case. Yet, Express processes 42.97% fewer requests per second than http.Server , and that's without any additional middleware or external I/O. How does Fastify manage to squeeze out an extra 51.37% requests per second when compared with Express?\n\nClosures\n\nCompared with other frameworks, Fastify has a much smaller call stack when dealing with a request. In the presentation at the end of this blog post, Matteo provides flame graphs to show both the call stack of different frameworks and what functions take the most time to complete. Reusify is used to squeeze a 10% increase in performance when handling middleware. To read more about how reusify works, check out Matteo's post about both reusify and Steed.\n\nRouting\n\nOne of the key areas of optimisation was in routing. Internally, Fastify uses a radix tree based router called find-my-way . Compared with routers used by other frameworks, find-my-way has a clear advantage in the amount of operations per second it can perform.\n\nTo compare how the two perform against each other, we're using router-benchmark to benchmark the most commonly used routers.\n\nfind-my-way supports simple path strings, wildcards, named parameters, and regular expressions (though they add some additional overhead). Check it out on GitHub to find out more.\n\nJSON Serialisation\n\nJSON.stringify() is one of the most commonly used functions when building web services. The function itself is part of the JavaScript language and is implemented in V8 (the JavaScript engine that powers Node.js) as C++.\n\nFastify makes use of fast-json-stringify which as the name suggests is a more performant version of V8's JSON.stringify() function. It's written entirely in JavaScript, but manages to outperform JSON.stringify() in most cases by using schemas and new Function() in a safe manner.\n\nTo compare how the two perform against each other, we're using the benchmark module. The code for this benchmark is available from the fast-json-stringify GitHub repo .\n\nBenchmarks show a considerable boost when serialising JavaScript object literals, over 2.5x the amount of operations per second . Similarly, it can perform twice as fast as JSON.stringify() when serialising short strings.\n\nThere's also a minor boost when serialising arrays. Performance with long strings is roughly on-par with JSON.stringify() , due to fast-json-stringify using JSON.stringify() to serialise strings more than 42 characters in length.\n\nfast-json-stringify isn't a drop-in replacement for JSON.stringify() , but using it is simple:\n\nconst fastJSON = require('fast-json-stringify')
const schema = {\n // the object type we want to stringify\n type: 'object',
// define all object properties\n properties: {\n username: {\n type: 'string'\n },\n fullName: {\n type: 'string'\n },\n age: {\n type: 'integer'\n }\n }\n}
const stringify = fastJSON(schema)
console.log(stringify({\n username: 'johndoe',\n fullName: 'John Doe',\n age: 30\n}))\ntextCopy to clipboard\n{ \"username\": \"johndoe\", \"fullName\": \"John Doe\", \"age\": 30 }\ntextCopy to clipboard\n\nHow It Works\n\nFirst we outline a schema for our data. In this case, we define a simple object containing username, fullName and age keys.\nCalling fastJSON(schema) generates and returns a new function capable of returning a JSON version of an object, based on the schema.\nstringify(object) takes an object and returns a JSON representation of it as a string.\n\nNot only is fast-json-stringify more performant than JSON.stringify() in most cases, it also prevents data from accidentally leaking. If we were to stringify an object containing properties besides username , fullName , and age , they wouldn't appear in the JSON string.\n\nThe example below demonstrates how this adds an extra layer of security to your application:\n\nconsole.log(stringify({\n username: 'janedoe',\n fullName: 'Jane Doe',\n age: 31,\n occupation: 'Programmer',\n socialMedia: {\n twitter: \"Jane2017P\",\n github: \"Jane2017P\"\n },\n securityNumber: \"00000E\"\n}))\ntextCopy to clipboard\n{ \"username\": \"janedoe\", \"fullName\": \"Jane Doe\", \"age\": 31 }\ntextCopy to clipboard\n\nfast-json-stringify supports additional features such as setting required fields, pattern properties, and 64-bit integers. Check it out on GitHub to find out more.\n\nThe Server Lifecycle\n\nThe lifecycle of most web frameworks is similar: the server starts, route handlers are registered, and the server listens for requests and calls the appropriate function to handle them. Fastify behaves slightly differently to gain extra performance.\n\nWhen the server is started, Fastify carries out a preinitialisation stage. This stage performs a number of optimisations - JSON schemas are processed with fast-json-stringify , and handler functions are optimised with reusify.\n\nBuilding with Fastify\n\nOften times, writing libraries and frameworks with the aim of maximising performance leads to a reduction in readability, good API design, or features. Fastify's feature set resembles a combination of hapi and Express, and exposes an API that was built with developer happiness in mind.\n\nHere's a list of Fastify's feature set in comparison with Express and hapi:\n\n\tExpress\thapi\tFastify\nRouter\t\t\t****\nMiddleware\t\t\t****\nPlugins\t\t\t****\nValidation\t\t\t****\nHooks\t\t\t****\nDecorators\t\t\t****\nLogging\t\t\t****\nasync/await\t\t\t****\nRequests/sec\t20,690\t19,824\t31,319\n\nTo start using the framework, we need to install Fastify. Version 0.35.6 is the latest version as of this tutorial, so we'll go ahead and grab it via npm:\n\nnpm install fastify@0.35.6\ntextCopy to clipboard\n\nBelow is a simple server written using Fastify. It has a single GET / route which sends a JSON object to the client. (Note: this example doesn't take advantage of fast-json-stringify . We'll take a look at that in a bit!)\n\n// Instantiate a Fastify server\nconst fastify = require('fastify')()
// Declare a route\nfastify.get('/', function (request, reply) {\n reply.send({ hello: 'world' })\n})
// Start the server\nfastify.listen(3000, function (err) {\n if (err) throw err
let port = fastify.server.address().port\n console.log(`Server listening: ${port}`)\n})\ntextCopy to clipboard\n\nFastify also supports async / await . The above route could be simplified into the following:\n\nlet simpleHandler = async (request, reply) => ({ hello: 'world' })
fastify.get('/simple-async', simpleHandler)\ntextCopy to clipboard\n\nIf we were to wait for external I/O such as a database response, we could use the async / await syntax to simplify our business logic.\n\nlet awaitHandler = async function (request, reply) {\n // grab details from a database\n let user = await users.get('sigkell')\n return user\n}
fastify.get('/async-await', awaitHandler)\ntextCopy to clipboard\nMaking Use of fast-json-stringify\n\nThe examples above don't take advantage of fast-json-stringify to serialise response objects. To get the additional performance boost, we need to set the schema in our route's options object.\n\n// This object contains additional config for our route\nconst options = {\n schema: {\n response: {\n 200: {\n type: 'object',\n properties: {\n hello: {\n type: 'string'\n }\n }\n }\n }\n }\n}
// Set our options object as the second argument\nfastify.get('/fastjson', options, function (request, reply) {\n reply.send({ hello: 'world' })\n})\ntextCopy to clipboard\nConclusion\n\nFastify is a great choice to build an application where performance is a critical concern. Compared with some of the more established frameworks, Fastify is capable of processing over 1.5 times the amount of requests per second when dealing with JSON data, maximising the price/performance ratio of your servers.\n\nTo evaluate how Fastify could enhance the performance of your application, take a look at the documentation available on GitHub and take it for a test drive.\n\nIf you're interested in learning how Fastify came about, and about HTTP server performance in general, be sure to check out Matteo Collina's Take Your HTTP Server to Ludicrous Speed below!"
],
"categories": {
"primary": "backend",
"others": [
"perf",
"devops"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"insights-simple-hardware-mods-for-your-nodeconf-eu-hackable-badge": {
"href": "https://nearform.com/insights/simple-hardware-mods-for-your-nodeconf-eu-hackable-badge",
"postType": "blog",
"slug": "insights-simple-hardware-mods-for-your-nodeconf-eu-hackable-badge",
"date": "2018-01-09",
"title": "It started as just a \\*small\\* battery upgrade but of course I couldn't stop.",
"authors": [],
"content": [
"Note: This post was originally published on Conor's Blog .\n\nIf you attended NodeConf EU 2017 in Kilkenny, Ireland, you'll know all about the digital badge powered by Espruino that we created with Gordon Williams. You can read more about it on the blog and check out the docs site .\n\nI hope you've continued to learn about Espruino and the power of JavaScript on tiny microcontrollers. Don't forget that the badge consists of Open Source Software and Hardware. Our Github repo is here .\n\nI've been having lots of fun recently with LEDs, NeoPixel rings, BLE and general messing.\n\nOf course if you use NeoPixels you're going to burn through that CR2032 battery pretty darned quickly. Like really really quickly :-) My first attempt to solve this, which worked well, was to use various sizes of LiPo batteries connected to the power pins via an LD1117 voltage regulator. I had some full size regulators sitting around but they took up too much room. So I ordered some SMD ones and they were just as good. Note you should not connect a LiPo directly to the power pins. When fully charged they get to 4.2 volts which will probably kill the microcontroller.\n\nGordon mentioned the LiFePO4 batteries to us as an alternative. I'd read a bit about them previously but hadn't realised their multiple benefits:\n\nThey can't catch fire!\nThey max at 3.2V so can be connected directly to 3.3V electronics\nThey come in the same sizes as many LiPos, like 18650.\n\nThe downsides are:\n\nYou need special chargers (not too expensive)\nThey have lower capacity than the same-sized LiPo.\n\nYou can see the ridiculously oversized one on the badge here. I'll be buying more.\n\nOther mods I did included an on-off switch, a mobile-phone vibrator, a mini-loudspeaker and various LEDs on the front (no NeoPixels in the picture, I've ordered a large ring of them).\n\nThe vibrating motor was a little weak initially as it was running directly off an IO pin which is probably a terrible idea. I re-wired things to use a simple BC547 transistor to turn on/off the motor connected to +/- and the entire badge now vibrates strongly when it's on.\n\nThe loudspeaker was a replacement for the disc ones we provided at NodeConf EU. TBH those discs were pretty bad - my fault. Gordon did a great job figuring out how to double the voltage swing to increase the volume but they were still very quiet. These green ones are much much louder and very usable. Here's one in action. Impressive eh? ;-)\n\nI had ordered some microphone modules for the event but they arrived afterwards. It turns out they were useless. They only trigger on/off for loud sounds. So avoid these if you are searching on eBay. I've ordered some alternatives to see if they are better.\n\nAnother small fail was my order of some generic PIR detectors which I couldn't get working well. It turns out they needed 5V not 3.3V. I'm waiting on some 3.3V modules to see if they behave or not.\n\nOnce the NeoPixel rings arrive, I'll be doing something like this which shows a smaller ring controlled by Espruino:\n\nSo have any of you been hacking your badges or writing interesting software for it?"
],
"categories": {
"primary": "oss",
"others": [
"backend",
"mobile"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"digital-community-oauth-and-pkce-with-react-native": {
"href": "https://nearform.com/digital-community/oauth-and-pkce-with-react-native",
"postType": "blog",
"slug": "digital-community-oauth-and-pkce-with-react-native",
"date": "2018-01-16",
"title": "OAuth and PKCE with React Native",
"authors": [
"KADI KRAMAN"
],
"content": [
"OAuth is an authorization protocol that utilizes a third party to gain access to user information without exposing the user’s password. The OAuth website describes the process with a great analogy:\n\nMany luxury cars today come with a valet key. It is a special key you give the parking attendant and unlike your regular key, will not allow the car to drive more than a mile or two. Some valet keys will not open the trunk, while others will block access to your onboard cell phone address book. Regardless of what restrictions the valet key imposes, the idea is very clever. You give someone limited access to your car with a special key, while using your regular key to unlock everything.\n\nOur new React Native library, react-native-app-auth, allows you to securely communicate with OAuth 2.0 and OpenID Connect. It bridges existing native authentication implementations for iOS and Android by OpenID and benefits from the same security enhancements.\n\nBut why did we bother? What’s so tricky about OAuth on mobile devices? The rest of this article will give you a brief overview of OAuth and the additional complications it brings to mobile devices.\n\nThe difference between OAuth and OpenID\n\nThe lines seem blurred between OAuth and OpenID, as they are frequently used together and have some common authors. To clarify: OpenID allows you to use an existing account to sign in to multiple websites without needing to create new passwords. Anyone can register to be an OpenID provider. This is how the “log in with Google/Facebook/Github” buttons have come about. These companies have registered to be OpenID providers and allow other websites to authenticate through them. OAuth, on the other hand, is an authorization protocol that dictates the exact API of the authorization server, how and when tokens get exchanged, and what security measures need to be taken to mitigate risks of malicious agents hijacking tokens.\n\nOAuth: the 2 minute overview\n\nImagine you want to log into Medium using your Google account. We know that Google is an OpenID provider that implements the OAuth2 spec. How does that workflow work? Our example has 4 characters:\n\nClient (Medium) - the third party application that would like access to a user’s account. It needs permission in order to do so\nThe Resource Server (Google API) - the API server used to access the user’s information\nThe Authorization Server (Google UI) - the server that presents the interface where the user approves or denies the request\nThe Resource Owner (you) - the person that is giving access to some portion of their account\n\nStep 0 (only done once): a developer registers the app with the service\n\nA Medium developer would have had to register the application on Google. That would include registering basic information such as application name, website, a logo, etc. In addition, they must register a redirect URI to be used for redirecting users.\n\nStep 1: the user clicks on the “log in with Google” button\n\nThe user will be redirected to a Google-hosted page and prompted to log in. The request includes:\n\nClient ID - received from Google after setting up Step 0\nRedirect URI - the URI back to Medium\nScope - how much of the user’s information the website would like, e.g. email\n\nStep 2: The user is redirected back to Medium\n\nAfter a successful authentication, the user is redirected back to Medium using the code.\n\nStep 3: The token is requested using the auth code\n\nOnce the client had verified that the code received is authentic, it can make the request to exchange the auth code for the auth token.\n\nStep 4: The auth server returns an access token\n\nThe auth server will verify this request and return the access token as well as a refresh token and expiry date when applicable.\n\nNative Apps and PKCE\n\nThe second step of our authentication flow above involves linking back to our application with an auth code. This is a problem for native applications because the nature of how they are distributed through public stores prevents individual instances of applications from having unique (or secret) credentials. That means that it is impossible to guarantee that linking back into a native app will be caught by the application intended. Android prompts the user to choose between multiple apps claiming the same scheme, but iOS does not. If a malicious application gets itself registered as a handler of those URLs, they could intercept the handoff of the authorization code.\n\nSince we cannot guarantee that the auth code is received by the correct application, the security problem needs to be handled elsewhere. PKCE to the rescue! PKCE (pronounced Pixie, believe it or not), or Proof Key for Code Exchange, is a spec that is designed to mitigate exactly this risk by preventing the malicious application, having already gotten hold of the auth token, from exchanging it for a more substantial token.\n\nThis works exactly as the auth flow described above, but with an additional parameter added to certain messages. When the native application first loads the login page in the browser, it also generates a code_verifier string and passes that as a parameter on the URL. The Authorization Server stores away this string before returning the code back to the native application. When the native application then exchanges the code for the access token, it will include the code_verifier string on that call. If the code_verifier is missing or doesn’t match the previously recorded one, the Authorization Server will not return the access token. So, even if a malicious application is able to obtain a code, without the corresponding code_verifier it will be unable to turn that code into an access token, and thus unable to access the business or personal data accessed through the APIs.\n\nOAuth2 and React Native\n\nSince a built React Native application is indistinguishable from a native app, it is also challenged by the same security vulnerabilities. OpenID has built tools to work with OAuth2 on the web, on Android and iOS. However, the existing JavaScript module was incompatible with React Native, which motivated us to build our own library - a React Native wrapper, bridging the native iOS and Android libraries - to allow you to easily and securely communicate using OAuth2 spec in React Native."
],
"categories": {
"primary": "security",
"others": [
"mobile"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"insights-introducing-node-clinic-a-performance-toolkit-for-node-js-developers": {
"href": "https://nearform.com/insights/introducing-node-clinic-a-performance-toolkit-for-node-js-developers",
"postType": "blog",
"slug": "insights-introducing-node-clinic-a-performance-toolkit-for-node-js-developers",
"date": "2018-01-25",
"title": "Clinic simplifies the process of investigating and fixing performance issues in your Node.js applications",
"authors": [],
"content": [
"Dig into your app's performance issues\n\nOne of the problems Node.js developers have to deal with is figuring out why their app is \"slow\". There aren't many tools available to help dig into performance issues so we decided to create some. We're really happy to announce the open source Clinic.js toolkit and Clinic Doctor tool.\n\nIn a nutshell, Clinic.js simplifies the process of investigating and fixing performance issues in your Node.js applications.\n\nDevelopers First\n\nOur overarching aim with the project was to create developer tools with amazing user experience and a focus on performance. This means the tools should not require a large infrastructure to run and should be usable on developer laptops. They should generate portable outputs that can be shared between developers and they should have a progressive approach to information display where the fine detail is only provided if you want it.\n\nTo achieve this we assembled a team of experts in Node.js Core, Data Science, Design, Front-End Development, Data Visualisation and Product, to create Clinic.js.\n\nClinic Doctor: Diagnose Performance Issues\n\nDoctor is the first tool that we are releasing in the toolkit. It helps diagnose performance issues in your application and guides you towards more specialised tools to look deeper into your specific issues.\n\nSymptoms such as low CPU usage, blocking garbage collection, frequent event loop delay or a chaotic number of active handles may indicate a number of potential problems. Doctor helps narrow down the possibilities by generating a recommendation based on those symptoms. Examples such as I/O issues, non-optimized garbage collection and blocked event loop are quite common. Doctor will help you with all of these performance issues.\n\nEvent loop delay has been marked in red to indicate a problem. Once the performance problem is diagnosed, Doctor helps you find the right solution. It may point you to a specific profiling tool or suggest a common approach to the problem. For those who prefer more context, Doctor also provides an in-depth explanation of the performance issue. In situations where you have a hunch that the issue may be different than the recommendation, Doctor provides easy access to the documentation of all the other performance issues.\n\nRead More section helps you understand the issue in-depth. Doctor is very easy to use - all it takes is a single command to monitor your app and generate a recommendation.\n\nDoctor is compatible with Node.js versions 8 and 9. (Note you might hit some issues if you pick an old version of those release lines)\n\nExplore Clinic on Github:\n\nhttps://github.com/nearform/node-clinic\nhttps://github.com/nearform/node-clinic-doctor\nhttps://github.com/nearform/node-clinic-doctor-examples\nRe-introduction to 0x\n\nNearForm has a long history working on performance in Node.js apps and our own David Mark Clements created the 0x tool many moons before we kicked off Node Clinic.\n\n0x helps profile your application with the use of flamegraphs and is one of the tools that Doctor will recommend in certain situations.\n\nFlamegraphs simplify identification of hot paths in your code. Each block in a flamegraph represents a function. Its color matches how often it was observed still executing whilst not having called any other function yet (where applicable).\n\nThe darker red a block is the hotter it is - and the more likely it is a bottleneck blocking the event loop (synchronously). Each block on top of another block represents one function that has called another.\n\nThe width of the block represents the total time a call frame was part of a stack on CPU relative to the total time sampling. 0x is very easy to use - all it takes is a single command to monitor your app and generate a flamegraph.\n\n0x is compatible with Node.js v6+ (if you require Node.js v4 support, 0x v2 supports Node.js v4).\n\nExplore 0x on Github: https://github.com/davidmarkclements/0x\n\nClinic Flame\n\nClinic Flame wraps 0x so that it can be used by Node Clinic. Just type clinic flame to learn how to use it.\n\nParticipate in the community\n\nClinic is an open-source project, which means everyone is welcome to join us.\n\nIf you don't know where to start, please see our CONTRIBUTING.md .\n\nClinic is a safe environment for everyone, thanks to our Code of Conduct .\n\nProject is licensed under Apache 2.0 license.\n\nPlease send us your data\n\nWe'd really appreciate it if you would send us your Doctor data so we can continue to improve our models and recommendations. Note this is only timing data and will not leak any information about your code or app data. Please consult the README to find out how to send the data. Be assured that the tool does not send any data automatically.\n\nFinally\n\nWe are actively expanding our Clinic toolkit. Expect more tools very soon!\n\nMore Performance Tools for Node.js\n\nCheck out our post on Clinic Bubbleprof , a new way to visualize your app's performance!"
],
"categories": {
"primary": "perf",
"others": [
"backend",
"oss"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"digital-community-introducing-urql": {
"href": "https://nearform.com/digital-community/introducing-urql",
"postType": "blog",
"slug": "digital-community-introducing-urql",
"date": "2018-01-30",
"title": "Introducing URQL (beta), a Universal React Query Library",
"authors": [
"KEN WHEELER"
],
"content": [
"[drinking spiked punch] What is this? Mango? -- Steve Urkel\n\nToday we are formally releasing our newest OSS offering, urql. Pronounced \"urkel\", it is technically an acronym for Universal React Query Library. urql is a GraphQL client created in the hopes of simplifying the use of GraphQL in React.\n\nThere are some amazing solutions in the space already, notably Relay and Apollo, both of which are incredibly full-featured, brilliantly engineered, and wonderfully flexible. That said, these libraries might feel like a bit much to get started with at times, especially for beginners.\n\nOur goal with urql is to simplify the process of using GraphQL in React apps. There are simpler solutions, but they end up pushing the complexity of handling data storage and caching onto the user. There are also more complex solutions that allow unimagineable flexibility in a variety of library/framework contexts, but we're looking for the sweet spot that allows developers to be productive in React with GraphQL.\n\nWhat it looks like\n\nGetting started is as simple as creating a Client instance and passing it down through your app with our Provider:\n\nimport React from 'react';\nimport ReactDOM from 'react-dom';\n\nimport { Provider, Client } from 'urql';\nimport Home from './home';\n\nconst client = new Client({\n url: 'http://localhost:3001/graphql',\n});\n\nexport const App = () => (\n \n
\n);\n\nconst wrapper = mount();\n\nexpect(wrapper).toContainReact(
const db = connectDB() // your db instance
const username = 'user'\nconst email = 'user@email.com'\nconst password = 'Password1'
const sql = SQL`INSERT INTO users (username, email, password) VALUES (${username},${email},${password})` // generate SQL query
db.query(sql) // execute query\ntextCopy to clipboard\n\nImport SQL module, connect to your DB and prepend SQL to your template strings.\n\nIt's really easy to use if you already have some queries; simply prepend SQL module and you are secured.\n\nHow Does it Work?\n\nThe SQL template string tag parses the query and returns an object that's understandable by PostgreSQL Node.js client :\n\nconst username = 'user'\nconst email = 'user@email.com'\nconst password = 'Password1'
const sql = SQL`INSERT INTO users (username, email, password) VALUES (${username},${email},${password})` // generate SQL query\nsql.text // INSERT INTO users (username, email, password) VALUES ($1 , $2 , $3)\nsql.values // ['user, 'user@email.com', 'Password1']\ntextCopy to clipboard\n\nWith PostgreSQL Node.js client , you can pass text and values separately. This is the most efficient way of preventing SQL injection attacks.\n\nTesting for SQL Injections\n\nTesting your application for SQL Injection is critical.\n\nOne of our favourite penetration testing tools for testing SQL Injection attacks is sqlmap .\n\nComing up with a good test plan and tools such as sqlmap is a good starting point.\n\nFor reference, here's a comprehensive example of how we've tested Udaru for SQL injection attacks.\n\nTesting in @nearForm/SQL\n\nThere are two levels of testing in the @nearForm/SQL module:\n\nunit tests that confirm that functionality works\nsecurity tests which test for SQL Injection\n\nWe have implemented sqlmap testing and it confirms that our code is fully secured.\n\nHow does sqlmap testing work?\nWe run a PostgreSQL database and a users table.\nWe run a Hapi.js server and expose POST and GET endpoints to do CRUD operations to a users table.\nWe then run sqlmap and try to attack the app through those endpoints.\n\nIt fails to do SQL Injection - our build is green.\n\nThis is automated through CircleCI and you can also run it locally: bash npm run test:security\n\nConclusion\n\nWe created @nearForm/SQL Injection protection module to help developers protect their apps from SQL Injections.\n\nIt's small, fast and uses modern ES6 syntax without much boilerplate code.\n\nNext time you start to write a SQL query, think about installing @nearform/sql module!\n\nDon't miss a beat\n\nNeed help building a fast and secure web application for your business? Contact us today!" ], "categories": { "primary": "security", "others": [ "data", "oss" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-nearform-is-speaking-and-exhibiting-at-red-hat-summit-in-san-francisco": { "href": "https://nearform.com/insights/nearform-is-speaking-and-exhibiting-at-red-hat-summit-in-san-francisco", "postType": "blog", "slug": "insights-nearform-is-speaking-and-exhibiting-at-red-hat-summit-in-san-francisco", "date": "2018-04-01", "title": "Come talk to us at Red Hat Summit and OpenShift Commons Gathering", "authors": [], "content": [ "This year sees nearForm attending Red Hat Summit for the second time and me attending for the fourth. Summit is the highlight of the Red Hat event calendar and is looked forward to by Red Hatters, customers and partners such as nearForm alike.\n\nIn addition to my talk about migrating your existing applications to Node.js on OpenShift on Tuesday 8th, we'll be there in force for all of Summit at booth 833. I think you're going to like our message a lot .\n\nIf you want to learn more about why Node.js is the ultimate runtime for OpenShift or why all your new web applications should be full stack JavaScript, then you should come on over for a chat.\n\nWe'll have DevOps/DevSecOps experts on-hand to guide you on best practices around containerized JavaScript applications. They'll also explain the benefits of using our Node.js images for OpenShift , including the brand-new Node.js 10.0.0 .\n\nIf you'd like to set up a meeting in advance, please contact me on conor.oneill@nearform.com Oh, we'll also be at OpenShift Commons Gathering on Monday, May 7th. Keep an eye out for the people in the nearForm t-shirts!" ], "categories": { "primary": "devops", "others": [ "backend", "cloud" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-nearform-data-science-exploration-of-recurrent-units-in-rnn": { "href": "https://nearform.com/insights/nearform-data-science-exploration-of-recurrent-units-in-rnn", "postType": "blog", "slug": "insights-nearform-data-science-exploration-of-recurrent-units-in-rnn", "date": "2018-04-09", "title": "The challenges in making an autocomplete AI understand text, using recently developed techniques.", "authors": [], "content": [ "An exploration of recent developments of Recurrent Units in Recurrent Neural Networks (RNN) and their effect on contextual understanding in text.\n\nUser types input sequence.\n\nRecurrent neural network processes the sequence.\n\nThe output for the last character is used.\n\nThe most likely suggestions are extracted.\n\nThe indices are looked up in a dictionary.\n\nAutocomplete: An example application, showing how a simple recurrent neural network can be used for autocompletion. The network uses past information and understands the next word should be a country. Try removing the last letters and see that the prediction uses contextual understanding (reset).\n\nIntroduction\n\nRecent advances in handwriting recognition, speech recognition [1] , and machine translation [2] have with only a few exceptions [3] [4] been based on recurrent neural networks.\n\nNeural Networks\n\nRecurrent neural networks are, funnily enough, a type of neural network. Neural networks have been around since at least 1975 but have over the recent years got a comeback and become very popular. This is likely due to the advances in General Purpose GPU (GPGPU) programming, that provides the computational resources to train them and larger datasets that provide enough data to train large networks.\n\nIf you are not familiar with neural networks, it is recommended that you become at least a bit familiar. Today there are many sources to learn from. The Neural Networks and Deep Learning book by Michael Nielsen is quite easy to get started with, chapter 2 should give most of the required background. If you are more curious the Deep Learning book by Goodfellow et. al. is much more extensive, chapter 5 should be a good start.\n\nTo give a too short introduction, vanilla neural networks are essentially composed of two things: sums and non-linear function, like the sigmoid function . In matrix notation this can be written as: Where is the output?\n\nIn this article, the output is in terms of probabilities. To turn something into probabilities the Softmax function can be used.\n\nMemorization problem\n\nThe examples mentioned earlier may use additional techniques such as attention mechanisms [5] to work with an unknown alignment between the source and the target sequence.\n\nHowever, the foundation for these networks is still the recurrent neural network. Likewise, a common challenge for many of these applications is to get the network to memorize past content from the input sequences and use this for contextual understanding later in the sequence.\n\nThis memorization problem is what is explored in this article. To this end, this article doesn't go into the details of how to deal with an unknown alignment but rather focuses on problems where the alignment is known and explores the memorization issue for those problems. This is heavily inspired by the recent article on Nested LSTMs [6] , which are also discussed in this article.\n\nRecurrent Units\n\nRecurrent neural networks (RNNs) are well known and thoroughly explained in literature . To keep it short, recurrent neural networks let you model a sequence of vectors. RNNs do this by iterating over the sequence, where each layer uses the output from the same layer in the previous \"time\" iteration, combined with the output from the previous layer in the same \"time\" iteration.\n\nIn theory, this type of network allows it in each iteration to know about every part of the sequence that came before.\n\nGiven an input sequence, such a model can be expressed using the following set of equations: Note how the output from the previous iteration ( ) and the output from the previous layer in the same iteration ( ) are combined, is abstracted away.\n\nFor a vanilla recurrent neural network, the recurrent unit is:\n\nVanishing Gradient Problem\n\nDeep neural networks can suffer from a vanishing gradient problem where the gradient used in optimization becomes minuscule. This is because the used in backpropagation ends up being multiplicatively depending on the of the next layer. This problem can be mitigated through careful initialization of the weights , by choosing an activation function such as the Rectified Linear Unit (ReLU), or adding residual connections 7 .\n\nIn classic recurrent neural networks, this problem becomes much worse, due to the time dependencies as the time dependencies essentially unfold into a potentially infinite deep neural network.\n\nAn intutive way of viewing this problem is that the vanilla recurrent network forces an update of the state . This forced update, is what courses the vanishing gradient problem.\n\nThis forced update is also insufficient as irrelevant input data, such as skip words, blur out important information from previous iterations.\n\nLong Short-Term Memory\n\nLSTM: (Long Short-Term Memory) allows for long-term memorization by gateing its update, thereby solving the vanishing gradient problem.\n\nThe Long Short-Term Memory (LSTM) unit replaces the simple unit from earlier. Each LSTM unit contains a single memory scalar that can be protected or written to, depending on the input and forget gate. This structure has shown to be very powerful in solving complex sequential problems [8] . LSTM is well known and thoroughly explained in the literature and therefore not discussed here.\n\nHowever as it plays a critical part in the Nested LSTM unit, that is discussed later, its equations are mentioned here.\n\nThe gate activation functions are usually the simoid activation function.\n\nWhile are usually .\n\nNested LSTM\n\nNested LSTM: makes the cell update depend on another LSTM unit, supposedly this allows more long-term memory compared to stacking LSTM layers.\n\nEven though the LSTM unit and GRU solves the vanishing gradient problem on a theoretical level, long-term memorization continues to be a challenge in recurrent neural networks.\n\nThere are alternatives to LSTM, most popular is the Gated Recurrent Unit (GRU). However, the GRU doesnt necessarily give better long-term context, particularly as it solves the vanishing gradient problem without using any internal memory.\n\nThe Nested LSTM unit attemps to solve the long-term memorization from a more practical point of view. Where the classic LSTM unit solves the vanishing gradient problem by adding internal memory, and the GRU attemps to be a faster solution than LSTM by using no internal memory, the Nested LSTM goes in the opposite direction of GRU - as it adds additional memory to the unit [6] .\n\nThe idea here is that adding additional memory to the unit allows for more long-term memorization.\n\nThe additional memory is integrated by changing how the cell value is updated. Instead of defining the cell value update as , it uses another LSTM unit: Note that the variables defined in are different from those defined below. The end result is that an unit have two memory states.\n\nThe complete set of equations then becomes:\n\nLike in vanilla LSTM, the gate activation functions are usually the simoid activation function. However, only the is set to . While, is just the identity function, otherwise two non-linear activation functions would be applied on the same scalar without any change, except for the multiplication by the input gate. The activation functions for remains the same.\n\nThe abstraction, of how to combine the input with the cell value, allows a lot of flexibility. Using this abstraction, it is not only possible to add one extra internal memory state but the internal unit can recursively be replaced as many internal units as one would wish, thereby adding even more internal memory.\n\nFrom a theoretical view, whether or not the Nested LSTM unit improves long context is not really clear. The LSTM unit theoretically solves the vanishing gradient problem and a network of LSTM units is Turing complete. In theory, an LSTM unit should be sufficient for solving problems that require long-term memorization.\n\nThat being said, it is often very difficult to train LSTM and GRU based recurrent neural networks. These difficulties often come down to the curvature of the loss function and it is possible that the Nested LSTM improves this curvature and therefore is easier to optimize.\n\nComparing Recurrent Units\n\nComparing the different Recurrent Units is not a trivial task. Different problem requires different contextual understanding and therefore requires different memorization.\n\nA good problem for analyzing the contextual understanding, should have a humanly interpretive output and depend both on long and short-term memorization.\n\nTo this end, the autocomplete problem is used. Each character is mapped to a target that represents the entire word. To make it extra difficult, the space leading up to the word should also map to that word. The text is from the full text8 dataset, where each observation consists of maximum 200 characters and is ensured to not contain partial words. 90% of the observations are used for training, 5% for validation and 5% for testing.\n\nThe input vocabulary is a-z, space, and a padding symbol. The output vocabulary consists of the most frequent words, and two additional symbols, one for padding and one for unknown words. The network is not penalized for predicting padding and unknown words wrong.\n\nThe GRU and LSTM models, each have 2 layers of 600 units. Similarly, the Nested LSTM model has 1 layer of 600 units but with 2 internal memory states.\n\nAdditionally, each model has an input embedding layer and a final dense layer to match the vocabulary size.\n\nModel\tUnits\tLayers\tDepth\tParameters\n\t\t\t\tEmbedding\n---\t---\t---\t---\t---\nGRU\t600\t2\tN/A\t16200\nLSTM\t600\t2\tN/A\t16200\nNested LSTM\t600\t1\t2\t16200\n\nModel Configurations: shows the number of layers, units and parameters for each model.\n\nThere are 508583 sequences in the training dataset and a batch size of 64 observations is used. A single iteration over the entire dataset then corresponds to 7946 epochs, which is enough to train the network, therefore the models only trained for 7946 epochs. For training, Adam optimization is used with default parameters.\n\nModel training: shows the training loss and validation loss for the GRU, LSTM, and Nested LSTM models when training on the autocomplete problem.\n\nModel\tCross Entropy\tAccuracy\nGRU\t2.1497\t51.61%\nLSTM\t2.2899\t49.90%\nNested LSTM\t2.6051\t45.47%\n\nModel testing: shows the testing loss and accuracy for the GRU, LSTM, and Nested LSTM models on the autocomplete problem.\n\nAs seen from the results the models are more or less equally fast.\n\nSurprisingly the Nested LSTM is not better than the LSTM or GRU models.\n\nThis somewhat contradicts the results found in the Nested LSTM paper [6] , although they tested model on different problems and therefore the results are not exactly comparable.\n\nNever or less one would still expect the Nested LSTM model to perform better for this problem, where long-term memorization is important for the contextual understanding.\n\nAn unexpected result is that the Nested LSTM model initially converges much faster than the LSTM and GRU models. This, combined with the worse performance, indicates that the Nested LSTM optimizes forwards an unideal local minimum.\n\nConclusion\n\nThe Nested LSTM model did not provide any benefits over the LSTM or GRU models. This indicates, at least for the autocomplete example, that there isn't a connection between the number of internal memory states and the models ability to memorize and use that memory for contextual understanding.\n\nAcknowledgments\n\nMany thanks to the authors of the original Nested LSTM paper [6] , Joel Ruben, Antony Moniz, and David Krueger. Even though our findings weren't the same, they have inspired much of this article and shown that something as used as the recurrent unit is still an open research area.\n\nReferences\nDeep Speech: Scaling up end-to-end speech recognition [PDF] Hannun, A., Case, C., Casper, J., Catanzaro, B., Diamos, G., Elsen, E., Prenger, R., Satheesh, S., Sengupta, S., Coates, A. and Ng, A.Y., 2014. arXivreprint arXiv:1412.5567.\nSequence to Sequence Learning with Neural Networks [PDF] Sutskever, I., Vinyals, O. and Le, Q.V., 2014. arXivreprint arXiv:1409.3215.\nAttention Is All You Need [PDF] Vaswani, A., Shazeer, N., Parmar, N., Uszkoreit, J., Jones, L., Gomez, A.N., Kaiser, L. and Polosukhin, I., 2017. arXivreprint arXiv:1706.03762.\nNeural Machine Translation in Linear Time [PDF] Kalchbrenner, N., Espeholt, L., Simonyan, K., Oord, A.v.d. and Kavukcuoglu, A.G.K., 2017. arXivreprint arXiv:1610.10099.\nNeural Machine Translation by Jointly Learning to Align and Translate [PDF] Bahdanau, D., Cho, K. and Bengio, Y., 2014. arXivreprint arXiv:1409.0473.\nSupervised Sequence Labelling with Recurrent Neural Networks [PDF] He, K., Zhang, X., Ren, S. and Sun, J., 2015. arXivreprint arXiv:1512.03385.\nSupervised Sequence Labelling with Recurrent Neural Networks [PDF] Graves, A., 2008.\nSupervised Sequence Labelling with Recurrent Neural Networks [PDF] Cho, K., Merrienboer, B.v., Gulcehre, C., Bahdanau, D., Bougares, F., Schwenk, H. and Bengio, Y., 2014. arXivreprint arXiv:1406.1078.\nNested LSTMs [PDF] Moniz, J.R.A. and Krueger, D., 2018. arXivreprint arXiv:1801.10308." ], "categories": { "primary": "ai", "others": [ "data" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-the-node-js-enterprise-maturity-curve": { "href": "https://nearform.com/insights/the-node-js-enterprise-maturity-curve", "postType": "blog", "slug": "insights-the-node-js-enterprise-maturity-curve", "date": "2018-04-17", "title": "Adopting certified images in your supply chain is crucial to establish a mature posture with Node.js.", "authors": [], "content": [ "Using NearForm's Certified Node.js Image Pipeline to build a compliant, open source supply chain\n\nIn this post I'll outline how Node.js can be maturely operated by Enterprises in Production with an understanding of the first major building blocks needed to build a compliant, open source supply chain and how NearForm's Certified Node.js Image Pipeline can play an important role.\n\nNode.js in the Enterprise Market\n\nNode.js is a phenomenal runtime and programming model transforming the way modern systems should be built, it also requires a different approach to operations which architects, operators and developers must address.\n\nToday there are ways to implement Node.js at a mature enterprise-grade for Production systems, and the Node.js Collaborators are working hard to make Node.js even better. Node.js has taken hold of the Enterprise market through developer adoption.\n\nThe challenge now for both the Node.js Community and Enterprise consumers is addressing deeper observability, security and compliance concerns. On the community side, Node.js Core contributors are currently working to address diagnostics and debugging improvements.\n\nMoving toward a more coherent approach to adopting Node.js\n\nNode.js is not a singular thing, but rather an ecosystem - a JavaScript runtime, C/C++ extension models, build system, developer tooling, the largest OSS community and a dependency model built to address the way modern application supply chains should be architected. However, most development teams struggle to implement an enterprise-grade Node.js system.\n\nThe C-Suite cannot sleep comfortably at night with nightmares of data breaches caused by shipping unknown code through open source package managers like npm or a lack of guarantees that their code and configuration hasn't been altered on its way to Production.\n\nUnfortunately, the rapid innovation in Node.js makes the Production challenge even more complex. What is often the case in developer-led adoptions is that security, compliance and governance come in the later stages of the software development lifecycle.\n\nA more certified and coherent approach to adopting Node.js with safety has not existed to date. Fortunately, sophisticated open source providers are focusing on these gaps and addressing solutions within the existing continuous integration and cloud-native space.\n\nSource: Node.js Foundation Release Working Group Since 2015 the Node.js Foundation has adopted a release cadence driving a predictable new version adoption rate, a better understanding of additive or deprecated features and importantly bug fixes and security patching conducted in partnership with the security community during a known Long Term Support (LTS) window.\n\nStaying current with the latest LTS version of software in Production is a requirement for any type of enterprise support agreement or certification.\n\nNode.js contains that same implicit Enterprise contract - LTS version adoption, verifiably immutable artifacts in your supply chain, the ability to publish system events and a forward-leaning approach with business partners.\n\nVerifiably Immutable Artifacts\nWhat is a verifiably immutable artifact?\n\nIt's any component of your Production system, from your infrastructure to your UI which you can verify has not been altered in any way since you built this version of the artifact, tested it and passed any additional quality gates or sign-offs you've built into your CI pipeline.\n\nIdeally, you can verify these artifacts have not changed or mutated through some type of cryptography scheme, hashing or other differential technique.\n\nWhy are containers a great packaging and virtual machine choice?\n\nI think the answer comes down to the ability to have immutable and 100% deterministic artifacts in your supply chain from your developer's machine all the way through qa, staging and production.\n\nIf you were manufacturing cars you wouldn't change the wheels after attaching them, you'd need to retest every time. The same problem exists in software supply chains!\n\nWhether you use docker, containerd, rocket or something else you have an immutable unit of deploy. It could be argued that a VM can represent this same unit, however the size, speed of deploy to run and developer experience make containers a clear winner. This also why it's the only supportable artifact in NearForm's Certified Node.js Image Pipeline.\n\nThe challenges of an open source runtime\n\nAddressing the challenges of an open source runtime requires a holistic approach across your enterprise's entire supply chain.\n\nWe cannot solve this fully within the Node.js ecosystem. It requires wrapping our arms around the entire DevSecOps lifecycle and should ideally be more heavily weighted as early (left) in this lifecycle as possible.\n\nIt starts with vetted images, ideally in partnership with industry experts. These images will need to be integrated into the early stages of the supply-chain, the days of patching in Production are over (at least they should be!).\n\nIf you can adequately assess, log and trace the provenance of your base distribution images then you have the means to statically correlate feature changes, bug fixes and even specific lines of code that changed in the event of a regression.\n\nThe flow diagram below illustrates how NearForm's Certified Node.js Image Pipeline addresses this critical stage.\n\nNearForm offers a few different options in incorporating this process into your supply chain whether you have a more homegrown situation, leverage an enterprise distribution mechanism such as Red Hats OpenShift or you have adopted a public cloud managed service like ECS , EKS or AKS .\n\nUnderstanding the source of your distributions is critically important, however, this alone can come directly from the distributions made available by the project maintainers themselves.\n\nTesting and Vetting steps\n\nWhere the enterprise-grade intersection really comes in is the additional testing and vetting steps taken by your support partner.\n\nIn this case NearForm's approach covers the following critical steps:\n\nApply any needed configurations - can address perf tuning, custom client configs or security lockdowns where possible\nRun docker squash - creates as minimal a container image size as possible\nRun a battery of unit and smoke tests on the new build - ideally, the definition of these tests are informed by both the vendor and the client\nTrigger build approval process - manual or automated\nPublish Release!\n\nGiven the various environments we encounter across our partners and clients it's necessary to maintain a certain level of flexibility in how we publish our releases.\n\nFor most organisations publishing these images to Docker Store (Hub) is acceptable. However, there are environments which sometimes would not have access to public artifact repositories.\n\nThis is certainly the case in regulated industries such as Financial Services or Healthcare. In these situations we work with our clients either on-prem or in the public cloud to deliver images in a way that is compliant with their security standards, one size does not fit all.\n\nPublishing System Events\n\nAdopting certified Node.js images is a critical step in moving to a more mature Production system. However simply re-building your containers based on the certified images is a portion of promoting discoverability and establishing Production provenance.\n\nEvery build step in your supply chain, whether internal or external, should provide metadata, change outputs, repo history and other data collected and associated with versioned releases across distros, dependencies, your own source code, infrastructure or configuration files.\n\nAll of this data can then be published and made available to downstream systems and consumers over a message stream built on Kafka, AWS Kinesis, Azure Event Hubs or an Enterprise solution like MQ or Tibco.\n\nForward Leaning Approach with Audit & Legal Teams\n\nWhat an event-driven approach allows you to do is communicate early and often through automation with full forensic detail. You can then immediately get stakeholders involved where needed.\n\nIt will be important to teach your auditors how to investigate in the cloud as DevOps moves us away from traditional resource catalogues or ITIL style change management techniques.\n\nIn the cloud resources are ephemeral, self-composing and auto discovering - your audit logs and information sharing need to match this reality.\n\nBy adopting immutable Node.js releases in an event-driven supply chain you can statically determine exactly what was running and when, test results, who created and published any code, dependency traceability and a means to roll-back or patch forward using the same process. Your system becomes comprehensively observable.\n\nEmbracing the process we're describing demands that providers you partner with understand their obligations to testing. This means no breaking minor changes, additive only changes between majors as well as upfront and early warning communications in navigating the depreciation and feature removal process.\n\nHowever as is the case in software development breakages will happen. Your organisation will need governance and quality gates put in place between your vendors and your customers' production systems.\n\nNearForm represents the best people, process and tools to deliver software on-time and on budget. Our Solutions team and Node.js Core contributors are experts in de-risking digital delivery.\n\nWe'd love to discuss your needs and how NearForm can help you mature your Node.js and digital supply chain capabilities. Contact us for more information." ], "categories": { "primary": "backend", "others": [ "cloud", "devops", "security", "oss" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-the-future-of-native-modules-in-node-js": { "href": "https://nearform.com/insights/the-future-of-native-modules-in-node-js", "postType": "blog", "slug": "insights-the-future-of-native-modules-in-node-js", "date": "2018-04-19", "title": "N-api and prebuilt native modules are ready for prime time.", "authors": [], "content": [ "Node.js 10 to Update the Native Module Library n-api\n\nNode.js 10 is just around the corner and with it comes a number of improvements. One that is exciting us is the update to the native modules library n-api. It comes out of experimental status in the upcoming release.\n\nJavaScript has always had a minimal standard library compared to other languages. In the beginning we only used JavaScript in the browser. As browsers evolved and matured into application virtual machines, so did the need to add more capability through browser libraries. This brought new applications like Web Bluetooth, Web USB and so on; ever expanding the things we can use JavaScript for.\n\nA bit of history\n\nAt one point we realised that JavaScript would be a great language for writing highly scalable server applications due to its event driven nature. Node.js was born. A new minimal standard library, composed with some essential features needed for writing non-browser applications, such as filesystem bindings, a TCP stack, a module loader, and much more. It is hard to estimate exactly what the use cases of the future are, so to try and make the platform more flexible, the ability to write modules in C/C++ was added. This allows developers to take full advantage of any APIs available on their platform, but still expose it as a JavaScript API for users to consume.\n\nLots of great modules were written this way. LevelDB , an embedded and fast database was written as a native module that glued the LevelDB C++ code with an easy-to-use JavaScript API. LevelDB sparked an ecosystem where a lot of interesting modules and applications were developed on top. Few LevelDB users know how the C++ in the module works, but luckily we don't have to - the native module abstracts all that away.\n\nAs more people started using native modules, we also learned some of the drawback. It turns out they can be hard to maintain, as the V8 APIs you use to implement the modules change a lot. For users to use a module they needed a full compiler stack installed on their machine (on Windows this used to involve users having to install Visual Studio!).\n\nAlong came NAN\n\nTrying to solve the problem of the ever-changing V8 APIs, NAN was born. NAN stands for \"Native Abstractions for Node.js\" and is a series of macros that abstract away the differences between the changing V8 APIs. In fact, NAN was originally created by Rod Vagg to help with LevelDB development. This meant you could write a native module using the latest version of Node.js and have it work on most of the previous versions without too much complexity. It also meant that on most newer Node.js versions your old modules would continue to compile. This was a massive improvement in terms of being able to maintain native modules.\n\n// silly NAN backed module that prints a string from c++
#include \n#include
using namespace v8;
NAN_METHOD(Print) {\n if (!info[0]->IsString()) return Nan::ThrowError(\"Must pass a string\");\n Nan::Utf8String path(info[0]);\n printf(\"Printed from C++: %s\\n\", *path);\n}
NAN_MODULE_INIT(InitAll) {\n Nan::Set(target,\n Nan::New(\"print\").ToLocalChecked(),\n Nan::GetFunction(Nan::New(Print)).ToLocalChecked()\n );\n}
NODE_MODULE(a_native_module, InitAll)\n\n\n( See the full NAN example repo here )\n\nPrebuilds\n\nTo avoid having to install a compile toolchain, a series of experiments were performed around prebuilding modules before publishing them. The prebuilt binary would be hosted online on a place like Github releases and downloaded by an npm install script when the module is installed. If no available prebuild is available the npm install script would fall back to compiling the module as usual.\n\nYou can see an example of this in the leveldown repository .\n\nStill a lot of issues continued to pop up. Once in a while NAN would have to make a backwards incompatible change. This meant old modules wouldn't compile on newer versions of Node.js without upgrading them. The introduction of new Node.js compatible runtimes such as Electron, made the situation even more complex. Modules compiled using Node.js would not run on Electron, leaving the users with obscure errors.\n\nDownloading prebuilds turned out to be difficult with network proxies and security concerns about downloading binaries from 3rd party sources. Ironically, prebuilds made Electron tricky to use as well. The prebuild downloaded targeted the Node.js version that npm install was running on instead of the Electron one. In addition, the hard requirement for an npm install script can be a security issue also, as users disable these to avoid running an npm worm .\n\nThe Present\n\nNAN and prebuilds make things better; but still not quite as good as we want. Native modules are still considered \"expensive\" dependencies, and are often used as an argument to include something in Node.js core VS an NPM module.\n\nLuckily things are rapidly improving and we are already at the stage now where we have the tools to write and publish native modules that users can install with little or no technical overhead.\n\nN-api\n\nTo make native modules easier to write and maintain, Node.js core contributors have been developing a new core API called n-api (or node-api).\n\nThe idea behind n-api is to build a stable interface on top of the V8 APIs that you write your native modules against. This approach introduces a series of benefits:\n\nRemove the need to recompile modules, as the interface never breaks (think of it as syscalls but for Node.js).\nAllows JavaScript engines other than V8 to implement n-api.\nUses native modules across Electron and other runtimes as long as they implement n-api.\n\nN-api has a tiny performance impact as you have to go through a slim abstraction layer instead of raw V8 code. However, it has great documentation .\n\nHaving been an experimental feature for a while, n-api recently landed as a non-experimental API. It is due to be released as such in Node.js 10 with backports coming to Node.js 8 and 6 (although as experimental in 6 for now).\n\nHere is our NAN example from above ported to n-api:\n\n// silly n-api backed module that prints a string from c\n#include \n#include
napi_value print (napi_env env, napi_callback_info info) {\n napi_value argv[1];\n size_t argc = 1;
napi_get_cb_info(env, info, &argc, argv, NULL, NULL);
if (argc < 1) {\n napi_throw_error(env, \"EINVAL\", \"Too few arguments\");\n return NULL;\n }
char str[1024];\n size_t str_len;
if (napi_get_value_string_utf8(env, argv[0], (char *) &str, 1024, &str_len) != napi_ok) {\n napi_throw_error(env, \"EINVAL\", \"Expected string\");\n return NULL;\n }
printf(\"Printed from C: %s\\n\", str);
return NULL;\n}
napi_value init_all (napi_env env, napi_value exports) {\n napi_value print_fn;\n napi_create_function(env, NULL, 0, print, NULL, &print_fn);\n napi_set_named_property(env, exports, \"print\", print_fn);\n return exports;\n}
NAPI_MODULE(NODE_GYP_MODULE_NAME, init_all)\n\n\n( See the full n-api example repo here and checkout the examples in Node.js core )\n\nIn addition to the C API, a higher level C++ wrapper is available as well called node-addon-api . The C++ wrapper is an npm module maintained by the n-api collaborators. Using the C++ wrapper you get support back until Node.js 4 as it has a compatibility layer for older versions.\n\nIn general I use the C API when wrapping C interfaces and the C++ one when wrapping a C++ API.\n\nBundled prebuilds\n\nWith n-api supporting prebuilds become a lot easier. Since n-api has a stable API we can prebuild a module for Node.js 10 and it will work on Node.js 11, 12, and newer.\n\nTo work around the issues of having to download prebuilds at installation, myself and some other contributors recently published a set of modules called prebuildify , node-gyp-build and prebuildify-ci .\n\nprebuildify will prebuild your module\nnode-gyp-build can test a prebuild at install time and supports loading a prebuild from disk using a JavaScript api.\nprebuildify-ci helps you setup prebuildify on ci to automatically build for Linux 32/64 bit, MacOS, and Windows 32/64 bit\n\nOther prebuild modules exist on npm. So how do they differ from prebuildify? With prebuildify instead of downloading a prebuild for your platform at installation time, we simply bundle all prebuilds for all platforms inside a ./prebuilds folder in the node_modules before it is published to npm. At installation then we use node-gyp-build to simply test if any of the prebuilds bundled in the module can load on the platform. If not we call out the compiler toolchain as npm normally does.\n\nIf you disable the installation script for security reasons the prebuilds still load on runtime. The installation script is just to test if it works.\n\nWhen we first tried out this approach, we, the prebuildify collaborators, were worried that the footprint of adding multiple prebuilds inside the node_modules folder would make it slower to install due to the bigger package size. Ironically, it has actually made all the modules we ported to prebuildify faster to install. It usually takes longer to download all the dependencies needed to download a specific prebuild than it does to simply download them all in one go, gzipped, along with the rest of the module.\n\nCombining prebuildify with n-api is close to being a perfect fit. N-api means you need to do very few prebuilds - one for each platform you need to support VS one for each platform x Node.js versions. You don't need to publish a new module when a new Node.js release is issued.\n\nYou can see a full example of how to use prebuildify with n-api and ci in the n-api example repo Building the prebuilds on platforms other than the one you are developing on can be a bit tedious. That's why we created prebuildify-ci; it sets up travis and appveyor to build your module when you tag a new release.\n\nFirst setup your module. Running prebuildify-ci init will setup a appveyor.yml and travis.yml file that prebuilds your module when it is tagged. After a succesful build, it will upload the prebuilds temporarily to Github releases so we can download from there before releasing the module. prebuildify-ci init\ngit push a tagged release (and do not release it on npm yet). git commit -am \"new cool stuff\" npm version minor git push && git push --tags\nWait for ci to finish.\nDownload the releases from Github. prebuildify-ci download This should download and extract the prebuilds to ./prebuilds.\nSimply publish your module to npm with the prebuilds. npm publish\n\nIt is as easy as that.\n\nThe Future for Native Modules\n\nThe future is bright for native modules. In a years time n-api will be supported in all active Node.js release lines.\n\nNative modules can be incredibly powerful and enable us to modularize Node.js core even more as it allows things like an alternative tcp stack , efficient bloomfilters and a modern crypto library to be built outside core without forcing users to compile them on installation. This will help us continue to bring great things like LevelDB and another non JavaScript projects into the Node.js ecosystem."
],
"categories": {
"primary": "backend",
"others": [
"oss"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"digital-community-nuka-react-carousel": {
"href": "https://nearform.com/digital-community/nuka-react-carousel",
"postType": "blog",
"slug": "digital-community-nuka-react-carousel",
"date": "2018-04-23",
"title": "Nuka Carousel: The React Carousel, Rethought and Refined",
"authors": [
"CARLOS KELLY"
],
"content": [
"What is Nuka Carousel\n\nNuka Carousel is a pure-React carousel component that can support any kind of component as children, including text and images. Nuka Carousel has no built-in design, so it can be styled to fit any app. The carousel navigation can be controlled with either a container component or your app’s state management, making it easy to incorporate into your build.\n\nAll-new API for custom controls\n\nCustom components can be added to eight zones along the edge of the carousel. By default, Nuka Carousel displays a previous and next button along with page indicators. The carousel component now has render props for all eight zones (top left, center left, bottom left, etc.) that pass control functions and state to your custom components. For example:\n\n
{\n- a: 1\n+ a: 2\n }\ntextCopy to clipboard\n\nA similar treatment has been given to the assert.ifError() method, which throws an assertion error if the input argument is an Error object:\n\ntry {\n assert.ifError(new TypeError());\n} catch (err) {\n console.log(err);\n}\ntextCopy to clipboard\n\nWhen running Node.js 9.11.1, the output is:\n\nTypeError\n at repl:1:22\n at Script.runInThisContext (vm.js:65:33)\n at REPLServer.defaultEval (repl.js:248:29)\n at bound (domain.js:376:14)\n at REPLServer.runBound [as eval] (domain.js:389:12)\n at REPLServer.onLine (repl.js:496:10)\n at REPLServer.emit (events.js:185:15)\n at REPLServer.emit (domain.js:422:20)\n at REPLServer.Interface._onLine (readline.js:285:10)\n at REPLServer.Interface._line (readline.js:638:8)\ntextCopy to clipboard\n\nWhich is OK in that the original error message is preserved, but the fact that this is a failed assertion is lost.\n\nIn Node.js 10.0.0, the output becomes:\n\n{ AssertionError [ERR_ASSERTION]: ifError got unwanted exception: TypeError\n at repl:1:14\n at repl:1:22\n at Script.runInThisContext (vm.js:91:20)\n at REPLServer.defaultEval (repl.js:311:29)\n at bound (domain.js:396:14)\n at REPLServer.runBound [as eval] (domain.js:409:12)\n at REPLServer.onLine (repl.js:609:10)\n at REPLServer.emit (events.js:200:15)\n at REPLServer.emit (domain.js:442:20)\n at REPLServer.Interface._onLine (readline.js:285:10)\n at REPLServer.Interface._line (readline.js:633:8)\n generatedMessage: false,\n name: 'AssertionError [ERR_ASSERTION]',\n code: 'ERR_ASSERTION',\n actual: TypeError\n at repl:1:22\n at Script.runInThisContext (vm.js:91:20)\n at REPLServer.defaultEval (repl.js:311:29)\n at bound (domain.js:396:14)\n at REPLServer.runBound [as eval] (domain.js:409:12)\n at REPLServer.onLine (repl.js:609:10)\n at REPLServer.emit (events.js:200:15)\n at REPLServer.emit (domain.js:442:20)\n at REPLServer.Interface._onLine (readline.js:285:10)\n at REPLServer.Interface._line (readline.js:633:8),\n expected: null,\n operator: 'ifError' }\ntextCopy to clipboard\n\nSignificantly more verbose but also significantly more useful.\n\nThere are several other important changes in the assert module worth exploring and playing around with including improved error message detail, promises support, and better object comparisons.\n\nBuffers again\n\nThe venerable Node.js Buffer object is once again getting some attention. You may recall that back in Node.js 6.0.0 a number of new methods were introduced for creating Buffer objects (e.g. Buffer.from() , Buffer.alloc() , Buffer.allocUnsafe() , and so on). You may also vaguely recall something about how these were added because of security concerns around using the new Buffer() and Buffer() (without the new keyword). What may have gone unnoticed, however, is the fact that when the new methods were introduced, the old constructors were marked as deprecated in the documentation.\n\nCome to find out, three years later, not only are Node.js developers still using the old new Buffer() and Buffer() constructors, there's even more code published to the ecosystem today using the deprecated versions than there were when we introduced the new methods. Unfortunately, we still need developers to migrate so Node.js 10.0.0 introduces a new deprecation warning that is emitted at runtime whenever the old constructors are used by any code not located in the node_modules directory.\n\nWhat does that mean in practice? It means you should not see Buffer deprecation warnings emitted from your dependencies, but if your code uses the old Buffer constructors, you will see the warning and will be reminded to update to the new methods.\n\nError improvements\n\nOf the nearly 300 semver-major commits that have landed in Node.js 10.0.0, most are improvements to error messages and error handling in general. The effort started in Node.js 8.0.0 to assign static error codes to all Node.js produced Error objects has continued and makes a significant leap forward in Node.js 10.0.0. Error messages should be more consistent, more predictable, and generally more useful.\n\nHistorically, changes to Error messages and detail have been forced to be treated as semver-major changes within Node.js because the lack of consistency and detail in the Errors themselves has forced user code to parse through error messages to understand the specific kinds of failures that may have occurred. Changing even the punctuation in an Error message could break application code in very awful ways. With the assignment of static error codes, we begin to be able to relax this requirement.\n\nExpect the assignment of Error codes and the improvement of Error messages to continue through Node.js 11.x\n\nFile System\n\nThe Node.js fs (file system) module has received the most significant internal overhaul it has had likely since it was first introduced. The improvements include restructuring of code for easier maintainability, improved error handling and type checking, and the introduction of a new experimental fs/promises API, featuring Node.js' first first-class Promise-based API.\n\nUse of the new fs/promises API should be straightforward and familiar to anyone already familiar with both the existing fs API and Promises in general:\n\nconst fs = require(\"fs/promises\");\nasync function openAndStat() {\n const fd = await fs.open(\"somefile.txt\", \"r\");\n try {\n return await fs.fstat(fd);\n } finally {\n await fd.close();\n }\n}\nopenAndStat()\n .then(console.log)\n .catch(console.error);\ntextCopy to clipboard\n\nThe new API is still experimental and will emit a warning at runtime when first used. Once we are sure it is stable and there are no significant bugs still lurking, we will remove the experimental status.\n\nHTTP and HTTP/2\n\nHTTP and HTTP/2 have each received a number of incremental improvements in 10.0.0.\n\nFor HTTP changes include stricter standards support, improved upgrade header handling, improved Streams API compatibility, and improved error handling.\n\nFor HTTP/2, work continues on improving both the internal implementation and public API, with a significant change made to how trailing headers in HTTP/2 requests and responses are implemented.\n\nconst http2 = require(\"http2\");\nconst server = http2.createServer();\nserver.on(\"stream\", stream => {\n stream.respond({ \":status\": 200 }, { waitForTrailers: true });\n stream.on(\"wantTrailers\", () => {\n stream.sendTrailers({ abc: 123 });\n });\n stream.end(\"Hello World\");\n});\ntextCopy to clipboard\n\nOverall, work on HTTP/2 is beginning to wind down as the implementation becomes more and more stable and performant. The goal is to move it out of experimental status as soon as possible before Node.js 10.x enters the Long Term Support cycle in October of 2018.\n\nStreams API\n\nA number of important improvements have been made to the implementation of Streams in Node.js 10.0.0 but the standout features are experimental support for async iterators and the introduction of the new pipeline() method.\n\nAsync iterators are a new JavaScript language feature that allows asynchronous iteration using a for await () loop. The experimental support that has been added to all stream.Readable class instances make it possible to consume a stream of data using the new syntax:\n\nconst fs = require(\"fs\");\nasync function readFile() {\n let result = \"\";\n const r = fs.createReadStream(\"myfile.txt\");\n for await (const chunk of r) result += chunk.toString();\n return result;\n}\ntextCopy to clipboard\n\nThe new pipeline() utility establishes a pipe between multiple streams with proper end-to-end error handling and flow control. It is essentially the same functionality as the userland pump module, implemented and contributed to Node.js core by pump author @mafintosh (Mathias Buus).\n\nconst { pipeline } = require(\"stream\");\nconst fs = require(\"fs\");\nconst zlib = require(\"zlib\");
// Use the pipeline API to easily pipe a series of streams\n// together and get notified when the pipeline is fully done.
// A pipeline to gzip a potentially huge tar file efficiently:
pipeline(\n fs.createReadStream(\"archive.tar\"),\n zlib.createGzip(),\n fs.createWriteStream(\"archive.tar.gz\"),\n err => {\n if (err) {\n console.error(\"Pipeline failed\", err);\n } else {\n console.log(\"Pipeline succeeded\");\n }\n }\n);\ntextCopy to clipboard\n\nRelated to the efforts to introduce pipeline() are a several of significant behavioral changes to Streams in Node.js including:\n\nAlways emitting the 'error' event before the 'close' event;\nAlways deferring the 'readable' event using process.nextTick().\n\nSuch changes are subtle but critical to ensuring proper operation of the Streams API.\n\nPerformance and Diagnostic Monitoring\n\nThe experimental trace events mechanism allows the collection of diagnostic information output to a file usable by the Chrome browsers DevTools utility. Previously, this mechanism could only be enabled using a command-line flag when the Node.js process was launched. New to 10.0.0 is a JavaScript API for enabling and disabling trace events dynamically:\n\nconst trace_events = require(\"trace_events\");\nconst tracing = trace_events.createTracing({\n categories: [\"node.async_hooks\", \"v8\"]\n});\ntracing.enable();\n// do stuff\ntracing.disable();\ntextCopy to clipboard\n\nAlso important is the addition of the node.perf.usertiming tracing category which adds the ability to capture Performance API user timing marks and measures in the trace events timeline.\n\nconst trace_events = require(\"trace_events\");\nconst { performance } = require(\"perf_hooks\");\nconst tracing = trace_events.createTracing({\n categories: [\"node.perf.usertiming\"]\n});\ntracing.enable();
performance.mark(\"A\");\nsomeAsyncFunction(() => {\n performance.mark(\"B\");\n performance.measure(\"A to B\", \"A\", \"B\");\n});
tracing.disable();\ntextCopy to clipboard\n\nLastly, when the node.bootstrap tracing category is enabled using the --trace-event-categories command-line flag, Node.js will automatically record trace events to the timeline marking key moments in the startup of the Node.js binary.\n\nWork is expected to continue within Node.js 10.x and beyond to further extend the tracing information published via the trace events mechanism.\n\nSay Helllo to V8 6.6\n\nLast, but certainly not least, V8 has been updated to version 6.6 in Node.js 10.0.0 with guaranteed forward ABI compatibility with V8 6.7.\n\nV8 6.6 delivers a range performance improvements and updated JavaScript language features that are covered quite well by Google's own V8 release announcement so I won't cover those in detail here. Early testing has shown significant performance improvements across the board with V8 6.6 and we expect to see the trend continue with 6.7 and beyond.\n\nWe've run the synthetic hello world benchmark across Node.js 8.11.1, 9.11.1, and Node.js 10.0.0, and have seen a significant improvement in performance over Node.js 8. Moreover, thanks to the tireless work of Benedikt Meurer and the whole V8 team, Promise and async/await execution has improved significantly, resulting in Hapi v17 realizing a 30% increase in throughput. Remember to migrate to Node.js 10 once it reaches LTS status in October.\n\nNext in line for Long Term Support\n\nIn October 2018, roughly six months from now, the Node.js 10.x release line will become the next active Long Term Support branch. With the codename Dubnium, Node.js 10.x promises to deliver improved reliability, performance, monitoring, and developer experience.\n\nSource: Node.js Foundation Release Working Group It would be negligent of me not to include a reminder that Node.js 4.x is reaching the end of it's life on April 30th, 2018. If you are still using 4.x (or any earlier version of Node.js), it is well past the time to migrate to a newer version. You can go to Node.js 6.x if necessary, but the ideal Long Term Support target right now is the latest version of Node.js 8.x, which will remain under Active Long Term Support coverage until December 2018 (note: the graphic above is slightly off on the Active/Maintenance transition for 8.x because of a limitation in the tool used to visualize the schedule). You will want to begin working on your transition to 10.x once it enters the Active Long Term Support cycle in October.\n\nTeam Effort\n\nWhile the Node.js project is supported by a broad and diverse ecosystem of individual developers and companies, I want to directly call out the contributions to Node.js 10.0.0 made specifically by my fellow NearFormers. Combined, NearForm-authored contributions account for around 27-28% of the commits included in 10.0.0. Visit the NearForm website to learn more about our commitment to supporting Open Source ." ], "categories": { "primary": "backend", "others": [ "perf", "devops" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-minishift-as-a-development-environment-for-node-js-on-openshift-updated": { "href": "https://nearform.com/insights/minishift-as-a-development-environment-for-node-js-on-openshift-updated", "postType": "blog", "slug": "insights-minishift-as-a-development-environment-for-node-js-on-openshift-updated", "date": "2018-04-27", "title": "Overcoming early obstacles to local development with Minishift", "authors": [], "content": [ "Container-based Software Deployment and Management with OpenShift\n\nSince Adrian wrote the original post on local development a few of our early challenges have been overcome with simpler solutions. Two challenges addressed are:\n\nMounting Volumes\nNative Modules\n\nIn addition, we have switched to using the latest NearForm-supported Node.js LTS images .\n\nLike Adrian previously mentioned we like to us nodemon in development to sync/restart services with the latest local changes. Thus reducing the feedback loop to the developer about the changes and reducing wait time on deployments.\n\nOriginally we had to jump through a few hoops to get our local files into the pods using hostmounts and volumes . With this update, we are building, deploying and syncing a bit differently.\n\nThe create-project.sh will now setup configurations, build the image and then deploy. Once the deployment is complete you can rebuild using build.sh .\n\nIt's safe to use create-project again when changes to your docker file happen, it just has a few extra steps that are unnecessary. Our deployment is now only triggered when there is a change in the image.\n\nTo get around the Native Modules issue we ran into originally, I changed our Dockerfile around to npm install in /tmp .\n\nWe then copy this into /opt/app-root/src where our application now lives.\n\nThis does two things:\n\nFirst, It allows native dependencies to be built in the container and not your local development directory.\nSecondly, when rebuilding your image, we will only have to npm install when the package actually changes.\n\nWhile researching how to mount our local files into the pod I came across a familiar command in the OpenShift documentation that made life very simple.\n\noc rsync {local directory} {pod name}:{path within pod}
example:\noc rsync ./hello-server/ hello-server-7-hrlld:/opt/app-root/src\ntextCopy to clipboard\n\nSo with this command and the --watch flag appended we end up with a fully synchronized local to pod development environment. If you look in our deploymentConfig you will notice that we don't mount any volumes in the pod.\n\nIt appears the OpenShift team have been tackling pain points and pushing to make the Developer Experience much more enjoyable over the past year. We're looking forward to what this next year brings.\n\nOriginal Article\n\nOn a recent client project, our team was tasked with setting-up local development environments for a new Node.js-based microservices system that would eventually be deployed on Red Hat's OpenShift platform .\n\nWe have found a good approach by making use of the MiniShift project and we have put together a demo with some accompanying documentation about what we've learnt.\n\nYou can jump straight into the code and docs , or you can stick around for more on the journey that led us to this point.\n\nWhy target OpenShift?\n\nOpenShift is a computer software product from Red Hat for container-based software deployment and management.\n\nIn concrete terms, it is a supported distribution of Kubernetes using Docker containers and DevOps tools for accelerated application development. Wikipedia So OpenShift is Kubernetes plus some very impressive Enterprise and quality-of-life improvements that form a compelling bigger offering.\n\nTechnical Reasons\n\nSome of OpenShifts additions have been built upon other upstream projects such as the integrated Jenkins instance for an out-of-the-box CI/CD pipeline and the integrated Docker registry for your build artefacts.\n\nOthers are completely custom but very sensible, such as the router to direct traffic between your services. If this wasn't provided you'd probably end up having to write your own version of this component.\n\nOne of the more pleasant surprises from our time with OpenShift has been the very clean user interface that ties all of the concepts together and provides you with some good insight into how your system is working. You can view logs for all your services, scale number of instances and even track the progress of builds in the integrated CI/CD pipeline.\n\nOnce you become accustomed to OpenShift, you would find yourself missing this functionality if you ended-up back on plain Kubernetes.\n\nBusiness Reasons\n\nIt should also be noted that some of the non-technical reasons why OpenShift is an attractive platform are almost equally important.\n\nWhen evaluating adoption of a platform, it is wise to consider the amount of risk that it introduces into a project, and here Red Hat has a solid reputation for acting as a filter of what can sometimes be chaotic development of the upstream projects it packages.\n\nThis process is Red Hat's bread-and-butter and is one of the reasons they have built strong relationships with many enterprise customers who trust them to reduce the risk for critical infrastructure components such as this.\n\nMore and more clients are requesting OpenShift from us because of this.\n\nWhat makes a good development environment?\n\nThere are many aspects for which you can optimise when building a development environment but these may change through the life of even a single project. The following are a few of the things that were important to us when evaluating our MiniShift based solution.\n\nTime to first code\n\nWe wanted a solution that would allow us to start building our services as quickly as possible, and not require us to build too much custom tooling that would make it more time-consuming to onboard our developers.\n\nIt might seem a bit counterproductive to optimise for this. However, increasing the ease with which a developer can bring up a completely fresh environment has a significant long tail of improved productivity. That can benefit you throughout the lifetime of your project.\n\nWe find that the way that MiniShift makes use of Dockers libmachine in combination with VirtualBox or Xhyve (depending on your platform) allows us to wipe and reinstall the environment with minimal fuss.\n\nNow that we've conquered the initial learning curve and documented our findings clearly, we feel confident in our ability to get new developers up and running.\n\nBut this approach hasn't been without its gotchas. For one, we have found that starting-up MiniShift is sometimes unreliable, although retrying the command usually does the trick.\n\nProduction Parity\n\nThe holy grail of DevOps is a development environment that mirrors the production environment as closely as possible. This should theoretically reduce the possible bugs that could occur from slight differences, which you would only catch once you've deployed your code into production.\n\nIt goes without saying that there are situations where being as close as possible to production suffers from diminishing returns. While we have something running now that feels fairly solid, we can imagine that there will be scaling issues in the future as your application grows to a higher number of more complex services.\n\nRunning a full Kubernetes / OpenShift in a single virtual machine on your own hardware introduces a lot of complexity, which could also provide many opportunities for things to break.\n\nWhile we acknowledge this risk, it is our hope that things would at least break in the same way that they would once you head into production, allowing you to catch problems earlier.\n\nWe have yet to explore and document the process of taking a system developed locally using MiniShift to an OpenShift environment deployed in either the public or private clouds. It is likely that we will need to make more compromises as we map out that path.\n\nQuick feedback loops\n\nIt is critical in a local development environment that you be able to execute your code changes as quickly as possible, lest you lose a few minutes on every change resulting in many hours of waiting around each week.\n\nThis was the part of this process that was the trickiest to figure out because for the most part Kubernetes and MiniShift weren't designed for this use case.\n\nChallenges\nScaling Instances\n\nKubernetes will only start new pods (instances) up to the level your hardware allows, and this decision is based on the memory limits set for each service and (in MiniShift) the number of CPU cores/memory handed to the virtual machine on startup. We were able to tweak these quite easy to get up to 50 pods of our little test server running. Interestingly, there is a recommended upper limit of 110 instances across all services when using OpenShift Origin (the upstream project for MiniShift).\n\nIf you are interested in more of the technical details of this implementation, please check out the extensive Readme we have created for the demo project.\n\nWe also recommend reading the material on Kubernetes By Example by the OpenShift team.\n\nInterested in learning more about MiniShift and OpenShift? Read our article Develop in MiniShift, Deploy to OpenShift" ], "categories": { "primary": "cloud", "others": [ "devops", "backend" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-building-progressive-web-apps": { "href": "https://nearform.com/insights/building-progressive-web-apps", "postType": "blog", "slug": "insights-building-progressive-web-apps", "date": "2018-04-30", "title": "How to build performant progressive web apps and why they matter", "authors": [], "content": [ "Fast and Engaging Progressive Web Apps\n\nWe love creating fast and engaging Progressive Web Apps at NearForm. Its part of our DNA to take whatever we do to the next level. Even though we are known for caring about the performance of what we build, we are also known for caring about the end-user experience.\n\nNew web standards are coming out often, it's a constantly changing world with new technologies and frameworks. We like to lead the way on what we do best: rock-solid, blazing-fast and all-around awesome software that incorporates the bleeding edge without compromising compatibility, keeping existing audiences in mind. Progressive Web Apps (PWA) gives us the perfect opportunity to do just that.\n\nIn this article we detail how to build progressive web apps covering the following topics:\n\nWhat are Progressive Web Apps.\nWhat makes Progressive Web Apps \"progressive\".\nThe core principles of Progressive Web Apps: Fast, Reliable and Engaging.\nWhat is an App Shell and how can it help us deliver a great user experience.\nWhat are Progressive Web Apps?\n\nA progressive web app is an enhanced version of a Single Page App (SPA) with a native app feel. Progressive web apps are developed using web standards, but they have some native features because they are fast, smooth and responsive. They are installable on the device, they work regardless of the network state and they engage with a user just like a native-app does.\n\nProgressive Enhancement\n\nThe P in PWA stands for progressive as in progressive enhancement 1 . This is when a web app provides the best experience possible within the available capabilities of the browser being used; ultimately taking advantage of cutting-edge features while still providing an experience to the user without relying on JavaScript.\n\nServer-side rendering\n\nTo achieve the ultimate level of progressive enhancement we need a web app that can fully render content on the server, not just a header and footer for example. You can argue that no one is using a browser without JavaScript, thought this can be true, in fact, we can see the browser as JavaScript-less while initially loading a page. Without this JavaScript-less experience, the user won't see any content until a page is fully loaded, neither can search engine bots because most of them don't run JavaScript.\n\nBesides enabling progressive enhancement, server-side rendering also brings performance and SEO benefits. By making sure the first step is done right and our content is rendered on the server, we have a solid baseline for creating the best experience possible.\n\nFast - Performance matters\n\nPerformance matters the most the first time your user visits. Local caches are empty and resources have to be downloaded from the server through the network. Depending on the network and device being used, there is a period of time where the user has to wait until something is displayed on screen. On high-latency mobile networks like 3G, that period can go up to dozens of seconds if no optimizations are in place.\n\nThe amount of time the user has to wait is critical. The user's attention span decreases as the waiting time increases, ultimately forcing the user to leave after a certain threshold 2 . This has a huge impact on a business. Studies show that the conversion rates are much higher on web apps that load faster when compared to their slower counterparts, concluding that 1 extra second of page loading can be worth millions in lost revenue! 3 In order to avoid this scenario, the load time must be optimized. Looking at a simplified way of how the browser handles the initial page load, some prioritization can be put in place to optimize the critical render path. This helps deliver meaningful content as fast as possible creating the perception that the page is loaded, even if the loading is still ongoing.\n\nA simplified way of how the browser handles the initial page load It becomes obvious that we need to remove JavaScript and CSS files from the critical render path by making them non-render-blocking. These resources are still downloaded concurrently but only loaded after the first render finishes. It's important to remember that our goal is to deliver content as fast as possible so we don't rely on JavaScript to fetch and display the content. Server-side rendering must be used to ensure content is displayed at the first render.\n\nSome optimizations that can be used to improve the perceived load time of Progressive Web Apps are:\n\nImprove HTML download time\nReduce HTML size (probably not much to reduce)\nReduce TTFB4 as much as possible: Use CDN / caching for static pages and improve server page rendering performance\nImprove other resources download times. For example JS, CSS and so on..\nReduce JS and CSS size by splitting code into separate bundles eg: homepage.js and homepage.css, about_us.js and about_us.css\nServe these resources fast, ideally using a CDN / caching\nUse HTTP2 push to send those files reducing overall RTT5\nImprove time for render-blocking resources to load\nLoad CSS files after first render (using JavaScript)\nInline styles above the fold (otherwise page will be unstyled)\nUse defer or async on script tags tag in your html and is not available to be installed as a dependency via npm or yarn. By including this script, the Spreedly object will become available to use and access on the window.\n\n
\n \n \n\nhtmlCopy to clipboard\n\nNext, we must set up a series of event listeners. Spreedly's library emits events we can listen for and react to such as ready, errors, validate, etc. This gives us a way to tie in our own application logic to these events.\n\nwindow.Spreedly.on('errors', console.error);\n\nwindow.Spreedly.on('validate', validateForm);\n\nwindow.Spreedly.on('ready', () => {\n // Because the elements Spreedly targets in our application/form are just unstyled divs,\n // we must format them through their UI API.\n window.Spreedly.setFieldType('number', 'text');\n window.Spreedly.setNumberFormat('prettyFormat');\n window.Spreedly.setPlaceholder('number', '···· ···· ···· 1234');\n window.Spreedly.setPlaceholder('cvv', '000');\n\n // spreedlyFormStyles is an array of our custom styles to apply to the Spreedly-managed\n // fields that must be applied via `window.Spreedly.setStyle(field, style)`\n spreedlyFormStyles.forEach(([field, style]) =>\n window.Spreedly.setStyle(field, style)\n );\n});\njavascriptCopy to clipboard\n\nFinally, we can initialize the library by calling window.Spreedly.init from the Lifecycle API. We pass init our Spreedly environment key and an object with key values that include the element IDs of the unstyled divs, which the library should manage and transform into form inputs for us. Another important thing to note is that the init function will emit the ready event once it has bootstrapped our controlled form elements.\n\nwindow.Spreedly.init('super-secret-spreedly-environment-key', {\n numberEl: 'spreedly-cc-number',\n cvvEl: 'spreedly-cvv',\n});\njavascriptCopy to clipboard\n\nFrom this point on we should be good to go and able to take full advantage of the remaining features and APIs provided by Spreedly such as tokenization and recaching.\n\nThe Missing console.log\n\nNow that we have a base understanding of how the Spreedly library works, the available APIs, and how we can interact with it, let's jump into debugging this. What do we know so far that might give us a good starting point? We know that when we call init on the Spreedly client it uses the string element IDs of our credit card number and CVV divs to somehow start controlling and managing them for us. We also know that once the initialization process is complete that it will emit the ready event. With these two things in mind, my initial instinct was that something was failing during the call to init or that we were failing to properly register our event handlers.\n\nMy strategy for testing this hypothesis would rely on one of the most timeless debugging tools in our toolbox; console.log. I would be placing a series of log statements in our application and then examining the order and output of both when our application was running normally and also when it was running in Cypress. I chose to add log statements in the following places: one when we register our event handlers, one when we call init, and one when we receive the ready event.\n\nconsole.log('adding event handlers');\n\nwindow.Spreedly.on('errors', console.error);\n\nwindow.Spreedly.on('validate', validateForm);\n\nwindow.Spreedly.on('ready', () => {\n // Spreedly styling API code excluded for brevity\n console.log('ready');\n});\njavascriptCopy to clipboard\nconsole.log('initializing');\n\nwindow.Spreedly.init('super-secret-spreedly-environment-key', {\n numberEl: 'spreedly-cc-number',\n cvvEl: 'spreedly-cvv',\n});\njavascriptCopy to clipboard\n\nLet's examine the output in the console from both contexts.\n\nRunning Normally\nadding event handlers\ninitializing\nready\n>\n\nCypress\nadding event handlers\ninitializing\n>\n\n\nThis confirmed my suspicion that something was going awry during the initialization process and I decided to double check the Spreedly docs for anything that may be helpful. I ended up finding the reload function as part of the Lifecycle API. Calling this would reinitialize the form and would also emit the ready event. I wanted to call this from the console in Developer Tools after the application had loaded and see what happened.\n\nBecause our application runs in an iframe, I didn't initially have access to the Spreedly client so I quickly added this line of code for testing purposes:\n\nwindow.parent.Spreedly = window.Spreedly;\njavascriptCopy to clipboard\n\nLet's see what happens when we call reload.\n\nRunning Normally\n> window.Spreedly.reload()\nadding event handlers\nready\n\nCypress\n> window.Spreedly.reload()\nadding event handlers\n\n\nAt this point I was feeling confident that the bug was not in our own application code. This would require taking a closer look at what Spreedly is doing under the cover of its init function and trying to resolve why it wasn't firing the ready event.\n\nDown The Rabbit Hole\n\nTo continue troubleshooting this bug, it would require jumping into Spreedly's third party script(s), which are being served to us minified. To do this, we need to open our browser's Developer Tools and head over to the Sources tab. From there, we just need to look under the Page pane. Here we'll find a tree showing us a hierarchy of windows and the sources that they load. You can see the various iframes in this view as denoted in the tree by the window icon and the names top, localhost/, spreedly-cvv-frame-7206 (cvv-frame.html), and spreedly-number-frame-7206 (number-frame.html). These are a one-to-one mapping of the iframe boundaries we looked at previously.\n\nLet's open iframe-v1.min.js and see what we've got.\n\nAt first glance this looks pretty intimidating and like it would be a nightmare to attempt to read through and parse. Fortunately for us, Developer Tools gives us a way to \"Pretty Print\" and format this minified code by clicking the {} in the bottom left-hand corner.\n\nNow that we have some formatted code to work with we can start searching for the init function in the file. After jumping through a few instances of search results we hit the following block of code with the function definition:\n\n(this.init = function (t, e) {\n this.isLoaded() && this.unload(),\n e && e.source && (this.source = e.source),\n e && e.numberEl\n ? (this.numberTarget = e.numberEl)\n : (this.numberTarget = m('data-number-id')),\n e && e.cvvEl\n ? (this.cvvTarget = e.cvvEl)\n : (this.cvvTarget = m('data-cvv-id')),\n (this.environmentKey = t || m('data-environment-key')),\n (this.numberFrameId = 'spreedly-number-frame-' + this.uniqueId),\n (this.cvvFrameId = 'spreedly-cvv-frame-' + this.uniqueId),\n this.addIframeElements();\n}),\njavascriptCopy to clipboard\n\nThe init function is taking our input (the environment key and object containing the element ids for both fields), doing some validation, adding those values to its own state, and then calling this.addIframeElements.\n\n(this.addIframeElements = function () {\n var t = a(p);\n (t.id = this.numberFrameId),\n (t.name = this.numberFrameId),\n t.setAttribute('src', b(g, w(this.source))),\n document.getElementById(this.numberTarget).appendChild(t);\n var e = a(d);\n (e.id = this.cvvFrameId),\n (e.name = this.cvvFrameId),\n e.setAttribute('src', b(v, w(this.source))),\n document.getElementById(this.cvvTarget).appendChild(e);\n}),\njavascriptCopy to clipboard\n\nThis function is creating the
http\n .createServer(function (req, res) {\n setTimeout(function () {\n res.end(\"hello world\");\n }, 200);\n })\n .listen(3000);\ntextCopy to clipboard\n\nWe run the program in a terminal:\n\nnode http.js\ntextCopy to clipboard\n\nAnd hit it with autocannon:\n\nautocannon https://localhost:3000\ntextCopy to clipboard\n\nWhen the autocannon run completes, you will see several statistics about latencies and request rate.\n\nThe primary number we’re interested in is the 99% percentile of latency, as it represents the latency of most of the requests:\n\nRunning 10s test @ https://localhost:3000\n10 connections
\n┌─────────┬────────┐\n│ Stat │ 99% │\n├─────────┼────────┤\n│ Latency │ 218 ms │\n└─────────┴────────┘\ntextCopy to clipboard\n\nAs long as our latency is around the 200ms mark, we’re looking good because that’s what we expect from our server.\n\n[caption id=\"attachment_300014660\" align=\"alignnone\" width=\"600\"]\n\nFigure 1: Load testing with autocannon[/caption]\n\nAn increase in latency would mean that the program is struggling to keep up with the number of requests it’s receiving.\n\nLet’s see if we can put pressure on the application by increasing the load produced by autocannon:\n\nautocannon https://localhost:3000 -p 100 -c 1000
Running 10s test @ https://localhost:3000\n1000 connections with 100 pipelining factor
┌─────────┬────────┐\n│ Stat │ 99% │\n├─────────┼────────┤\n│ Latency │ 741 ms │\n└─────────┴────────┘\ntextCopy to clipboard\n\nBy hitting the server with 1,000 concurrent connections and telling each connection to send 100 requests before waiting for a response, we’ve been able to make the latency jump significantly. Requests that should complete in roughly 200ms are now taking more than 700ms.\n\n[caption id=\"attachment_300014661\" align=\"alignnone\" width=\"600\"]\n\nFigure 2. Increasing load on the application[/caption]\n\nOur Node.js server is now taking on more work than it can handle.\n\nConsequences of pressure\n\nWhen this happens, we can clearly see a deterioration in the performance of the server. How can we deal with it?\n\nNode.js has no built-in mechanism to avoid load, meaning that it will happily accept any number of requests and it will allow them to queue up and wait for their turn to be processed.\n\nThe real question is, do we want to allow this? If our purpose is to keep our system responsive we should probably find better ways to handle increasing workloads, perhaps by scaling our application.\n\nWithout going into the realm of infrastructure concerns yet, and keeping things at the application level, it is likely that when response times exceed a certain threshold, it means that our server shouldn’t keep queuing up requests because it may never be able to handle them in time for the client to process the responses.\n\nIn fact, by the time our server responds, clients may have already timed out, meaning that the server has done unnecessary work at a time when its processing power was most needed.\n\nCauses of slowdown\n\nIn our earlier example, there were no application-related reasons for the slowdown; the server was simply receiving too much load, and the resources on the machine where it was running could not handle it.\n\nIn other circumstances, the high mark for the amount of load the server can handle is more likely influenced by real operations the application is performing. Common causes of slowdowns are:\n\nCPU-intensive work blocking the main thread, such as cryptographic operations or parsing/serialising JSON data structures.\nInteracting with resource-constrained external services such as Databases or APIs.\nDetecting excess pressure\n\nThe first thing to do is identify the metric to use to detect that the application is receiving too much load. Depending on the scenario, we could use:\n\nResponse times, based on how long we would normally expect our server to take to respond to requests and how long we want to make our users wait for a response\nError rates, meaning that errors are happening in the system, possibly due to external services not responding in a timely manner and thereby causing requests to queue up in our server\nApplication-level metrics — for example, the length of an in-application queue we use to perform tasks with a certain level of concurrency\n\nTo keep it simple and practical, let’s consider response times as the primary metric we will use to determine that we’re under pressure.\n\nCollecting metrics\n\nNow that we’ve determined that response times will be our reference metric to detect load, let’s see how we can collect this information.\n\nWe’ll use the Prometheus client for Node.js, available via the prom-client package. Furthermore, we’ll also start using a real web framework to simulate a more realistic application. Fastify is our framework of choice at NearForm.\n\nWe won’t go into the details of how to set up a Fastify application here, you can read the Fastify Getting Started guide to set up one, or you can use the example code provided.\n\nconst prometheus = require('prom-client')\nconst endTimer = Symbol('endTimer')
const metric = new prometheus.Summary({\n name: 'http_request_duration_seconds',\n help: 'request duration summary in seconds',\n maxAgeSeconds: 60,\n ageBuckets: 5\n})
fastify.addHook('onRequest', async (req) => {\n req[endTimer] = metric.startTimer()\n})
fastify.addHook('onResponse', async (req) => {\n req[endTimer] && req[endTimer]()\n})
fastify.get('/metrics', (_, reply) => {\n reply.send(prometheus.register.metrics())\n})
fastify.get('/slow', (_, reply) => {\n setTimeout(() => reply.send('hello world'), 200)\n})\ntextCopy to clipboard\n\nIn the above example:\n\nWe instantiated a Prometheus Summary metric, which allows us to collect interesting statistics about request duration, specifically percentiles.\nThe metric is used in Fastify’s request and response hooks to track request duration.\nWe registered a /metrics endpoint that we can use to look at the metric itself in the Prometheus format.\nWe reimplemented the earlier endpoint responding after approximately 200ms.\n\nIf we hit the application again with autocannon we can see the metrics exposed by the /metrics endpoint reflecting the response durations.\n\n# HELP http_request_duration_seconds request duration summary in seconds\n# TYPE http_request_duration_seconds summary\nhttp_request_duration_seconds{quantile=\"0.01\"} 0.0006875\nhttp_request_duration_seconds{quantile=\"0.05\"} 0.0006879672875\nhttp_request_duration_seconds{quantile=\"0.5\"} 0.0010178125\nhttp_request_duration_seconds{quantile=\"0.9\"} 0.06336875068888909\nhttp_request_duration_seconds{quantile=\"0.95\"} 0.19818964862222216\nhttp_request_duration_seconds{quantile=\"0.99\"} 0.214746601\nhttp_request_duration_seconds{quantile=\"0.999\"} 0.214746601\nhttp_request_duration_seconds_sum 0.228651799\nhttp_request_duration_seconds_count 14\ntextCopy to clipboard\n\nThe metric is collecting and summarising all our data — awesome!\n\nEven though we’re using a single custom metric to collect response times of our slow endpoint, there are more comprehensive ways to collect and expose Prometheus metrics in a Fastify application. In a real application we would use something like fastify-metrics , which also uses the same Prometheus client, but we’re keeping it simple here for demonstration purposes and to avoid adding unnecessary noise to the example.\n\nDealing with pressure\n\nNow that we know request durations, we can decide what to do with them. To prevent our server from entering a situation whereby requests take longer and longer to process, we can put in place a circuit-breaking mechanism which causes the application to stop accepting requests when that happens. When the circuit opens, the server responds with an error status code, communicating back to the client that it cannot handle the request.\n\nThere are several ways we can do that, but for the sake of this article we will use under-pressure , an open source implementation of a circuit breaker for Fastify.\n\nAfter installing it, we can then extend our earlier example by adding the snippet of code below:\n\nfastify.register(require('under-pressure'), {\n healthCheck() {\n const three9percentile = metric.get().values[6].value
// four times the expected duration\n return three9percentile <= (200 * 4) / 1e3\n },\n healthCheckInterval: 5000,\n})\ntextCopy to clipboard\n\nunder-pressure can be configured in different ways. In this case, we are using a custom health check, which reads the .999th percentile of our metric at intervals of 5 seconds and reports the status as unhealthy when its value exceeds the expected request duration by a factor of 4. When that happens, under-pressure stops accepting requests and returns a 503 Service Unavailable error back to the client.\n\nTo try this, run autocannon with high enough values of concurrency and pipelining so that the slow endpoint takes longer than 800ms to respond. You can check how long the endpoint is taking by hitting the /metrics endpoint in a browser.\n\nAt that point, you will see the application returning errors as soon as it receives a request.\n\nClosing the circuit\n\nOnce the circuit opens, it must be possible to close it again, otherwise the application will not be able to recover.\n\nWhen we configured the Prometheus Summary metric, we provided a couple of options that enable this behaviour:\n\nconst metric = new prometheus.Summary({\n name: 'http_request_duration_seconds',\n help: 'request duration summary in seconds',\n maxAgeSeconds: 60,\n ageBuckets: 5,\n})\ntextCopy to clipboard\n\nmaxAgeSeconds and ageBuckets are the configuration options that allow the Prometheus client to use a sliding window, so that it only collects recent metrics data and it forgets about old data. Read more about this in the prom-client docs.\n\nThis also enables the application to recover after the circuit has opened. Because the application is not accepting any more requests, the metric wouldn’t have a chance to change and the under-pressure health check would keep reporting the app as unresponsive.\n\nWhen the autocannon run that caused the circuit to open completes, the application will recover automatically after a while.\n\nAt the infrastructure level, this will allow us to detect that an instance of the application is unable to handle additional load and to exclude it from the load balancer, while dynamically scaling the number of running instances to handle the increasing load. We will focus on this in a later article.\n\nLimiting the area of effect of the circuit-breaker\n\nWhen the app stops responding because under-pressure has opened the circuit, the /metrics endpoint also starts returning 503 errors. This is clearly not what we want — only the slow endpoint should be affected by the circuit-breaker.\n\nAchieving this in Fastify is simple enough, thanks to plugin scopes. Instead of registering the slow endpoint and under-pressure in the main application, we move their registration to a plugin. This will create a new scope and cause under-pressure to apply only to the routes that are registered in that plugin instead of the whole application. You can read more about Fastify plugin scopes in the official documentation .\n\nCreating a safety net\n\nIn this article we’ve looked at a simple approach to detect when a Node.js application is under load and implemented a circuit-breaking mechanism. This preserves the health of the application and minimises the impact that a slowdown will have on the system.\n\nWe took a somewhat binary approach by rejecting requests as soon as we detected that the application was taking too long to respond. Though seemingly extreme, this approach provides the foundations for a more thorough and reliable scaling mechanism and serves as a safety net until our infrastructure can detect that we’re under load and take appropriate action." ], "categories": { "primary": "backend", "others": [ "devops", "perf" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-stores-no-context-api": { "href": "https://nearform.com/digital-community/stores-no-context-api", "postType": "blog", "slug": "digital-community-stores-no-context-api", "date": "2021-02-23", "title": "Stores: Making State Global Without React's Context API", "authors": [ "MAX YINGER" ], "content": [ "tldr; If you just wanna see how to implement a store, check out the demo here. If you plan on utilizing them in your React app, check out zustand.\n\nI often come across application code catering to the needs of React's Context API to make state globally accessible throughout an application. However, just because something is provided to us by the React team doesn't mean it is immune to having use cases it's built for and others for which it is not.\n\nLately, you may have noticed a second generation of Store-like libraries for React that are deceivingly simple and take inspiration from older approaches, similar to what MobX and unstated did for React in the past. Among these libraries are zustand and valtio, which promise to bring reactive state encapsulation to React, just like it's seen in Svelte or Vue 3.\n\nIn this article we're going to explore some drawbacks of context-based state in typical application architecture, then explore an alternative construct, Stores, which should ultimately help us write cleaner code and increase our in-app performance. First, though, let's dive into how I typically see React's Context API used in application code.\n\nThis Old Song and Dance?\n\nSo we have a component that needs to get and alter some data in our application. Great, let's use a useState hook to hold and access state:\n\nconst Foo = () => {\n const [count, setCount] = React.useState(0);\n return (\n <>\n
\n
\n
\n};\n\nconst Buz = () => (\n
\n};\n\nconst App = () => (\n
\n)\njsxCopy to clipboard\n\nTo fix the code above, we need to force renders from our generated hook, such that a render occurs when the global store gets updated. Let's use an emitter for our notification system, create a cloned, local version of the global store in state, and reflect any changes to the global store in our local instances of it.\n\nconst createEmitter = () => {\n const subscriptions = new Map();\n return {\n emit: (v) => subscriptions.forEach(fn => fn(v)),\n subscribe: (fn) => {\n const key = Symbol();\n subscriptions.set(key, fn);\n return () => subscriptions.delete(key);\n },\n }\n};\n\nconst createStore = (init) => {\n // create an emitter\n const emitter = createEmitter();\n\n let store = null;\n const get = () => store;\n const set = (op) => (\n store = op(store),\n // notify all subscriptions when the store updates\n emitter.emit(store)\n );\n store = init(get, set);\n\n const useStore = () => {\n // intitialize component with latest store\n const [localStore, setLocalStore] = useState(get());\n\n // update our local store when the global\n // store updates. \n //\n // emitter.subscribe returns a cleanup \n // function, so react will clean this\n // up on unmount.\n useEffect(() => emitter.subscribe(setLocalStore), []);\n return localStore;\n };\n return useStore;\n};\njsxCopy to clipboard\n\nLet's walk through those three major additions real quick to grasp exactly what we just did. First is updating our set method to perform emissions here:\n\nconst set = (op) => (\n store = op(store),\n // notify all subscriptions when the store updates\n emitter.emit(store)\n);\njsxCopy to clipboard\n\nThis essentially makes our set method act like a dispatch call. It allows all subscriptions to be notified whenever a change has occurred.\n\nNext we create our local clone of the store here:\n\n// intitialize component with latest store\nconst [localStore, setLocalStore] = useState(get());\njsxCopy to clipboard\n\nCopying our store into state provides us with an update mechanism. This allows us to notify our consuming components to re-render when the localStore updates.\n\nLastly, we have to reflect changes to the global store in our local store:\n\n// update our local store when the global\n// store updates. \n//\n// emitter.subscribe returns a cleanup \n// function, so React will clean this\n// up on unmount.\nuseEffect(() => emitter.subscribe(setLocalStore), []);\njsxCopy to clipboard\n\nThis effect runs once on the initial mount and basically taps our local store into the global store. Any changes that occur in the global store, through its set method, will now notify all consumers of this hook to to update their local store and reflect the changes.\n\nOh Hot Damn. Did We Just Create Global State Without Context?\n\nWhy yes. Yes we did.\n\nconst useCountStore = createStore((get, set) => {\n count: 0,\n increment: () => set(store => ({ ...store, count: store.count + 1 })),\n decrement: () => set(store => ({ ...store, count: store.count - 1 }))\n});\n\nconst Increment = () => {\n const { increment } = useCountStore();\n return
\n};\n\nconst App = () => (\n
\n)\njsxCopy to clipboard\n\nBeautiful! Brings a tear to my eye 😿. Now let's go through some of the benefits of our shiny new tool.\n\nThe Fruits of Our Labor 🍑\n\nIn creating a solution that only tries to do what we need, and nothing more, we're gonna see some noticeable improvements in the following areas:\n\nCo-Location\n\nFirst off, Hooks were built with co-location in mind. Keeping related code closer together. With a store, if we decide we need some state to persist globally, it's easy to add it right then and there with its associated logic. No more navigating to a file containing markup to make state globally accessible.\n\nUntied from Markup\n\nSince we're no longer tied to our markup, we can connect multiple parts of the app (components) without deciding on an arbitrary grouping. Sure, we can distribute this via Context, but as zustand and others show (like MobX did before), we don't need a Context parent to connect state in our application from A to B. We don't need to necessarily decide where to hoist state to if we can teleport it from site to site.\n\nWith stores, state is truly shareable with any component. The state is there, scoped to a module and waiting to be accessed at your component's leisure. Since it is instantiated when you are creating the hook to access it, you no longer have to consider behavior where your global state is inaccessible because of the markup you render.\n\nAvoiding Needless Renders\n\nThis is honestly my biggest reason for advocating the necessity of stores in a codebase: I know a lot of us are able to create applications with perfectly fine performance metrics using Context, but the web is advancing, and demands are growing.\n\nAs we evolve into the future, stakeholders are going to start asking for more motion-rich user experiences. Entrance and exit animations for components as we switch routes or as parts of our state update.\n\nIf you have a large-scale application using context-based state, chances are that most top-level context updates cause React's reconciliation to eat up the 100ms budget you have before there's a noticeable lag to the human eye. With this in mind, even low-cost animated transitions would shine a light on noticeable jank pre-existing in your application.\n\nWith stores, as global state updates occur, only nodes subscribed to that store and their children actually get diffed by React. This allows React to remain performant and interactive as we keep global state subscriptions closer to the leaf elements of our applications.\n\nImplementation-Agnostic\n\nStores are unopinionated on how you manage your state. They simply don't care how you do what you do. This isn't really an improvement from Context (since it also doesn't care how you manage your state), but it is still worth mentioning.\n\nHere's a quick example with a reducer for reference:\n\nconst initial = 0;\n\nconst reduce = (state, action) => {\n\tswitch (action.type) {\n\t\tcase 'increment':\n\t\t\treturn state + 1;\n\t\tcase 'decrement':\n\t\t\treturn state - 1;\n\t\tdefault:\n\t\t\treturn state;\n\t}\n}\n\nconst useStore = createStore(\n\t(get, set) => ([\n\t\tstate: initial,\n\t\tdispatch: (action) => set(store => ([\n\t\t\treduce(store.state, action),\n\t\t\tstore.dispatch\n\t\t])),\n\t])\n);\n\nconst Counter = () => {\n const [state, dispatch] = useStore();\n return (\n\t\t<>\n\t\t\t
\n\t\t\t
const metric = new prometheus.Summary({\n name: 'http_request_duration_seconds',\n help: 'request duration summary in seconds',\n maxAgeSeconds: 60,\n ageBuckets: 5,\n})
metric.get999Percentile = () => {\n return metric.get().values[6].value\n}
module.exports = metric\ntextCopy to clipboard\n\nThen, in the root of our application we create the two endpoints that will be used by Kubernetes probes:\n\nfastify.get('/liveness', async () => {\n return 'OK'\n})
fastify.get('/readiness', async () => {\n if (slow.canAcceptMoreRequests()) {\n return 'OK'\n }
throw new TooManyRequests('Unable to accept new requests')\n})\ntextCopy to clipboard\n\nThe readiness probe is configured to respond with an error before the circuit opens, so we are relying on the infrastructure to stop serving requests when the probe delivers such a response.\n\nThe circuit breaker is a safety net in case the infrastructure doesn’t respond quickly enough.\n\nThe liveness probe is simpler because it will always return a successful response. Our example has no errors from which the application cannot recover. A more realistic implementation of the liveness probe would take into account additional factors, such as a database connection that cannot be established, which would cause the application to be permanently unhealthy. In that case, the liveness endpoint should return an error.\n\nDeploying the application to Kubernetes\n\nThe first thing we need to do to run our application in the Kubernetes cluster is create an image of the application using Docker:\n\ndocker build -t backpressure-example .\ntextCopy to clipboard\n\nThen we install all the Helm charts needed in our example, which includes the application and other services, which we’ll look at later.\n\nhelm install backpressure-example helm/\ntextCopy to clipboard\n\nFinally, we can check the local port on which the application is running by executing:\n\nkubectl get service backpressure-example\ntextCopy to clipboard\n\nThe command above gives an output similar to:\n\nNAME TYPE CLUSTER-IP EXTERNAL-IP \nPORT(S) AGE\nbackpressure-example NodePort 10.103.50.71 \n80:31470/TCP 22h\ntextCopy to clipboard\n\nWe can now access the application at https://localhost:31470 (the port will most likely be different on your machine).\n\nTriggering the readiness probe\n\nThe configuration for the Kubernetes deployment can be found in the source code repository accompanying this article. The relevant section of the configuration file is:\n\nlivenessProbe:\n httpGet:\n path: /liveness\n port: web\n initialDelaySeconds: 3\n periodSeconds: 3\nreadinessProbe:\n httpGet:\n path: /readiness\n port: web\n initialDelaySeconds: 3\n periodSeconds: 3\ntextCopy to clipboard\n\nThis configures the liveness and the readiness probes. We’re now going to trigger the readiness probe by putting the application under load via autocannon as we’ve done in the first part of this article.\n\nIf you haven’t used autocannon before, you can install it via npm:\n\nnpm install -g autocannon\ntextCopy to clipboard\n\nBefore hitting the application, let’s keep an eye on the status of the Kubernetes deployment so we can check when the single Pod we currently have turns from ready to non-ready due to the readiness probe:\n\nkubectl get deployment backpressure-example-deployment -w\ntextCopy to clipboard\n\nThis will show an output similar to:\n\nNAME READY UP-TO-DATE AVAILABLE AGE\nbackpressure-example-deployment 1/1 1 1 22h\ntextCopy to clipboard\n\nThe above output means that there is 1 Pod ready out of a total of 1 Pods, which is what we expect because only one is deployed.\n\nIn another terminal window, we can now run autocannon in the usual way, making sure to use the HTTP port the service is bound to on our host machine:\n\nautocannon https://localhost:31470/slow -c 20 -p 20\ntextCopy to clipboard\n\nTo make the /readiness endpoint return an error status code, we need to put enough load on the application to make the .999th percentile of the requests last at least 400ms, which is the threshold we configured.\n\nYou can check how long requests are taking by hitting the /metrics endpoint in your browser and by changing the autocannon options accordingly.\n\nWhen the threshold is reached, Kubernetes will detect that the application is reporting that it’s not ready to receive more requests and will remove the Pod from the load balancer. The output of the earlier kubectl get deployment command will show something like this:\n\nNAME READY UP-TO-DATE AVAILABLE AGE\nbackpressure-example-deployment 1/1 1 1 22h\nbackpressure-example-deployment 0/1 1 0 22h\ntextCopy to clipboard\n\nWhen the autocannon run completes, the application will reflect the shorter response times in the metrics values, which will cause Kubernetes to detect a successful readiness probe and put the Pod back into the load balancer:\n\nNAME READY UP-TO-DATE AVAILABLE AGE\nbackpressure-example-deployment 1/1 1 1 22h\nbackpressure-example-deployment 0/1 1 0 22h\nbackpressure-example-deployment 1/1 1 1 22h\ntextCopy to clipboard\n\nUp to this point we’ve achieved the ability to stop overloading the application by means of an internal circuit breaker and via Kubernetes’ readiness probe. The next step is to automatically scale the application based on load.\n\nExposing custom metrics\n\nTo allow Kubernetes to scale our application, we will need to expose custom metrics that can be used by Kubernetes’ Horizontal Pod Autoscaler (HPA).\n\nBy default, the autoscaler can use a range of metrics built into Kubernetes, and we could use those metrics for autoscaling. In our example, we want to use a custom metric. Therefore, we need to make sure we expose that metric to Kubernetes and make it available to the autoscaler.\n\nWe achieve that by using Prometheus Adapter , which is already running inside our Helm deployment.\n\nThe relevant section of the configuration is:\n\nrules:\n default: false\n custom:\n - seriesQuery: 'http_request_duration_seconds'\n resources:\n overrides:\n kubernetes_pod_name: { resource: 'pod' }\n kubernetes_namespace: { resource: 'namespace' }\n metricsQuery: sum(http_request_duration_seconds{quantile=\"0.999\", \nkubernetes_pod_name =~\"backpressure-example-deployment.*\"}) by (kubernetes_pod_name)\ntextCopy to clipboard\n\nWith this configuration we can then query the metric:\n\nkubectl get --raw\n \"/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/http_request_duration_seconds\" | jq .\ntextCopy to clipboard\n\nThis will provide an output similar to:\n\n{ \n \"kind\": \"MetricValueList\", \n \"apiVersion\": \"custom.metrics.k8s.io/v1beta1\", \n \"metadata\": { \n \"selfLink\": \"/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/%2A/http_request_duration_seconds\"\n }, \n \"items\": [ \n { \n \"describedObject\": { \n \"kind\": \"Pod\", \n \"namespace\": \"default\", \n \"name\": \"backpressure-example-deployment-ff555459f-5g5x7\", \n \"apiVersion\": \"/v1\" \n }, \n \"metricName\": \"http_request_duration_seconds\", \n \"timestamp\": \"2021-01-05T13:31:14Z\", \n \"value\": \"0\", \n \"selector\": null \n } \n ] \n}\ntextCopy to clipboard\n\nThe output above shows a value of 0 for the http_request_duration_seconds , which is the name of the metric we expose and which maps to the .999th percentile reported by our custom metric.\n\nIf you try hitting the /slow endpoint manually or with autocannon, you will see the value of the metric reflect the value reported by the /metrics endpoint. The values will not be in sync because there is a certain delay in the update of the Kubernetes metric due to polling and propagation of the metric from the application to Prometheus and then from Prometheus to Kubernetes.\n\nAutoscaling\n\nThe last step in getting our infrastructure to handle the increasing load on the application properly is to enable automatic scaling via Kubernetes’ Horizontal Pod Autoscaler .\n\nThis requires a simple change in our Helm chart, which deploys a resource of type HorizontalPodAutoscaler . We will include an additional chart in our Helm deployment. This is available in the branch part-2-hpa .\n\ngit checkout part-2-hpa\ntextCopy to clipboard\n\nThe autoscaler will need metrics upon which to carry out the auto scaling logic. In our case, it will be our custom metric:\n\napiVersion: autoscaling/v2beta1\nkind: HorizontalPodAutoscaler\nmetadata:\n name: test\n namespace: default\nspec:\n scaleTargetRef:\n apiVersion: apps/v1\n kind: Deployment\n name: backpressure-example-deployment\n minReplicas: 1\n maxReplicas: 4\n metrics:\n - type: Pods\n pods:\n metricName: 'http_request_duration_seconds'\n targetAverageValue: 300m\ntextCopy to clipboard\n\nWe have configured a minimum of 1 and a maximum of 4 replicas for the Pods running our application and a target value of 300ms for the custom metric exposed to Kubernetes via the Prometheus Adapter.\n\nWe can test the behaviour of the autoscaler by upgrading our deployment with:\n\nhelm upgrade backpressure-example helm/\ntextCopy to clipboard\n\nWe can now run autocannon against the application and, by watching the value of the /metrics endpoint, increase the load so that the response times go above 300ms.\n\nautocannon https://localhost:31470/slow -c 20 -p 20\ntextCopy to clipboard\n\nIf we keep an eye on the deployment...\n\nkubectl describe deployment backpressure-example-deployment -w\ntextCopy to clipboard\n\n...we will see that when the metric value exceeds the threshold, the autoscaler will increase the number of Pods:\n\nNAME READY UP-TO-DATE AVAILABLE AGE\nbackpressure-example-deployment 1/2 2 1 26h\nbackpressure-example-deployment 2/2 2 2 26h\ntextCopy to clipboard\n\nTo confirm this, we can look at the output of:\n\nkubectl describe hpa\ntextCopy to clipboard\n\nThis will tell us the reason why the autoscaler increased the number of replicas:\n\nConditions:\n Type Status Reason Message\n ---- ------ ------ -------\n AbleToScale True SucceededRescale the HPA controller was able to update the target scale to 2\n ScalingActive True ValidMetricFound the HPA was able to successfully calculate a replica count from pods metric http_request_duration_seconds\n ScalingLimited False DesiredWithinRange the desired count is within the acceptable range\nEvents:\n Type Reason Age From Message\n ---- ------ ---- ---- -------\n Normal SuccessfulRescale 55s horizontal-pod-autoscaler New size: 2; reason: pods metric http_request_duration_seconds above target\ntextCopy to clipboard\nPutting it all together\n\nHere is a summary of how our application will behave using the circuit breaker, the readiness probe and the autoscaler:\n\nWhen the average value across Pods of the .999th percentile of the response time is above 300ms, the autoscaler will increase the replicas up to a maximum of 4.\nWhen the .999th percentile of the response times of each single Pod is above 400ms, the Pod will fail the readiness probe and will be taken out of the load balancer by Kubernetes. It will be added back to the load balancer when the response times decrease below the threshold.\nWhen the .999th percentile of the response times of each single Pod is above 800ms, the application’s circuit breaker will open as a safety mechanism, and the application will reject further requests until the circuit is closed. This happens when the response times fall below the threshold and is handled by under-pressure.\n\nThough seemingly arbitrary, the threshold values are chosen so that:\n\nThe autoscaler kicks in first (300ms threshold).\nIf for any reason a Pod keeps receiving more requests than it can handle, it will fail the readiness probe, causing Kubernetes to stop serving it requests (400ms) in order to preserve the responsiveness of the Pod for the outstanding requests.\nIf for any reason a Pod keeps being served requests despite failing the readiness probe, it will trigger the circuit breaker which will cause further requests to be rejected (800ms).\n\nIn this pair of articles, we’ve outlined how to create a complex mechanism capable of preserving the performance and health of a Node.js Fastify application deployed to Kubernetes.\n\nThe mechanism consisted of an in-application circuit breaker implemented via under-pressure, a readiness probe handled by Kubernetes and an autoscaling algorithm handled by Kubernetes HPA.\n\nWe used a custom metric calculated and exposed via Prometheus to define whether the application was healthy and responsive.\n\nThis allowed us to scale our application automatically when the response times increased, preserve the performance of the application by temporarily excluding it from the load balancer when response times were higher than normal and stop responding to requests when doing so would compromise the health of the application." ], "categories": { "primary": "backend", "others": [ "cloud", "devops", "perf" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-the-year-we-all-went-remote": { "href": "https://nearform.com/insights/the-year-we-all-went-remote", "postType": "blog", "slug": "insights-the-year-we-all-went-remote", "date": "2021-03-02", "title": "How you worked before the pandemic could determine how successful your remote working experience has been since.", "authors": [], "content": [ "How you worked before the pandemic could determine how successful your remote working experience has been since.\n\nYou are sitting at your desk in a shirt and pyjama bottoms, and it doesn’t seem strange anymore. You are well acquainted with your colleagues’ children, pets and bookshelves, even though you have had no physical contact with them for a full year. This has been the world of work for many people since the Covid-19 pandemic sent most of us home in March 2020. So, how has it been for you?\n\nThe answer probably depends on the way you worked before the pandemic.\n\nOffice mindset vs. remote working\n\nCompanies that had remote work policies before last March were feeling a little smug when the pandemic struck. Their employees were equipped with the devices, technologies and processes to ensure a smooth transition to fully remote working. But more importantly, they had the right mindset to work productively.\n\nSuccessful remote-first working is all about building a team whose members can work together while physically apart. At NearForm, remote-first has long been our approach. With 90% of our employees working remotely before the pandemic, we are able to serve clients irrespective of their location by fostering a team culture based on trust, collaboration, communication and support. This ensures an optimum environment for productivity, creativity and focus.\n\nOther companies have not had such happy experiences with remote working. Netflix co-founder and co-CEO Reed Hastings voiced his opposition to working remotely in a Wall Street Journal interview , saying that he can’t see any positive aspects in it and that not being able to meet in person is completely negative. CEO Marissa Mayer famously ended Yahoo!’s remote-working experiment back in 2013, claiming that speed and quality were often sacrificed when employees worked from home.\n\nMany company leaders who are reluctant to continue with remote working beyond the pandemic believe that employees need to be present in the office to facilitate productive interactions and experiences.\n\nThe issues that proved problematic\n\nNobody would claim the global experiment in remote working has been a total success.\n\nDepending on the tasks they are required to complete, some workers simply do not have the option of working remotely. Caregiving, machine operation and food serving are just some of the activities you cannot undertake successfully from a spare bedroom. Even other jobs that can be done remotely — such as teaching and counselling — are often less effective in a remote context.\n\nSome organisations do not provide their employees with adequate technology and equipment to support successful remote working. Unreliable internet connections and a lack of suitable work space are other issues that can make remote working an unsatisfactory experience for both company and employee.\n\nOnce you get beyond the technical aspects of remote working, a central criticism it attracts is that workers can feel isolated. Such feelings can reduce productivity if workers feel they have to juggle home and work responsibilities without support from their colleagues or clear guidelines about separating work and home life.\n\nIn some organisations, measuring productivity remains a challenge even when employees are seated in the same space. Many companies that traditionally relied on time spent at a desk as an indicator of performance have moved to tracking their employees’ activities by installing software on their computers. This kind of monitoring software logs keystrokes, email, file transfers, applications used and the amount of time an employee spends on each task. Screenshots may also be taken periodically to keep managers informed of what employees have on their screens.\n\nIn many cases, organisations that have had poor experiences with remote working operate under cultural and performance norms that do not build trust or support collaboration and social cohesion. If this foundation is not in place from the outset, remote working will simply highlight the gaps. Without making trust, cohesion and collaboration mainstays of your company culture, remote working is unlikely to be a positive experience.\n\nThe winning aspects of remote working\n\nEven those who are wary of remote work concede that it reduces the time and money spent commuting. This gives workers more opportunities for cultivating a better work-life balance and means companies can save money renting and maintaining office space in major centres where rents have soared. From a global perspective, a reduction in traffic congestion and time spent travelling reduces the emission of greenhouse gases.\n\nLess immediately obvious benefits of remote work have inspired companies like NearForm to embrace the approach as part of their corporate culture. Offering remote work means you can hire from anywhere on the planet. Not only does this give you the broadest possible pool of talent to choose from, it also allows you to serve clients worldwide, irrespective of time zone. Organisations are beginning to realise the democratisation of remote work is something worth retaining long after the pandemic has ended, if only for the opportunities for talent acquisition — and retention — it creates.\n\nOptimising the remote working experience\n\nThis past year has been a baptism of fire for many organisations and their employees, plunging them without warning into a remote working experience that shows no signs of ending anytime soon. Whether companies like it or not, working outside the office is something that many of them will have to continue for the foreseeable future. This means they need to support their workers in providing the physical infrastructure and processes they need to create a productive work environment outside the office.\n\nFor example, NearForm provides employees with an allowance for equipping a home office, so that team members don’t have to make do with kitchen tables and chairs. It is important that every employee has access to the equipment they need to perform their work properly, including laptops, monitors and all software required to ensure the security and quality of work. Organisations could also investigate the potential for diverting resources into renting space in local digital hubs for employees if their home environment isn’t suitable.\n\nPhysical supports are not the only elements required for a good remote working experience. For remote work to succeed, it has to be supported and encouraged. It’s not about running the same meetings you had in the office, but via Zoom. You need to ensure that communication is designed around the unique constructs of the remote work experience, so that nobody feels as if they are omitted from important developments or obstructed in making progress.\n\nAt NearForm, we use Slack to keep everyone informed of what is going on, as well as to maintain active social contact among our team members. On Zoom calls, we encourage everyone to keep their cameras on to reinforce the human element of communication. We also run regular remote water cooler sessions via Zoom to combat feelings of isolation and disconnect, and ensure that people get the opportunity to interact on a human level on matters unrelated to work.\n\nWhy trust matters\n\nOne of the biggest barriers to a successful remote work experience is trust — some managers simply don’t trust their people to work when they cannot see them because they tend to manage by headcount rather than by results.\n\nThis tendency can be combated if managers measure by agreed milestones rather than by hours logged. At Gitlab, for example, a results value means employees take ownership of the tasks to which they are assigned. This approach demands organisation-wide trust and a mentality that colleagues will do what they are supposed to do without the need for strict rules.\n\nTrust your team members to focus on what they think is the most beneficial use of their time. You will find that people are more productive when they have agency to use their time in a way that extracts most value. This could mean skipping meetings in which their participation is not critical in order to focus on more constructive tasks. Managers need to agree measurable KPIs with those who report them, something that requires mutually respectful relationships to work.\n\nWhat the future may look like\n\nA recent Gartner survey found that 82% of company leaders supported a move to some kind of remote working post-pandemic. A hybrid working model is gaining traction in many quarters, although that raises its own issues. Among them is the risk that twin organisational cultures will emerge, with the dominant one centring on in-office workers who collaborate in-person while the remote workforce is abandoned, with scant consideration for their cultural and social cohesion.\n\nIt doesn’t take long for remote workers in these kinds of organisations to start feeling isolated, disenfranchised and frustrated. The feeling of belonging and common purpose they had established while work was done exclusively outside the office soon declines, productivity deteriorates and organisational performance suffers as a result.\n\nPhysical offices are not going to disappear any time soon. Larger organisations may operate satellite offices in key urban centres, allowing them to attract talent and offer flexibility for employees who do not wish to work from home. The hybrid approach may appeal to businesses seeking a balance between office-based and fully remote work, but they are likely to face challenges maintaining that balance and preventing remote workers from feeling alienated.\n\nIn the long run, companies that embraced the experience during the year we all went remote will experience distinct, ongoing benefits by consolidating their efforts and becoming remote-first. Having solid remote working practices in place and — more importantly — establishing a culture of trust and collaboration will help employees do their best work in the place that suits them." ], "categories": { "primary": "work", "others": [ "devops" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-5-essential-developer-skills-for-a-post-digital-world": { "href": "https://nearform.com/insights/5-essential-developer-skills-for-a-post-digital-world", "postType": "blog", "slug": "insights-5-essential-developer-skills-for-a-post-digital-world", "date": "2021-03-09", "title": "With the world nearer than ever to a fully digital future, developers should prioritise skills that set them up for long-term success.", "authors": [], "content": [ "As the world readies for a fully digital future, developers should prioritise skills that set them up for long-term success.\n\nNow that the Covid-19 pandemic has forced digital transformation on organisations everywhere, people are starting to ask “what happens next?” As the world adjusts to the reality of doing virtually everything digitally, what skills should software developers hone now to stay ahead of the game?\n\nWe asked some of our expert technical directors which skills they consider to be table stakes for any developer seeking to advance in the coming years. Here, we share some of the skills they see as the most important.\n\nServerless\n\nThe need for speed, security and scalability in business has brought serverless to the fore. Serverless architectures free organisations to focus on event-driven development and business logic while a service provider such as AWS, Microsoft Azure or Google Cloud manages their infrastructure, abstracting every layer from the bare metal to the software environment.\n\nAlthough applications continue to run on a server, that space is managed by the provider, automatically scaling applications horizontally so that multiple instances of a function can run concurrently without impeding performance. The microservices that applications depend on are also hosted in the cloud allowing for more efficient testing and faster implementation of new features.\n\nServerless functions such as AWS Lambda mean the developer simply needs to provide a function with the exact business logic to handle a request. There is no need for them to initialise a server, maintain software or take care of other related tasks.\n\nDevelopers and software engineers working with serverless don’t need an understanding of the infrastructure that runs the software they create, but there are several considerations they need to bear in mind when adopting a serverless approach. Understanding when and why to use the serverless services specific to each provider is an essential skill for developers, particularly given that serverless is a relatively new approach that not all developers may have.\n\nServerless technology was key to NearForm’s successful delivery of an optimised, scalable and extensible data processing, analytics and visualisation platform for the drone data collection and analysis company Skycatch .\n\nThe ability to understand serverless techniques aligns with the predicted increase in demand for cloud-native development skills, as organisations strive to achieve the agility required to maintain a development model that spans data centres and multicloud environments.\n\nCloud native\n\nCloud native is a holistic approach to development that leverages the distributed, scalable, flexible nature of the public cloud to streamline operations and refocus the organisation’s energies on developing performant, reliable applications that can be scaled automatically in line with demand.\n\nWhereas cloud-based development relies on a browser to point to a cloud-based infrastructure, cloud-native development is grounded in containers, microservices and serverless functions — abstracting away infrastructure layers such as networks, servers and operating systems. It slashes time to market while making operations more efficient.\n\nNearForm embraces cloud native infrastructures to create dynamic applications built on open source technologies that prioritise continuous integration and continuous development (CI/CD) in growing your product. Technical director Sergi Mansilla underlines the importance of cloud-native skills: “I can’t emphasise enough how important cloud native is — particularly embracing the tools and philosophy of your cloud provider of choice.”\n\nWith businesses increasingly moving to scalable cloud-native infrastructures, software developers can capitalise on an organisational shift to the cloud by honing their cloud-native development skills. Developers should be proficient in containerisation and how to deploy scalable apps to the cloud, and they should also understand microservices development and service mesh.\n\nAs businesses move to the cloud, developers will also need to understand how to leverage API-driven microservices and domain-driven design.\n\nSecurity\n\nGiven the primacy of cybersecurity in recent times, every developer and software engineer should understand security across the ecosystem – from their application, code and software supply chain to the environment their tooling is run in.\n\nDevelopers need to be proficient in integrating security testing in each domain of software development to identify vulnerabilities in a piece of software or system. The key areas of security testing are:\n\nNetwork security\nSystem software security\nClient-side application security\nServer-side application security\n\nDevelopers should be able to execute all of the above tests on their technical output. This ensures that their work is of high quality and works effectively.\n\nWithout proper security practices, an organisation’s ability to innovate confidently can be hindered. This makes up-to-date security skills crucial. For the foreseeable future, it is likely that organisations will champion security principles with a return to threat modelling to identify risks and an emphasis on practical experiences to reinforce learning and enhance security literacy.\n\nData analysis and visualisation\n\nAutomating and scaling processes and operations to meet the needs of larger customer bases requires reliable data-driven intelligence. Companies are collecting and processing vast amounts of structured and unstructured data from business transactions, smart devices, industrial equipment, social media and other streams. That data is only as valuable as the insights gained from it, so organisations need people skilled in data analysis and application.\n\nIf you can help an enterprise leverage its data in the right way, you can generate valuable insights for streamlining operations and responding faster and more effectively to changing customer demands. To consume massive datasets, you will need to be proficient in data analysis and visualisation . The right visualisation automatically releases more value from your data because it becomes more accessible to a wider range of users. As data streams multiply and generate exponentially greater volumes of data, visualisations need to remain focused on making the information useful for as many users as possible.\n\nAdaptability\n\nWhen you sit down to audit your skills and marketability as a software developer, it is natural to start thinking about your proficiency in various languages. However, it is more important to be able to demonstrate transferable skills than a long list of accomplishments. Python, Javascript and Java may be in demand, but many hiring managers are moving toward language agnosticism.\n\n“Some developers might be surprised to learn that soft skills are the most important consideration in any hiring decision,” explains Sergi Mansilla.\n\n“Learning a new language is a matter of practice and time, but learning to adapt quickly to new requirements and other changes is a lot trickier.”\n\nSo-called soft skills rarely appear in lists of sought-after proficiencies, but they are among the most important qualifications for any job. Are you a good communicator, a reliable team player, a fast learner? All of these skills help make you a valuable developer.\n\nAdaptability is one of the most important soft skills you can demonstrate. Hiring managers look for people who can learn new skills and behaviours in response to rapidly changing circumstances and will often include it in job descriptions because of its importance for growth within a role.\n\nIf you can demonstrate adaptability as a developer, it means you are flexible and able to respond creatively when things don’t go as planned. You probably work equally well with your team or on your own.\n\nWith the world adapting to a fully digital future, now is the time to consider your toolkit as a developer. Do you have the accomplishments and experience to achieve your career goals? By prioritising key skills in your resume, you can ensure your path to career fulfilment is a swift and interesting one." ], "categories": { "primary": "cloud", "others": [ "devops", "security", "data" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-openhive-js-talks-with-liz-parody-communities": { "href": "https://nearform.com/insights/openhive-js-talks-with-liz-parody-communities", "postType": "blog", "slug": "insights-openhive-js-talks-with-liz-parody-communities", "date": "2021-03-11", "title": "In this episode of OpenHive.js, Liz Parody talks about the most important elements for building communities.", "authors": [], "content": [ "This episode of OpenHive.JS was recorded across four continents, with people in Italy, Colombia, California and Dubai — a fitting setup for a conversation focused on building and strengthening global communities and connections. As our guest Liz Parody points out, it’s what you put into your interactions that matters, and this conversation is proof of that.\n\nA self-taught, highly skilled software engineer and Head of Developer Relations at NodeSource, Liz has made a name for herself building key communities within open source. Through her work organising JSConf, Pioneras Developers and StartUp Weekend Women Edition, Liz has gained valuable insights and techniques for growing, sustaining and empowering OSS communities, many of which she shares in this episode.\n\n“\"Build, then engage and finally grow — that's how you create a very successful community.\"”\n\nWelcome back to OpenHive.JS.\n\nListen to the full conversation now on Apple , Spotify or Google podcasts — or go to the OpenHive.JS page on Anchor.fm to find links to other podcast players. And don’t forget to subscribe so you’re sure to catch every episode.\n\nOpenHive.JS\n\nThe podcast for all things JavaScript, OpenHive.JS presents conversations with key contributors and open source leaders around new developments, challenges and perspectives in JS technology.\n\nHosted by James Snell and Matteo Collina , OpenHive.JS publishes new episodes monthly and is produced and distributed by NearForm." ], "categories": { "primary": "oss", "others": [ "work" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-doomscroll-design": { "href": "https://nearform.com/digital-community/doomscroll-design", "postType": "blog", "slug": "digital-community-doomscroll-design", "date": "2021-03-16", "title": "How to Remain A Successful Product Designer In Our Current Digital Hellscape", "authors": [ "MARK PRESCOTT" ], "content": [ "The internet is a scary place. I don’t just mean the internet in 2021, coming off the chaos-in-all-directions kind of year we just had; I mean the internet itself and the way we are bound to it, and our chosen devices on which to serve it up. The average millennial spends almost six hours per day in front of a phone. That number goes up to seven hours for most gen-z’s. We’ve all read the reports on the negative effects this has on our health. This is apart from the emotional toll, exposing ourselves constantly to Everything Going On in the world, enough that the word “doomscrolling” has entered our vocabulary—the steady stream of bright colors and bad news that we can’t get enough of.\n\nTo detach oneself from this is a tempting choice. You can do it for health reasons, or political reasons, or both. Several studies have been done examining the link between excessive screen time and depression (reasons beyond reading the news and comparing your life to those of your high school friends on Facebook). There is a trend of children who grow up using tablets and laptops getting lower test scores in thinking and language areas. You can become legitimately addicted to the dopamine blasts in your brain from interacting with your bright and shiny screen. I can continue, but we’ve all likely seen these kinds of reports. In the end you may ditch your smartphone for a burner (or a sleeker version like the Light Phone), dig out your iPod for unconnected music, or set a daily screen time limit on your devices. You may find the need to delete your accounts on certain products after a CEO does some shady behaviors, or you start to disagree with their policies, or due to their impact on the world and the environment. Many have found the obvious bliss of ungluing from our screens and looking up.\n\nBut!\n\nAs digital product designers, this is a much tougher feat to accomplish. Our jobs are designing the experiences for these devices; to be successful, we need a deep understanding and plenty of practice using them. It would be like if I was a car designer who had built a successful career designing cars, who one day decided to quit driving cars. I wanted to save myself the costs, the risk of injury, the toll on the environment. But I still want to work designing cars. As the years go by, keeping or finding a job would be harder and harder. I’m no longer a user of the thing I’m designing. I have little awareness of the current trends or new technologies that other car companies are using.\n\nNo matter how much we designers want to unplug, we still have a duty to keep our fingers in our devices, if only to keep our designs (and our employment) relevant. We need to know about any new fun new navigation styles that are catching on, what the next design trend will be (Remember neumorphism? Where did that go? Did it ever get off the ground at all?) Are there design changes at the operating system level that inform the design of the apps that run on it? Are there patterns that have been proven unsuccessful that need to be replaced? A large part of maintaining a delightful experience is keeping it “fresh” in the world it lives in.\n\nStaying Sane\n\nAmong these restraints, there are things we can do to keep experiencing our digital world in a healthy way, without cutting off entirely from it.\n\nCreate a shared “inspiration library” with your team\n\nResearch is a huge part of the product design process. If you’re designing a podcast app, it’s normal to spend days or weeks analyzing every competing app out there. You’ll download every other podcast app in the app store (ok, maybe not all of them). You’ll look at music apps. Hell, you’ll even download TikTok, to see whatever is going on over there. You’ll take screenshots, annotate them, stick them into your whiteboarding tool of choice. This doesn’t have to be a solo task though. I have had success setting up shared documents to house all of these inspirations and competitive audits. In one example I was working with a director who spent a LOT of time researching similar products to the ones we were building; he would drop screenshots and comments in Slack to discuss in the moment, then they went into a shared Figma file. Screenshots were organized by both brand and feature. This was a living document beyond the research phase; new items were constantly being added. When it came to improving a feature, we had a bank of images of competitors doing a similar feature at the ready.\n\nCollecting competitors’ loyalty program screenshots\n\nTeam show and tells\n\nAnother useful idea is to hold a weekly or monthly time with your team to show off things you’ve found that you think are cool. It could be a website or app that is well done in its entirety, a nice new typeface, a fancy menu transition, or a cool illustration style. Or a bad illustration style. Calling out the things we don’t like is just as important as noting the things we admire. Many minds are more powerful than one—rely on your colleagues to keep everyone informed.\n\nExternal resources\n\nAlong with doing your own research, there is a wealth of competitive data on the internet. Here a few worthwhile sources to spend some quality time with:\n\nreallygoodux.io\n\nlittlebigdetails.com\n\nuxarchive.com\n\nNiceverynice.com\n\ncss-tricks.com\n\nSome of these even have email newsletters. Even better!\n\nTimebox yourself\n\nThe most obvious one might be to simply limit your screen time in a more manual way. Keep your research to working hours. Resist the urge to keep playing with them and analyzing them after hours. Resist the urge in general to be on-screen at all hours. Set a time each week to go through all your email newsletters so you can really focus on them. Turn off most of your notifications. Put a screen time limit on your phone. While you’re at it, keep your phone outside of the bedroom to prevent the hours of scrolling and blue light beaming into your brain before going to sleep.\n\nThe bigger goal above this is to be more intentional with your plugged-in time. For the past few years I have set small rules for myself: the laptop stays in the office, the phone sits on its charger in the living room as much as possible (after 10pm being the “curfew”), the iPad is used 90% for making art (the reason I bought it), etc. I noticed quickly how much I started to value that time on-screen and wanted to do quality things with it. If I limit myself to one more hour on my phone today, should I spend it in the bottomless pit of Twitter, or play more Two Dots levels (I had to stop myself at 2000)? Or how about I learn something or create something new?\n\nWhat Works For You?\n\nEverything is collaborative. Do you have other tactics that you’ve found to work? Tweet us at @formidablelabs if you have insights to share.\n\nPS: A bigger, separate topic is the responsibility of us designers to create products that don’t lead to screen addictions and overuse in the first place. We don’t need to keep measuring success based on how long we can keep someone’s eyes locked in. How can we protect our users, digitally and holistically? A book called The Best Interface is No Interface is a good read on this.\n\nPPS: On the larger topic of improving your relationship with technology, the Center for Humane Technology has put together many more resources and strategies, along with tactics for building healthy digital products for humans.", "DESIGN\nObservation as a prerequisite for design\nJOE ALTERIO\n30 JAN 2019\nREACT-NATIVE\nThe New React Native Architecture Explained\nLORENZO SCIANDRA\n26 MAR 2019\nREACT\nDESIGN\nIs the Future of Web Design Polymorphic?\nLUKE JACKSON\n24 SEP 2020" ], "categories": { "primary": "design", "others": [ "product" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-how-discovery-engagements-unlock-a-projects-potential": { "href": "https://nearform.com/insights/how-discovery-engagements-unlock-a-projects-potential", "postType": "blog", "slug": "insights-how-discovery-engagements-unlock-a-projects-potential", "date": "2021-03-16", "title": "How discovery engagements unlock a project’s potential", "authors": [], "content": [ "A collaborative discovery workshop can be a game changer for organisations seeking practical solutions.\n\nDeciding how to build and implement a software solution are among the trickier elements of digital innovation. A lack of internal alignment or expertise can push the process beyond the abilities of a single enterprise. That’s why access to strong facilitation and informed external expertise is a must.\n\nCombined in the form of a well-conceived discovery workshop , this kind of engagement sets you up for successful innovation because the focus from the outset is on developing a shared understanding of what is required. Right from the start, the team and the client immerse themselves in a process that centres on the needs and considerations of all relevant stakeholders.\n\nWithin days, the team can produce a workable idea of what the internal fix or product should be and transforms that idea into a prototype for testing and refinement by users.\n\nGetting the process right\n\nAt NearForm, we start every engagement with a discovery workshop because it is the key to aligning teams and encouraging collaboration from the very start. Over the years, we have refined the process, recognising how much time and energy are wasted when clients are asked to create complicated documents encompassing all the aspirations they have for a project and when teams spend hours sifting through the various visions different departments have for a finished product.\n\nInstead, we use a process-driven discovery engagement to quickly establish consensus among stakeholders on a route from strategy to delivery and to generate tangible assets to accelerate development and deployment, such as prototypes, plans and architectures. To ensure success, each engagement is tailored to the client’s specific context, experience and goals. This approach both minimises risk when validating proposed projects and optimises the potential for successful delivery.\n\nHarnessing the power of workshops\n\nWith their strong social energy, collaborative dynamic and set focus, workshops can really accelerate progress in a way that no other technique can. For our discovery workshops, we bring key stakeholders together with a senior product designer and senior technical director to define the project goals and strategy clearly and with minimal delay.\n\nThe setting encourages stakeholders to communicate ideas freely, and our team gets to work harnessing these nuggets of information immediately. The workshop makes it easier to address challenges as they surface — for example, by letting ideas that may have sounded great on paper be abandoned quickly when shortcomings become apparent during open discussion.\n\nWorkshops provide the chance to contribute and discuss ideas in a natural way, so we can start using this valuable information straight away, just as we did for TELUS . What’s vital, of course, is that the discovery workshop produces not just ideas but real results.\n\nProducing results\n\nBy following a focused schedule, an efficient discovery workshop can produce actionable results within a few days. On day one, our senior product designer and senior technical director get straight down to discussing and understanding your business needs, goals and ambitions, so they can extract the detail required to create a roadmap for your product design and development.\n\nIf all stakeholders commit to aligning their understanding of the specific problem on the first day, the team then can dive into high-fidelity customer journeys. Pairing design and tech, our team adopts a tag-team approach to requirements research and problem solving so they can transfer knowledge efficiently while maximising productivity.\n\nThe second day of the workshop generally concludes with a review of the concepts presented to the client and agreement on the direction to take. This is not simply an abstract discussion: The team often presents a prototype for the client to test, approve or propose changes. It is common for the team to have covered any outstanding issues and outlined a plan for delivery by the third day of a discovery engagement.\n\nReal-time collaboration, the streamlined nature of design-led development and our proven expertise speed up the process dramatically. In the space of 72 hours, clients often progress from a position of simply knowing they have an unresolved internal issue or an unmet customer need to one where they possess a working model of a viable solution they can test with users, a roadmap for future development and a deeper understanding of their products and processes.\n\nWrapping it up\n\nIf you choose to continue working with us after the discovery engagement, our development team can jump straight into working on your project, armed with the prototype and product roadmap. The rapport established during the workshop process creates a good working relationship between teams as they move forward into product development, maximising the potential for a fast, successful outcome.\n\nEven if you choose to end your engagement following the discovery workshop, you will be armed with tangible assets, a deeper understanding of the problem you are trying to solve and the route to a viable solution. The power of the design thinking methods we use in our engagements helps to surface and test new ideas and build consensus around them. No matter how innovative the ideas generated during the discovery engagement, we ensure that every solution is feasible and optimal within the client context.\n\nIf the external facilitator of your design engagement maintains an unwavering focus on best practice applied to modern technologies, you can have confidence that they will make the most informed choices for modern technology platforms and practices. A constant feedback loop from solutions they have delivered and maintained previously will inform their engagement with you, making it easier and safer to make complex choices. This means you can innovate with minimal risk.\n\nThis method of discovery goes far beyond user journeys and prototypes. With outline architectures, workable plans and proper estimates, you enjoy the freedom to innovate, safe in the knowledge that all of the outputs you receive are feasible, powerful and actionable." ], "categories": { "primary": "product", "others": [ "design" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-react-three-fiber": { "href": "https://nearform.com/digital-community/react-three-fiber", "postType": "blog", "slug": "digital-community-react-three-fiber", "date": "2021-03-18", "title": "Building 3-D Web Experiences With react-three-fiber", "authors": [ "BRIAN MATHEWS" ], "content": [ "If you need to build a 3-D experience on the web, and plain old CSS, SVG, or canvas aren't going to cut it, using WebGL (the browser's API for 3-D rendering) is the way to go. Working with the raw WebGL API is hard and time consuming, though.\n\nThree.js is a popular library that makes working with WebGL easier. Most 3-D experiences you see on the web are built with Three.js. Their homepage features a ton of great real-world examples, from NASA to Github to games:\n\nDespite being an abstraction on top of WebGL, even Three.js can feel pretty low-level, especially if you're used to using libraries like React or Vue.\n\nConsider how large web UIs aren't often built with hand-crafted imperative DOM manipulation code like this:\n\nconst element = document.createElement('div');\nelement.innerText = 'Hello world';\ndocument.body.appendChild(element);\n\n\nThree.js has a similar imperative API:\n\nconst geometry = new THREE.BoxGeometry();\nconst material = new THREE.MeshBasicMaterial({ color: 'orange' });\nconst cube = new THREE.Mesh(geometry, material);\nscene.add(cube);\n\n\nThis imperative programming style can get unwieldy once you have enough state and lifecycle to manage, which is exactly why frameworks with a declarative API, like React and Vue, are so popular.\n\nWhat if you could build 3-D scenes with React? You can! react-three-fiber is a library that lets you do exactly that.\n\nreact-three-fiber\n\nRather than using divs and spans, react-three-fiber (R3F) lets you render Three.js objects like meshes, lights, cameras, and shaders. Your code looks more like this:\n\nconst MyScene = () => {\n return (\n \n );\n};\njsxCopy to clipboard\n\nYou declare the 3-D objects you want in a scene and R3F takes care of running the imperative Three.js code under the hood. And, in the same way that React gives you hooks to access the primitive DOM elements via refs, R3F lets you access the primitive Three.js objects for when you need a little more control.\n\nYou also have easy access to the existing, massive Three.js ecosystem of examples and libraries. The extend API from R3F lets you render third-party objects using JSX:\n\nimport { Canvas, extend } from 'react-three-fiber'\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'\n\nextend({ OrbitControls })\n\n...\n\n\njsxCopy to clipboard\n\nAt the end of this post you'll find resources and tutorials on how to use react-three-fiber.\n\nUse Cases\n\nThree.js is great for all kinds of 3-D experiences on the web, and I'd say you should always consider using react-three-fiber to manage a Three.js scene, whether that's for art, adding a 3-D product viewer to an e-commerce site, VR/AR experiences, productivity tools, or even games.\n\nIf you're already building a web page in React and need to add 3-D functionality, you can use all the same state management libraries, data fetching abstractions, and pass data and props between your 3-D scene and other parts of your React project.\n\nHere are some R3F examples:\n\nhttps://codesandbox.io/embed/r3f-game-i2160\n\nhttps://codesandbox.io/embed/r3f-moksha-f1ixt\n\nhttps://codesandbox.io/embed/r3f-train-l900i\n\nPerformance\n\nR3F on top of Three.js has the same performance characteristics as React on top of the DOM. Any abstraction has some overhead, and theoretically it's possible to write faster lower-level code yourself, but in practice and at scale, React's component model makes balancing complexity and performance significantly easier.\n\nBut, building performant 3-D experiences on the web can be challenging regardless of the abstraction you're using. Once you reach a certain level of complexity, you may need to start digging in to how the GPU and WebGL work in order to achieve your performance goals. You're significantly more likely to be bottlenecked by your specific approach rather than by the abstractions provided by R3F or Three.js.\n\nFor example, if React is a tool for building UIs on the web, can you use R3F to build 3-D UIs? I explored this from the perspective of futuristic, sci-fi UIs, and you absolutely can build 3-D UIs with R3F:\n\nhttps://formidable.com/blog/2021/future-ui/\n\nYou can easily render custom fonts, SVGs, 3-D objects, rounded rectangles, handle user interactions, and even make it all accessible. But, many of us take for granted the performance optimizations that browsers and the DOM take care of automatically.\n\nIf you take a naive approach to rendering a few hundred flat rectangles in raw WebGL, Three.js, or R3F, it's going to use a lot more CPU and GPU power than if you did that with the DOM. A naive approach will mean that every frame (every 16 milliseconds on most monitors), the CPU will send unique instructions to the GPU for every rectangle. It can get slow. Hundreds of divs, rectangles, borders, icons, and blocks of text are common in UIs.\n\nTo make performant UIs using the GPU, you need to minimize the number of instructions sent to the GPU, known as \"draw calls\". \"Instancing\" is the technique for reducing draw calls, which means that wherever possible, you send a single mesh to the GPU, (e.g., a rectangle), then tell it how many instances you want, where they should be located, and what scale. Three.js and R3F support instancing, but it's up to you to think of how to apply it for your type of UI. Neither Three.js nor R3F are a \"UI framework\", but you can build UIs with them if you're comfortable tackling these performance hurdles yourself, which may very well be required if you're building a VR/AR experience.\n\nWhat You Need to Know\n\nThe world of 3-D can be overwhelming at first. These libraries and abstractions help significantly, but building 3-D experiences can require understanding a few new concepts.\n\nIn the same way that you need to understand HTML when using React, you need to understand Three.js when using R3F, since ultimately, R3F is just a way to manage a Three.js scene. All of the actual rendering is done by Three.js. You will need to reference the Three.js docs when working with different types of concepts.\n\nIf you're new to Three.js you should get comfortable with these core Three.js concepts first:\n\nCameras\nLights\nMaterials, textures, shaders\nGeometry\nMeshes\n3-D model file formats\n\nOnce you're comfortable with these, the react-three-fiber documentation will make a lot more sense.\n\nThe last section of this article is a roundup of documentation, tutorials, and community libraries that will help get you started. Hopefully this overview and these resources give you everything you need to start building 3-D experiences on the web. Good luck!\n\nResources\n\nThree.js:\n\nhttps://threejsfundamentals.org\nhttps://threejs.org/docs/\n\nReact\n\nhttps://reactjs.org/docs/getting-started.html\nhttps://reactjs.org/docs/hooks-intro.html\n\nreact-three-fiber tutorials:\n\nhttps://www.smashingmagazine.com/2020/11/threejs-react-three-fiber/\nhttps://blog.logrocket.com/3d-rendering-in-the-browser-with-react-three-fiber/\n\nreact-three-fiber documentation:\n\nhttps://docs.pmnd.rs/react-three-fiber/api/canvas\n\nLibraries built on top of react-three-fiber\n\n@react-three/drei Tons of helpful components and hooks\n@react-three/flex Use flexbox to layout 3-D objects\n@react-three/postprocessing Shader effects like bloom, depth of field, and more\n@react-three/a11y Expose and describe your 3-D objects to assistive technologies", "OPEN-SOURCE\nDESIGN\nVICTORY\nBuilding Future UIs\nBRIAN MATHEWS\n28 JAN 2021\nOPEN-SOURCE\nBuilding Physics-Based Animations with renature\nPARKER ZIEGLER\n12 JAN 2020\nOPEN-SOURCE\nProgress Towards OSS Sustainability\nLAUREN EASTRIDGE\n28 AUG 2019" ], "categories": { "primary": "frontend", "others": [ "design", "oss" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-getting-to-know-hkdf": { "href": "https://nearform.com/insights/getting-to-know-hkdf", "postType": "blog", "slug": "insights-getting-to-know-hkdf", "date": "2021-03-18", "title": "Getting to know HKDF", "authors": [], "content": [ "The HMAC-based Key Derivation Function makes modern cryptographic capabilities easier for Node.js developers.\n\nAlthough the HMAC-based Key Derivation Function (HKDF) is not new (the specification for it, RFC 5869 was published by the IETF in May 2010), it is starting to gain prominence in more types of applications and systems.\n\nFor example, HKDF is one of the algorithms used within the Cryptography Specification of the Exposure Notification system created by Google and Apple that lies at the heart of the Covid-19 contact tracing applications NearForm and others have produced to help slow the spread of the virus. You can also find HKDF buried in the internals of the new QUIC protocol TLS 1.3 handshake , at the heart of the new Hybrid Public Key Encryption (HPKE) scheme, as a component of several evolving distributed identity frameworks and in many other systems.\n\nAs part of the effort to implement the standard Web Crypto API in Node.js 15 , we also implemented built-in support for using HKDF. Here, we introduce you to the fundamentals of HKDF and illustrate how it can be used — on both the server in Node.js and the client.\n\nIntroducing HKDF\n\nOne of the central goals of the Covid-19 digital contact tracing initiative has been to protect the privacy of individuals as much as possible. From the ground up, exposure notification applications such as Covid Green have been specifically built around this fundamental protection, and the underlying protocols provided by Apple's iOS and Google's Android operating systems have this protection built in.\n\nWhile full details of the Google-Apple Exposure Notification (GAEN) protocol can be found in the Bluetooth Specifications and published FAQs , we want to focus on one very specific component called the Rolling Proximity Identifier (RPI).\n\nAfter the contact tracing application is installed and active on your mobile device, the GAEN service will allocate a random Temporary Exposure Key every 24 hours. This key is stored securely on your device and is only shared with the exposure notification system if and when you test positive for Covid-19 and manually choose to anonymously share your diagnosis so others can be notified.\n\nAt 15-minute intervals throughout the day, your phone takes that Temporary Exposure Key (TEK) and uses it as part of a function to create a new RPI. Your phone then continuously broadcasts the current RPI over Bluetooth to any other devices in the local vicinity. Neither the TEK nor the RPI contains any information that connects to your phone or you personally in any way.\n\nWhen a mobile device detects another phone nearby that is broadcasting proximity identifiers, those are recorded and stored securely on the device along with the timestamp of when it was seen.\n\nIf a user of the application later tests positive for Covid-19, they open the application and choose to share the list of TEKs their phone has accumulated over the past two weeks. A copy of all uploaded keys is then sent to every phone with the app. When my phone receives the lists of keys, it goes through each, regenerates the associated RPI and checks whether that identifier has been encountered at any time during the past two weeks. If it has, I will get a notification that I may have been exposed.\n\nThis system is designed such that none of the keys and identifiers can be correlated with any single individual or device, while still allowing deterministic and algorithmic generation and verification. The HKDF is one of the core mechanisms it uses to accomplish this.\n\nThe specific algorithm used in the exposure notification service is straightforward:\n\nteki ← CRNG(16) RPIKi ← HKDF(teki, NULL, UTF8(\"EN-RPIK\"), 16) RPIi, j ← AES128(RPIKi , PaddedDataj)\n\nThe steps here are essentially:\n\nGenerate the TEK (the tek) by generating 16 cryptographically random bytes. Generate the 16-byte RPI Key (the RPIK) by passing the tek into the HKDF algorithm using no salt, and the UTF-8 encoded string literal \"EN-RPIK\" as the info.\nFinally, generate the RPI (the RPI) by passing the RPIK into the AES-128 encryption function along with some standard padding data that includes a rolling counter called the \"ENIntervalNumber\".\nThe use of HKDF and AES-128 together is enough to ensure that the 16-byte RPI generated has a very low probability of collision, is fully deterministic and does not leak any private information.\nHKDF in the new QUIC protocols TLS handshake\n\nAside from contact tracing, HKDF is also used as a critical component of the new QUIC protocols TLS handshake — specifically, HKDF is used to derive the initial set of secrets that are used to kick off a QUIC connection.\n\nWhen a QUIC client wants to initiate communication with the server, the first thing it does is create a new identifier for itself called a Connection ID (CID). Each endpoint participating in a QUIC connection is persistently identified by a CID throughout the connection's lifetime, and the CID for an endpoint can change multiple times. At the very beginning of the conversation, however, the client sends its initial CID to the server to start the flow of data.\n\nThe server takes that initial CID and passes it into the HKDF function with standard salt and info values to generate the initial set of secrets the two peers will use to establish the rest of the TLS session. The algorithm is straightforward:\n\ninitial_salt = 0xafbfec289993d24c9e9786f19c6111e04390a899\ninitial_secret = HKDF-Extract(initial_salt, client_dst_connection_id)
client_initial_secret = HKDF-Expand-Label(initial_secret,\n \"client in\", \"\",\n Hash.length)\nserver_initial_secret = HKDF-Expand-Label(initial_secret,\n \"server in\", \"\",\n Hash.length)\ntextCopy to clipboard\n\nThe salt is standard and used for all QUIC connections, as are the info values \"client in\" and \"server in\". The CID provides the source of pseudo-randomness that helps to avoid collisions in the generated initial keys. Once the TLS handshake has started and a stronger cryptographic session has been established, these initial keys are discarded.\n\nNote that the HKDF mechanism works such that, so long as both the client and server are using the same initial CID, they can both independently derive the client and server initial secrets. That determinism lies at the heart of the HKDF scheme.\n\nHow it works\n\nThe HKDF scheme is detailed precisely in RFC 5869 and consists of two distinct phases, each of which can be used independently or together. The first phase, called \"Extract\", involves simply generating an HMAC hash over a given salt value and an initial key. Any standard cryptographic hash algorithm can be used, but the most common are the SHA family of hashes — with SHA-256 being the most frequent choice.\n\nOnce the cryptographic hash is generated, the second phase, called \"Expand\", takes the hash through a series of transformations and subsequent additional HMAC generations to produce the output keying material. To give an idea of what this looks like, here is a snippet of the algorithm as documented in RFC 5869:\n\nN = ceil(L/HashLen)\nT = T(1) | T(2) | T(3) | ... | T(N)\nOKM = first L octets of T\nwhere:\nT(0) = empty string (zero length)\nT(1) = HMAC-Hash(PRK, T(0) | info | 0x01)\nT(2) = HMAC-Hash(PRK, T(1) | info | 0x02)\nT(3) = HMAC-Hash(PRK, T(2) | info | 0x03)\n...\ntextCopy to clipboard\n\nThe end result is a byte string that appears random but that can be deterministically regenerated given the identical inputs.\n\nThe cryptographic strength of HKDF is a factor of both the initial keying material and the salt selected. It is important that either or both are generated from a strong source of entropy to ensure the resulting key material is unique.\n\nHow to use it\n\nThe Web Crypto API has built-in support for the HKDF scheme, and whereas browsers have had support for a while, Node.js has only recently gained the built-in ability to use HKDF.\n\n// In Node.js, get the SubtleCrypto from the webcrypto implementation\nimport { webcrypto } from 'crypto';\nconst { subtle, getRandomValues } = webcrypto;
// First set up our initial key\nconst key = await subtle.importKey(\n 'raw',\n Buffer.from('initial key'),\n { name: 'HKDF' },\n false,\n ['deriveKey', 'deriveBits']);
// Then, perform the HKDF Extract and Expand\nconst out = await subtle.deriveBits(\n {\n name: 'HKDF',\n info: 'the info',\n salt: getRandomValues(new Uint8Array(16)),\n hash: 'SHA-256'\n },\n key,\n 128); // 16 bytes\ntextCopy to clipboard\n\nThe Web Crypto API is promise-based, and the Node.js implementation ensures that the HKDF operations occur off the main event-loop thread within the libuv thread pool. This should help performance when an application is generating a large number of derived keys.\n\nWith the exception of the first two lines, which are the Node.js-specific way of getting to the Web Crypto API, the example above will work consistently on both the client and server side.\n\nFor the sake of being complete, however, we took the additional step of adding HKDF support to the existing legacy Node.js crypto module in both an asynchronous callback version and a synchronous blocking version.\n\nconst { hkdf, hkdfSync } = require('crypto');
hkdf('sha512', 'key', 'salt', 'info', 64, (err, derivedKey) => {\n if (err) throw err;\n console.log(Buffer.from(derivedKey).toString('hex')); // '24156e2...5391653'\n});
const derivedKey = hkdfSync('sha512', 'key', 'salt', 'info', 64);\nconsole.log(Buffer.from(derivedKey).toString('hex')); // '24156e2...5391653'\ntextCopy to clipboard\n\nThere shouldn't be anything surprising about these two variations if you're already familiar with the legacy crypto API in Node.js. Each performs both of the two phases (Extract and Expand) of the HKDF scheme and both accept the initial key, salt and info, along with a cryptographic HMAC function and the total number of bytes to generate. Like the Web Crypto variation, the asynchronous callback function defers the cryptographic operation to the libuv thread pool off the main Node.js event loop, while the synchronous version blocks the current thread until it completes. The APIs have been designed to just do what they are supposed to do without getting in the way.\n\nWhat happens next\n\nThis is just a brief introduction to HKDF, a quick demonstration of a few ways it can be used and an illustration of the APIs available for JavaScript developers to use it. One of our motivations for adding the scheme to Node.js was to make it easier for developers to build more modern cryptographic capabilities into their Node.js applications.\n\nThe HKDF support is just one of the new pieces that we've been working on including the full Web Crypto API implementation, support for generating standards-compliant random UUIDs, enabling the allocation and use of secure memory regions and more. In an upcoming post, we will explore more of those new capabilities by looking at the new UUID generation API and drilling down on its performance relative to popular alternatives in the Node.js ecosystem. Stay tuned for more." ], "categories": { "primary": "security", "others": [ "backend", "cloud" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-max-stoiber-urql": { "href": "https://nearform.com/digital-community/max-stoiber-urql", "postType": "blog", "slug": "digital-community-max-stoiber-urql", "date": "2021-03-23", "title": "Chats About urql: With Max Stoiber", "authors": [ "PHIL PLÜCKTHUN" ], "content": [ "urql is our highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow. As part of our larger effort to support the community with a flexible GraphQL client in the ecosystem we're also growing urql's community. In this interview series we're chatting with ambassadors of our community on how they discovered and why they're supporting urql.\n\nFor our first part, we're chatting with Max Stoiber, a JavaScript engineer from Vienna in Austria, who's a well known constant in the React community, co-creator of styled-components, serial co-founder of Spectrum, Changefeed, and Feedback Fish, and specialty coffee geek.\n\nHi, Max! We're excited to have you be the first to chat with us in this series about urql. We know you're not only an engineer and a maker but also highly adept at making coffee. What coffee bean are you having this week?\n\nI've been drinking a lot of Alpha Coffee's El Palto because that's what my favorite local coffeeshop, Kaffemik, uses for their espressos! It's a nice washed Peruvian coffee that goes well with milk.\n\nYou always seem to be at the forefront of new developments in the React community and beyond. Your first big project with GraphQL was at Spectrum, right? It was rather new at the time, but something must've convinced you that GraphQL was perfect for a new community platform—evidently there was already prior art around with GitHub moving towards building a public GraphQL API, so what pushed you in that direction in the end?\n\nNone of us at Spectrum had ever built an API before, nevermind one used by hundreds of thousands of users. The fact that GraphQL is strictly typed and well-specified gave us confidence to use it. That meant that we could follow its conventions and know we would be on a good path. Worked out well for us!\n\nIt seems that as you were moving around from project to project, urql kind of followed you along or rather, you were taking urql with yourself, like at Gatsby. How did you feel about introducing a \"newcomer\" project to the teams around you when other solutions existed, and what aspect of it made it a convincing option over choosing a more established GraphQL client?\n\nInterestingly, until I announced Bedrock nobody had ever asked me \"Why urql?\" I've literally never had to enumerate the reasons before! I think that's a testament to the convenient and intuitive APIs that urql has. Most engineers I worked with just went \"Ah, nice!\" and kept building.\n\nI have used urql for all of my projects over the past two years and love it for four main reasons:\n\nthe fantastic developer experience and APIs;\nthe great extensibility;\nthe small bundle size;\nand the active maintenance. I wrote about this in more detail in my recent post!\n\nInitially you've reached out to us just as our normalized caching was being implemented, helping us to cover all edge cases and making sure it would work for you and your team. Why did you chose urql back then and what motivated you to reach out directly?\n\nI was building an app at GitHub based on Preact and needed the small bundle size and the hooks API. However, I also had caching needs that weren't covered by the default document cache, so I reached out to be an early tester of the normalized cache, which worked out perfectly!\n\nWe hear you're now building a new project, \"Bedrock\", to help SaaS (Software as a Service) founders to build MVPs for their projects more quickly. This seems to be a really natural continuation of your work on React Boilerplate. What need are you trying to fill this time and is that building on how you built your last project, Feedback Fish? I understand you built the first MVP for Feedback Fish in just a single weekend.\n\nI've built multiple SaaS apps, yet every time I have a new idea it takes me weeks to months to build it—because I have to spend weeks implementing the same basic functionality over and over and over again!\n\nThat was frustrating me, so I made Bedrock, really for myself to have something to base my own SaaS apps on. However, I quickly realised through conversations with friends that other people could also benefit from it, so I launched a landing page and took pre-orders to gauge interest.\n\nTurns out, a lot of other people are also frustrated by this and are happy for this solution!\n\nAnd since \"Bedrock\" builds on GraphQL, why do you think GraphQL is the right choice for most new founders?\n\nThe tooling around GraphQL is simply unparalleled. Between Nexus, GraphQL Codegen, and urql I can move way faster with GraphQL than building an API any other way!\n\nYou've also recently announced that you'll be supporting early-stage startups as an advisor and investor. It seems that being a young founder yourself, helping other founders is just part of your drive.\n\nIt's fun to be a fly on the wall during other startup's journey's. The founders are still the ones building their company day-to-day, but sometimes an outsider can notice (potential) problems ahead of time that the founders might be too busy to see. Honestly, it's really fun, I love doing it!\n\nObviously, we have a long way to go and are supporting efforts like \"Bedrock,\" which help us to learn more about how GraphQL clients in general, and urql specifically, are used. For you, what's your favourite feature in urql, or do you have a future feature that you're looking forward to?\n\nOne feature?! That's impossible to pick, but I guess I'll cheat and say \"the exchanges\". The fact that I can adjust the way my GraphQL client behaves down to the most core details gives me so much power, I love it!\n\nIs there anything you'd like to tell our core contributors?\n\nKeep rocking!\n\nThank you so much for your time! We wish you great success with \"Bedrock\" and we'll see you later on the urql repo!", "OPEN-SOURCE\nGRAPHQL\nurql DevTools: Introducing Explorer View\nNEARFORM COMMERCE\n17 OCT 2019\nOPEN-SOURCE\nGRAPHQL\nHow to urql, Part 1\nJOVI DE CROOCK\n10 FEB 2020\nOPEN-SOURCE\nGRAPHQL\nHow to urql, Part 2: Authentication & Multiple Users\nJOVI DE CROOCK\n26 FEB 2020" ], "categories": { "primary": "backend", "others": [ "cloud", "oss" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-2021-call-for-code-with-ibm-the-united-nations-and-nearform": { "href": "https://nearform.com/insights/2021-call-for-code-with-ibm-the-united-nations-and-nearform", "postType": "blog", "slug": "insights-2021-call-for-code-with-ibm-the-united-nations-and-nearform", "date": "2021-03-23", "title": "The Call for Code Global Challenge drives humanitarian progress with practical applications built on open source. Sign up!", "authors": [], "content": [ "People of all backgrounds can sign up for the Call for Code, a United Nations Human Rights Office supported initiative to promote global humanitarian progress with practical applications built on open source–powered software.\n\nIt's hard to believe that a full two years have passed since NearForm first got involved with Call for Code, in the UN building on Lake Geneva.\n\nFor those not familiar with it, Call for Code aims to drive immediate and lasting humanitarian progress around the world through the creation of practical applications built on open source–powered software.\n\nhttps://www.youtube.com/watch?v=JA01afv7lqk\n\nI’ve been thinking about the IBM team that brings this together every year and the impact they have. Far too often, we allow ourselves to become immediately cynical as soon as we hear mentions of giant corporations such as IBM doing something positive. We assume it’s just some CSR box-ticking exercise and forget that inside every apparent monolith there are groups of deeply passionate people striving to make a difference in our world.\n\nIn this case, I’m talking about people like Bob Lord, Ruth Davis, Willie Tejada, Daniel Krook, Shari Chiara and Liz Klipp. They, along with other IBM teams, have now brought together over 400,000 people in 179 countries to take part in Call for Code.\n\nAs I said in the 2019 post :\n\n“I found myself deeply affected by the entire experience and I must congratulate Call for Code creator David Clark, IBM, the UNHCR, and all the other organisations for coming together in such a powerful and transformative way. I hope that I and NearForm can contribute even more in the future.”\n\nIn 2020, I was so pleased that Antoine Marin from our design practice could represent us in Geneva. Antoine was able to bring his skills as a product designer to bear on the challenges around water sustainability .\n\nCall for Code 2021\n\nIn 2021, we are back , albeit not in Geneva, and we are all just as passionate about contributing to this initiative. Working remotely in three distributed teams, our task this year was to develop starter kits around:\n\nZero hunger\nClean water and sanitation\nResponsible production and green consumption\n\nThe idea behind the starter kits is to help bootstrap people who want to get involved in Call for Code but may not have a specific idea to work on. By taking care of the ideation, initial research and outline architecture, we hope to onboard more people and to do so more quickly. NearForm has helped to craft these starter kits from the first year in 2019.\n\nResponsible Production and Green Consumption\n\nI was particularly happy to be assigned to the “Responsible Production and Green Consumption” team as it’s a topic that has been occupying more and more of my thinking, having switched to a plant-based diet in 2020 at the ripe old age of 51. I have also been a proponent of repairability for many years, as my children with their old franken-Nintendo-DSes can attest.\n\nYou can read all about our kit on the web-site and in the GitHub repo . In summary, it’s about creating a transparent and trustworthy platform for trading resources and knowledge, as well as providing access to a community of experts. This platform will enable producers and consumers to build and buy products in a sustainable way for our society — by reducing waste, increasing the use of recycled materials and improving the overall repairability of products.\n\nFrom talking to the Subject Matter Experts and researching what was out there, we were surprised to find that everything in the recycling and reusability space is still very fragmented. There are lots of standards and standards bodies. There are some materials-trading platforms. There are quite a few aggregated datasets. There are many producers, consumers and repairers. But there is nothing bringing all the stakeholders together with the type of user experience that everyone expects in 2021.\n\nConsumers are slowly but surely starting to demand that producers stop merely greenwashing and take practical steps towards reducing their environmental impact. It’s not just early exemplars like Patagonia doing this, you now have luxury brands like Kering releasing an interactive EP&L (Environmental P&L). Or Salomon releasing running shoes made from recycled/recyclable materials and only two materials in total. And with the EU making major efforts around repairability, even laggards will be forced to up their game.\n\nA platform that enables any business to begin taking part in the circular economy and enables any consumer to find those brands that align with their values could be very powerful indeed.\n\nhttps://www.youtube.com/watch?v=3gcJrSZfsx8\n\nThe Team\n\nOne of the most exciting aspects of working on Call for Code is in connecting with people around the world on creating these kits. Just to give a flavour of global spread, our team involved:\n\nNicole Pitter Patterson, Co-founder and Director, Caribbean Girls Hack\nStijn Polfliet, Director, Developer Platform and Ecosystem, New Relic\nDebjani Chatterjee, IBM Developer Advocate, Platform Development\nDipali Chatterjee, IBM Developer Advocate, IBM Cloud\nDaniel Rodrigues, IBM Developer Advocate, Artificial Intelligence\nGeorges-Henri Moll, IBM Developer Advocate, Data Science\nAtishay Abbhi, Disaster Risk Management Specialist, The World Bank\nNiraj Swami, Conservation Technology Strategy and Enablement, The Nature Conservancy\nConor O’Neill, CPO, NearForm\n\nFrom Ireland to Jamaica, Spain, India and on to Brazil, the US and beyond, we had a wonderful diversity of views and life experiences. And deftly pulling all of those views and experiences out of us was IBM’s Gabriele Crisman.\n\nGetting involved\n\nBy any measure, Call for Code has been an amazing success. Having the United Nations Human Rights Office involved means that it’s not just groups of technologists devising utopian solutions to non-problems. The NGO Subject Matter Experts are critical to keeping it all very real.\n\nIf you’re reading this and thinking “That’s all great but I’m not a developer, I can’t get involved,” I have good news for you! It might be Call for Code but none of these projects can succeed and scale without designers, communicators, organisers and many other roles. So please, no matter what your background, sign up and join one of the many projects that will be kicked off in the coming weeks.\n\nDon’t forget, the winning team in the Call for Code Global Challenge receives $200,000 and support from the IBM Service Corps, technical experts and ecosystem partners to incubate and deploy their idea.\n\nNearForm and Open Source\n\nNearForm has been making major contributions to Open Source projects like Node.js for nearly a decade. Our work on Covid Green brought that to the attention of many more people, and it’s very satisfying to see that some of our Open Source is also being used in these Call for Code Starter Kits.\n\nPlease feel free to reach out to me about anything mentioned above — and if you do take part in Call for Code, let us know on social media." ], "categories": { "primary": "oss", "others": [ "ai", "design", "product" ] }, "verticals": { "primary": "sustainability", "others": [] } }, "insights-is-serverless-right-for-your-organisation": { "href": "https://nearform.com/insights/is-serverless-right-for-your-organisation", "postType": "blog", "slug": "insights-is-serverless-right-for-your-organisation", "date": "2021-03-23", "title": "The business case for going serverless is becoming more compelling. Find out how you should approach it for optimum results.", "authors": [], "content": [ "Businesses benefit by assessing the use case for serverless and approaching it in the right way.\n\nThe business case for going serverless is becoming more compelling. Driven by the promise of freedom from data centres and their attendant costs and complexities, the global serverless computing market size is projected to grow at a CAGR of 20.8% between 2021 and 2026.\n\nThe first cloud serverless platform, AWS Lambda, remains the standard against which all other services are measured. Now, Microsoft’s Azure Functions and Google’s Cloud Functions offer other options for companies that have traditionally run code and hosted websites on their own servers.\n\nFor organisations that have started to embrace cloud native , serverless is the natural evolution. Allowing developers to build and run applications without having to manage servers, serverless transfers responsibility for server provisioning and compute management away from the organisation to a cloud provider.\n\nServers continue to be used; but, unlike cloud computing run on self-managed servers, the resources are allocated on-demand and billed based on usage. Because you are not hosting your own infrastructure, those servers you have moved to the cloud cease to be your concern. For most companies, hosting your own servers does not provide a competitive advantage, so serverless makes sense . But you need to know how to embrace serverless for your specific needs and prepare for it in the right way.\n\nWhich benefits make serverless so compelling?\n\nManaging and maintaining servers takes considerable time, effort and expense. It’s also a complex process to add and adjust server space as services scale. Going serverless removes a considerable burden of budget and project planning from your organisation.\n\nQuicker deployment\n\nWith serverless, all of the infrastructure exists already, so you can get to market more quickly. Engineers can focus on implementing business logic without needing to address underlying infrastructure challenges. You don’t need to upload code or containers to servers or do any backend configuration when you want to release a working version of an application.\n\nDevelopers can deploy code and release a new product with no delay. Whether they want to upload all the code together or one function at a time is up to them because the application is a collection of functions provisioned by the vendor rather than a single stack. This facility also means that developers can update applications one function at a time, without having to change the entire application.\n\nScalability\n\nServerless infrastructure allows applications to scale up or down automatically as the user base grows or declines. This increases your organisation’s business agility because it can adjust to customer needs with ease.\n\nWith serverless, the provider’s servers can start up, run and terminate functions that need to be run in multiple instances, often using containers. The serverless application can therefore handle sudden spikes in requests and single requests from single users with similar ease. A conventionally structured application with a set amount of server space can be swamped by a sudden increase in usage.\n\nCost savings\n\nServerless follows a pay-as-you-go model to bill for usage, with developers charged only for what they use. In stark contrast with traditional architecture — which requires developers to determine their usage and pay for it in advance — serverless provisioning is dynamic, exact and takes place in real time, so you don’t have to pay for unused capacity.\n\nLongevity\n\nServerless is no longer a bleeding-edge technology that larger enterprises fear adopting. Now used by such household names as Netflix, Lego and Coca-Cola, it has been derisked to such a degree that businesses can embrace it without worrying about its imminent demise.\n\nWith major players such as Amazon, Google and Microsoft behind it, the technology will be supported for the long term, and its widespread adoption means there is a rich and supportive serverless community that engages members through meetups, discussions, articles, user groups and podcasts.\n\nHow do you know whether serverless is right for you?\n\nIf you decide to go serverless, there are trade-offs for the increased efficiency you will enjoy.\n\nYou won’t have visibility by default into all of your application’s performance characteristics, making it a significant challenge to ensure that all the elements of your system are working well together. This compromised observability can be managed by close attention to logging, monitoring and traceability. These activities are extremely important to ensure that you are prepared should something go wrong.\n\nSecurity is also regularly raised as a consideration for anyone considering serverless. However, serverless offers many opportunities for improved security — not least because security and compliance are shared , with the vendor taking responsibility for the infrastructure that runs all of the services offered in the cloud. The customer’s responsibility depends on the services they use, the integration of those services into their IT environment and relevant laws and regulations.\n\nWith serverless in place, your developers may have greater control, so it is good practice to implement the Principle of Least Privilege to mitigate any security concerns. This reduces the risk of a data breach because nobody gets more access than they need to complete a specific job. This reduces the risk of hackers gaining access to critical systems or sensitive data because it stops any compromises from spreading to the system at large.\n\nVendor lock-in is often cited as a barrier to serverless. It is true that the cost of switching serverless providers can be so high that you are effectively stuck with your vendor, but the risks associated with vendor lock-in may be overblown. Rather than worrying about being tied to a serverless vendor, you should be more concerned about the risk of a competitor going to market earlier and iterating quicker because they have gone serverless and you have not. A rival who leverages serverless to move faster by focusing on their business and customer needs is likely to be far more of a threat to you than potential vendor lock-in.\n\nHow should you approach serverless?\n\nTo generate maximum value from serverless , you need to be properly organised. Ensure that you have a proper structure for artifacts such as code, architecture and other components you’ve been using up to now. You won’t be able to harness the benefits of serverless without oversight of what you have and the discipline to organise it in the right way. Documentation is key.\n\nEngaging an experienced partner to help you leverage the benefits of serverless can help. At NearForm, we work with our customers to help them realise the cost efficiencies, scalability, enhanced UX and product evolution that serverless can facilitate. We help them to design and deliver products in highly performant serverless environments, strengthen their teams and migrate existing applications from legacy systems to a serverless architecture.\n\nOne of the tools we use to do this is Mira, an opinionated AWS cloud native open-source project foundation that we have created for developing AWS cloud native solutions. Harnessing the full power of AWS, Mira provides a working AWS configuration that sets businesses on the right course to fulfilling the requirements of the AWS Well-Architected Framework and enables them to deliver solutions faster.\n\nDevelopment gets off to a flying start, driven by the AWS Cloud Development Kit and supported by ready-to-use CLI, preconfigured delivery pipeline, developer tooling and sample applications. With underlying services configured correctly for scalability and cost efficiency, the focus is on business logic rather than infrastructure. For organisations daunted by the prospect by serverless, Mira removes much of the uncertainty.\n\nWhen approached correctly, the development velocity and business value serverless offers could open up opportunities that your organisation never even considered before. The secret is to start small, perhaps with a greenfield project. Set realistic expectations and choose an offering with the potential to generate the best value from a serverless solution — for example, a project with recognised scalability issues. Once you see the benefits of serverless for yourself, you will be confident embracing it across your organisation." ], "categories": { "primary": "cloud", "others": [ "backend", "devops" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-github-dependabot-automation": { "href": "https://nearform.com/insights/github-dependabot-automation", "postType": "blog", "slug": "insights-github-dependabot-automation", "date": "2021-03-25", "title": "NearForm's GitHub Dependabot app is a useful tool for unattended approval and merge of dependency updates.", "authors": [], "content": [ "Our GitHub Dependabot app is a useful tool for unattended approval and merge of dependency updates.\n\nDependabot is a tool for automatic dependency management that was created initially as an external service before being acquired and integrated natively into GitHub. We have been using it extensively since its early versions to automatically upgrade versions of the packages used by our repositories.\n\nWe believe that continuous dependency upgrades allow our applications and packages to stay up to date with the latest features, bugs and security fixes by spreading the effort of doing so over a longer period of time. Conversely, delaying package updates postpones the effort to a time when upgrading may be too costly, or even impossible.\n\nWe have successfully used dependency automation via services including Greenkeeper (now Snyk) and Renovate, but since Dependabot was integrated natively within GitHub last year we started using it almost exclusively.\n\nThe common element across these tools is that they scan your repository for dependency descriptor files and create pull requests to update outdated packages. We work primarily with JavaScript, so our dependency descriptors are usually package.json , package-lock.json and yarn.lock .\n\nAt NearForm, we maintain tens of open source npm packages and many other applications we build internally and for our customers. We also contribute to many open source projects, including a large number of repositories in the Fastify ecosystem.\n\nDoing manual maintenance on all of them involves considerable effort, so we looked into ways to automate this process.\n\nHow Dependabot works\n\nDependabot is configured using a .github/dependabot.yml file in any repository. This file contains configuration options to choose which package ecosystems to include (e.g. npm , github-actions ) and a set of configuration options to tune the schedule, ignores and so on. For a list of all configuration options, see the documentation .\n\nA dependabot.yml file may look something like this:\n\nversion: 2\nupdates:\n - package-ecosystem: npm\n directory: '/'\n schedule:\n interval: daily\n ignore:\n - dependency-name: 'husky'\n versions: ['5.x']\n - package-ecosystem: 'github-actions'\n directory: '/'\n schedule:\n interval: 'daily'\nymlCopy to clipboard\n\nWhen a dependency is out of date, Dependabot opens a pull request on the repository, which updates the files where the dependency is tracked.\n\nA typical Depandabot PR will look like this:\n\nThe advantage of using a tool like Dependabot to automatically attempt to upgrade dependency versions is that by opening a pull request, all the checks in place in the repository will run against the updated versions. For example, these checks could run automated tests against the upgraded dependency, which provides a certain degree of confidence about whether the upgrade is safe or if manual changes are needed.\n\nHow we use Dependabot\n\nMost of the repositories we contribute to contain npm packages. Because of their standalone nature they often have very high test coverage, meaning that a green build usually implies that the change made in a PR is safe to integrate into the base branch.\n\nWe usually configure the repositories so that a PR cannot be merged until:\n\nSome required status checks have succeeded. These often include linting and automated tests.\nThe PR is approved by a contributor of the repository.\n\nWhen both requirements are satisfied, the PR can be merged and a repository contributor usually does that manually.\n\nGitHub has recently introduced the ability to automatically merge PRs whose requirements are satisfied without human intervention. We have used this feature in some repositories, but we haven’t found it extremely useful in the scope of the automation that we have set up for Dependabot PRs.\n\nAutomating Dependabot merges\n\nManually reviewing, approving and merging Dependabot PRs over a large number of repositories is a lot of effort, so we looked into ways to automate this.\n\nOur first approach was to use a custom GitHub action that we could include in any workflow. We configured it in this way:\n\nbuild:\n # ...\nautomerge:\n needs: build\n runs-on: ubuntu-latest\n steps:\n - uses: fastify/github-action-merge-dependabot@v1.2.1\n if: ${{ github.event_name == 'pull_request' }}\n with:\n github-token: ${{ secrets.GITHUB_TOKEN }}\nymlCopy to clipboard\n\nThis would trigger the automerge job after the build job completed successfully and invoke the custom fastify/github-action-merge-dependabot action if the run was triggered by a pull request. It would also provide the built-in GITHUB_TOKEN secret to the action, which could use it to approve and merge the PR.\n\nThis approach worked flawlessly until recently, when GitHub introduced restrictions on the permissions of the GITHUB_TOKEN secret and the visibility of secrets in workflow runs triggered by Dependabot PRs.\n\nFrom one day to the next, all our automatic approvals and merges were failing because of GITHUB_TOKEN loss of write permissions on the repositories.\n\nEvaluating alternatives to GITHUB_TOKEN\n\nAs described in Keeping your GitHub Actions and workflows secure: Preventing pwn requests , GitHub recommends two alternative options:\n\npull_request_target workflow trigger\nworkflow_run trigger to run a workflow as a consequence of another workflow finishing\n\nWe evaluated both options and deemed them unsuitable for our purposes for similar reasons: Both of them required changes to the rest of our workflows, and we didn’t want the automerge behavior to affect how the workflows should be written.\n\nThe pull_request_target option requires the checkout action to be provided with the commit SHA.\nThe workflow_run option requires the originating workflow to publish an artifact containing the number of the pull request, which is then read and processed by the second workflow.\n\nAnother alternative we evaluated was creating a GitHub App and using it to generate a temporary token with write permissions, to be provided to our custom action as a replacement for the now read-only GITHUB_TOKEN .\n\nWe tried using tibdex/github-app-token to do this but we faced the second issue in GitHub’s changes around Dependabot PRs: No secrets besides GITHUB_TOKEN are available.\n\nTherefore, all we are left with is a GITHUB_TOKEN which has read-only permissions and can’t do what we need — approving and merging the pull request.\n\nUsing a GitHub App\n\nWith possibly hundreds of builds broken because of the automerge action failing, we were under pressure to find a solution, so we came up with the idea of implementing a GitHub App running on a server. Once installed on a repository or an organisation, the app would get write permissions on the repository and would be allowed to approve and merge pull requests.\n\nThe problems to solve were:\n\nHow to trigger approvals and merges from the app\nHow to do it in a secure way\n\nThis is what we came up with:\n\nThe GitHub App needs to be installed on the repository and running as a Web API on a server. It requests permissions to approve PRs and merge them.\nA Dependabot PR executes a GitHub workflow which invokes the custom GitHub action with the read-only GITHUB_TOKEN.\nThe custom GitHub Action sends a HTTP request to the GitHub App including the GITHUB_TOKEN.\nThe GitHub App checks that the token has access to the repository and then approves and merges the PR.\n\nThis approach eventually worked, and we have put it in place to restore full automation of Dependabot in our repositories. We are sharing it as open source for anybody who wants to use it, leaving the option to self-host the GitHub app.\n\nfastify/github-action-merge-dependabot contains the custom GitHub action that you can use in your GitHub workflows.\nfastify/dependabot-merge-action-app contains the source code of the HTTP API (built with Fastify) for the GitHub app, which we host on Heroku for convenience.\nA note on security\n\nUsing this approach, we are basically working around the security limitations imposed by GitHub around GITHUB_TOKEN permissions and visibility of secrets in workflow runs. We are basically trading a read-only token for one with write permissions, even though the latter never leaves the GitHub App.\n\nWe believe this is an acceptable compromise between functionality and security because:\n\nThe GitHub app can only operate on repositories it’s installed on.\nThe repository on which it operates is inferred from the GITHUB_TOKEN it is provided, which is scoped to just the repository where the workflow is running, thereby preventing use on another repository. Also, this token is valid only for the duration of the workflow run, thereby preventing reuse.\nThe operation of the GitHub App is limited to Dependabot PRs only, as the app does an internal check on the author of the PR to ensure it’s Dependabot.\nIn order to be merged, PRs must have satisfied the merge constraints, and if they do, we will merge it. It doesn’t make much difference whether it is us or an attacker merging.\n\nTherefore, we believe that the surface of attack and the possible damage are so limited that the risk of a Dependabot PR being unintentionally merged is acceptably low." ], "categories": { "primary": "devops", "others": [ "oss", "backend" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-strengthening-security-in-open-source": { "href": "https://nearform.com/insights/strengthening-security-in-open-source", "postType": "blog", "slug": "insights-strengthening-security-in-open-source", "date": "2021-03-30", "title": "Supporting security in open source", "authors": [], "content": [ "Companies need to incentivise maintainers to keep open source software secure.\n\nEvery enterprise today is using open source software (OSS) or software with open source components, with Facebook, Google and IBM just some of the household names relying on and contributing to open source.\n\nThe OSS movement has delivered some of the most important technologies, including operating systems, web browsers and databases, and is responsible for the breakneck speed of technology development over the last several decades. Not only that, a 2020 Red Hat report found that 95% of survey respondents (up from 89% the previous year) considered OSS to be strategically important to their organisation’s overall enterprise infrastructure software strategy.\n\nOSS gives enterprises the agility to succeed\n\nHistorically, enterprises have built proprietary solutions to protect their intellectual property, but the accelerating speed of software development means trying to do everything on your own is an increasingly difficult and costly option. By the time many organisations are ready to launch a project, a rival has overtaken them.\n\nIn contrast, using OSS to leverage existing code means organisations can prioritise work on their IP and product-differentiating features — which means lower costs and a shorter time to market. Open source provides many of the building blocks needed for a new project, so it can be rolled out faster.\n\nOnce a proprietary project is deployed, the cost of maintaining the software can be significant. As time goes on, support costs for legacy software increase in line with a decline in the benefits gained from that support. However, by adopting OSS and sharing the cost of maintenance across multiple companies, organisations can target their investments more effectively and keep their focus on innovation.\n\nThe OSS movement provides maintenance support through a community of security researchers and maintainers who identify and fix bugs. With a broad community of developers maintaining the code, there are more opportunities to catch potential bugs before they become a problem.\n\nEnterprises that take a proactive approach to open source and engage actively in it also get the opportunity to influence the future of the open source projects that power their infrastructure, as well as contribute tools that make software development better for all teams. This kind of influence helps to attract and retain top talent, as well as build an organisation’s reputation.\n\n“
Companies that strive to establish themselves as good open source citizens, contributing to the good of the projects and the industry, are perceived as good companies. Click to tweet
”\n\nGaps in OSS security are becoming apparent\n\nThe wide adoption of OSS across all industries has subjected popular projects to the scrutiny of malicious actors that want to use them as an attack vector to gain access to companies and their data. Because the code is open source, attackers can study it and use its vulnerabilities to target the company and take data, launch ransomware and commit other cyber crimes.\n\nIn an ideal world, security researchers study vulnerabilities in OSS dependencies and notify maintainers who fix the vulnerabilities. Maintainer-led disclosures ensure that vulnerabilities are fixed and that a patched version of the library is deployed and published in the cloud. However, if the maintainer does not fix it, the security researcher reports a CVE (Common Vulnerabilities and Exposures), notifying everyone that the library is vulnerable and that there is no patch available for it.\n\nSecurity vulnerabilities benefit cyberattackers, the vendors of security products and the security researchers who are sponsored or employed to find the bugs, but there is little incentive for maintainers to fix the vulnerabilities. They want their software to be used, but they don’t want the aggressive emails they often get when they don’t patch vulnerabilities quickly enough. This situation needs to change.\n\nDon’t be the person who expects somebody else to do the work. If you use OSS, you should be prepared to help in maintaining it.\n\nEverybody gains when everybody contributes\n\nThe more people involved in the open source community, the more secure the code becomes. With greater numbers of people watching security alerts and, more importantly, fixing the vulnerabilities that arise, enterprises can be confident that the software is protected.\n\nFurthermore, organisations that engage actively with open source and support it in practical ways can influence the direction and outcomes of the open source projects that drive their infrastructure and contribute tools that enhance software development for everyone.\n\nCompanies need to step up\n\nThe open source community operates in a culture of collaboration, which can be alien to companies pursuing commercial goals. But if enterprises want to ensure the health and security of the open source they use in their overall infrastructure software strategy, they must be prepared to invest in it.\n\nThese companies have an interest in ensuring bugs are fixed and that projects evolve in the direction they want them to. They should contribute to open source projects because it is in their business interest to do so.\n\nLarge enterprises such as Intel, Yahoo and Snapchat all run bounty programmes to incentivise the identification of security vulnerabilities. In November 2019, the Github Security Lab launched a specialised bounty programme that incentivises eradicating security vulnerabilities at scale, rather than paying hunters to find them. It has since increased the bounty rewards for the High and Critical levels of its programmes. Hacker-powered security platform HackerOne has also joined forces with the Node.js foundation to create a bug bounty program to make Node.js third-party modules more secure.\n\nThe issue with most bounty programmes is that they reward those who find bugs — not those who fix them. The obligation falls to companies to invest resources in incentivising maintainers too, because they are the people who ensure the software companies and their customers rely upon is secure.\n\nContributing to the open source community in such a practical way is not just the right thing to do — it translates into more innovative, interoperable, scalable and secure solutions for everyone." ], "categories": { "primary": "oss", "others": [ "security" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-optimising-tech-for-retails-omnichannel-future": { "href": "https://nearform.com/insights/optimising-tech-for-retails-omnichannel-future", "postType": "blog", "slug": "insights-optimising-tech-for-retails-omnichannel-future", "date": "2021-04-06", "title": "Optimising tech for retail’s omnichannel future", "authors": [], "content": [ "Retailers can adapt quickly to changing consumer demands with a tech stack that facilitates agility, innovation and growth.\n\nRetailers have spent years chasing consumer demand for a seamless shopping experience across every channel — with mixed success. The pursuit of a 24/7 personalised experience that integrates physical and digital channels to give customers precisely what they want when they want it is impossible for retailers who lack the ability to respond effectively to relentless change.\n\nHowever, a tech stack that facilitates rapid adaptation, innovation and growth can help retailers remain relevant to customers into an uncertain future.\n\nThe challenges for today’s retailers\n\nThe Covid-19 pandemic accelerated the shift to online shopping and home delivery, a shift that is likely to persist post pandemic. Shoppers who had positive experiences when they had a reason to experiment with new ways to shop, such as for groceries and essentials, are likely to continue the practice once they are no longer compelled to shop remotely.\n\nChina’s experience suggests retailers should expect year-on-year growth of between 10% and 20% in online activity in most categories as the market moves beyond Covid-19 restrictions.\n\nThe realisation that more flexible order fulfillment options and working arrangements would have made life considerably easier for retailers during the crisis is awakening a stronger sense among businesses that they need to up their game significantly to deliver what customers want. More advanced technology would have made them more flexible and better able to manage steep fluctuations in demand.\n\nPressure on retailers is driven not just by consumer demand but by the cost of trying to satisfy that demand while competing with discounters and digitally native rivals. Retail margins declined from 5.1 per cent to 3.4 per cent between 2013 and 2019, establishing a continuing trend impacted by factors like increased competition and the high cost of running omnichannel operating models.\n\nAs technology advances, retailers will need to reconsider the very nature of their retail offerings and revisit value propositions for both customers and employees. Instead of just automating their existing operating models, many need to overhaul the whole suite of tasks required to run a store.\n\nHow retailers can differentiate themselves\n\nWith consumers now accustomed to alternating between online retailers and physical stores, they see no reason why the brands they buy shouldn’t do the same. The hybrid model of shopping that has emerged from the pandemic makes it increasingly clear that retailers need to focus on omnichannel excellence to give shoppers their desired combination of digital commerce and brick-and-mortar stores. Some of the key retail technology trends that have emerged include an increased reliance on shopping and payment apps, as well as more retail mobile apps.\n\nSome shoppers are keen to return to physical stores once restrictions are eased, whereas others now prefer the convenience and safety of shopping in comfort at home. Research indicates that 70% of consumers plan to continue or increase their online shopping after the pandemic restrictions end. But not all of these will avoid stores completely; some enjoy the experience of browsing in a real store.\n\nNonetheless, consumers will want a safer, more enjoyable in-store experience to entice them off the sofa to do their shopping. Retailers will need to provide an omnichannel experience that includes unique product offers and other attractions to keep their customers from straying to digitally optimised rivals.\n\nThey could learn from Nike, which expanded its omnichannel experience in 2006, when it partnered with Apple to introduce the Nike+ program. Customers could connect their Nike sneakers to an iPod and track activities such as distance run and calories burned. By allowing users to sync their data to the Nike+ website, Nike created a digital community of athletes.\n\nNike doubled down on its digitalisation during the pandemic while also focusing on member engagement , with the aim of strengthening relationships with customers in value-added ways. In its physical stores, Nike Live bases its inventory on local member activity and buying patterns.\n\nMembers can use Nike’s mobile app in stores to scan barcodes for product details and reservations and to avail of promotions. This hybrid of physical and digital experiences encourages a sense of community among customers and boosts brand loyalty.\n\nThe role of an advanced tech stack in facilitating omnichannel retail\n\nThe key to succeeding in an omnichannel retail environment is to build agility and resilience so you can adapt and scale as required. With 77% of executives emphasising the importance of their technology architecture to their organisation’s overall success, industry competition is now a contest between technology stacks.\n\nRetailers will need to re-architect the entire business to get closer to their customers, remove internal silos and align staff behind the organisation’s goals. This is possible with a well-designed technology stack that can accommodate the demands of an ever-changing retail reality. When planning such a tech stack for your retail business, certain elements will determine success.\n\nBuild platforms\n\nPreparing your organisation for an omnichannel future extends beyond devising solutions to specific problems. Instead, you need to focus on developing a platform of technology, people, processes and tools that can scale and adapt quickly to suit your business. A scalable platform enables a holistic approach to technology, so you can be confident your tech stack will meet future business needs and avoid obsolescence. Such a platform evolves in line with your organisation’s requirements. Whether you decide to optimise your existing stack or build an entirely new digital platform, it needs to work now and into the future.\n\nAdopt a cross-platform approach\n\nMany companies maintain multiple teams to develop, test and run different versions of the same app for Android, iOS and the web. This is a costly and cumbersome approach to the frontend and can be avoided with a cross-platform strategy , which involves developers reusing the same code across each OS.\n\nAt NearForm, we recommend using a reliable technology such as React Native , which leverages the native resources of the mobile device and allows developers to create full, native mobile apps for both iOS and Android using JavaScript. With React Native, teams can iterate faster, reuse code across platforms and share more knowledge and resources.\n\nEmbrace design-led development\n\nDesign-driven development treats development as an interdisciplinary, integrative process. It is an approach that has proved very successful for many NearForm projects across a range of clients, including the Covid-19 contact tracing apps .\n\nThe process starts with a discovery workshop that gives the stakeholders a roadmap for development and tangible assets for reaching their objectives. The engagement unites designers and developers in ensuring that the finished product aligns with the end user’s requirements. By adopting a design-led approach to developments, retailers shift their mindset to one that focuses on user-centric strategies across the organisation.\n\nChoose a flexible, modern architecture\n\nOptimising your tech stack to take advantage of an omnichannel retail future prioritises characteristics that will encourage your organisation to be flexible. For example, microservices support an architecture that structures an application as a collection of lightweight, independent services that centre on particular business-focused objectives. This approach enables flexibility and means teams can be agile and deliver the change your retail business needs without undergoing massive disruption or cost.\n\nYour architecture should support a continuous change engine that allows you to align your teams with your business KPIs rather than with technology silos. Adopting a multiplatform approach with React/React Native teams means your people develop cross-platform from a single codebase, so they focus on specific business logic rather than the technology required to develop separately for each platform.\n\nWhen considering your architecture, it’s important to assess the overall ecosystem, the talent that you require and the kind of organisation you could create with the help of the right technology and the right processes. Ultimately, you need to figure out where you want to be in order to identify the technology to get there.\n\nPrioritise componentisation\n\nComponentisation is an approach to software development that involves separating software into identifiable modules that developers write and deploy independently, then configure with network connections and workflows.\n\nIt means that components can be reused and connected using standard interfaces, facilitating easier collaboration, accelerated product development and increased software reliability in the short term. In the longer term, componentisation enables greater flexibility because components can be changed or replaced easily to fulfill shifting business requirements.\n\nScale with cloud-based apps\n\nEven with limited in-house resources, engaging with a partner to provide you with design artifacts means you can build out the cloud-based web applications you need into the future. Developing capability in your teams enables them to become self-sufficient and create new concepts and web pages independently, as required. By combining recurring patterns and using elements from an expanding library, they can create user-friendly cloud-based apps that scale with your business.\n\nThis is what we did for Spanish technology company Datumize . After an initial discovery workshop, NearForm redesigned and built the user interface for the company’s self-service dark data collection and processing platform, Zentral, and used the Zentral codebase to develop a modern, touch-compatible, React web application that connects to the microservices a Datumize user requires to build and deploy their data pipeline.\n\nTo enable the scalability of the Datumize portfolio, NearForm supplied the team with a library of design artifacts they can use to create new concepts and webpages themselves in the future.\n\nSeizing the omnichannel opportunity\n\nEquipped with a robust and flexible tech stack, a forward-thinking retailer can respond to constant disruptions, establishing the sort of sustainable resilience it needs to drive innovation and growth.\n\nRetailers with the right mindset will see the level of disruption on the horizon as more than a challenge — it also represents an opportunity to adapt consumer value propositions and operating models so they can deliver an attractive, tech-enabled omnichannel offering that outperforms the competition." ], "categories": { "primary": "cloud", "others": [ "frontend", "mobile", "devops", "product" ] }, "verticals": { "primary": "retail", "others": [] } }, "digital-community-design-technologist": { "href": "https://nearform.com/digital-community/design-technologist", "postType": "blog", "slug": "digital-community-design-technologist", "date": "2021-04-08", "title": "Why Have Design Technologists?", "authors": [ "PAULA LAVALLE" ], "content": [ "A design technologist can move between the design and engineering worlds seamlessly. They can change their shape and blend in depending on the environment, and therein lies their power: they are powerful advocates for holistic thinking. They are the first point of contact for engineers because of their eye for design. They are the first point of contact for designers because of their ability to confirm feasibility and prototype rapidly.\n\nThe role of the design technologist is just another part of the process as they are made to interface with both the design and engineering teams. They are the glue that holds the design context as the product (and they) moves from idea to software. They can facilitate communication between design and engineering, but do not be mistaken: their presence alone cannot fix bad processes or make processes out of nothing.\n\nBringing designers closer to the screen\n\nDuring the initial phase of a product, design technologists enable designers to explore the potential and possibility. How does this idea feel? How does it flow? Is something missing? Could animations be added in certain areas? What’s possible? Design technologists bring the medium of the browser to the forefront for designers: Throw away the static mocks. They do not serve you, because we do not work in print.\n\nDesign technologists enable design teams to see, play, and explore ideas before committing to a decision. Most engineers hate throwing out their code, but design technologists love it. Throwing out code means we’re one step closer to the right answer. The product can validate thinking early in the process, before upsetting engineering with tentative, unsettled ideas.\n\nAs the product moves from design-ready to engineering-ready, design technologists can transfer to the engineering team. They can make accessible, beautifully coded, beautifully designed user interfaces.\n\nFocusing on the solution, not the pixels\n\nDuring the engineering phase of a product, design trusts them to bring their creations to life, and they no longer need to spend tedious amounts of time redlining minor differences between the static mockups and the final product; they can continue to do what they do best: creative thinking. Similarly, engineering trusts them to build user interfaces that are easy to reuse. Design technologists can build component libraries from the ground up. They are experts in CSS and HTML.\n\nDesign technologists have the design context from the initial phase of design, so they are able to embody that logic within the very code.\n\nDesign is not adverse to rules or structure. In fact, I’d say in the world of product design, the design process is to bring a murky problem into the light, really look at it, and impose a structure within the constraints of business and technical requirements, so that users do not have to go through the same murky process. That’s the job.\n\nEngineering loves and thrives on rules. The design solution is often far less about the actual pixels and more about the rules and constraints. Engineering can sometimes get bogged down in the pixel details, which is why “pixel-perfect” permeates design job listings. I’d argue a better approach would be to solve the pixels once in a robust Component Library and re-focus engineering on the point of the solution: imposing a structure so that users do not have to go through the same murky process that design did.\n\nFormalizing values into code\n\nAdditionally, many design teams have principles that serve as a checklist or guidance as they critique their own and the rest of the team’s work. They can sound pretty vague or abstract: Relevant, Human, Unified, Aesthetic Integrity, Consistency, Metaphors, etc., See and Experience, Dimension and Diagram, etc. are just some examples of many possibilities.\n\nHow do you bring these abstract principles into code? By the same process! Engineering can fall into the trap of ego-driven development, in which a chosen Coding Genius promises the path of a silver bullet that can solve all technical problems. Each project is different, just as each human (each user, each audience for a product) is different, so there is no such thing as one-size-fits-all development.\n\nInstead, I’d advocate for engineering to use the same design principles and guidelines to inform their technical decision-making: What technologies to use? How is the code documented and shared internally? Pull request reviews are akin to design critiques: code styles and preferences can be just as subjective as answering the question, “What makes good design?” Instead, focus the discussion around, “Does this follow our principles?” rather than “What’s Company A/Person X doing?”\n\nBaking principles into the developer experience means the code now reflects design and product thinking catered to a specific product, a specific audience, at a specific time; it seems inherently flawed to me to try to do otherwise. My favorite developer experiences are the ones where it’s hard to do the wrong thing, and it’s made clear why it was designed in a certain way.\n\nIn service of the user\n\nUltimately, design technologists are freeing designers to be more creative and aligning engineering with the design principles of the product: all in service of the best possible user experience. Designers can get closer to the product earlier in the process, and engineers have a good developer experience to easily do the right thing. The process repeats itself. At this point, do we even need to worry about facilitating communication anymore? Everyone is already working together toward the same goal, and the software is in service of the designers, the engineers, and ultimately, the user.\n\nMany thanks to the eyes of Joe \"Joebus\" Alterio, Scott \"why don't I have a nickname yet\" Stewart, Alex \"King Lande\" Lande, and \"Don\" Amy Dickson", "MOBILE\nDESIGN\nHow to Remain A Successful Product Designer In Our Current Digital Hellscape\nMARK PRESCOTT\n16 MAR 2021\nDESIGN\nHow To Create an Ideal Design to Dev Workflow\nJOE ALTERIO\n13 JUN 2019\nDESIGN\nREACT\nBest Practices for Making (super duper) Useful Dashboards\nPAULA LAVALLE\n3 SEP 2020" ], "categories": { "primary": "design", "others": [ "frontend", "product" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-how-key-design-trends-impact-software-development": { "href": "https://nearform.com/insights/how-key-design-trends-impact-software-development", "postType": "blog", "slug": "insights-how-key-design-trends-impact-software-development", "date": "2021-04-13", "title": "Current design trends share the same goal: to enhance the user's experience and make the applications easier and more pleasurable to use.", "authors": [], "content": [ "A designer looks at how the latest UX and UI trends can enhance the digital experience.\n\nOnce reserved simply for communication, mobile devices are now the preferred tool for everything from healthcare management and fitness tracking to online shopping. With people increasingly relying on devices for everyday tasks and activities, designers are asking themselves what can be done to make these experiences more memorable. And the latest UX and UI trends are offering some intriguing answers.\n\nCredits: Berkan\n\nThe next big thing\n\nUI design has become extremely simplistic over the years. The process of simplification started back in 2008, when Skeuomorphism used three-dimensional gradients and shadow techniques to make the items represented look like their real-life counterparts. Around 2012, flat design emerged, greatly reducing gradients and shadows, making them more subtle or removing them altogether to place a greater focus on accessibility and UX.\n\nAfter Skeuomorphism and flat design came Neumorphism, which takes trends from the early 2010s and gives them a 2020s twist. Essentially, it means taking flat icons, buttons and other UI elements, and giving them a makeover. Introducing subtle, coloured shadows and gradients, and a carefully harmonised colour scheme preserves a cartoonish simplicity while adding an eye-popping realism that gives the elements depth and makes them jump from the screen.\n\nThe Neumorphism trend not only makes the design more beautiful, it also makes the experience of using and interacting with it more enjoyable. A design principle that has always resonated with me is: What can I take away from the design without taking away from the impact? When I learned this principle, the focus was on designing icons that convey information in their simplest form, but it can be applied across a range of design concepts.\n\nCredits: Inna Kondratyeva View video example on Dribble\n\nDesign interaction\n\nInteraction with design is extremely important. This is where mobile has the edge over desktop: Although clicking is quick, easy and very functional, swiping is just far more fun. Other gestures available on mobile include scrolls, zooms and long taps. Gestures on mobile devices can have endless possibilities. Over time, as users’ learning habits evolve, gestures can have a dramatic effect on how we design and interact. For instance, the existence of a button could be questioned if a gesture works just as well and is understood by all users.\n\nCredits: Afrills\n\nBack to the future\n\nAlthough the Neumorphism approach has its advantages, sometimes designers go against the grain and reintroduce hints of retro inspiration to their designs. These styles could evoke analogue influences or abstract and geometric art. They represent familiarity and warmth to the user, making the design feel more real, homely and satisfyingly tactile.\n\nExamples of retro-inspired UX techniques include VHS pixelated typography, screen tearing, glitch transitions and primitive 3D animation. It is more common on interfaces that are generally more adventurous, such as those used by music and clothing brands.\n\nCredits: Andrea Eppy View video example on Dribble\n\nA new reality\n\nCovid-19 restrictions imposed in the past year have meant we need to adapt to a new, temporary reality. Among the features of this new reality are technologies based on virtual reality (VR) and augmented reality (AR).\n\nOnce viewed by some as futuristic gimmicks, VR and AR have evolved from simple entertainment to functional adaptations and extensions of how we go about everyday life. Incorporating VR and AR into design has had an important impact on how people visualise things, because they immerse the user in a deeper and hopefully more enhanced experience.\n\nAR is now being used in everything from museum tours to property rentals. Its growing ubiquity is likely to inspire UX designers to prioritise interfaces that can be easily adapted to a camera overlay.\n\nCredits: Alien pixels\n\nMaking data beautiful\n\nWith activities such as health and fitness becoming increasingly digitised, and users wanting to log and share data in a friendlier way, creative data visualisation has become more prominent in design.\n\nThe principle of reducing design to its simplest and purest form without reducing its effectiveness is being increasingly applied to data. Instead of spending hours looking at dull, confusing numbers, users can now see them presented in vibrant colours and simple shapes.\n\nThe future\n\nAll of these design trends share the same goal: to enhance the user's experience and make the applications easier and more pleasurable to use. Apps are no longer simply tools; they are evolving into companions we like to spend time with and, in the case of smartwatches and other wearables, even extensions of our bodies. As past trends re-emerge and continue to evolve, it will be interesting to see where these trends will take us." ], "categories": { "primary": "design", "others": [ "frontend" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-using-fastify-on-google-cloud-run": { "href": "https://nearform.com/insights/using-fastify-on-google-cloud-run", "postType": "blog", "slug": "insights-using-fastify-on-google-cloud-run", "date": "2021-04-15", "title": "Using Fastify on Google Cloud Run", "authors": [], "content": [ "A closer look at using HTTP/2, WebSockets and Server Sent Events with Fastify on Google Cloud Run\n\nGoogle recently announced end-to-end HTTP/2, WebSockets and streaming support in their Cloud Run service offering. This is great news because our projects often rely on cloud architectures, and being able to use these features natively opens up scenarios that were not possible until now.\n\nFastify is NearForm’s web framework of choice and it has supported these features for a long time, but when running in the cloud it needs the service provider to support them.\n\nThis blog post will show you how to use Cloud Run to run Fastify applications that use HTTP/2, WebSockets and streaming of Server Sent Events. The source code accompanying this post is available at nearform/fastify-cloud-run .\n\nFor a primer about using HTTP/2 in Node.js, we recommend watching James Snell’s Having fun with HTTP/2 in Node.js .\n\nHTTP/2\n\nCloud Run has always supported HTTP/2. Until now, all HTTP/2 connections were downgraded to HTTP/1 when they were sent to a container running your Cloud Run code.\n\nThe recent release of Cloud Run introduced end-to-end support for HTTP/2, meaning that we can fully leverage Fastify support for HTTP/2 when running in Cloud Run.\n\nBelow is a simple Fastify application to illustrate this. It can also be found in the repository accompanying this blog post.\n\nconst fastify = require('fastify')({\n http2: true,\n logger: true,\n})
fastify.get('/', function (request, reply) {\n reply.code(200).send({\n hello: 'world',\n httpVersion: request.raw.httpVersion,\n })\n})
fastify.listen(process.env.PORT || 3000, '0.0.0.0')\ntextCopy to clipboard\n\nThe main difference between a non-HTTP/2 application and the above example is the use of the http2 flag in the server option. Setting it to true enables HTTP/2 support in the server.\n\nRunning the example locally\n\nTo run this application locally, simply execute:\n\nnpm install\nnpm start\ntextCopy to clipboard\n\nThe server will start listening on port 3000, and you can check it works by making a request to the server via curl, for example:\n\ncurl -v --http2-prior-knowledge localhost:3000\ntextCopy to clipboard\n\nWe force curl to assume the server supports HTTP/2 using the --http2-prior-knowledge flag.\n\nThe response will look similar to the following:\n\n< HTTP/2 200\n< content-type: application/json; charset=utf-8\n< content-length: 37\n< date: Sat, 06 Feb 2021 08:42:31 GMT\n< {\"hello\":\"world\",\"httpVersion\":\"2.0\"}\ntextCopy to clipboard\n\nBecause the application’s code included Node’s raw request httpVersion property, we can be sure that HTTP/2 was used to handle the request.\n\nRunning the example in the cloud\n\nTo run the application on Cloud Run you must open a Google Cloud Shell and execute the following commands:\n\ngit clone https://github.com/nearform/fastify-cloud-run.git\ncd fastify-cloud-run/http2\ngcloud beta run deploy fastify-http2 --use-http2 --source=.\ntextCopy to clipboard\n\nWe use the beta version of the gcloud program because the new features are not yet available in the stable release. Also, we explicitly enable support for HTTP/2 by using the --use-http2 flag. You may need to provide additional input to prompts that Cloud Shell will output on the screen, or additional arguments to the command, depending on how your Cloud Shell is configured. A common mandatory argument is the Google Cloud project ID, which is specified using the --project argument and it needs to have billing enabled.\n\nCloud Shell will carry out a few steps to prepare the environment to run the application. It will upload the application’s source code to Cloud Run, it will build it, create a container inside which to run it, create a revision for the application and finally start serving traffic to it. When all the steps are complete, Cloud Shell will output a URL which can be used to send requests to the application.\n\nBuilding using Buildpacks and deploying container to Cloud Run service [fastify-http2] in project [fastify-secrets] region [europe-west1]\n✓ Building and deploying... Done. \n ✓ Uploading sources...\n ✓ Building Container... Logs are available at [https://console.cloud.google.com/cloud-build/builds/180cd8a5-c98f-4fef-aa38-44bf1157262c?project=1027534643217].\n ✓ Creating Revision...\n ✓ Routing traffic...\nDone.\nService [fastify-http2] revision [fastify-http2-00005-woz] has been deployed and is serving 100 percent of traffic.\nService URL: https://fastify-http2-p2vqyxuqoq-ew.a.run.app\ntextCopy to clipboard\n\nWe can then use the application’s url to send a request to it in the same way we did with the local version of the application.\n\ncurl --http2-prior-knowledge https://fastify-http2-p2vqyxuqoq-ew.a.run.app\n{\"hello\":\"world\",\"httpVersion\":\"2.0\"}\ntextCopy to clipboard\n\nBecause the Cloud Run version of the application is running over HTTPS, we can also use a browser to send requests to it. Most browsers support HTTP/2, but only when the server is running over HTTPS, which wasn’t the case with the locally running application. Don’t forget to remove the fastify-http2 service from Cloud Run to avoid further billing. You can do so via the Cloud Run Console.\n\nWebSockets\n\nWebSockets are another useful feature that Cloud Run didn’t support until recently. Fastify supports WebSockets via the fastify-websocket plugin . A simple WebSocket echo server written with Fastify is shown below:\n\nconst fastify = require('fastify')({\n logger: true,\n})
fastify.register(require('fastify-websocket'), {\n // echo server\n handle: conn => conn.pipe(conn),\n})
fastify.listen(process.env.PORT || 3000, '0.0.0.0')\ntextCopy to clipboard\n\nWhen it receives a message via WebSocket, this server will echo it back to the sender.\n\nWe can test it out locally by running the application:\n\nnpm install\nnpm start\ntextCopy to clipboard\n\nWe then connect to it with any WebSocket client. We used websocat in the example below:\n\nwebsocat ws://localhost:3000\nhello↵\nhello\nworld↵\nworld\ntextCopy to clipboard\n\nNote the use of the ws:// scheme to access the server via Websocket. Typing any text and pressing ENTER will send the message to the server over WebSocket, and the server will echo it back.\n\nRunning this in Cloud Run is very similar to the HTTP/2 example, with the exception that WebSockets don’t run on HTTP/2 but over HTTP/1:\n\ngit clone https://github.com/nearform/fastify-cloud-run.git\ncd fastify-cloud-run/ws\ngcloud beta run deploy fastify-ws --source=.\ntextCopy to clipboard\n\nTo test it, simply change the URL provided to the websocat command. For example:\n\nwebsocat wss://fastify-ws-p2vqyxuqoq-ew.a.run.app\nhello↵\nhello\nworld↵\nworld\ntextCopy to clipboard\n\nNote the use of the wss:// scheme, as the WebSocket example runs over secure WebSocket in Cloud Run, which is the same as HTTPS but for WebSockets instead of HTTP.\n\nServer Sent Events\n\nGoogle Cloud Run now enables streaming via Server Sent Events over HTTP/2 , which are a mechanism that web servers can use to push messages to clients.\n\nServer Sent Events existed and worked over HTTP/1 too, but they had limitations that were removed in HTTP/2. The example we show uses SSE over HTTP/2.\n\nAn example of using SSE over HTTP/2 with Fastify is shown below:\n\nconst fastify = require('fastify')({\n http2: true,\n logger: true,\n})
fastify.get('/', function (request, reply) {\n const interval = setInterval(function () {\n reply.raw.write(`data:${new Date().toISOString()}\\n`)\n }, 1000)
request.raw.on('close', () => {\n clearInterval(interval)\n reply.raw.end()\n })\n})
fastify.listen(process.env.PORT || 3000, '0.0.0.0')\ntextCopy to clipboard\n\nWhen it receives an HTTP request, this simple application starts a timer that sends a SSE containing the current server date back to the client approximately every second. When the client connection is closed, the timer is stopped so we don’t leak memory, and we close the response stream.\n\nOnce the application starts, we can then make a request to it:\n\ncurl -N --http2-prior-knowledge https://localhost:3000\n< HTTP/2 200\n< date: Sat, 06 Feb 2021 09:36:00 GMT\n<\ndata:2021-02-06T09:36:00.338Z\ndata:2021-02-06T09:36:01.348Z\ndata:2021-02-06T09:36:02.354Z\ndata:2021-02-06T09:36:03.366Z\ntextCopy to clipboard\n\nThe -N flag disables buffering of the response stream because we want to see the data as soon as the server sends it to us, without any buffering. This application can be run in Cloud Run in the same way as for the HTTP/2 and WebSocket examples:\n\ngit clone https://github.com/nearform/fastify-cloud-run.git\ncd fastify-cloud-run/sse\ngcloud beta run deploy fastify-sse --use-http2 --source=.\ntextCopy to clipboard\n\nAnd tested in the same way:\n\ncurl -N --http2-prior-knowledge \nhttps://fastify-sse-p2vqyxuqoq-ew.a.run.app\ndata:2021-02-06T09:46:36.917Z\ndata:2021-02-06T09:46:37.918Z\ndata:2021-02-06T09:46:38.917Z\ntextCopy to clipboard\nA whiteboard with Fastify over WebSocket\n\nWe used WebSockets to create a fun whiteboard demo. Fastify can be used as a static web server via fastify-static and with WebSockets via the fastify-websocket plugin . A simple way to broadcast the messages is to get the list of WebSocket clients, iterate through them and check that the current connection client is not the same as one of the client’s.\n\nfastify.register(require('fastify-websocket'), {\n handle: (connection, req) => {\n connection.socket.on('message', message => {\n fastify.websocketServer.clients.forEach((client) => {\n if (client.readyState === 1 && client !== connection.socket) {\n client.send(message)\n }\n })\n })\n }\n})\ntextCopy to clipboard\n\nThe code above avoids delivering the same message to the sender by filtering the WebSockets client list and excluding the sending connection from the list of recipients.\n\nRunning this in Cloud Run over HTTP/1:\n\ngit clone https://github.com/nearform/fastify-cloud-run.git\ncd fastify-cloud-run/whiteboard\ngcloud beta run deploy fastify-websocket-whiteboard --source=.\ntextCopy to clipboard\n\nWe can test it out locally by running the application:\n\nnpm install\nnpm start\ntextCopy to clipboard\n\nThe application starts at port 3000 by default if no PORT environment variable is present. The picture below shows it in action using two browser windows to collaborate on the same whiteboard:\n\nThe picture below shows an example of a piece of artistic work done with the whiteboard:\n\nThis post was cowritten with Paul Isache."
],
"categories": {
"primary": "backend",
"others": [
"cloud",
"devops"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"insights-applying-data-engineering-to-applications-with-kedro": {
"href": "https://nearform.com/insights/applying-data-engineering-to-applications-with-kedro",
"postType": "blog",
"slug": "insights-applying-data-engineering-to-applications-with-kedro",
"date": "2021-04-20",
"title": "Applying data engineering to applications with Kedro",
"authors": [],
"content": [
"Using data engineering tools to improve control over data has never been easier.\n\nThanks to a massive effort from the data science community, we are in the midst of a data revolution. Machine learning and artificial intelligence sectors are evolving to produce more advanced solutions, with a common factor being the way both sectors have adopted data pipelines to improve the way they use the data.\n\nIn computing, a pipeline (also known as a data pipeline) is a set of data processing elements connected in series, where the output of one element is the input of the next one.\n\n[caption id=\"attachment_300015073\" align=\"alignnone\" width=\"1230\"]\n\nHow data flows through operations[/caption]\n\nApplying data engineering concepts and technologies to our applications creates another level of control over the data. We can build transformation processes that are easily implemented, maintained and reused.\n\nIn this post, we show you how to complete a simple data manipulation task using an open source data engineering solution called Kedro .\n\nThe problem: A simple day-to-day task\n\nFor the sake of simplicity, let’s define a simple product dataset that contains these fields:\n\nItem that is our database ID\nProduct field that contains the product name\nCategory of the product\nUnits as the amount of products\nUnitCost is the base cost of the product\nMargin is the percentage of benefit we want to apply on the product cost\n\nAnd a few very simple TODO list tasks:\n\nRead some data from a spreadsheet.\nDo some cleaning (missing data) and fixes (names not capitalised).\nCalculate the final price (unit cost + unit cost * margin).\nSave the results to a JSON file.\n\nUsing Kedro makes it easier to manage large workflows and to build and reuse pluggable nodes.\n\nPreparing the working environment\n\nKedro is an open source Python framework for creating reproducible, maintainable and modular data science code.\n\nTo run Kedro on our computer, we need to have the following installed:\n\nPython > 3.6\nA virtual environment activated (try Anaconda if you are not familiar with venvs)\nThe project example downloaded to our computer\n\nAs with any Python package, we install Kedro with :\n\n> pip install kedro\ntextCopy to clipboard\n\nThe easiest way to verify if Kedro has been installed correctly is to run this command:\n\n> kedro info\ntextCopy to clipboard\n\nWe should see Kedro printed as an ASCII art graphic:\n\nOnce Kedro is installed, we can continue installing our project dependencies, which have been declared in our repository already. Simply run this command to install them:\n\n> kedro install\ntextCopy to clipboard\nA brief overview of Kedro\n\nThe framework has plenty of documentation and examples , but for this example, we need to understand just three main concepts:\n\nNodes are the building blocks and represent tasks or operations.\nPipelines organise the dependencies and execution order of our collection of nodes.\nDataCatalog is a dictionary to store datasets.\nOur implementation\n\nThe scaffolding of this example has been generated using the basic Kedro starter template . This step is not mandatory, but it is useful if we want to have good separation of concerns .\n\nIf you are starting a new project, Kedro provides a command to kickstart it, but you won’t need it for this demo:\n\n> kedro new\ntextCopy to clipboard\n\nKedro has been built on top of some very powerful libraries, including numpy and pandas , which will give us a huge performance boost and simplify the process. However, their scope is beyond this article. Let’s learn it in a practical way. As we explained previously, our Data Catalog will contain datasets definitions. Datasets can be defined either via YAML or programmatically, using an API. Both methods allow you to specify the dataset name, type, location, save and load arguments, as well as credentials.\n\nDataset type\n\nIn our example, we define our input and output datasets in catalog.yml . The first dataset will point to our spreadsheet, and the second dataset will point to our final JSON file.\n\nexample_spreadsheet: # Dataset Name\n type: pandas.ExcelDataSet # Library to handle the operations\n filepath: data/01_raw/kedro_example.xlsx # Relative file path\n Load_args: # Arguments used when we load data\n engine: openpyxl # A Python library to read/write Excel 2010 xlsx/xlsm files\n \n product_data: \t\t\t\t # Dataset name\n type: pandas.JSONDataSet \t\t # Library to handle the file operations\n filepath: data/03_primary/calculate_pricing.json # File to read/write data\n save_args: \t\t\t\t # Arguments used when we save the dataset\n orient: 'records' # listlike [{column -> value}, ... , {column -> value}]\ntextCopy to clipboard\n\nKedro is an opinionated framework, and it encourages good practices about folding structure. In this implementation, we are including our spreadsheet file in data/01_raw , and the output dataset will be saved, for example, in the folder data/03_primary ,\n\nIf we want to add validation in any interim step, we can define the node output in our Data Catalog. Otherwise, Kedro will keep this information in-memory using the MemoryDataSet .\n\nDefining our nodes or operations based on our TODO list example\n\nWe need to read data from a spreadsheet. By defining the dataset in the Data Catalog, we have taken care of this already.\n\nApplying data transformation to prepare the data for clients\n\nEach node will be a function that may accept some parameters and may return some data. We declare all inputs and outputs using Python typing .\n\nOur example nodes expect a panda dataframe , which is two-dimensional, size-mutable, tabular data. It also contains both row and column labels, and they will return a modified dataframe. Step 1: Let’s clean any row which has an empty product name. Calling the panda method dropna , we are able to remove missing values. With the subset parameter, we are pointing to the label selected.\n\ndef remove_missing_label(data: pd.DataFrame) -> pd.DataFrame:\n return data.dropna(subset=['Product'])\ntextCopy to clipboard\n\nStep 2: We also want to remove any products that have been sold out (no more units). Assigning the data frame to a filtered version of itself is quite convenient when we want to filter by conditions.\n\ndef remove_no_units(data: pd.DataFrame) -> pd.DataFrame:\n return data[data['Units'] > 0]\ntextCopy to clipboard\n\nStep 3: Product names are not well formatted either. Following the same approach, we create another function in which we apply a lambda function to capitalise each name.\n\ndef capitalize_product_names(data: pd.DataFrame) -> pd.DataFrame:\n data['Product'] = data.Product.apply(lambda x: x.capitalize())\n return data\ntextCopy to clipboard\n\nStep 4: Calculate the final price of each product. Adding an extra column is simple. In a couple of lines, we can calculate the final price, which basically is the cost of the product plus the benefit (unit cost * margin). Finally, we drop these internal fields.\n\ndef calculate_pricing(data: pd.DataFrame) -> pd.DataFrame:\n data['Price'] = data.UnitCost + data.UnitCost * data.Margin\n return data.drop(['UnitCost', 'Margin'], axis=1)\ntextCopy to clipboard\nSave the final output into a JSON file\n\nAgain, this has been done already. We defined this output in our data catalog, so Kedro will export it in the format selected.\n\nConnecting our nodes through a pipeline\n\nAt this point, we have defined our data inputs and outputs and our operations or nodes, and now we are going to connect them, creating a data pipeline as follows:\n\ndef create_pipeline(**kwargs):\n return Pipeline(\n [\n node(\n remove_missing_label,\n \"example_spreadsheet\",\n \"remove_missing_label\",\n ),\n node(\n remove_no_units,\n \"remove_missing_label\",\n \"remove_no_units\",\n ),\n node(\n capitalize_product_names,\n \"remove_no_units\",\n \"capitalize_product_names\",\n ),\n node(\n calculate_pricing,\n \"capitalize_product_names\",\n \"product_data\",\n ),\n ]\n )\ntextCopy to clipboard\nRegistering and running our pipeline\n\nThe final step is to register our new pipeline into Kedro’s main execution. Reusing the default class ProjectHooks , we import and instantiate our new pipeline. Basically, it will return all defined nodes, and Kedro will organise them depending on their inputs and outputs.\n\nfrom kedro_nearform_example.pipelines import data_engineering as de\n \n class ProjectHooks:\n # With this decorator we declare a hook and we use the custom class register_pipelines to define our implementation\n @hook_impl\n def register_pipelines(self) -> Dict[str, Pipeline]:\n \"\"\"Register the project's pipeline.\n Returns: A mapping from a pipeline name to a ``Pipeline`` object.\n \"\"\"\n data_engineering_pipeline = de.create_pipeline()\n \n return {\n \"de\": data_engineering_pipeline,\n \"__default__\": data_engineering_pipeline,\n }\ntextCopy to clipboard\n\nAnd that’s it. Let’s run our program:\n\n> kedro run\ntextCopy to clipboard\n\nIf everything goes well, Kedro will generate a JSON data file like this:\n\n[\n {\n \"Item\": 1,\n \"Product\": \"Basketball\",\n \"Category\": \"Sports\",\n \"Units\": 100,\n \"Price\": 6.0\n },\n {\n \"Item\": 2,\n \"Product\": \"Tennis ball\",\n \"Category\": \"Sports\",\n \"Units\": 100,\n \"Price\": 4.0\n },\n...\n]\ntextCopy to clipboard\n\nIf we install Kedro Viz , we can graphically view the full process:\n\nThis was just a brief introduction to Kedro. It has many additional helpful features. We can continue building applications using data as a part of our objects, functions and modules — but we can also try this new paradigm of building data-oriented architectures using reusable, testable, high-performance data science tools.\n\ntextCopy to clipboard"
],
"categories": {
"primary": "data",
"others": [
"ai",
"cloud",
"oss"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"digital-community-good-documentation": {
"href": "https://nearform.com/digital-community/good-documentation",
"postType": "blog",
"slug": "digital-community-good-documentation",
"date": "2021-04-21",
"title": "The Case for Consistent Documentation",
"authors": [
"ERIKA SMITH"
],
"content": [
"(Or, How to Leave a Client in 10 Days)\n\nWords can't begin to express the anxiety I felt leaving my first job last spring. I'd been at the company for just under two years and felt an immense amount of loyalty to the team. (I think something about them hiring me as a junior engineer without experience made me feel indebted to them, even years down the line.) As I put in my notice, a question kept nagging me: how could I wrap up two years in two weeks?\n\nWhat did leaving this company powerfully even look like? Making as much progress on our backlog as possible while I could? Or just doing exactly what I'd been doing for the past two years until the clock ran out? Would any of these approaches put them in a better position? Probably not.\n\nI decided that, for me, a powerful departure meant slowing down. It meant giving myself and my co-workers closure. It meant transferring domain knowledge to the newer team members. It meant leaving open space on my calendar for any questions or chats that might arise. It meant writing zero code and a ton of documentation. The process was uncomfortable, but when 5 PM came on my last Friday, I knew I'd used my time wisely and I felt fully available to start my next position.\n\nWhile I had succeeded in making a graceful departure in this instance, I began to think about the future. I certainly wasn't done leaving projects in my career. The questions I was left with included: How could I avoid getting caught off guard by the next inevitable exit? And, how could I begin to craft a formulae for seamless transitions?\n\nOne Foot Out the Door\n\nThese questions got me thinking about the transient nature of not only consulting projects, but also engineering engagements of all shapes and sizes. Now a year into working at Formidable, I'm more comfortable with the concept of leaving—it's fundamental to what we do as consultants. The advice I would have given myself at the beginning of my career is this: You should approach any project knowing that it's temporary. It's not an exaggeration to say that this is the last thing fresh-out-of-bootcamp-, no-production-experience-, I-swear-I-can-code- me would have wanted to hear. All I wanted was to feel comfortable and to know a codebase intimately enough to do what was asked of me. The idea of having to learn a codebase knowing I wouldn't be there long would have felt futile at best. And now, that's the epitome of my job. Funny how life works.\n\nSo at the beginning of any project, I think about the end.\n\nThe good news is this: I've found that it's not as daunting as it sounds. When I approach client projects as guaranteed temporary engagements, I feel empowered to make the leaving process so much less chaotic (and, I would argue, this philosophy makes my time on the project much more impactful). So at the beginning of any project, I think about the end. I think about what leaving this project will be like for me, and what onboarding this project will be like for the next engineer after I'm gone. I think about what kind of influence I can have on this client during the limited amount of time I'm here. I think about the problem, knowing with near certainty that I won't be there to see it entirely solved, but that I can make an impact nonetheless. If I've lost you and you're thinking, \"This isn't how to leave a client, it's how to be on a client,\" I'd argue it's one and the same—and that's the whole point.\n\nThe Recipe\n\nI frame every client engagement in roughly the same way. First, and arguably most importantly, I make a Notion page for my personal documentation of the client (what lives in here will be covered in the next few points).\n\nThe Onboarding Process\n\nWhen I join a team, I first ask for written documentation. As I go through it, I take note of any questions that arise:\n\nDoes it include a list of the team members and their roles and locations?\nDoes it provide links to all codebases/ticket tracking systems/designs?\nDo I understand the team's objectives for the next 12-18 months and what phase of the project we're currently in?\nDo I understand how we, the consultants, fit into the mix? Is our contract for another six months? A year? Do they have specific objective they would like us to meet, or do they just need some help getting on track?\n\nI schedule a meeting with the team lead immediately after, where I usually get those questions answered pretty quickly. The key here is that I don't delete my questions. Even if I don't have the time at that moment to update the official documentation myself, I keep track of what was unclear and the answers that I had to dig around to find. This all goes into my personal page.\n\nContributing & Tracking Work\n\nAs I receive work, I push for tickets to include all necessary context—even if I've had conversations outside of the ticket for clarification, even if I have to add it myself. Likewise, when I create a PR, I leave nothing to the imagination. I do my best to include all relevant links (tickets, designs, related PRs) and leave comments throughout the code regarding why I've made the changes and any downstream effects they might incur.\n\nNote - This isn't overkill. This is history being written. Leaving super-detailed PRs is A) a timesaver and general courtesy for those who review your PRs, B) a great way to document your thought process at that point in time should currently held assumptions change, and C) a sweet way to introduce future team members to the multitude of factors they should consider when contributing to this codebase.\nIf it becomes clear that this is work that is commonly performed, I link the PR in my personal page. It's a quick reference for me if I'm asked to repeat the task later on, and a great way to build context around our processes for a future new team member.\nUnderstanding the Full Scope\n\nI try to understand the larger problem fully, knowing I probably won't be there to fully solve it. Even if our engagement with the client is six months, understanding their 12-month objectives allows us to make recommendations that reflect and empower their long term goals. For example, if we understand that the client's end goal is X, and we're being asked to implement Y as a step toward X, but we know that Z is a better fit, we shouldn't just go forth and implement Y in a vacuum. Or maybe we should, but we should definitely provide this insight to the client so they understand the long-term implications. Sometimes the strongest impact you can have on a client isn't the code you write, it's the direction you provide and the processes you enhance. That being said, code is pretty sweet too.\n\nSometimes the strongest impact you can have on a client isn't the code you write, it's the direction you provide and the processes you enhance.\nSlowing Down\n\nWhen I know my time at a client is ending, as I did in my last job, I focus on slowing down and leaving powerfully. Overwhelmingly, this equates to writing documentation. Luckily, I have a resource to draw from: I've been writing my personal documentation the whole time. In the end, I know exactly how I felt at the beginning—because in the beginning, I was thinking about the end.\n\nPerfect Impermanence\n\nSo how do you leave a job in 10 days? Maybe the answer is you don't. You lean into the impermanence and leave it the whole time. Whether it's a consulting job, product company, or anything in between, we, as engineers will almost certainly not stay on the same team/project/codebase forever. In the meantime, we do ourselves and our teammates a service by ensuring that the past is documented and every aspect of the project is approached with the future in mind.",
"The Many Benefits of Good Pull Request Descriptions (+ How to Write One)\nBRITTANY FEENSTRA, SAMUEL ESTRELLA\n20 APR 2020\nDEVELOPER-TOOLS\nREACT\nREACT-NATIVE\nOPEN-SOURCE\nCalibrated Code Reviews\nBECCA BAILEY\n10 DEC 2020"
],
"categories": {
"primary": "work",
"others": [
"oss",
"frontend"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"insights-devops-7-reasons-to-automate-security-in-your-pipelines": {
"href": "https://nearform.com/insights/devops-7-reasons-to-automate-security-in-your-pipelines",
"postType": "blog",
"slug": "insights-devops-7-reasons-to-automate-security-in-your-pipelines",
"date": "2021-04-27",
"title": "DevOps: 7 reasons to automate security in your pipelines",
"authors": [],
"content": [
"The DevSecOps evolution — incorporating security into DevOps practices\n\nDevOps is on the rise. The DevOps market is predicted to reach $12.5 billion by 2025 , growing at a CAGR of 25.2% during 2020-2025. Driven by the need for faster innovation, a shift towards microservices architectures and the evolution of automation and collaboration tooling, the DevOps juggernaut has dramatically changed how enterprise software is built. However, despite more than 90% of companies in a recent survey stating that DevOps had a direct impact on business metrics , 85% of respondents have faced barriers in their DevOps implementation .\n\nDevOps is not easy. It’s more than a set of automation tools and agile processes; it’s a mindset and culture. And, for many traditional industries and organisations, change is a journey with plenty of roadblocks: Mentality and processes need to be shifted to inject DevOps earlier in the development process. When making the transition, one major roadblock involves shifting traditional security processes so that they become embedded in your DevOps activities. In an emerging movement towards DevSecOps, DevOps teams aim to incorporate security into their CI/CD (Continuous Integration / Continuous Delivery) pipelines, in a “shift left” paradigm, moving from a final blocking security review into a layered approach across the whole software development lifecycle (SDLC).\n\nSeven reasons to justify a DevSecOps journey\n\nIn this post, we explore seven reasons why security needs to be embedded into DevOps practices.\n\n1. Education\n\nLack of expertise is the number one security problem. It is a lot to ask software engineers to deliver the functional requirements as well as such underlying non-functional requirements as performance, scalability and security. However, leveraging DevSecOps practices throughout the software development life cycle makes your team security-aware from the first line of code and the first component of infrastructure. This really changes the mindset and helps to deliver better products and services. By integrating security into your engineering processes and establishing KPIs around this, you can set a path toward success.\n\n2. Visibility\n\nCompanies are often unaware of potential security threats until they are exploited. Vulnerability scanners, monitoring tools and penetration testing are some of the ways to gather invaluable information about threats that previously may have been undetected. As a result, the global security testing market is forecast to grow at a compound rate of 20.7% between 2019 and 2027. Being able to identify vulnerabilities across your software and infrastructure components is a key part of a solid governance strategy.\n\n3. Velocity\n\nContrary to popular belief, DevSecOps can help you speed up your release cycles. Traditionally, security has been a blocker because it entailed a series of non-functional requirements that were reviewed at the latter stages of the software development lifecycle (SDLC). With DevSecOps, this changes dramatically: Security is pushed to the early stages of the process — this is called ‘shift left’ in the industry. The main advantage of this approach is the ability to identify and fix problems earlier in the delivery pipeline, preventing flawed builds from being deployed into production and thereby saving time and resources.\n\n4. Confidence\n\nDevOps activities need to empower developers to release to production multiple times a day with a single click. This can create a gaping security hole because the number of people with access to mission-critical systems can grow significantly. However, embedding security into DevOps automation increases confidence in the system’s integrity. With the right combination of technology and processes, the required level of security can be achieved, including enforcing PCI or HIPAA compliance.\n\nDelaying security to the later stages of the development process is difficult to plan for. How can you know how many defects will be spotted? How long will it take to fix them? DevSecOps promotes the idea of adding security checkpoints to every phase of the pipeline. This process reveals defects from the moment the software is conceived, allowing the engineers to fix them early in the pipeline. It also allows everyone to plan because the final security review simply ensures that all the steps have been properly assessed and vulnerabilities managed accordingly.\n\n5. Forensics\n\nAudit trailing is already a legal requirement in financial systems, but we argue that it should now be required in most software components because it allows the engineers to trace and audit entire transactions (user actions, automated operations, etc. ) in order to reproduce issues or attacks. DevSecOps encourages teams to build systems in ways that are easily auditable. Log collection, event sourcing and event monitoring are just some of the techniques used by DevSecOps engineers to ensure your systems are transparent and facilitate the required governance.\n\n6. Automation\n\nContainers filled with microservices get deployed and rescheduled unpredictably on your platforms. Only automated systems can keep up with that fluid behaviour. Intervention by humans can no longer keep up. Runtime monitoring coupled with rule-based or AI-driven automated containment is the only way to keep these highly dynamic application landscapes safe.\n\n7. Unique Selling Point\n\nIt doesn’t matter if you are selling a service or a product, your customers need to be confident that their data is safe. Building your SDLC on a strong security foundation is a very strong selling point. Security is now table stakes for many enterprises — and it's even a requirement in cases where the customer is audited for ISO-27001.\n\nReady for the journey to secure DevOps?\n\nArchitecting DevOps processes and systems with a focus on security accelerates software delivery even further. Shifting security to “the left” and automating every security measure possible reduces surprises and frustration along every step of the process. It doesn't matter if you are starting a new project or thinking of transitioning to DevOps, security has to be centre-stage to prevent outages in your systems.\n\nAt NearForm, we are firm advocates and practitioners of DevSecOps activities, supporting companies in the transition to what we call DevOps AID: Assess, Implement, Direct. This is a three-step process involving an initial assessment of your current practices and recommendations for change, embedding our DevOps specialists in your team to implement a strategy for improvement, and providing post-implementation support. This approach is tailored to each organisation's requirements, equipping you with the tools you need to optimise your DevOps in a secure way."
],
"categories": {
"primary": "devops",
"others": [
"security"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"digital-community-reanimated-two": {
"href": "https://nearform.com/digital-community/reanimated-two",
"postType": "blog",
"slug": "digital-community-reanimated-two",
"date": "2021-04-29",
"title": "Animations in React Native: Performance and Reason-about-ability with Reanimated 2",
"authors": [
"GRANT SANDER"
],
"content": [
"If you're reading this, I don't think I have to convince you that React Native is pretty great: it drastically simplifies the mental model of cross-platform mobile application development. Developers can use a single codebase to generate native iOS and Android apps, allowing them to focus primarily on application code and very little on platform-specific APIs and quirks. Furthermore, React Native (which we'll refer to as RN in this piece) is underpinned by React, which has proven to be a powerful model for reasoning about dynamic UIs. RN helps us developers simplify the mental model needed to reason about building cross-platform mobile UIs, freeing up more mental space for the important stuff: business models and building pleasant and useful application experiences.\n\nEven with a simplified model for building cross-platform mobile UIs, mobile app development is still hard. There are many challenges to overcome such as navigation, permissions, push notifications, smooth animations, and gestures, and so on. The upside is this: the RN ecosystem is now quite strong, and there are a lot of good libraries and tools out there to help us tackle these hard problems in ways that—like RN—help us simplify our mental models so that we don't become bogged down with platform APIs and differences between Android and iOS.\n\nIn this article, I'm going to discuss one of the aforementioned challenges of mobile app development with RN—building smooth animations and gestures—and a tool in the RN ecosystem, React Native Reanimated, that helps us take on this challenge without fear. While discussing building smooth animations and gestures with a simplified mental model, we'll build out a sample UI that's potentially not that useful, but showcases a lot of animation and gesture techniques we'll be developing with this new tool. To whet your appetite a bit, here's a teaser of what we'll building:\n\nAnimation in React Native\n\nOne of the beauties of RN is that we can write our application code in JavaScript and somehow we end up with native application artifacts. There's some magic in RN—it actually ships a JS engine that runs your JS code on its own thread—and then communicates to a native thread via a \"bridge\". Here's a very simplified diagram to help us think about this:\n\nYour JS code is executed on the left, RN passes information through this magical \"bridge\", and native things are executed on the native thread.\n\nGenerally, this works quite well! We often don't have to remember that there's this magical \"bridge\" thing there—we just write JS and create awesome applications. But you might be thinking to yourself: \"What's the performance cost of passing through this bridge? Surely it can't be quite as efficient as just writing raw native code.\" The performance cost is non-zero but generally small enough that users aren't going to notice.\n\nHowever, there are certain aspects of an application where users are surely going to notice when performance is taking a hit. One of those aspects is animation. Once you start dropping under 60 frames per second (fps) for animations and start \"dropping frames\", attentive users will likely notice, and start wondering why your application feels \"choppy\" or \"laggy\".\n\nIt turns out, creating smooth (60fps) animations while living only in the land of JS can be quite challenging. Luckily, RN ships with some animation tools (https://reactnative.dev/docs/animated), and those tools can be used to create some smooth animations. RN's Animated API helps you declare animations in JS, and then push your animation declarations to the native UI thread for execution. However, there are certain limitations to what you can do with RN's Animated API, how much performance you can get out of it, and how easy it is to reason about.\n\nIn an ideal world, we’d have a tool that allows us to create animations that:\n\nrun primarily on the native UI thread;\nare written declaratively in JS;\nand allow us to largely forget about \"the bridge\".\n\nSuch a tool would allow us to simplify our model of animation while allowing us to remain confident our animations are performant enough to feel buttery smooth.\n\nIntroducing React Native Reanimated (Version 2)\n\nThat tool that's going to help us build smooth animations and gestures while keeping our mental model of animation slim? That's React Native Reanimated Version 2. I'll be referring to Version 2 of this library as \"Reanimated 2\" or just \"Reanimated\". It's worth pointing out that V2 of Reanimated is a huge overhaul of the library, and the API is drastically different from V1 (and in a good way).\n\nSo what is Reanimated? It's a library that replaces RN's Animated API, providing JS-based animation APIs that are easy to use and run on the native thread (which entails performance out of the box).\n\nFor the rest of this post, I'm going to be walking through some of the core APIs of Reanimated, how I have been thinking about them, and provide some examples to demonstrate some of these ideas. The end result will be a custom slider, and a circular progress that animates as you drag the slider handle.\n\nThe \"Reanimated Mental Model\"\n\nBefore we get too deep into Reanimated, I want to share my mental model for animating with Reanimated. I think of Reanimated as the intermediary between JS-based app code and native-thread animation execution. Here's a little diagram of that thinking:\n\nIn the back of my head, I know that my animation code must play nicely with both JS code and native code, but that Reanimated will abstract away a lot of the dirty details for me. The Reanimated primitive that does this dirty-detail-abstraction is a worklet. Worklets, according to the Reanimated docs, are\n\ntiny chunks of JavaScript code that can be moved to a separate JavaScript VM and executed synchronously on the UI thread.\n\nBasically, worklets are just JS functions that get executed on the UI thread (magic!) which allows us to define native-level animation commands in JS without worrying about the cost of the bridge. This is insanely powerful, but also still a bit hard to reason about. One of the beauties of Reanimated is that the library largely abstracts away the notion of worklets by providing us with a handful of useful React hooks to define animations. We'll get our hands dirty with a custom worklet, but we'll largely focus on said hooks, as they'll be the bread and butter of using Reanimated to define animations.\n\nShared Values\n\nIn my mental model of animating with Reanimated, the core concept is the shared value. A \"shared value\" is essentially a simple primitive value on the JS-side of things, but can be used to drive animations on the UI-side of things. We can update shared values on the JS side and see these changes reflected on the UI thread.\n\nBack to our diagram of our mental model for animation with Reanimated, a \"shared value\" sits in that sweet spot between JS-code and UI-thread execution.\n\nLet's look at a really simple example of creating a shared value:\n\nimport * as React from \"react\";\nimport { Button } from \"react-native\";\nimport { useSharedValue } from \"react-native-reanimated\";\n\nconst MyComponent: React.FC = () => {\n const x = useSharedValue(0);\n\n return
fastify.register(mercuriusApolloRegistry, {\n schema,\n apiKey\n})\ntextCopy to clipboard\n\nRegistering the plugin requires two mandatory options. The schema is a string representation of the GraphQL schema you wish to report to the Apollo Registry. The apiKey is the unique API Key for the Graph you wish to send schema updates for. Full information about each of these options can be found in the plugin documentation .\n\nThe plugin depends on Mercurius, so it must be added after the Mercurius plugin itself has been registered to satisfy dependencies. Once registered, it will take care of reporting the loaded schema automatically. The plugin uses the same Fastify logging system as Mercurius and by default aims to be conservative in the number of messages raised. By increasing the log verbosity in Fastify (for example from info to debug), the plugin can also be made to report registry responses and payloads to help debug issues.\n\nAs changes are made to the schema over time and reported to the registry, a change log is produced in Apollo Studio. This allows you to investigate differences as they evolve over time. As a premium feature, you can also automatically check for breaking changes whenever an updated schema is reported to the registry.\n\n[caption id=\"attachment_300015215\" align=\"alignnone\" width=\"796\"]\n\nApollo Studio showing the history of various schema changes[/caption]\n\nThe registry reporting protocol\n\nA detailed description of the protocol has been released as part of the registries documentation to allow third-party clients to integrate successfully with Apollo’s infrastructure. The protocol itself is implemented via GraphQL queries and defines two mutations that should be used for reporting, as well as some retry and timeout logic.\n\n[caption id=\"attachment_300015216\" align=\"alignnone\" width=\"560\"]\n\nDiagram explaining each registry reporting step[/caption]\n\nWhen an edge server wishes to update the registry with its local schema, it first makes a request with some basic information about itself and includes a SHA2 hash of the schema it wishes to report. If the SHA2 hash differs from the one known by the registry (indicating the schemas no longer match), the registry gives the edge server permission to report their schema in full after an agreed timeout has expired.\n\nThe registry expects each edge server to submit a normalised string version of their schema as well as its matching SHA2 hash. The registry can then compare and make changes to the global schema based on the report. This update, if valid and accepted, now replaces the previous schema, and all future reports are judged against this new value.\n\nThe key to making this reporting successful is in the normalisation of the schema string itself. The protocol defines rules for how each of the fields should be sorted, how white space should be removed and the consistency required. This allows the registry to interoperate with changes from multiple third-party applications without issue.\n\nFuture development\n\nThe plugin currently supports the basics of schema reporting and aims to be a good foundation for future integration with the Apollo Registry. As an open source plugin, it can be extended and modified over time as the registry adds new functionality and features.\n\nThe most eagerly awaited feature is schema reporting with a Federated Graph. While this feature is not currently supported by the Apollo Registry itself, it is certainly on its roadmap. Once it becomes available, it will be an excellent future addition to the plugin as the protocol is expanded. The ability to report metrics to Apollo Studio for various queries may also be of future development interest, as it complements the existing schema-checking functionality.\n\nTry it out\n\nIf you are interested in trying Mercurius, we encourage you to take a look at the GitHub repository and learn how to get started. With the initial feature of schema reporting in place, end users can now benefit from the additional visibility Apollo Studio brings, and they can also use Mercurius as their GraphQL adapter of choice. It is also now possible to combine Mercurius with the various Continuous Integration abilities offered by the Apollo registry, including GitHub checks when a given schema is updated.\n\nThis plugin may be small for now, but it is certain to enable a whole new range of possibilities with Mercurius and Apollo."
],
"categories": {
"primary": "backend",
"others": [
"data",
"cloud"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"digital-community-choose-react-native": {
"href": "https://nearform.com/digital-community/choose-react-native",
"postType": "blog",
"slug": "digital-community-choose-react-native",
"date": "2021-05-24",
"title": "Why Choose React Native?",
"authors": [
"CARLOS KELLY",
"KADI KRAMAN"
],
"content": [
"React Native unifies web and mobile development teams by leveraging the same set of technologies on multiple platforms. Since React works the same way on the web as it does on native, any developer familiar with React and JavaScript can create UI components for any platform. In addition, React components render to native UI elements specific to each platform, which produces apps that are more performant than web-based ones on mobile devices.\n\nHere are some of the key reasons why you might want to consider React Native for your next development project.\n\nDeveloper and Performance Improvements\n\nReact Native has several key advantages that accelerate the development cycle and make it easier for JavaScript engineers to get started. Native apps built in Android Studio or Xcode require a recompilation and run on each change. By contrast, React Native offers live reload on each save, like many modern web apps using webpack, and lets developers see their changes without disruptive gaps.\n\nYou may have heard of mobile apps built using JavaScript experiencing performance issues due to utilizing tools optimized for the web. To eliminate these inefficiencies, the React Native team has introduced Hermes — a JavaScript engine built specifically for improving JavaScript performance on mobile apps. It reduces the app's time to interactivity and reduces the bundle size by replacing the previous Just-in-Time compiler with Ahead-of-Time compilation. Hermes generates efficient byte code that runs on the device. This has especially significant implications on Android app performance compared to previous React Native apps running on JavaScriptCore.\n\nShared Architecture Between Web & Mobile Apps\n\nReact Native is best viewed as a way to deploy a React application as a mobile iOS or Android application. At the core React Native apps follow the same architectural patterns as web-based React apps. Declarative UIs, state management, request logic, styles can all be the same. When using iOS and Android native SDKs, each follow very different patterns that require different approaches and designs for applications targeting each platform. This can cause variations in feature development effort and velocity on a certain platform and/or larger functional differences to the end-user. With React Native an engineering team doesn’t have to resolve the same technical challenges three times for web, Android, and iOS because they all share the same React core principles.\n\nWith a JavaScript and React-based platform, web and native apps can share more code, for example, state management, API requests, and GraphQL queries or mutations. This can help reduce inconsistencies and bugs across a suite of applications since logic doesn’t need to be duplicated across three platforms. React Native’s access to the ecosystem of JavaScript modules, including urql and Sanity, offers the reuse of large portions of an existing web client for new mobile apps.\n\nDesign & User Experience\n\nBuilding the user interfaces is typically the most time-consuming portion of a mobile application when leveraging existing business logic. React Native unifies the experience with a consistent set of components and patterns that let each platform be true to itself. When building user interfaces using UIKit or Android XML, each platform takes a very different approach to layout and design. React Native follows a flexbox-based approach that is very similar to the web and feels comfortable for React developers. Familiar paradigms such as padding, margin, and flex all exist within React Native and work generally the same way, reducing the learning curve.\n\nNavigation\n\nThe most impactful difference in user experience between a mobile application and web is navigation and flow. React Navigation is the established standard for implementing stacks, tabs, and drawer navigation. Similar to URL-based routing in a web app, navigation defines how different flows in an application are visited by the user. Most modern apps use a mixture of a tab-based navigation with stacks for each tab. Stack navigation is common for list and detail views or sequential steps like a checkout flow. At Formidable, we have experience with what navigation patterns work best for the user flows and experience. Hamburger or slide-out drawers are common, but unfortunately often end up as a “junk drawer” with low discoverability. Android and iOS users are accustomed to apps working in a consistent way and React Navigation lets developers theme and customize elements that also maintain platform interface guidelines.\n\nImage Assets & Guidelines\n\nMany web apps include numerous SVG assets for icons and images. Unfortunately, the Android and iOS SDKs do not support SVGs out of the box. Xcode requires conversion to PDF, and Android has a custom format for responsive images. Neither support animating assets or dynamic colors based on some state. By contrast, React Native with React Native SVG supports the same SVG content used within the current web app and renders them performantly using platform-specific drawing APIs for both iOS and Android. This is a big win as the ability to use the same assets for all platforms cuts down on diverging artwork and development times.\n\nAnimations\n\nReanimated is a sophisticated animation library for React Native that leverages next-generation TurboModules for improved performance and a consistent experience. TurboModules are a new architecture for the JavaScript layer to communicate with native code without using the React Native bridge using C++, a low-level language that runs on both Android and iOS. Reanimated animates integers, floats and colors using springs or timing. Springs are ideal for natural animations like movement or resizing. Timing animations are useful for situations like ensuring a sequence of animations perform within a certain timeframe. Both animation functions allow for the use of a callback to execute code after the animation. Animations in Reanimated can also be canceled and stacked to create complex and interactive animation sequences.\n\nNative Modules\n\nA React Native app is at its heart a native app, meaning that we're not losing anything by using React Native, we're only gaining. We retain the flexibility of enhancing our existing app with native code using native modules. This means that any native SDK can be used in React Native by simply writing the required native code — a bridge — to make it accessible in to React Native. On a high level, all of React Native is built like this — JavaScript code that interacts with the native code on both platforms, which is why the React Native experience for users is nearly identical to a real native experience.\n\nDeployments & Integrations\n\nMobile applications typically require significantly more steps than web applications to create a testable, runnable application. Web deployments usually live on a web server that is accessible via a URL. Mobile applications require signing, provisioning, and proper deployment channels via the Apple App Store portal or the Google Play portal. With React Native, we can use existing mobile automation services for building and distributing new versions for testing and app stores.\n\nThere are several mobile CI/CD services to choose from, with App Center and Bitrise being some of the more popular.\n\nCodePush\n\nUnlike the web where new releases can be deployed in minutes, each update to the App and Play Stores must go through a review process. This can take anywhere between a couple of hours to a week or more, depending on how busy the App Review teams are. Furthermore, Apple also has a Christmas freeze between December 23-28 when no app updates can be published at all.\n\nWith JavaScript-based mobile apps, this restriction can be mitigated to some degree using CodePush. CodePush is an App Center service that enables deploying mobile app updates directly to the user's devices immediately and effectively skip the store review process for these updates. It only possible for JavaScript-only updates: it relies on users downloading a new JavaScript bundle on top to the existing native app, meaning all changes that include any native code will still go through the store review process as usual.\n\nAlternatives to React Native\n\nReact Native is far from being the only framework to enable developers to build apps for multiple targets from a single codebase. Some more popular alternatives to React Native are Cordova, Ionic, Xamarin, and Flutter.\n\nXamarin and Flutter are frameworks from Microsoft and Google respectively — the first is written in C# and the latter in Dart (a programming language designed especially for Flutter). Whereas both of these are strong frameworks, our preference leans towards React Native for the simple reason that React Native apps are written in JavaScript, using React, which allow us to reuse all the tools, frameworks, knowledge and programming patterns from the web.\n\nCordova and Ionic (built on top of Cordova) apps are written in JavaScript, and you can even use React. However they work by wrapping your HTML/JavaScript code in a native container. This is different from the React Native approach where we write the code in JavaScript, but the components are then mapped to iOS and Android native components to be used under the hood. With Cordova, mobile apps are quick to build and distribute since you can reuse all the web UI code, however it comes with a trade-off of losing some of the native look and feel. Gestures, animations and anything that doesn't exist on the web in the same way are especially tricky to get right.\n\nIn contrast, React Native combines the ability to use tools and frameworks we already know incredibly well and allows us to write apps that utilize gestures and animation to provide a near-native experience.\n\nIn Conclusion\n\nReact is already a fantastic way to build UIs for the web and components are a great way to conceptualize your UI as a function of some data. React Native builds upon React's philosophy of \"Learn once, write anywhere,\" making it easy for React web developers to build native apps. Composable unified UI codebases, instant app updates, and better development tooling make React Native the better way to make native apps.",
"REACT-NATIVE\nThe New React Native Architecture Explained\nLORENZO SCIANDRA\n26 MAR 2019\nREACT-NATIVE\nOPEN-SOURCE\nAnimations in React Native: Performance and Reason-about-ability with Reanimated 2\nGRANT SANDER\n29 APR 2021\nREACT\nMOBILE\nOPEN-SOURCE\nREACT-NATIVE\nOAuth and PKCE with React Native\nKADI KRAMAN\n16 JAN 2018"
],
"categories": {
"primary": "mobile",
"others": [
"frontend"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"insights-nearform-at-openjs-world-2021": {
"href": "https://nearform.com/insights/nearform-at-openjs-world-2021",
"postType": "blog",
"slug": "insights-nearform-at-openjs-world-2021",
"date": "2021-05-25",
"title": "NearForm at OpenJS World 2021",
"authors": [],
"content": [
"OpenJS World 2021 features contributions from no fewer than five NearForm speakers.\n\nScheduled for June 2, OpenJS World is a global virtual conference where JavaScript professionals connect with community members to discuss and learn about projects such as AMP, Dojo, Electron and Node.js. Developers, software engineers, developer advocates and business leaders network, collaborate and get insights from experts — many of whom come from NearForm.\n\nThis year’s event features a keynote from NearForm founder and president Cian O Maidin, two talks on Fastify from Matteo Collina, talks by James Snell and David Gonzalez and a panel discussion including Dominykas Blyze.\n\nHere is a flavour of what to expect:\n\nCian O Maidin — Keynote: Breaking transmission chains with JavaScript\n\nIn 2020, NearForm built what was to become the most widely adopted COVID-19 Exposure Notification app in the world. In just five months, the team successfully deployed and scaled their digital contact tracing solution for nine governments.\n\nIn this keynote, Cian will talk about the challenges NearForm faced building an app for all and the need to get it right from the start, despite working to tight deadlines during a pandemic that kept evolving. He will discuss how NearForm used an open source approach to public health to help break chains of transmission and save lives using JavaScript.\n\nMatteo Collina — A fast introduction to Fastify\n\nFastify is a web framework for Node.js that enjoys impressive satisfaction levels among developers, with an 89% rating in the last state of javascript. It combines an excellent developer experience with top-class performance, with minimal reduction on top of Node.js core.\n\nIn this talk, Matteo will take the audience through the fundamentals of Fastify and present a live coded example of Fastify in action.\n\nMatteo Collina — Can we double the Node.js HTTP client throughput?\n\nThe Node.js HTTP client is a fundamental element of any application, yet many think it cannot be improved. Matteo set out to prove them wrong: In this talk he will present undici , a new HTTP client for Node.js that doubles the throughput of your application.\n\nThe story behind this improvement begins with the birth of TCP/IP and is rooted in one of the fundamental limitations of networking: head-of-line blocking (HOL blocking). HOL blocking is one of those topics that developers blissfully ignore, yet it profoundly affects the runtime experience of the distributed applications they build every day. Undici is a HTTP/1.1 client that avoids HOL blocking by using keep-alive and pipelining, resulting in a doubling of your application throughput.\n\nJames Snell — Aligning Node.js with the web platform\n\nAlthough there is much validity to the argument that Node.js is not a web browser and therefore shouldn't act like one, it is still beneficial to ensure that JavaScript that works in the browser works the same way on the server.\n\nConsiderable effort has gone into aligning Node.js with the web platform recently, including implementation of the WHATWG URL API, TextEncoder, Intl and more. Node.js 15 has moved even closer, with the addition of EventTarget, AbortController, and the Web Crypto API.\n\nJames’s talk will introduce developers to the new web platform superpowers that are now built into Node.js and present insights on ongoing efforts for what may be coming in the near future.\n\nDavid Gonzalez — Fighting Covid with serverless and JavaScript\n\nAt NearForm, we built a number of COVID-19 tracking applications but — more important — we also open sourced the core. This source can be found at COVID Green .\n\nIn this talk, David discusses the major challenges NearForm encountered along the way and reveals how to operate a planetary scale application with a small team of people and a surprisingly low number of outages. He will outline why the company chose a serverless approach, the key problems we dealt with and his recommendations for running large-scale geographically dispersed apps.\n\nDominykas Blyze - Panel: Node.js Package Maintenance Working Group Year 3\n\nSenior developer Dominykas is a passionate advocate of Node.js and a member of several teams within the community. He is participating in a panel discussion on the work of the Node.js Package Maintenance Working Group. Established in 2018, the group includes users, authors, and maintainers who work toward solutions to ensure that key Node.js ecosystem modules are maintained, safe and up to date.\n\nThis talk will showcase the working group’s current focuses, guidance and tooling three years since it was set up.\n\nAbout OpenJS\n\nThe OpenJS Foundation ’s mission is to encourage wider adoption and continued development of key JavaScript solutions and related technologies. It does this by providing “a centre of gravity” for the open source JavaScript ecosystem. The portfolio of open source technologies that developers depend on to create, test and deploy critical applications is growing all the time. The main objectives of the OpenJS Foundation are:\n\nDriving the broader adoption and ongoing development of key JavaScript and web solutions and related technologies\nFacilitating collaboration within the JavaScript development community\nProviding a centre of gravity for the open source JavaScript ecosystem, steering them toward open governance and diverse collaborator bases\nHosting the infrastructure to support hosted JavaScript open source projects\nEnabling an open, accessible web, via the advancement of Projects and strategic partnerships\n\nThe foundation’s central belief is that there must be a neutral home for critical projects, with shared principles of technical governance and accountability. By providing this, it is helping to secure the long-term sustainability of both individual projects and the entire ecosystem.\n\nOpenJS World 2021 happens virtually on June 2. Make sure you register to attend !"
],
"categories": {
"primary": "oss",
"others": [
"cloud",
"backend",
"frontend"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"insights-modernise-your-react-development-stack": {
"href": "https://nearform.com/insights/modernise-your-react-development-stack",
"postType": "blog",
"slug": "insights-modernise-your-react-development-stack",
"date": "2021-05-27",
"title": "We look at create-react-app and other alternatives for React tooling.",
"authors": [],
"content": [
"A look into React tooling beyond create-react-app\n\nOne of the first challenges of starting a new React application is all the work needed to get a React component tree to render in the browser. Assuming you’re using JSX, as most React developers do, you need to get that converted into code that browsers can understand. Then you will probably want to use import statements to reference other JavaScript modules, as well as other types of assets, such as images and stylesheets.\n\nSetting this up manually usually requires configuring and running a module bundler capable of transpiling and bundling all the modules together. Webpack and Babel are popular, widely used tools in this category. Tools such as create-react-app put all of this together to provide a seamless development experience, including Hot Module Reload for fast iteration during development and all the goodies we’re familiar with.\n\nMeanwhile, browser vendors are including more and more modern JavaScript features in their products, making some of the processing done on the source code unnecessary, at least during development.\n\nYou can find all the source code accompanying this article at nearform/web-dev-perf .\n\ncreate-react-app\n\ncreate-react-app (CRA) has been a personal favourite for a long time. The effort of setting everything up from scratch is hard to justify when you can simply run a command in the terminal and have a fully working application in a matter of seconds.\n\nnpx create-reate-app myApp\ntextCopy to clipboard\n\nBesides, CRA has evolved to include more features and customisation options over time, and it also brings together many best practices that are expensive to reproduce when starting from a blank slate. Finally, when you need ultimate customisation, you can eject and get access to all the scaffolding that CRA would otherwise hide from sight. The downside of ejecting is that it is destructive and cannot be undone.\n\nCRA is easily the most widely used and mature React development stack. It is also the most conservative: It supports very old browsers like IE9 (via polyfills), and everything is entirely bundled, both during development and for production builds.\n\nAt a high level, it does this by using Webpack and Babel to create a bundle of the application that is compatible with all the supported browsers. This means that all the source code of the application and its dependencies are bundled together (or in multiple chunks), which are then served to the browser.\n\nCreating these bundles is an expensive operation that takes place in memory at development time to speed up the development experience without hitting the file system.\n\nNevertheless, much of this work is unnecessary because the browsers we use for development support features like es modules (ESM), which make bundling and transpilation largely unnecessary. CRA doesn’t leverage this but newer development stacks fill this gap.\n\nVite\n\nVite can be thought of as a CRA on steroids, built to leverage modern browser features and the latest build tools.\n\nUnlike CRA, Vite is not tied to React, but it can be used to create applications for different web frameworks. It supports vanilla javascript, vue, react and preact, among others.\n\nYou start a new React app with Vite with a simple command:\n\nnpm init @vitejs/app myApp --template react\ntextCopy to clipboard\n\nIn the scope of a React application, the main difference between Vite and CRA is that Vite uses native browser support for ESM, thereby avoiding the need to do much of the bundling that CRA does. The upside of this is that development builds are much faster, leading to lower startup and refresh times.\n\nIn practice, some bundling still happens in order to support features that are not available in browsers, such as bare modules . This is done using esbuild , an extremely fast module bundler.\n\nFor production builds, Vite can still use a module bundler to support browsers without native ESM support. Whereas CRA uses Webpack, Vite uses Rollup.\n\nAs well as an optimised development experience, Vite also provides additional features not available in CRA or other more mature frontend frameworks:\n\nGlob imports\nSupport for Web assembly\nSupport for monorepos and linked dependencies\nMulti-page apps\nSupport for building libraries via library mode\nOther players\n\nCRA and Vite are far from being the only two options for building React apps. Other notable mentions go to Next.js and Snowpack, and there are others. The comparison between Next.js and Snowpack is even broader than that between CRA and Vite.\n\nNext.js\n\nNext.js is a mature React framework with a host of features, including an entire server application to support Server Side Rendering of the Next.js application. In this regard, Next.js’s feature set is a superset of CRA and Vite.\n\nWhereas the previous two provide only the basic scaffolding for building React applications, Next.js provides pre-made design decisions about routing, styling and more. Overall, Next.js is more powerful by design and it's also more opinionated because many choices have been made on your behalf.\n\nSnowpack\n\nSnowpack is similar in scope to Vite in that it uses modern browser features such as ESM and tools like esbuild. Because of that, Snowpack is blazingly fast, but it offers just a fraction of the features that Next.js does. On the other hand, its output is highly optimised in terms of file size. It makes fewer upfront decisions than Vite does, which means it’s more flexible but less featured because those decisions are left to the user.\n\nComparisons\n\nComparing the full feature sets of the aforementioned React development stacks is outside the scope of this article. We focus on measuring the performance in terms of development speed and output efficiency.\n\nThe repository accompanying this article contains a suite of benchmarks and is accessible at nearform/web-dev-perf . The repository documentation explains in more detail what is measured and how to interpret the output of the benchmarks.\n\nIn order to make the comparisons reliable, all the development stacks implement the same React application, which consists of a simple Todo list. The original source code of the Todo list example application is available at gabrielsanttana/react-todolist .\n\nThe benchmarks can be run on your local machine and are also available as output of the CI process on the hosted repository. They capture various statistics about the development and production experience of each of the development stacks.\n\nDevelopment experience\n\nThe first table focuses on development experience and captures:\n\nstartup time (cold start) of the development build\nmin/mean/99th percentile/max time between the modification of a source file and the result appearing in the browser during development\nProduction experience\n\nThe second table focuses on production experience and captures:\n\nbuild time of a production build\nsize of the output of the production build\n\nNote: When comparing Next.js with other stacks, it should be noted that Next.js outputs a server side application as well, which others don't.\n\nHow to choose a React development stack\n\nAs usual, there is no right or wrong answer — it all comes down to needs and personal preferences.\n\nNext.js is the most heavyweight and opinionated of the development stacks, but it also comes with many features not available anywhere else (e.g. SSR). Its development and build times are slower than most other tools but are comparable — and in some cases better — than those of CRA. Next.js is a good option if you like decisions to be made on your behalf and need an easy way to set up SSR.\nCRA is the mature, frontend-only option that relies on battle tested tooling like Webpack and Babel. It’s a good option if you want to ensure the widest compatibility with older browsers and don't mind compromising a little on development speed for that purpose.\nVite is a great option for the CRA lovers who want to benefit from the higher development speed and newer feature set of a more modern development stack and are not afraid of the limitations of a relatively young stack.\nSnowpack is the extreme approach to React development that focuses entirely on modern tooling and leaves much of the rest of the work to the user. If speed and cutting edge tooling are your priorities and Vite doesn’t give you enough of those, Snowpack may be the tool you’re looking for."
],
"categories": {
"primary": "frontend",
"others": [
"product"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"insights-optimise-node-js-performance-avoiding-broken-promises": {
"href": "https://nearform.com/insights/optimise-node-js-performance-avoiding-broken-promises",
"postType": "blog",
"slug": "insights-optimise-node-js-performance-avoiding-broken-promises",
"date": "2021-06-03",
"title": "Understand how Node.js schedules asynchronous execution and why you need to use promises correctly.",
"authors": [],
"content": [
"Understanding the Node.js event loop is crucial for optimising Node.js performance.\n\nSeveral years ago, I was called out by a customer to help them resolve some performance issues they were having in their Node.js application. They were experiencing massive event loop blocking issues in their server, getting a whole 5 requests per second — and, in one extreme case, an event loop delay of over one minute!\n\nAfter reviewing some of the preliminary background details, the first question I asked them was simple: \"Are you using Promises?\" When they all looked at me and said \"yes\", my immediate response, without even looking at their code first, was, \"Then you're likely using them wrong\". It was a bold statement. I spent the next three days onsite with them going through their code in detail helping to find the specific issues and proving that initial bold assertion correct — their codebase was full of misuses of promises and async await.\n\nThat engagement, and many more similar ones, prompted me to develop the \" Broken Promises \" workshop that Matteo Collina and I present to customers and periodically at conferences. Here, I want to pull back the curtain on that workshop just a bit to help folks better understand one of the most critical aspects of Node.js performance: Understanding how Node.js schedules asynchronous execution.\n\nBut first, a puzzle\n\nWhenever we present the Broken Promises workshop, I like to start with a bit of a brain teaser to get things going. The puzzle is a specially (and a little sadistically) designed piece of code that is meant to highlight how difficult it often is to reason about the order in which asynchronous code executes in JavaScript and Node.js.\n\nHere's the challenge: The example prints a message to the console. It does so using all the various ways in which the execution of code can be scheduled in Node.js. Without running the code, can you tell me what message it prints to the console?\n\nNo cheating! And if you figure it out, keep the answer to yourself so that it's not spoiled for others who are trying to figure it out. (And if you have a difficult time with it, don't feel bad — I've shown this to seasoned Node.js core contributors who had difficulty working through it!)\n\n'use strict';\n\nconst { promisify } = require('util')\nconst {\n Worker,\n isMainThread,\n workerData,\n parentPort\n} = require('worker_threads');\n\nconst sleep = promisify(setTimeout);\n\nasync function bar(n, s, t) {\n setImmediate(() => process.stdout.write(s));\n await sleep(n);\n return t;\n}\n\nprocess.on('unhandledRejection', (err) => {\n process.stdout.write(err.message);\n});\n\nif (isMainThread) {\n const lock = new Int32Array(new SharedArrayBuffer(4));\n const worker = new Worker(__filename, { workerData: lock });\n worker.postMessage('S');\n worker.on('exit', async () => {\n try {\n const items = ['U', 'F']\n const p = Promise.reject(items);\n p.catch((items) => process.stdout.write(items[items.length-1]));\n p.then(() => process.stdout.write('P'))\n .catch((items) => process.stdout.write(items.shift()));\n throw new Error('D');\n } finally {\n process.stdout.write(' ');\n throw new Error('N');\n }\n });\n\n async function foo() {\n process.stdout.write('O');\n for (const m of await Promise.all([bar(20, 'R', 'M'), bar(10, 'O', 'I')]))\n process.stdout.write(m)\n }\n\n sleep(50).then(() => process.stdout.write('S'));\n\n new Promise((res) => {\n process.stdout.write('B');\n res('E');\n }).then((m) => process.stdout.write(m))\n .finally(() => process.stdout.write(' '));\n\n queueMicrotask(() => process.stdout.write('N'));\n\n process.nextTick(() => process.stdout.write('K'));\n\n setTimeout(() => {\n process.stdout.write('E');\n lock[0] = 1;\n Atomics.notify(lock, 0, 1);\n }, 100);\n\n setImmediate(() => process.stdout.write('P'));\n\n process.stdout.write('R');\n\n foo();\n} else {\n parentPort.on('message', (value) => {\n Atomics.wait(workerData, 0, 0);\n process.stdout.write(value);\n parentPort.close();\n });\n}\njsCopy to clipboard\n\nI encourage you to really take the time to dig through this example. Through the rest of this blog post — particularly the part where we break down how the Node.js event loop works — we will give you the clues you need to figure out what message it generates.\n\nReasoning about order in the Node.js event loop\n\nIn nearly every case where we have worked with customers who are struggling with the performance of their Node.js applications, the issues come down to developers either not understanding, or not paying attention to, the order in which code will be executed and what effect that may have on everything else the application may be doing.\n\nSpecifically: if you cannot reason about the order in which your code will execute, you will be unable to optimise its performance.\n\nLet's start with an example. Save the following script in a file called first.js :\n\nnew Promise(function (resolve) {\n console.log('new promise')\n resolve()\n}).then(() => {\n console.log('then 1')\n})\n\nasync function foo () {\n console.log('async function')\n}\n\nfoo().then(() => {\n console.log('then 2')\n})\n\nsetImmediate(() => {\n console.log('immediate 1')\n})\n\nsetTimeout(() => {\n console.log('timeout 1')\n})\n\nprocess.nextTick(() => {\n console.log('nextTick 1')\n})\n\nqueueMicrotask(() => {\n console.log('microtask 1')\n})\n\nsetTimeout(() => {\n console.log('timeout 2')\n})\n\nsetImmediate(() => {\n console.log('immediate 2')\n})\n\nprocess.nextTick(() => {\n console.log('nextTick 2')\n})\n\nprocess.nextTick(() => {\n console.log('nextTick 3')\n})\n\nqueueMicrotask(() => {\n console.log('microtask 2')\n})\njsCopy to clipboard\n\nAs with the earlier puzzle, develop a hypothesis on the order the console.log statements will be printed before you run this code. Then run the code using the command node first.js and see if your hypothesis was correct.\n\nDid the statements execute in the order you expected? What do you notice about the scheduling priority of each of the scheduling mechanisms? What surprised you most?\n\nNow, let's change the example up just a little. Save the following in a separate file named second.js :\n\nconst { readFile } = require('fs')\n\nreadFile(__filename, () => {\n new Promise(function (resolve) {\n console.log('new promise')\n resolve()\n }).then(() => {\n console.log('then 1')\n })\n\n async function foo () {\n console.log('async function')\n }\n\n foo().then(() => {\n console.log('then 2')\n })\n\n setImmediate(() => {\n console.log('immediate 1')\n })\n\n setTimeout(() => {\n console.log('timeout 1')\n })\n\n process.nextTick(() => {\n console.log('nextTick 1')\n })\n\n queueMicrotask(() => {\n console.log('microtask 1')\n })\n\n setTimeout(() => {\n console.log('timeout 2')\n })\n\n setImmediate(() => {\n console.log('immediate 2')\n })\n\n process.nextTick(() => {\n console.log('nextTick 2')\n })\n\n process.nextTick(() => {\n console.log('nextTick 3')\n })\n\n queueMicrotask(() => {\n console.log('microtask 2')\n })\n})\njsCopy to clipboard\n\nThe order in which the various console.log elements are scheduled is identical to the first example. However, the difference is that we are scheduling those from within a callback that is invoked after asynchronously reading a file. In your best guess, will the order of the console.log statements be the same when this code is executed? If not, why not? What role does the Node.js event loop play in the timing of these various operations?\n\nBefore we start to break it down, let's look at a third example. In this case, simply copy the first example from first.js to first.mjs — that is, create an identical file that differs only in the file extension. The *.mjs file extension identifies it as an ESM module, rather than Node.js's more traditional \"CommonJS\". When you run this example using the command node first.mjs , will the ordering of the console.log statements remain the same as node first.js ? If not, why not?\n\nHere is the output of each of the three examples shown side-by-side:\n\nRemember, the order in which all three examples scheduled the console.log statements is identical across all three examples, and the code in first.js and first.mjs is line-for-line identical. Why, then, would each example produce such different results? And what does all of this have to do with promises anyway? The answer to these questions and more lies in understanding the fundamental operation of the event loop.\n\nThe Node.js event loop: How it works and why it matters\n\nOne of the most important pieces of Node.js documentation that exists isn't even a part of the official Node.js documentation . It is a guide that breaks down the basic operation of the Node.js event loop, published as a separate document on the Node.js website: https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/ .\n\nIn this guide, you will find precise explanations of the event loop phases, the operation of process.nextTick() , a description of how timers work, a description of setImmediate() , an explanation of how asynchronous polling works and more. We consider it to be required reading for all developers who are building applications on top of Node.js. I don't want to duplicate everything that guide says here, but I do want to touch on a couple of fundamentals. Specifically, let's explore this diagram from the guide:\n\nThis diagram illustrates the phases of the Node.js event loop.\n\nThe event loop itself is really nothing more than a simple do/while loop. Within each iteration of the loop, a number of queues are checked to see if there is any work to do. Each of these queues represents one of the \"phases\" outlined in the diagram. At the end of loop iteration, an exit condition is checked to see if another iteration of the loop is needed. If that check determines that there's nothing more for the event loop to work on, the do/while loop exits and the Node.js process terminates.\n\nThere are queues for timers and pending callbacks, as well as an idle queue, a prepare queue, a polling phase (where we check to see if there are any pending notifications from the operating system), a check queue and a close callbacks queue. Each of these queues is essentially just a list of function references waiting to be executed. At each phase, the relevant queue is drained by executing its functions one after the other.\n\nSo, for instance, whenever you use setTimeout() or setInterval() to schedule a timer in Node.js, a callback in the event loop's timers queue is scheduled to process those timers. Whenever you asynchronously read a file from the underlying operating system, a callback is scheduled during the polling phase of the event loop. Whenever you use setImmediate() , a callback in the check queue is scheduled.\n\nSo here's a key question: Where do promises fit in with all of this? The event loop guide was written several years ago and does not include any information about promises and async await, so some people have trouble understanding how and when promises get executed.\n\nThe answer lies in one of the most important, yet least understood, characteristics of the Node.js event loop.\n\nThe Node.js event loop is implemented in C by the libuv dependency library. At each phase the callbacks that are triggered are C/C++ functions (what we'll call the \"native layer\"). When that native layer function is invoked, it may or may not cause JavaScript to be executed. What's important to know, however, is that while that native layer function is executing (for however long it takes to execute) the event loop is stopped. The event loop will not continue until after that native layer function returns. Specifically, this means that while the callback is executing, the event loop cannot do the other things it is meant to do, like trigger timers, poll for operating system events, accept new HTTP requests, and so forth.\n\nIf the native layer function does execute JavaScript, it will call into V8 to invoke a JavaScript function. That JavaScript function may end up doing things like creating and resolving promises or calling process.nextTick() to schedule tasks. What is unique about promises and \"nextTicks\" is that those are stored in two separate queues that are processed independently of the event loop. Those queues are special in that they are drained every time control returns back to a native layer function that has used V8 to invoke JavaScript. This can happen many times per event loop turn and can happen many times during any phase of the event loop.\n\nThe diagram above illustrates what is perhaps the single most important concept that you will ever need to know about the performance of Node.js applications, so study it well.\n\nLook back at the examples given previously — both the puzzle and the three example orders. Can you identify what JavaScript in each of those examples is blocking the Node.js event loop? Think about it carefully because it's actually a bit of a trick question!\n\nThe answer? All of it!\n\nThe basic rule of thumb is this: Whenever JavaScript is executing in Node.js, the event loop is blocked. The longer your JavaScript takes to run, the longer your event loop will be blocked from doing anything else. The longer your event loop is blocked, the worse your Node.js application performance will be. It's really that simple.\n\nSo what does this have to do with \"broken promises\"?\n\nIn our experience, the overwhelming majority of cases we see with our customers are applications that allocate thousands upon thousands of synchronously-resolved promises in tight synchronous loops or hot code paths that are repeatedly executed. In one extreme example, for instance, I worked with one customer who created over 30,000 synchronously-resolved promises in a single for-loop that ended up blocking the Node.js event loop for over a minute! The worst part was that only a very small part of that code actually scheduled asynchronous work, meaning that most of the promises created were wasted allocations.\n\nThink about the diagram above and what this code was doing: Some bit of JavaScript was being executed, creating thousands of promises in a blocking for loop, most of which were resolved synchronously — which means the thousands of then or catch functions were being put immediately into the microtask queue that is immediately drained after the for loop exits and control returns back to the native layer function. Those thousands of then handlers would each schedule additional then handlers which would also be put into the microtask queue, and drained, and so on. Because most of those were resolved synchronously, all of this would simply cause the event loop to be blocked waiting for the native layer function to finally return control back to it so it could move on to the next thing.\n\nLet's return to the three examples running side by side that schedule code in the same order but print different results:\n\nUsing what we just explained about the event loop phases and the nextTick and microtasks queues, can you reason about why these examples have such different results?\n\nIn the first example, the Node.js native layer invokes the JavaScript in first.js at startup, then starts the event loop only if there is work for the event loop to do. When that initial bit of JavaScript has finished running and control returns back to the native layer, Node.js drains the nextTick and microtask queues — in that order. That is why, in the first column, we see the three nextTick statements followed by the two then statements and microtask statements. After those print, the event loop starts to turn and we move through each phase of the event loop where timers and immediates are invoked.\n\nIn the second example, the only thing that the initial bit of JavaScript does is schedule an asynchronous read of the file. None of the other callbacks are scheduled until after the event loop has started. The callback that does the scheduling is invoked during the event loop polling phase. Here we see that as soon as that JavaScript callback is complete, the nextTick and microtask queues are drained, exactly as in the first example. However, notice that, unlike the first, the immediates are executed before the timers. That is because we are still in the middle of the event loop turn. Functions scheduled using setImmediate() are executed after the polling phase and before the start of the next event loop iteration. Timers are always executed at the start of the next event loop iteration.\n\nIn the third example, although the code is identical to the first, we see that the order of the statements has diverged even further. That is because the file is processed as an ES6 Module — which means the JavaScript is being executed within the context of a promise after the event loop has already started. Any synchronously pending microtasks end up being drained before the nextTicks in that case, and because the event loop has already started and the JavaScript ends up being run during the polling phase of the event loop, we again see the immediates being printed before the timeouts.\n\nThe timing differences here matter a great deal when we need our Node.js applications to perform well under load. It also depends a great deal on what kind of application you are building. If your Node.js application is intended to be used by just one person locally on their own desktop, reading a file and crunching through some data, then event loop blocks really are not that big of a deal — in fact, in some cases, it is better to block the event loop. However, if your Node.js application is driving an HTTP server that needs to serve thousands of requests, it is critical that you allow your event loop to turn — you need to carefully reason about and design your code to allow JavaScript functions to run as quickly and as efficiently as possible, so that the event loop can continue to turn and move on to processing that next request.\n\nUsing promises correctly\n\nIn our Broken Promises workshop, we break down all of the various ways we've seen promises abused in real world applications and show how to correct those issues. Some of the areas covered include:\n\nThe dangers of using promises in APIs that do not expect them\nThe dangers of creating and resolving promises in loops (and how to do so correctly)\nThe correct way to mix events and promises\nThe correct way to mix traditional callbacks and promises\nThe correct way to cache promises\nUnderstanding how promises branch and fork and how to handle those correctly\nThe dangers of using Promise.race() and Promise.all() and how to handle those correctly\nHow to cancel promises correctly using the standard AbortSignal and AbortController APIs\nHow to handle errors and promise rejections correctly\n\nWe frequently present an abridged three-hour version of the workshop at events and conferences, but to really get the full picture we offer companies a more expansive three-day workshop that not only breaks down promises but our entire methodology around diagnosing and fixing Node.js performance issues.\n\nIf you feel your team would benefit from having a deeper understanding of promises and Node.js performance in general, please reach out for details on pricing and availability of the full Broken Promises and Node.js Performance Workshop."
],
"categories": {
"primary": "backend",
"others": [
"perf"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"insights-5-drivers-of-a-post-pandemic-resurgence-in-healthcare": {
"href": "https://nearform.com/insights/5-drivers-of-a-post-pandemic-resurgence-in-healthcare",
"postType": "blog",
"slug": "insights-5-drivers-of-a-post-pandemic-resurgence-in-healthcare",
"date": "2021-06-08",
"title": "With a post-pandemic world on the horizon, it's time to prepare for the Covid-19 recovery and maximise the opportunities in healthcare that lie ahead.",
"authors": [],
"content": [
"As we emerge from the devastating effects of Covid-19, we must embrace the potential for technology to transform healthcare delivery.\n\nWith a post-pandemic world on the horizon, it’s time to prepare for the Covid-19 recovery and maximise the opportunities in healthcare that lie ahead. It will probably take between five and ten years to address the backlog of health issues that built up during the pandemic, so there is no denying the magnitude of the crisis — but the accelerated delivery of digital health that it forced on us presents an opportunity to embrace a new era in healthcare.\n\nCovid-19 exposed many gaps in our ability to respond to a major crisis. We need to find ways to improve our day-to-day delivery of services while also developing greater resilience to weather inevitable future pandemics.\n\nProvide more efficient access to care\n\nHealthcare spending is forecast to increase at a CAGR of 4% over 2020–24, up from 2.8% in 2015–19, and healthcare spending as a share of GDP worldwide will probably hover around 10.3% through 2023. We can help to reduce the cost of healthcare by making it easier to access care early.\n\nBy giving physicians, pharmacists and other healthcare providers access to care systems in real time, we can intervene earlier and drive down the cost of care by treating conditions before they become more serious. Delayed detection and treatment of serious health conditions not only reduces quality of life, it also means the care required is likely to be more extensive — and therefore costly. However, if conditions such as heart disease and diabetes are detected early, lifestyle changes can form a larger part of effective treatment and therefore reduce the level of costly clinical interventions otherwise needed.\n\nFor patients, real-time access to care systems helps to ensure continuity of care and makes it easier to schedule appointments. Telehealth and remote patient monitoring, including the use of mobile apps for self monitoring — central elements of care during the pandemic — have proved themselves to be a cost-effective and reliable means to increase capacity in under-resourced and geographically dispersed health systems. Scaling these approaches to be the default for appropriate cohorts will require both new tools and new processes.\n\nFocus on the patient\n\nIt might sound obvious, but we need to start approaching healthcare from the patient’s perspective. This means giving them the tools to manage their healthcare pathways. Individuals want access to their own information and some level of control over their health journey.\n\nIn the United States, the 21st Century Cures Act gives patients greater access to their records and makes it easier for organisations to share records. Healthcare providers, developers of certified health IT and health information exchanges and networks must permit patients to access their electronic health information through their preferred application.\n\nSecure inclusive patient portals engage patients by allowing them, not only to access their health data, but to pay bills, refill prescriptions, schedule appointments and increase their involvement in managing their own care. In the future, we are likely to see more apps and services being built on top of this data, so the potential for increased self-management of patient care will expand.\n\nIntegrate healthcare systems\n\nSimply put, healthcare systems need to talk to each other. The siloed approach to healthcare means consultants and other health practitioners have to log into multiple systems to find the data they need. This causes unnecessary delays and can make it more difficult to coordinate an effective care plan for the patient.\n\nAlthough more than 80% of US physicians' offices use some form of Electronic Health Records (EHRs), interoperability remains a huge gap. 2020 proved that it's possible to move quickly and securely with interoperability. The same bold approach must be taken in adopting standards such as Fast Healthcare Interoperability Resources (FHIR), a standard for exchanging EHRs.\n\nA more efficient approach makes scans, test results and other records in the patient pathway available to the relevant people when required. These kinds of integrated systems are generally considered to offer superior quality and safety due to more effective communication and standardised protocols. Staff shortages, continuing cost inflation and service demand are intensifying the need for more effective and efficient use of scarce resources through integrated service delivery models.\n\nLeverage health data from consumer wearables\n\nThe growing popularity of smart watches and other wearable devices means patients are recording substantial amounts of useful health data in real time on an ongoing basis. They are doing this while going about their everyday lives, so the data is being gathered in a non-invasive way.\n\nHealthcare organisations could use that data in a careful and privacy-preserving way to produce better outcomes and decisions for patients. Harvesting and leveraging data from sensors and wearables to provide analytics and dashboards moves the pathway for care out of our clinical environment and into our homes. This creates a holistic picture of the patient in a process that is unobtrusive and cost-effective.\n\nThe data harvested from consumer wearables also offers the potential to intervene before health conditions advance. People with heart disease, lung disease and diabetes can use a pulse oximeter to monitor the progress of their illness by measuring significant changes in their blood oxygen levels, for example.\n\nDevelop tools for data decision-making\n\nCombining advanced analytics and machine learning with the latest approaches to data lakes allows healthcare providers to make smarter clinical and operational decisions. In the area of clinical decision-making, for example, longitudinal data on individual patients and cohorts gathered from imaging, laboratories and genomics can help improve decisions on everything from one-off interventions to entire populations. From an operational perspective, real-time, enterprise-wide data enhances the efficiency of workflows, teams and entire organisations.\n\nResearchers, providers and policymakers are turning to big data analytics models to help improve care delivery, allocation of resources and preventive health measures. Advances in data-collection technology are required to pull the salient information, process the data and provide meaningful information for physicians to improve outcomes and decision-making. A firmer data foundation, combined with physicians’ skills, techniques and experiences, will create the platform required to drive better outcomes for patients.\n\nFurther up the healthcare chain, patient data can be anonymised and supplied to the pharmaceutical and biotech industries to help them create better products, therapies and approaches. This will be particularly relevant during initial research and clinical trials.\n\nAs the industry continues to innovate and refine these tools, data-driven decisions will soon become standard, leading to more proactive, successful healthcare operations.\n\nWhere to next\n\nFrom NearForm’s experience working at speed with governments and HLS companies, we have demonstrated our ability to deliver solutions such as the Covid-19 contact tracing apps and vaccine credentialing passport to get the world back up and functioning.\n\nOur research team's work on machine learning inside the browser and on low-cost wearables proves that it's possible to quickly embrace these kinds of technologies and benefit from them now — not at some indeterminate point in the future.\n\nOur initiatives have focused on privacy-preserving solutions that centre on patients, customers and businesses, allowing our clients to work quickly and effectively, without ever compromising on quality or security.\n\nTechnology is transforming health. Now that we’re emerging from the devastating effects of Covid-19, with vaccines being distributed across the world, the resurgence in digital health must drive the future of healthcare."
],
"categories": {
"primary": "data",
"others": [
"ai",
"cloud",
"mobile",
"product"
]
},
"verticals": {
"primary": "health",
"others": []
}
},
"digital-community-prisma-orm": {
"href": "https://nearform.com/digital-community/prisma-orm",
"postType": "blog",
"slug": "digital-community-prisma-orm",
"date": "2021-06-09",
"title": "What is Prisma and Why Do We Need Another ORM?",
"authors": [
"BINOY PATEL"
],
"content": [
"Prisma is a next-generation object–relational mapper (ORM) that claims to help developers build faster and make fewer errors. Prisma takes a different approach to ORMs compared to traditional ORMs. It uses a custom Schema Definition Language (SDL) that automatically writes migrations and generates type-safe code. Unlike TypeORM and MikroORM, Prisma does not use classes or decorators for model definition. It instead uses code generation from schema, similar to the popular GraphQL Code Generator utility. This generated TypeScript code is used by the Prisma Client for stricter type safety and rich IDE auto-completion features. Later in the post, we will compare Prisma to TypeORM and how Prisma solves some issues that could still lead to runtime errors in TypeORM.\n\nComparing the approach with Prisma 1, which required a custom server running in a container to transform calls to database queries, which pushed away a lot of early adopters, Prisma 2 completely changes the approach, using a pre-compiled binary instead.\n\nHow Does Prisma Work?\n\nPrisma takes the models written in the schema and with the prisma migrate command generates the SQL migrations as well as types that are stored in node_modules/.prisma/client. These types are aware of the relations that are created in the models as well as provide generated code that can be used to query the models. In the section below, we will take a closer look at how to create models and use them with the Prisma client. When you query using the client, it takes the queries and passes them to a Query Engine binary that optimizes it and converts it to a database query.\n\nDescribes the Prisma architecture. Source: Prisma Docs\n\nPrisma's engine is something you would not have to interact with ever when working with Prisma, but it helps us understand how Prisma works. All communication to the database layer happens via the engine. The optimization the engine provides does have benefits—one of the biggest being that it solves the N+1 relationship problem, which is common in GraphQL applications.\n\nCreating Our First Model\n\nLet's start exploring Prisma by creating a simple library application where we have books with multiple authors. First we will bootstrap a Prisma application using this script:\n\ncurl -L https://pris.ly/quickstart | tar -xz --strip=2 quickstart-master/typescript/starter\njsxCopy to clipboard\n\nThis will create a new folder starter that we will navigate to using cd starter and run npm install.\n\nThe starter comes with some boilerplate for us to get started. We will look at the prisma folder and all the files that have been automatically created. The .env file can be used for specifying environment variables such as database URL, username, and password from which the Prisma SDL can read. dev.db is for SQLite, which we will be using for this tutorial.\n\nThe most important file is the schema.prisma, which is the SDL we will use to define our models. Let's delete everything in the file and replace its contents with the following, as we will write our own models and not use the one provided in the starter:\n\ndatasource db {\n provider = \"sqlite\"\n url = env(\"DATABASE_URL\")\n}\n\ngenerator client {\n provider = \"prisma-client-js\"\n}\njsxCopy to clipboard\n\nIn these lines, we are defining our data source and letting Prisma know that we will be using SQLite. The URL for it will come via the environment variables. Finally, the generator is used to let Prisma know which language we will be using with the Prisma client. In this case, it will be JavaScript.\n\nWe will now create our first model which will define our book entity:\n\nmodel Book {\n id Int @id @default(autoincrement())\n title String\n description String?\n}\njsxCopy to clipboard\n\nLet's break this model down and understand what everything means.\n\nModel\n\nmodel correlates to a table name in the database. The name of the model should adhere to the following naming conventions:\n\nMust start with an alphanumeric letter and otherwise consist of more numbers, letters, or underscores\nMust start with a letter and is typically spelled in PascalCase\nShould use the singular form (for example, User instead of user, users or Users)\nFields\n\nFields are defined in the following syntax:\n\nname of the field type of the field any attributes\n\n\nIn the case of id, we want the id to be of type Int and this will be the primary key that is defined using @id attribute. Finally, we want to automatically increment the id by default for it to be unique. This is achieved by using @default(autoincrement())\n\nCheck out these links for a list of all the Types and Attributes supported by Prisma\n\nhttps://www.prisma.io/docs/reference/api-reference/prisma-schema-reference/#model-field-scalar-types\nhttps://www.prisma.io/docs/reference/api-reference/prisma-schema-reference/#attributes\n\n? after the type indicates that the field is optional.\n\nMigrations and Prisma Client\n\nJust by writing the model, Prisma does not automatically update your database. We will need to create a migration and run it against our database. In development, this can be done using the following command:\n\nnpx prisma migrate dev --name init\nbashCopy to clipboard\n\nThis will create a new folder, migrations, in the prisma folder. Prisma will automatically create a SQL file which, in development, is automatically run against the database. Prisma also generates the types declarations for all the models that can be used with the Prisma Client for TypeScript.\n\nJumping to the script.ts file located at the root of the project, we can see that there is some boilerplate already setup for us to start using our Prisma client.\n\nTo connect to our database using Prisma client, we need to import and instantiate it:\n\nimport { PrismaClient } from \"@prisma/client\";\n\nconst prisma = new PrismaClient();\njsxCopy to clipboard\n\nAll the methods to query our data are located on the prisma variable itself. Let's create a new book and query all the books in our database.\n\nInside the main() function we will paste the following code to create a new book:\n\nconst book = await prisma.book.create({\n data: {\n title: \"Effective JavaScript\",\n description:\n \"Effective JavaScript is an in-depth look at the JavaScript programming language and how to use it effectively to write more portable, robust, and maintainable applications and libraries. Using the concise, scenario-driven style of the Effective Software Development Series, this book brings together tips, techniques, and realistic code examples to explain the important concepts in JavaScript.\",\n },\n});\nconsole.log(book);\njsxCopy to clipboard\n\nWe can run the script by running npm run dev. After the script successfully runs, we should see the new book printed to the console.\n\nLet's make sure that we can see this book when we query for all the books, which we can do using the following code:\n\nconst allBooks = await prisma.book.findMany();\nconsole.log(allBooks);\njsxCopy to clipboard\n\nRunning the script again with npm run dev, we return with an array with our book Effective Javascript as the only entry.\n\nThis link provides a list of all the available methods available on models that can be used to query or update the data.\n\nhttps://www.prisma.io/docs/reference/api-reference/prisma-client-reference#model-queries\n\nAdding a Relationship\n\nLet's look at how we can add a relation to our book model by adding a many-to-many relationship with author. Open schema.prisma again and update the book model with the following lines and add the author model\n\nmodel Book {\n id Int @id @default(autoincrement())\n title String\n description String?\n authors Author[]\n}\n\nmodel Author {\n id Int @id @default(autoincrement())\n name String\n books Book[]\n}\njsxCopy to clipboard\n\nRunning npx prisma migrate dev --name author will generate another migration for us. Let's take a look at what SQL code Prisma generated for us:\n\n-- CreateTable\nCREATE TABLE \"Author\" (\n \"id\" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,\n \"name\" TEXT NOT NULL\n);\n\n-- CreateTable\nCREATE TABLE \"_AuthorToBook\" (\n \"A\" INTEGER NOT NULL,\n \"B\" INTEGER NOT NULL,\n FOREIGN KEY (\"A\") REFERENCES \"Author\" (\"id\") ON DELETE CASCADE ON UPDATE CASCADE,\n FOREIGN KEY (\"B\") REFERENCES \"Book\" (\"id\") ON DELETE CASCADE ON UPDATE CASCADE\n);\n\n-- CreateIndex\nCREATE UNIQUE INDEX \"_AuthorToBook_AB_unique\" ON \"_AuthorToBook\"(\"A\", \"B\");\n\n-- CreateIndex\nCREATE INDEX \"_AuthorToBook_B_index\" ON \"_AuthorToBook\"(\"B\");\nsqlCopy to clipboard\n\nWhen we specify authors Author[] and books Book[] Prisma understands this is a many-to-many relationship and automatically creates a join table for us, which we don't have to worry about when interacting with the data.\n\nNow let's take a look at how we can interact with this data using the client. First, let's clear all the data currently in our DB and start fresh. We can do so using the following code:\n\nawait prisma.book.deleteMany()\njsxCopy to clipboard\n\nWe will now create a book and author in the same call. Let's take a look how we can do that:\n\nconst newBook = await prisma.book.create({\n data: {\n title: \"Effective JavaScript\",\n description:\n \"Effective JavaScript is an in-depth look at the JavaScript programming language and how to use it effectively to write more portable, robust, and maintainable applications and libraries. Using the concise, scenario-driven style of the Effective Software Development Series, this book brings together tips, techniques, and realistic code examples to explain the important concepts in JavaScript.\",\n authors: {\n create: {\n name: \"David Herman\",\n },\n },\n },\n});\n\nconsole.log(newBook);\njsxCopy to clipboard\n\nWhen we run the script again with npm run dev, we will see only the book information logged to the console but not the author. We will look at why that is the case later. Before that, let's understand what is happening in this method.\n\nWe are creating a new book, but we are also creating a new author using the create key, which tells Prisma to create the author and also to add an entry in the join table connecting the book and the author.\n\nNow, if we try to query the books using await prisma.book.findMany() we will not see the author again in the console. This is because, by default, Prisma does not automatically join all the relations; we have to manually specify which relationships we want to include in the query. To do so, we use the include keyword in the query. Let's take a look at the example again:\n\nconst allBooks = await prisma.book.findMany({ include: { authors: true } });\nconsole.log(allBooks);\njsxCopy to clipboard\n\nBecause we didn't tell the client to include the related author's data in the last query, it was missing the author's data. To include relationships in the query we can use the include keyword to specify which relationships we want to join. In the above query include: { authors: true } joins the authors to the books.\n\nType Safety\n\nWe looked at how we can create, query, and delete data from our database using Prisma client. Let's now explore the real power of Prisma, which is the type safety it provides.\n\nIf you are using Visual Studio Code as your IDE it is highly recommended that you install the Prisma extension as it helps provide formatting, syntax highlighting, linting and much more in the Prisma Schema. It can be found on the Visual Studio Marketplace: https://marketplace.visualstudio.com/items?itemName=Prisma.prisma\n\nLet's take a look at few examples where Prisma helps us prevent runtime errors especially when working with relationships:\n\nconst book = await prisma.book.findUnique({ where: { id: 1 }});\nconsole.log(book.authors);\njsxCopy to clipboard\n\nWhen we query a book by id we see two errors.\n\nFirst Object is possibly 'null'. This means that when we query a book by id it possibly does not exist. We can use optional chaining here to fix the error by changing it to console.log(book?.authors); . This still does not fix the error Property 'authors' does not exist on type 'Book'. The reason for this is that Prisma is aware that, although the relationship exists for Book and Author, we have actually not told the client to do the join. To fix this we can change our query and we see that there are no further errors:\n\nconst book = await prisma.book.findUnique({\n\twhere: { id: 1 },\n\tinclude: { authors: true },\n});\nconsole.log(book?.authors);\njsxCopy to clipboard\n\nCompared to this, relationships in TypeORM are not strongly typed. It just assumes that the relationships are included and will not provide an error message when querying nested fields. However, in reality this is not the case and this could lead to runtime errors. This is just one instance where Prisma helps us reduce errors. While it is highly recommended to use Prisma with TypeScript, you can use Prisma with plain JavaScript as well.\n\nConclusion\n\nIn this simple tutorial, we looked at just a few of the many things Prisma does well. In addition, the Prisma Studio, which is helpful for browsing your data, is part of the Prisma CLI and can be accessed with npx prisma studio\n\nPrisma documentation is also a great resource for finding exact answers for doing something specific with Prisma. https://www.prisma.io/docs/",
"GRAPHQL\nGame of Types: A Song of GraphQL and TypeScript\nSTEVEN MUSUMECHE\n23 MAY 2019\nOPEN-SOURCE\nBACKEND\nREACT\nTipple: Stealing Ideas From GraphQL and Putting Them to REST\nANDY RICHARDSON\n16 MAY 2019"
],
"categories": {
"primary": "backend",
"others": [
"data",
"cloud"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"insights-making-the-transition-to-figma": {
"href": "https://nearform.com/insights/making-the-transition-to-figma",
"postType": "blog",
"slug": "insights-making-the-transition-to-figma",
"date": "2021-06-15",
"title": "Ease of collaboration made Figma the logical choice for our design team.",
"authors": [],
"content": [
"Ease of collaboration made this tool the logical choice for our design team.\n\nAs a remote-first digital solutions delivery company, NearForm is no stranger to working across time zones and with a variety of different tech stacks. Our design team always works with the client’s software, and a feature we value highly in any tool is the way it facilitates collaboration with the client and within our team.\n\nIn an effort to improve this collaboration we recently decided to make the switch from Sketch to Figma .\n\nToday, we'll take a look at some of the reasons that prompted us to make the switch, how that switch came about and how we plan to approach changing design trends in the future.\n\nWhy we changed our design stack\n\nUntil we switched to Figma, NearForm generally worked with a combination of Sketch, Abstract, Zeplin and Invision , with occasional forays into Adobe XD .\n\nWith Sketch, you can create your design and then upload it in JPEGs to InVision to create a prototype that allows you to simulate the end product on a device and create clickable hotspots. Prototyping is an important part of the design discovery process at NearForm. We use discovery workshops to reduce the time spent on discovery and provide our clients with comprehensive product prototypes at the end of the process.\n\nThe design tools market is an active one, with constantly shifting trends and new players entering, dominating and leaving it on a regular basis. Sketch proved itself to be a good tool for user interface/user experience (UI/UX) designers working in the Mac environment, but it has faced growing competition in recent years.\n\nFigma emerged in 2016 as a cross-platform, browser-based design solution specifically created for UI design and quickly distinguished itself as a serious contender in the increasingly crowded market. At the time, Sketch simply wasn’t adding new features as quickly as rivals such as Figma. Following several iterations and the addition of numerous new features, Figma became more stable and emerged as a potential replacement for Sketch.\n\nOne of the most compelling reasons to move to Figma was its strength as a collaborative tool. Sketch did add Sketch for Teams to cater for designers working together, but it remained a product in which users worked and made their changes in isolation and shared the outcome when it was ready.\n\nSketch has since added real-time collaboration, but until recently Figma was the only design tool that allowed separate users to work on the same document at the same time. The experience was completely interactive, allowing designers to work in a truly collaborative fashion at the same time.\n\nFor teams working across timezones, it’s a huge benefit to be able to jump into the same file with someone as you work on it together. And it’s not just useful for designers; developers can access files at a much earlier stage of the process, allowing them to be part of the process sooner.\n\nIntegration with Storybook , an open source tool for developing UI components, also enhances the designer/developer workflow\n\nHow we moved\n\nNearForm always works with the software our clients use, so we are in touch with shifts in trends. By mid-2020, we noticed that many of our clients were transitioning to Figma. For example, part of the design work for the Covid-19 contact tracing app we built for Scotland was completed in Figma.\n\nWith some 90% of our design work taking place on Figma by early 2021, the logical decision was to move our entire stack to Figma. Although we still use Sketch and Adobe XD, the industry trend is toward Figma — primarily because of its collaborative tools, excellent enterprise plan, and the fact that it is based in the cloud.\n\nNo tool is perfect, but Figma is constantly adding features and improving. With an excellent developer community and an open API, Figma allows users to develop plugins and work more interactively with it. Furthermore, Figma reduces costs substantially by eliminating the need for separate branching and version control, prototyping and design tools for working with developers.\n\nWhere to next\n\nDesign software is constantly evolving.\n\nFrom MS Paint to Adobe Fireworks (formerly Macromedia Fireworks) to Photoshop to Sketch, the tools preferred by designers are always changing. And, although Figma is top of the design heap today, it could be toppled within a couple of years. Designers don’t tend to be brand loyal; they will use whatever makes their work easier to produce quality work. However, in a world driven by speed and the need to ship quickly and often, Figma offers the perfect tool for a collaborative workflow. With new features such as branching, it also blurs the lines between development practices and design practices, making it even easier for teams to work together."
],
"categories": {
"primary": "design",
"others": [
"product"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"digital-community-screen-readers": {
"href": "https://nearform.com/digital-community/screen-readers",
"postType": "blog",
"slug": "digital-community-screen-readers",
"date": "2021-06-17",
"title": "Front-End Development for Screen Readers: A Five-Second Jumpstart (macOS)",
"authors": [
"CHRIS FRITZ"
],
"content": [
"Think back to the last time you finished work on an interface.\n\nMaybe it was a small feature addition, or an entirely new application. In its completed form, the UI looked just like it should. The functionality was up to spec. If you're the kind of person who gets attached to your work, maybe it even seemed to sparkle around the edges. ✨\n\nWhile working on it, maybe you had some concerns about accessibility. But if no one had mentioned it as a deliverable, is it your responsibility to make sure that UI is useable by everybody? If you're a front-end developer, designer, QA engineer, or otherwise involved in creating interfaces for people, there's a fine collection of articles on the internet that could do better than me to convince you: accessibility is your responsibility, too.\n\nAccessibility can be a daunting field. There is a wide variety of disabilities, and no user is the same. Following best practices and using automated tools will get you a long way, but stepping into the shoes of your users, experiencing websites the way they do, will give you perspective and knowledge that can only be gained firsthand.\n\nOne tool used by millions of blind or visually impaired people, shaping how they experience the web, is the screen reader. Trying out a screen reader yourself can be intimidating, seemingly requiring specialized knowledge and a large time investment. But in fact, they are surprisingly approachable once you know a couple shortcuts. I'll show you how to use one for your work, starting today, in five seconds. Is five seconds quicker than you expected? Well, macOS and Windows both come with screen readers built in and ready to use, so trying out your website or web app with a screen reader is actually just a keyboard shortcut away. Learn just one or two more shortcuts, and you're ready to evaluate and solve a huge variety of essential accessibility problems that might come up in your UI.\n\nScreen reader demo\n\nReady to see it once before you try it yourself?\n\nA couple things to note in that video:\n\nWe found our first accessibility bug!\nIt only took us five seconds to do!\n\nStarting from the first point, the bug—did you notice how the buttons, a \"download from the cloud\" button and a \"trash can\" button, make their purpose pretty clear to sighted users, but to a screen reader user, all they hear upon highlighting each button is the word \"button\"? Considering that one button is meant to preserve data and the other to erase it from existence, getting the two mixed up could be catastrophic. That's an experience no developer would want to inflict on a user, and so it's great we caught this one and can now fix it. Perhaps you can even think about areas in your own recent work where such pitfalls might be lurking.\n\nNext, the speed! Bet you didn't know you had a screen reader so close at hand this whole time. Here are the only two shortcuts used in the video: ||Command + F5|| (Touch Bar users or those using the function key row as volume-changing shortcuts, etc., may need to additionally press and hold ||Fn|| to use ||F5||), to activate VoiceOver; and ||Control + Option + Right (or Left) Arrow||, to navigate from one item to the next. Note that instead of following a two-dimensional control scheme including directions of up and down, screen reader navigation treats the different parts of the page as a one-dimensional sequence of items, just like when you're tabbing through inputs and buttons on a website. If you're having trouble navigating to the right spot on the page, clicking or selecting something nearby with a mouse can jump you closer.\n\nGetting your screen reader start\n\nReady to try it out for yourself?\n\nFirst, open the demo app in a separate browser window so you can read these steps as you go along.\nPress ||Command + F5|| (or ||Command + Fn + F5||) to activate the VoiceOver prompt and click \"Use VoiceOver\".\nClick in the text area.\nPress ||Control + Option + Right Arrow|| to move the VoiceOver cursor (a black rectangle) down to the next item on the page, the buttons. Press it a few more times to find out where it goes, and use ||Control + Option + Left Arrow|| to backtrack your way up the page.\nYou can turn VoiceOver off with the same shortcut you used to activate it, or by clicking the close icon in the VoiceOver window.\nBonus: if you can handle one more shortcut, there's a handy tool called a rotor that helps screen reader users navigate pages. With VoiceOver active, press ||Control + Option + U|| to bring up the rotor and move through the different lists it provides with the arrow keys. Pressing enter on an item will set the VoiceOver cursor focus to that element, and you can interact with it further.\n\nNow, for a fun experiment—pull up a piece of UI you recently worked on, cross your fingers, and activate VoiceOver again. Hopefully your UI seems as friendly to a screen reader user as it does to sighted users. At the very least, now you know how to ensure it will be friendly to them in the future. On a side note: sharing this newfound perspective of yours with those in charge of your project can be a great way to get them invested in putting time into getting the accessibility right. A demo of the screen reader in action on your site is sure to be a persuasive bit of evidence.\n\nNext steps\n\nThe screen reader know-how you now have will be a great help in discovering a broad range of accessibility issues, but once you want to dig deeper into the tougher accessibility problems, here are some great resources to grow your knowledge:\n\nVoiceOver Quick Start: VoiceOver actually comes with its own training module to teach you all the fundamental shortcuts and navigation methods in about 20-30 minutes. You can access it from the \"Learn More\" button in the dialog that pops up when activating VoiceOver, or with ||Command + Control + Option + F8|| any time VoiceOver is active.\nLighthouse: In the Lighthouse tab available by default in Chrome Dev Tools, you can run accessibility tests on your app and get a detailed breakdown of any issues that were detected and advice on how to resolve them. The problematic buttons we spotted in our demo were flagged in Lighthouse tests as well.\nApple VoiceOver Guide\nWebAIM: This site covers the fundamentals of web accessibility in a very easy-to-follow format, with explanations of the important concepts as well as concrete HTML examples representing best practices.\nW3C Web Accessibility Initiative Site: Literally setting the standards for web accessibility, this organization offers a thorough guide for evaluating the accessibility of a website, teaching you what to look for along the way.",
"MOBILE\nDESIGN\nHow to Remain A Successful Product Designer In Our Current Digital Hellscape\nMARK PRESCOTT\n16 MAR 2021\nREACT\nBuilding a more accessible web with semantic HTML\nBRITTANY FEENSTRA\n2 OCT 2019\nResponsive Images: Improving performance by letting the browser do the work\nCODY CROZIER\n8 OCT 2019"
],
"categories": {
"primary": "a11y",
"others": [
"frontend",
"design"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"insights-getting-devsecops-right-in-azure": {
"href": "https://nearform.com/insights/getting-devsecops-right-in-azure",
"postType": "blog",
"slug": "insights-getting-devsecops-right-in-azure",
"date": "2021-06-17",
"title": "We explore how your Azure infrastructure and DevOps flow can be made more secure with DevSecOps.",
"authors": [],
"content": [
"Security features must be implemented at the start of every project and included in the architecture diagram.\n\nThe ratio of development engineers to operations and security engineers in a typical technology organisation is 100:10:1.\n\nThis minimal presence of security engineers means that, without automation and the integration of information security into the daily work of Dev and Ops, Infosec can only perform some compliance checking. This is the opposite of security engineering.\n\nA key aspect of DevSecOps is that security engineers build security decisions into the development lifecycle. By implementing security in applications from the beginning rather than applying it when issues arise, the team catches security vulnerabilities during the development process instead of finding problems after the app release. This explains why it is so important to implement as many security decisions as possible at the beginning of every project and every architecture.\n\nIn this post, we will explore how your Azure infrastructure and DevOps flow can be made more secure.\n\nArchitecture\n\nSetting up a secure cloud environment is not easy, and many things can go wrong. That is why all security features need to be implemented at the beginning of every project and why we need to put them in the architecture diagram.\n\nThe architecture diagram below shows a combination of several Azure resources supported by secure endpoints that are marked with an info flag.\n\nOur backend application is running on Kubernetes, and we have a web app that is deployed as a static website on Azure Blob Storage.\n\nThe mobile app and the web app are publicly accessible, and the communication with the backend application is happening over an API Management gateway.\n\nAll users are controlled by the Azure AD B2C service.\n\nThe data is saved in Azure Postgres DB Server, and all services are monitored by the Azure Monitoring service.\n\nOn the other side, we are using the Azure DevOps service for our code repository and for the CI/CD flow:\n\nThis diagram contains several info symbols. All of them are related to security features described in this blog post:\n\nGit pre-commit hooks\nCI/CD automation testing\nSecurity policies\nRBA\nLogically segment subnets\nDatabase encryption\nThreat monitoring\nGit pre-commit hooks\n\nThis is probably the easiest advice to implement, but many developers overlook it.\n\nWe can avoid a data breach and sensitive information exposure by using git pre-commit hooks to prevent developers from leaking passwords and secrets when they commit and push code to a repository. Pre-commit checks are used to find common security issues before changes are committed into source code repositories.\n\nSecrets in the working directory, such as the .env file, may need to be ignored to prevent them being committed to a repo or package registry. We need to control what we are going to push on the code repository. Here is an interesting repository with a list of useful hooks that can be implemented in your code.\n\nWe all know that the development teams put effort into reviewing Pull Requests. Furthermore, many automated stages in the pipelines are dedicated to checking the code. Sometimes those checks are time-consuming for the reviewers, which is why it is advisable to split the checks and make some of them run locally. Here is a good example of private keys detection and of how this is done with a Python script, but the same thing can be done directly in your hook directory with Bash code because it is the default hooks language.\n\nCI/CD Automation Testing\n\nSecurity implementation in Continuous Delivery is really important. The two most popular methods for security testing in a pipeline are:\n\nDAST (Dynamic Application Security Testing)\nSAST (Static Application Security Testing)\n\nSAST is a white-box testing methodology. White-box testing evaluates a range of static inputs, such as documentation and application source code.\n\nDuring the scanning process, SAST refers to a predefined set of rules to detect vulnerabilities. The scanning process can be easily integrated into the CI/CD pipeline, and the SAST tools are activated once the code is pushed to a source code repository.\n\nIn contrast to SAST, DAST uses a black-box approach and assumes that testers have no knowledge of the inner workings of the software being tested. Black-box testing needs to be dynamic. This dynamic approach allows DAST to detect a wide range of real work vulnerabilities, including memory leaks, SQL injection and XSS attacks. Snyk is a popular tool that can be integrated into your Azure DevOps pipeline. It offers both free and paid plans and enables security across the Microsoft Azure ecosystem, including Azure Pipelines.\n\nSnyk offers a set of application security tools, including open source vulnerability scanner, that help to automatically find, prioritise and fix vulnerabilities in the open source dependencies throughout your development process. Snyk automatically finds and fixes application and container vulnerabilities. Learn more about about implementing Snyk in your Azure Pipeline .\n\nRBAC\n\nAzure role-based access control (Azure RBAC) provides access management to the Azure resources. Azure RBAC helps you manage access for your team members. It determines who has access to which Azure resources, what they can do with those resources and what scopes they have access to.\n\nWith Azure RBAC, you can enable different roles within your team, and you can also grant users the minimum access required to do their jobs.\n\nRole is a collection of actions that the assigned user or application identity can perform. We can create different roles for a specific User, Group or Service Principal, and those roles can be assigned to different resources. Role assignment is a combination of the role definition, service principal and scope.\n\nAnother RBAC suggestion is to deny people access to Production. Only CI/CD should be able to make changes there.\n\nBuilt-in roles are fixed, with a predefined set of permissions. These role definitions cannot be updated. Azure AD supports many built-in roles o round off the edges and create something specifically for your requirements. Azure AD also supports custom roles.\n\nIn Azure Active Directory > Roles and administrators > New custom role. Select a permission for your custom role, and it will be ready for assignment.\n\nSecurity Policies\n\nWhereas RBAC focuses on the user actions, security policies focus on the resource properties. Policy definitions describe resource compliance conditions and the action to take if a condition is met. A condition compares a resource property field or a value to a required value.\n\nHere are two important facts about the policy definitions:\n\nYou can define a condition (if/else) and an effect (deny, audit, append, modify, etc).\nBuilt-in and custom policies are supported.\n\nBased on the architecture that we showed in the diagram, we will add a policy definition for our Kubernetes cluster from the Azure Portal. To do this, go to Policy and then to Definitions .\n\nLet’s search for Container Registry in the category field.\n\nDisabling public network access improves security by ensuring that container registries are not exposed on the public internet. Creating private endpoints can limit exposure of container registry resources. Select the following policy from the listed definitions: Public network access should be disabled for Container registries. Click on the three dots to the right and select Assign .\n\nThe following screen will be displayed:\n\nIn the basic setup, simply select the Scope where this certain policy will be assigned. From the Scope dropdown, select your Resource Group where the Container Registry is launched.\n\nThe Azure Policies do not check the user permission. It assumes the user already has write permissions.\n\nLogically segment subnets\n\nAzure Virtual Networks are similar to the Local Area Networks on your on-premises network.\n\nThe idea behind an Azure virtual network is that you create a network based on a single private IP address space, on which you can place all your Azure virtual machines. The private IP address spaces are available in the Class A (10.0.0.0/8), Class B (172.16.0.0/12) and Class C (192.168.0.0/16) ranges.\n\nSubnets and VNets are not changeable and require resource recreation. Each subnet must have a unique address range within the address space of the virtual network.\n\nThe address range cannot overlap with other subnets in the virtual network. There are limits to the number of network interfaces and private IP addresses that you can have within a virtual network.\n\nIn our scenario, we have 2 different Class A subnets in the same virtual network. The first one is dedicated to the Kubernetes cluster and to the Postgres DB server. The second one is dedicated to API management. Cross-subnet communication is allowed and the API management is able to communicate with the ClusterIP type services in the Kubernetes cluster.\n\nWe already know that our first subnet will be used for communication between the Kubernetes cluster and the Postgres DB server, so we need to select a service endpoint.\n\nVirtual Network (VNet) service endpoint provides secure and direct connectivity to Azure services over an optimised route via the Azure backbone network. Endpoints allow you to secure your critical Azure resources within your virtual networks only. Service endpoints enable private IP addresses in the VNet to reach the endpoint of an Azure service without needing a public IP address on the VNet.\n\nDatabase Encryption\n\nAzure PostgreSQL leverages Azure storage encryption to encrypt data at-rest by default using managed keys. Data encryption with customer-managed keys for Azure PostgreSQL Database Server is configured at the server-level for a given server, where a customer-managed key called the key-encryption key (KEK) is used to encrypt the data encryption key (DEK) used by the service. The KEK is an asymmetric key stored in a customer-owned and customer-managed Azure Key Vault instance.\n\nWhen the Database Server is configured to use a customer-managed key stored in the Azure Key Vault, the server sends the DEK to the Key Vault for encryption. In the encryption process, an encryption key (KEK) is used to encrypt the DEK. Use of a Key Encryption Key that never leaves Key Vault allows the data encryption keys themselves to be encrypted and controlled.\n\nKey Vault returns the encrypted DEK, which is stored in the user database. For decryption, the server sends the protected DEK to the Key Vault, and then the value is used on the Database Server side. In the following image, you can see visually how the data encryption works on a PostgreSQL Database Server.\n\nWe already have a Key Vault deployed on Azure, so we can use the same one for enabling the data encryption on our PostgreSQL database server. Several requirements need to be satisfied for setting up a key that will protect the data on our PostgreSQL DB server such as:\n\nKey Vault and Azure Database for PostgreSQL single server must belong to the same Azure Active Directory (Azure AD) tenant.\nThe Key Vault must be set with a 90-day retention period.\nYou must enable the soft-delete feature on the Key Vault.\nYou must enable purge protection to enforce a mandatory retention period for deleted vaults and vault objects.\nYou must grant the Azure Database for PostgreSQL single server access to the Key Vault with the get, wrapKey and unwrapKey permissions.\nThreat Monitoring\n\nAzure Security Center is a unified infrastructure security management system that strengthens the security posture of your data centres and provides advanced threat protection across your hybrid workloads in the cloud. You can use Azure Security Center for threat protection.\n\nAzure Security Center focuses on three security challenges:\n\nRapidly changing workloads\nIncreasingly sophisticated attacks\nSecurity skills in short supply\n\nSecurity Center can be involved in the functionality of different services. In our case, we will scan for potential vulnerabilities in the images that we push to the Azure Container Registry (ACR).\n\nSecurity Center pulls the image from the registry and runs it in an isolated sandbox with the Qualys scanner. The scanner extracts a list of known vulnerabilities.\n\nTo enable the Security Center for ACR, we need to enable the plan for Container Registries in the Security Center:\n\nOpen Azure Portal with Security Administrator privileges.\nSearch and open the Security Center.\nFrom the Security Center’s sidebar, open the Pricing & Settings page.\nChoose the subscription where you want to apply this setting.\nEnable the container registries option.\n\nAzure Defender for container registries includes a vulnerability scanner to scan the images in your ACR and provide deeper visibility into your image’s vulnerabilities. The integrated scanner is powered by Qualys, the industry-leading vulnerability scanning vendor.\n\nDevSecOps benefits\n\nDevSecOps is an approach for integrating security practices within the DevOps process, which ensures the application is less vulnerable and ready for production use. While selecting the right security tools for the CI/CD process is important, organisations also need security teams to meet the required security standards. Security is easier to implement if the requirements are defined early , not as an after-thought. The requirements should be part of the architecture diagram and be included in your project estimates.\n\nDevSecOps is well supported by Azure. The key role that enables this support is the way the Security Center controls the deployed resources. Azure suggests adding as many security solutions as possible in those resources."
],
"categories": {
"primary": "security",
"others": [
"devops",
"cloud"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"digital-community-react-components": {
"href": "https://nearform.com/digital-community/react-components",
"postType": "blog",
"slug": "digital-community-react-components",
"date": "2021-06-22",
"title": "Not All Components Are Created Equal",
"authors": [
"EMILY BARTMAN",
"PHIL PLÜCKTHUN"
],
"content": [
"We used to argue about dividing our components into categories, until we renounced this pattern as a community. But what if we missed out on valuable lessons about what makes our components more comprehensible?\n\nWhile components were not a new invention by any stretch of the imagination, when the community came around to React a lot changed. Building componentized apps with React didn't just feel better, it also proved to help us create more solidly built apps. It also enabled developers to think of components as a smaller abstraction on which to build more abstractions. But as we explored the boundaries of components we still found ourselves in familiar situations when large codebases started to become less comprehensible over time.\n\nThis was the perfect breeding ground for meta discussions. Every month the React community used to discuss a new problem that needed solving. Many rules were written to find answers and guide teams towards building more comprehensible codebases. In the end, a lot of these practices and opinions have been pushed aside. As the community iterated on some of the earlier discussions, many patterns and rules are now understood as a matter of taste and preference, while others are outright obsolete. And despite the lack of rigid rules, these days React codebases mostly turn out alright.\n\nOf course, some common advice and guidance is welcome for beginners, but the discussions we all once held so passionately (a la \"By what criteria do we group our files?\") are now much more toned down. The mantra is, as long as a codebase follows consistent patterns, we will manage.\n\nHowever, a once furiously held discussion stands out: How do we divide our components into separate categories?\n\n\"How to Component?\" reinvented again and again\n\nComponents don't have any natural limitations. We may write components that objectively are too large, too small, too nested, or are otherwise too complex.\n\nThis started a discussion on how to set a new rule to writing components, which would limit how we write them. This rule is one of the more infamous React patterns. You may know it as \"Dumb and Smart Components,\" or as \"Presentational and Container Components,\" or even later simply as \"Stateful and Pure Components.\" A rule to intentionally separate components by their responsibilities.\n\nCirca 2015, Dan Abramov, now part of the React core team, wrote about this pattern as well, as it proliferated in popularity:\n\n\"You’ll find your components much easier to reuse and reason about if you divide them into two categories.\"\n\nThis distinction became so forced and accepted that more patterns were enabled by it and created on top. The peak of this pattern came when Kent C. Dodds released Downshift, which extended the general idea of this pattern with \"render props.\"\n\nBut, as quickly as these patterns proliferated, they lost their popularity over time until React Hooks delivered the coup de grace, and the pattern disappeared entirely. It simply didn't feel natural to artificially establish a boundary between state driving the presentation, and the presentation's code itself right from the start of writing a component. Since components embraced composition and building up UIs and apps with small building blocks, arbitrary rules like these didn't lead to more comprehensible code.\n\nOther shifts in the community contributed to the inevitable downfall of the \"container & presentational component\" pattern as well. While this pattern was already on a slow but steady decline, styled-components gained in popularity. This started a shift in perspective amongst the React community even before React Hooks were introduced as it changed how \"presentational components\" are written in the first place. Suddenly it became clearer how styling and structure are already separate in componentized apps.\n\nThe changes in how we styled our apps, the advent of function components, and lastly, the introduction of React Hooks, all demonstrated the shortcomings of applying the \"presentational and container component\" pattern explicitly.\n\nWhy we seek constraints where there are few\n\nAs a community, we clearly feel strongly about good React development but find the codification of reliable categorization elusive. We struggled to differentiate between what patterns would serve us and which ones were arbitrary, and saw many examples of both. Time has given us a better perspective on what is obsolete and what we like or dislike. Developments on React itself such as Hooks and the React Context API were direct responses to enhance developer comprehension while still encouraging composition. But as for the principles we can and should apply to every component we write, we are left constrained only by the small set of rules that React imposes on us.\n\nReact imposing very few constraints may seem just as much to be a blessing as it is a curse, shown by patterns like the \"presentational and container components\" disappearing almost as quickly as they appeared. This may seem counterintuitive, even in the context of architecting a React application, but we seek constraints because constraints are at the core of designing anything.\n\nLet's say you were asked to draw something — anything. Just a simple drawing, no constraints. Your mind may be blank while you search for something meaningful to draw. But if you were asked to draw an animal, you may find an idea nigh instantaneously that's both thematic and personal. A single constraint provides the difference. But while this is just a thought experiment that isn't true in every case; some research shows that people are more innovative when working with well-chosen constraints*.*\n\nAn inkling of something great in a failed idea?\n\nApplying too many rules to React codebases can be detrimental to a team's success. That much is clear — albeit, consistency still being important for new readers of a codebase to know what to expect without having to scan the whole thing. However, what if components don't fit neatly into the two categories we dreamt up back then, but that the categories themselves do in fact exist? Could we understand these responsibilities of components as a discovered and self-emerging pattern rather than an imposed pattern or rule?\n\nWhile React Hooks, styled-components, and more styling, state management and data libraries (like GraphQL clients!) are entering the picture, it's clear that terms like \"presentational components\" and \"structural components\" have remained an unchanged fixed constant. If we look at Input or Button components rendering a single piece of UI, we can clearly identify them as \"presentational.\" Similarly, a component that accepts API data and passes it on to other components is clearly \"structural\" in nature, and when API request logic is added to a component it becomes \"stateful\" in nature.\n\nHence, in theory while we don't actively constrain ourselves to these categories, we do in fact find that components seem to generally fit into three distinct classes:\n\nPresentational Components\nStructural Components\nStateful Components\n\nPresentational components emerge quickly when we build component libraries, as typically all components in a component library can be understood to be built to be reusable and purely presentational, agnostic to what API or application state they're rendered with. They may abstract our styles and theming, concern themselves more with our users' interactions with the app, and provide a thin API layer to be used in other components.\n\nStructural components are seen whenever we think of \"screens,\" \"views,\" or \"pages.\" These components emerge as we compose presentational components into a structure that represents our app's views and will often distribute our backend's data throughout the app. They compose presentational components and are hence a mapping of our business logic and application state and data.\n\nLastly, every app will have places where it integrates backend data and business logic, which can be generally understood as state. This state is different from our presentational components' local state and instead is made up of backend data and API calls that are integrated into our views.\n\nThese three categories and descriptions of separate responsibilities can be applied to any componentized app and are a discovered pattern rather than an imposed one — meaning, that we're not saying we need to write components to fit these categories, but that components organically show characteristics of them. This also means that these are very loose definitions and chances are if you were to look at any given React app right now, you may find a couple of components that are taking on two responsibilities simultaneously or are hard to immediately categorize. We must accept that without this being a strict rule, some components may not always fall neatly into these three categories.\n\nStateful, presentational, and structural components are fluid classes that we can assign our components to and describe them with.\n\nA degree of reusability for components\n\nSince not all components will strictly fall into these separate categories, we can alternatively think of them as being on an \"axis of reusability\" instead. This describes a spectrum of our components instead by how reusable they are.\n\nOn one side we find our least reusable components, which we'd previously call stateful components. Stateful logic fetches API data, maintains global application state, and maintains business logic. This logic is the \"most specific\" part of our application as it's unique to the application we're building. While their logic may be further subdivided and abstracted (for instance with Hooks or Redux) stateful components are purpose-built and only show up once.\n\nOn the opposite side of this axis is where we find our most reusable components. The hallmarks of these components are that they're presentational and could be used in multiple parts of the app or even other apps. If we're working with a component library then the components in it will certainly be reusable.\n\nSome components are towards the middle of this axis as they'll be specific enough to accept some state or API data and pass it on to presentational components, but may also be used in several places as they aren't responsible for retrieving state or data themselves — hence they're the structural components.\n\nA few components may also have \"mixed responsibilities,\" which happens when components are yet to be split up and will be anywhere along this axis.\n\nIf we were to place an app's components onto this axis, chances are that we find less reusable components at the top of the component tree, while towards the bottom we find more reusable components. This happens naturally due to how components are composed. Because stateful components are by definition wrapping larger parts of our application they're at the top. Corollary presentational components are at the bottom as they'd only render other presentational components.\n\nHow do we know that something's gone wrong?\n\nImagine this: You're working on a large and complex React app and have done a lot of research and planning, have set up a component library, written nice providers and hooks for your backend data fetching, have split your app into views and pages beforehand, and have put time and careful planning into the architecture of this app — but after a few weeks your team still finds themselves with a handful of components and parts of your app that don't feel right. Sound familiar?\n\nIn this case, you may have found yourself with some \"bad components\" suffering from poorly chosen constraints, which are often not further analyzed and instead called \"hard to understand\" or just \"tech debt.\"\n\nMultiple signs lead us to believe that a component is bad. They may be too specific and tend to break if you remove them from their intended place, or they aren't as reusable as intended. On the other hand, some may be too generalized, which hinders comprehensibility and decreases their chance of being reused overall — a common issue with render props, which at its extreme appears reminiscent of Node.js' callback hell.\n\nSome components may or may not have an optimal interface or API. As props are our components' inputs, they are what makes components composable, which influences how and if they'll be reused. A component with a suboptimal interface will also lead to poor code in its parent components.\n\nAs we can see, there's a wide variety of reasons a component could be bad. However, oftentimes components simply become more complex, which is one of the hardest problems to rectify. Complex components often build up a large amount of dependencies and are discovered once we start testing them.\n\nThese are all subjective and vague factors. But, we can use a more nuanced definition of complexity and combine it with our understanding of classes of components to arrive at more actionable problem statements.\n\nProblems that the \"axis of reusability\" helps us identify\n\nComplexity is a factor of information scale (how much information), information diversity (how many elements), and information connectedness (how many cross-relationships between elements).\n\nThe component categories we've identified help us understand which components have overstepped an appropriate level of complexity by looking at how wide of a space they occupy on the axis of reusability. Complexity in this case it not only determined by how many pieces of information the individual component handles, but also grows exponentially if a given component falls into multiple categories, for instance if a component is structural and stateful at the same time.\n\nAssuming that complexity arises from three factors, we can also derive that there are three general problems that we can identify \"bad components\" as being afflicted by:\n\nA component may have too many responsibilities — in other words, it occupies a breadth of the component axis that is too wide, by incorporating both structural and presentational responsibilities, or stateful and structural responsibilities.\nA set of components may have been split awkwardly — for instance, a presentational component may have not been written to be less specific and instead isn't truly reusable. Two components that are used together may share too much information about one another, which may make both harder to read and reuse.\nA component may be \"surrounded\" by others that are in a skewed place of the axis in the component tree. This may happen when a presentational component renders a structural or stateful one, which complicates the relationships of all components in this path and forces us to reach for React's Context API too early for the sake of avoiding prop drilling in places where it isn't appropriate anyway.\n\nThe categories and hierarchies of components in componentized apps often matter more than the individual implementation details of a component. How components interact with each other combined with what we require them to do directly dictates how they'll be implemented, which gives us a new tool to identify bad components.\n\nIf it ain't broke...\n\nWhile we've looked at identifying and classifying these problems, which shows that they are absolutely avoidable and fixable, it's hard to impose strict rules on a codebase to prevent them in the first place.\n\nNot all components start out bad. At times, a \"good component\" may get hijacked for a problem it was never intended to solve, and instead of composing it with more structural components to add functionality, we edit it directly. \"Bad components\" are often under the influence of constraints as much as good components are— the difference is which constraints have been given significance.\n\nTime and energy are constant constraints too. It takes time to write unit tests, which can help us check for our mistakes and demonstrate the component's interface. It also takes more time and mental energy to take stock of a feature before it is implemented and break it down into its different states and concerns. It is also not a casual thing to \"just implement a design system\" so that a project can be served by good, well-behaved atoms that your app can reuse.\n\nIt may be more important that we recognize what makes a good or a bad component, rather than being able to define what not to do.\n\nHow common are these problems?\n\nWhile the first two categories of problems we've identified are very useful for isolated sets of components, it's the latter problem of the \"surrounding structure\" that tends to creep up slowly. Since identifying problems in component structures requires a high-level overview, simple additions may end up creating problems far down the line.\n\nPresentational components are very isolated pieces of our application that render UI elements with simple interfaces and props, but at the same time, styling and data make up most of our applications. At times, we may not be set up for success as an application grows, and it becomes harder to justify large refactors as time is a constant constraint.\n\nIn a growing project, it's too easy to lose track of all component hierarchy and add presentational logic to any given part of our application, or render new non-presentational components inside a previously presentational one. It's always just as easy to add new logic to the right place as it is to the wrong place.\n\nLuckily, React has a host of libraries that were solely created to improve the Developer Experience (\"DX\" for short) of writing applications in React. These libraries add additional constraints and layer APIs into our workflows and are aimed at making it easier for us to \"do the right thing.\" However, even given these libraries' additional constraints it's actually just as likely to find ourselves in situations where we create structural problems, as these libraries abstract styling and state management code (and make this code more effortless to write), but what causes these problems sticks around.\n\nThe Styled Components pattern\n\nstyled-components has become a well known library to alter the workflow of countless React developers when it comes to styling. While it allows us to create \"micro components\" that are only responsible for attaching CSS rules to a given element, the library also comes with a higher-order component pattern, styled(Component). This function usage of styled allows us to add styles to any component that accepts the className prop and passes it on to a DOM element. This is a convenient pattern to extend presentational components with some additional styling code.\n\nHowever, sometimes we're only a small step away from adding this to structural components too, which then pass the className property on to a presentational component. This small difference traps us in situations where we add styled presentational logic above a structural component, which blurs the line between structural and presentational components.\n\nInitially this may feel like an insignificant compromise — our presentational components remain highly reusable and our structural components override any styled as needed. However, this severely alters our expectations as to where we can find presentational code in the first place; both, in the browser's cascading styles, and in our codebase's component trees.\n\nProp drilling and React Context\n\nSince the introduction of useContext, the React Context API is more powerful than ever. But its new Hooks API made it quicker than ever to add context to any component. Unfortunately, Context can also be used to disguise the complexity of a set of components or set up bad component hierarchies. Primarily, this can be seen in its two most common use-cases:\n\nIt can be used to transfer a store-like object to any part of our application, which manages updates separately or is a store that abstracts a whole category of data.\nIt can be used to package up and transfer any data directly to a part of our application, without an intermediary store.\n\nThe latter is often used to avoid \"prop drilling\" in an application. When an application contains a large amount of data in a given subtree, a developer must pass several props and pieces of data through multiple structural components until it reaches their presentational components.\n\nProp Drilling isn't inherently bad as it's defined as data flowing through our application's tree from top to bottom and is hence a natural part of any React app. However, when structural components are wrapped and \"interrupted\" in the tree by other types of components, managing prop drilling can become tedious. The term is often used once there are props to manage in components that seemingly don't care about these props and just pass them on.\n\nUsing Context to wrap data up is a symptom of this problem, as it's then used to \"skip\" several levels of structural components, instead of passing props. Structural components may then pass on what's left or only represent what's being rendered. While this may make some component APIs seemingly easier to read on the surface, it may often simply obscure a component's data dependencies instead.\n\nWhile this pattern is certainly useful, it's also an example of circumventing the constraints of component structures. In many cases, composed structural components and type structures for props can prevent this from becoming necessary in the first place. When our API data flows through a view from top to bottom and other state is as close to where it's consumed as possible, this pattern starts to not look as useful anymore.\n\nThe hallmarks of good components\n\nBy now we've described several key ideas that hopefully help you gain new tools to identify why a set of components in your app may not be as readable as they could be.\n\nWe've identified that understanding components as more or less reusable, and as stateful, structural, or presentational helps us identify when we're overloading a component with too many responsibilities, and when we're disrupting our carefully set up component structures.\n\nWe've identified that keeping complexity of individual components below a threshold is extremely important, especially when it comes to creating presentational components with simple interfaces and props.\n\nHowever, in not having set any rules identifying the opposite has remained just as difficult. What makes a \"good component?\"\n\nDesign systems and good components\n\nIdentifying and creating \"good components\" is a trickier process than identifying patterns of \"bad components.\" After all, when we identify potential problems in our component structure and API, we're only looking at a limited list of problems. In contrast, when we attempt to define \"good components\" these aren't simply the opposite but must conform to our personal requirements and the needs of our apps. In short, a good component finds a balance of constraints while remaining reusable and integrating cleanly into the rest of our application — which will make it a different definition depending on the circumstances.\n\nWhile this sounds vague, we frequently define custom constraints when we create component libraries and design systems in React. A design system creates components that narrow dimensions of usage (typically props) to a limited set of inputs. In such a system we, for instance, narrow down all possible APIs and instead of designing any button, we'll design just \"our button\".\n\nThis can be contrasted with libraries that do attempt to make components for a multitude — if not any — possible usage and app, like Downshift. The problem with abstracting a UI element for any possible use-case is that it creates much larger dimensions that the library's API has to manage and control.\n\nHowever, no matter how complex this field of dimensions is, presentational components can always be composed to limit these dimensions based on our usage. If we were to use Downshift in an app, we'd be inclined to wrap it and narrow down its API for our specific use-cases. Similarly, as we're integrating presentational components into our app we're composing and wrapping them with structural components that transform our data and state as needed for them. If done right, components form multiple, nested abstractions at every level.\n\nGood components are our components\n\nEven as we're creating components for the application we're working on, we're often concerned with creating components that work in any part of any app we may create in the future. However, our applications have a unique shape, unique state, and unique look. If we think of our components as always having to handle one more page, we run the risk of making any component too complex rather than focusing on their structure for where they're currently needed.\n\nMany of the problems in this article are avoidable given time when several components' interfaces and structure get out of hand, or given enough constraints from our own requirements.\n\nNot all components are created equal, but no component is used in isolation.",
"REACT\nUpgrading styled-components from v3 to v4\nBRIAN MATHEWS\n20 FEB 2019\nREACT\nAchieving Reusability With React Composition\nCHRISTIAN IPANAQUE\n13 JAN 2021\nREACT\nStores: Making State Global Without React's Context API\nMAX YINGER\n23 FEB 2021"
],
"categories": {
"primary": "frontend",
"others": [
"design"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"insights-why-you-cant-hire-your-way-out-of-a-tech-talent-drought": {
"href": "https://nearform.com/insights/why-you-cant-hire-your-way-out-of-a-tech-talent-drought",
"postType": "blog",
"slug": "insights-why-you-cant-hire-your-way-out-of-a-tech-talent-drought",
"date": "2021-06-22",
"title": "Companies are struggling to hire and retain the experienced tech talent they need to compete. Adopting modern digital best practices can help.",
"authors": [],
"content": [
"But you can create a modern digital ecosystem to build your way out.\n\nIt is no secret that companies are finding it difficult to hire and retain the kind of experienced tech talent they need to compete in a global marketplace. However, dazzling prospective employees with dollar signs may not be the answer. We’ll explain why relying solely on attractive salaries and benefits is not the way to create and maintain the pool of talent you need to succeed.\n\nWhere is all the tech talent?\n\nRecruiters in almost every industry are battling to hire qualified tech workers. There are many reasons for this mismatch between supply and demand in the technological skills market, but most boil down to the fact that new technologies are disrupting all industries — not only the traditionally tech-based ones.\n\nFor example, cloud services, artificial intelligence and data analytics are now pivotal technologies across a swathe of sectors. This means that technology skills are no longer confined to the IT department, but dispersed across the organisation. The Covid-19 pandemic has exacerbated the issue, turning what were digital ambitions into digital necessities and putting immense pressure on HR departments to reconfigure the skills their organisations need to survive and thrive.\n\nThis means that everyone is looking for skilled workers, and advances in digital technology suggest that the situation is not going to improve anytime soon. A recent report from Korn Ferry predicts that by 2030, more than 85 million positions could be left vacant due to a lack of sufficient skilled people to fill them. It is true that the need for skilled tech workers is pressing, but many organisations are sabotaging their efforts to meet that need by:\n\nRelying purely on monetary incentives to attract talent\nUnderinvesting in their internal talent\nFailing to identify their skill requirements accurately\nNot engaging with the right kind of talent\nWhy can’t I just buy the talent I need?\n\nMany companies are dealing with their tech talent shortage by throwing money at the problem, vying with their rivals to present the most enticing compensation packages to attract suitably qualified candidates. This is not a sustainable approach for most organisations in the long term — and even for companies with the resources to offer irresistible packages indefinitely, it doesn’t create the kind of talent infrastructure they need to ensure maintainable, scalable growth into the future.\n\nCandidates are not just interested in money. A generous compensation package is obviously important, but a popular tech stack and flexible work practices are other deciding factors among tech professionals considering a new position. People weighing up alternative job possibilities tend to look beyond financial incentives when imagining what it would be like to work at a different company, so the draw must be more than monetary.\n\nYou could choose to bring in the talent you need for specific projects instead, but that approach does not encourage a sustainable, scalable model for growth, either for your organisation or for your people. You end up throwing disparate skill sets at a project to solve a specific problem, rather than building the kind of talent infrastructure you need to plan for the future.\n\nIt takes more than simply introducing new talent to ensure your company’s digital future; you need to create a culture that encourages people to work together as a team, take ownership of their work and see their long-term future in your organisation. You need to own the talent roadmap in your organisation with an attractive tech stack and ways of working. Otherwise, you end up devoting unnecessary time and money to recruitment efforts that never seem to pay off because staff never stay long enough to justify them.\n\nRemember, your rivals are also working to achieve the competitive edge that true digital transformation brings: A genuinely digital-first company employs the best digital talent, so when you build an enviable talent infrastructure you are filling not just your skills gap but your technology gap too.\n\nWhat is the answer?\n\nThe solution to the tech talent crisis lies in encoding rather than importing: Your organisation needs to embrace a culture of digital best practice with which all of your functions align.\n\nThe immediate benefit of this is that your existing talent immediately becomes more productive because you are eliminating silos. Teams align around business KPIs rather than technologies, encouraging greater reuse and avoiding duplication of effort. This approach enables true commercial agility, allowing small, streamlined operations powered by innovative ideas to overtake established behemoths.\n\nThe use of microservices exemplifies the streamlined corporate model that distinguishes digitally capable companies. Microservices are self-contained pieces of business functionality that work together to create a modularised overall architecture. This makes cross-team collaboration easier and encourages the construction of change-enabling platforms from reusable components. Efficiency and collaboration are paramount, ensuring the tech talent you have is optimised.\n\nTo attract that talent in the first place, you need to look at your tech stack. Any developer considering an alternative to their current employment will look closely at the tools and technologies they could be using elsewhere. No developer wants to work for a company that relies on outdated technology. In a 2020 survey , 70% of developers cited languages, frameworks and other technologies as a significant deciding factor when considering the relative benefits of one job over another.\n\nAttract the best talent with modern tech, and you will also further enhance your company’s efficiency and organisational health. For example, harnessing React Native makes a full cross-platform (iOS/Android/web) approach accessible for most organisations, cutting total cost of ownership and time to market, while also demonstrating that yours is the kind of outfit that values cutting-edge technology.\n\nNobody is suggesting that modernising your organisation’s technological ecosystem is something you can do with the flick of a switch: It takes time to change systems and practices that may have been in place for years. Engaging with an external partner to introduce new technology via a lighthouse project is a practical, low-risk way to generate positive results quickly. This kind of early success will give you the kickstart you need to build the kind of modern tech platform that attracts talent.\n\nFlexible work practices are another draw for tech talent in search of opportunities. Companies with remote-first cultures embrace this kind of flexibility, understanding the benefits of having team members in different time zones work collaboratively while managing their own personal work-life balance. Operating as a fully remote entity also opens up immediate access to a global pool of talent, unrestricted by geography.\n\nWhere to next?\n\nNobody is suggesting organisations that have always relied on the more traditional methods of recruitment can simply switch on a culture of digital capability overnight. Adopting a culture of digital best practice based on popular modern tech stacks and ways of working takes time and expertise.\n\nNearForm builds the kind of digital capabilities that facilitate continuous innovation and rapid, independent scaling. With our help, organisations develop the structures they need to enable ongoing success after we leave. By encoding digital best practices, we ensure that companies avoid hiring expensive, divergent skill sets but learn how to build their own happy, productive tech teams."
],
"categories": {
"primary": "work",
"others": [
"cloud",
"ai",
"data"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"insights-using-expo-to-build-a-mobile-app": {
"href": "https://nearform.com/insights/using-expo-to-build-a-mobile-app",
"postType": "blog",
"slug": "insights-using-expo-to-build-a-mobile-app",
"date": "2021-06-24",
"title": "Using Expo to build a mobile app",
"authors": [],
"content": [
"A full stack web developer shares learnings from a recent Expo/react-native project.\n\nExpo is an open-source toolkit and platform that allows you to build a mobile application from a single codebase and release it to Android, iOS and the web simultaneously. We have been working with Expo recently, so we can share some observations and tips to give you a head start on your next mobile development project.\n\nExpo offers a strong development workflow\n\nIf you are a developer who likes seamless workflows, you will really appreciate the ability to start Expo and test the code with a browser when developing for mobile. It allows you to get an app up and running and start iterating on the code within seconds. You can view the content with a web browser, and you don't need to install the Android or iOS development environments initially.\n\nSome quirks\n\nThe browser automatically refreshes the page when an update is made to the code, which means you lose the screen you were working on. Because of the refresh, you may want to use React Router to ensure that you do not lose the screen you are working on. However, the Expo app replaces the new components seamlessly without any need to navigate back to the screen you were developing.\n\nSome have found the Expo app to be buggy, forcing shutdown and restart on both the running app and the Expo app.\n\nEvery Expo component uses Flexbox\n\nSurprisingly, all components use Flexbox by default. Flexbox makes it much easier to organise UI components than the old methods of positioning components with absolute, float and other CSS attributes.\n\nOne of the main differences with web is that the default flex-direction in mobile is column rather than row. With most people holding their phone in portrait mode most of the time, this makes sense.\n\nReact-native styles are not CSS\n\nAlthough most style attributes are familiar, there are small differences between react-native and regular CSS when it comes to styling. The two main differences I noticed were:\n\nReact-native stylesheets do not cascade.\nThere are no pseudo elements, selectors or CSS animations.\nTesting must be done on your target platform\n\nTo be certain that your Expo code will work on your target platform, you need to test it on that platform. Even if your code works in a browser, it may not start in native. Browsers are more forgiving about what can be accepted. Some CSS and components will behave differently, and some code may not run on mobile.\n\nThis may be problematic for a developer whose main testing platform is the browser because you must always do final checks on the Expo app with an actual phone. Irrespective of the platform you are using, you will need to test thoroughly for runtime errors and inconsistencies on ALL target platforms before releasing your app.\n\nExample 1: CSS flex\n\nYour CSS types must be of the correct type. Using the wrong value type in some CSS styles may work fine on web but can throw a runtime error on mobile. This is the case for the flex CSS attribute that requires a number instead of a string.\n\nThe flex: '1' CSS will work for web but will fail at runtime for mobile: These errors can be prevented by using Typescript.\n\nExample 2: Sizing images\n\nTo display images so that they occupy 100% of the available width, telling react-native to scale the image to 100% of the parent container will not always work. It may also add unwanted padding above and below the image, depending on its ratio.\n\nThis is a known issue with a known workaround. One solution involves manually calculating the parent container size and adapting the image to it:\n\nDetermine the image width to height ratio from its size. (Note that the method to obtain an image’s size is different on mobile and web).\nObtain the parent component size from the onLayout event.\nSet the image size to the parent’s size multiplied by the image’s ratio.\nimport { StatusBar } from 'expo-status-bar';\nimport React, { useState, useCallback } from 'react';\nimport { Image, Platform, StyleSheet, View } from 'react-native';\n \nexport default function App() {\n const image = require('./assets/nearform_logo_full.png')\n const [imageSize, setImageSize] = useState({width: 100, height: 100})\n \n const updateImageSize = useCallback(\n function updateImageSize(event) {\n const containerWidth = event.nativeEvent.layout.width\n \n if (Platform.OS === 'web') {\n Image.getSize(image, (width, height) =>\n setImageSize({\n width: containerWidth,\n height: containerWidth * (height / width),\n })\n )\n } else {\n const size = Image.resolveAssetSource(image)\n setImageSize({\n width: containerWidth,\n height: containerWidth * (size.height / size.width),\n })\n }\n },\n [image]\n )\n \n return (\n
HLS businesses considering Agile must focus on culture, team structure and processes.
”\n\nProduct and process design must centre on end users, with team members using preliminary rather than complete information to make decisions earlier in the process and adjusting to the practice of sharing work in progress instead of finished products.\n\nAnother aspect of Agile that companies need to consider is team creation. Teams should include only those who need to be on them, and they should be elastic enough to expand and contract as needs evolve. At earlier stages of product development, for example, a team may be weighted in favour of medical and regulatory experts, but the composition may shift to include more digital specialists as the technology progresses.\n\nProcess design may also undergo a transformation. A design-thinking approach is a prudent way to re-engineer key processes. By focusing on how best to optimise user experience and quickly testing prototype solutions, agile organisations generally make one team responsible for a process end to end. That team will take input from internal and external stakeholders to create and test an MVP, building on feedback through successive iterations to create a solution.\n\nAgile pilot\n\nReflecting the incremental nature of Agile, HLS companies prepared to trial Agile should adopt its processes gradually. As teams deliver on small sprints, they build trust among all stakeholders. Regular stand ups and demos illustrate progress and create transparency. Any issues that arise are dealt with immediately rather than compounding and creating insurmountable problems at a later stage. This ongoing incorporation of feedback and regular monitoring of quality means the final product aligns closely with the customer’s needs while maximising patient safety and data integrity.\n\nEngaging an external partner with extensive experience working with the HLS sector also creates peace of mind for organisations hesitant about adopting Agile. NearForm has worked with health services worldwide, on developing Covid-19 tracker apps for international governments and digital transformation for clinical trials, for example.\n\nFor areas of the business that must follow a standardised process due to regulations, Agile may not be the answer. However, much of the activity in HLS businesses is not regulated, and the processes are complex simply because they have been made that way. By differentiating between processes that demand specific standards because of regulation and those that don’t, organisations can identify many areas where Agile can be leveraged to great effect. And even if Agile methodology is unsuitable for certain processes, key Agile principles such as customer focus, team empowerment, adaptability and a focus on results are tenets that any organisation can strive to embrace.\n\nBy getting the approach right over multiple iterations, companies avoid having to dive into another major transformation initiative a few years later. Adopting Agile in the right way will enable them to transform on a continuous basis." ], "categories": { "primary": "product", "others": [ "work" ] }, "verticals": { "primary": "health", "others": [] } }, "insights-how-to-improve-alignment-and-productivity": { "href": "https://nearform.com/insights/how-to-improve-alignment-and-productivity", "postType": "blog", "slug": "insights-how-to-improve-alignment-and-productivity", "date": "2021-08-10", "title": "Creating a reliable system for delivering effective digital solutions allows organisations to align their teams and boost productivity.", "authors": [], "content": [ "Choosing to build scalable digital solutions can have a direct, positive impact on team chemistry and productivity\n\nDigital services seamlessly blend a complex array of frontend and backend services , infrastructure and data and content management solutions to deliver an excellent customer experience. With an ever-growing ecosystem of tools and technologies to manage, it can be daunting to choose the right pieces to produce the results organisations are seeking.\n\nBuilding engaging, scalable and successful digital solutions depends as much on team chemistry as it does on the services used. For organisations embarking on digital transformation journeys, choosing to build scalable solutions can have a direct, positive impact not only on product performance but also on team chemistry and productivity.\n\nSuccessful transformations happen when planning, collaboration, developer experience, upskilling, qualitative focus and open communication are given priority and embraced by organisations.\n\nPlanning: Establish a digital roadmap\n\nIn order to establish a solid foundation for building a scalable digital solution , it is absolutely crucial to get the planning phase right. In this case, planning consists of more than just visualising the end result and mapping out the tools and technologies needed to get to that point.\n\nIt's important to understand the teams who will be building the product, select the right tools and technologies to maximise productivity and performance, establish documentation guidelines, define what success means in the context of the project, identify areas for upskilling and provide the appropriate resources for staff to obtain the skills needed to continually innovate and scale the product.\n\nBecause of the complexity associated with designing successful scalable solutions, it's important to embrace an agile approach to software development and set a Minimum Viable Product (MVP) to get the project up and running. As the project evolves, the tools, technologies and skills can evolve alongside the project.\n\nAt NearForm, we've found the best way to kickstart projects and start delivering immediately is to begin with a discovery workshop . Discovery workshops consist of pre-sales conversations with organisations to understand the scope of the project and project goals. The workshop itself is led by a Design Director and Technical Director who work with organisations to further define the scope of the project, establish a product roadmap and deliver interactive prototypes and project estimates that enable teams to begin delivering immediately.\n\nRegardless of whether you are working with a consulting firm or not, conducting a discovery workshop to define the project's goals, capabilities and architecture is a great way to establish a solid foundation for getting projects off the ground.\n\nCollaboration: Work together to deliver value\n\nSuccessful projects depend on more than just the speed at which developers can deliver. Bringing in key stakeholders early on in the process enables teams to build products that are more well rounded and more likely to succeed in the long run.\n\nAgain, discovery workshops are an excellent way to establish a culture of collaboration by giving everyone the chance to have input into the project from the beginning and therefore establishing a sense of ownership. By aligning teams on tooling, technology, design and an MVP, the path to success is clearer for everyone involved in the project.\n\nLikewise, selecting tools that allow developers and designers to collaborate seamlessly in real time enables quicker iteration and closer alignment between teams. For collaboration to be truly effective, it's important to define the tools to be used and document how the teams involved in delivery should use them to encourage maximum collaboration.\n\nBringing in an outside consulting firm such as NearForm is a great way to get these processes established from the start. We constantly monitor the newest tools and technologies for improving workflows, collaboration and developer experience, as well as establishing best practices for implementing them in client projects.\n\nDeveloper Experience: More than just a mature tech stack\n\nTransforming a digital ecosystem can be difficult, but giving employees tools they love, well-established frameworks and clear goals will empower them to create digital services that customers want to use.\n\nScalable digital services should be built on technologies that provide a great developer experience. Part of the process of ensuring a great developer experience is using tools and technologies with good documentation and thriving communities behind them.\n\n“When it comes to providing a good developer experience, working code counts. Example-rich documentation counts. And, interactivity at your fingertips counts. But, all the tools and techniques in the world won’t matter if there isn’t an engaged development community that has embraced the technology that you, the architect, intend to use to realize your architectural vision. In short, software without a community, ain’t.”\n\nRedHat\n\nDEVELOPER EXPERIENCE: AN ESSENTIAL ASPECT OF ENTERPRISE ARCHITECTURE\n\nInternal documentation is another aspect of product development that is often overlooked or neglected. Clear, consistent, accessible documentation is a key piece of all of the projects we undertake at NearForm. We understand the importance of great documentation and how it contributes to a great developer experience.\n\nBy taking the time to document the products we develop and selecting the appropriate established tools and technologies, we make onboarding for new hires and cross-team collaboration easier, allowing teams to innovate and evolve products faster.\n\nUpskilling: Shrink onboarding times\n\nAn essential part of developer experience and project planning is defining the skill sets needed to get the MVP launched and giving teams the skills they need to realise this.\n\nFor example, we work with a lot of clients in React/React Native, which are JavaScript frameworks. Experienced frontend developers can be onboarded to these frameworks relatively quickly — usually in a couple of days — and begin building immediately.\n\nEven if React is not the right path for your organisation, similar tools available have short onboarding times. That's why it's important to get developers involved early and make the decision together to choose technologies that get developers excited about the new project, while giving them the opportunity to improve their skills so that they can deliver more innovative products.\n\nFocus: Deliver software not story points\n\nIn today's world of agile development, it's important to have a clear path for getting products up and running. Encouraging developers to focus on innovating and contributing great ideas is more important than laying out a stale blueprint with story points that need to be met every two weeks.\n\nThe planning stage is important for setting the focus, but establishing rigid guidelines from the start can handcuff the project and prevent it from evolving organically. Vision is just as important as flexibility. As developers become more familiar with the tools and technologies they will be using to develop, new ideas and creativity should be welcomed and encouraged.\n\n“There are entire organisations of hundreds, thousands, of developers that do not focus on delivering software. They focus on doing story points. If your basic unit of measurement of how successful a team is are story points, then you have a problem. It doesn't really matter how quick we deploy if what we deploy makes no sense...We are very susceptible to gamification...[Developers] see that the people that get promoted are the people that are doing the most story points. Instead of actually considering something done... 'I know that thing has a bug, but I'm not going to fix that bug unless somebody points it out so that later on I can do more story points in the next sprint.' They start doing this type of game essentially bringing the actual progress of the team to a halt...but they are not doing any delivery.”\n\nMatteo Collina\n\nTHE PROMISE OF DEVOPS\n\nCommunication: Empower teams to engage\n\nPerhaps one of the most important aspects of developer productivity is clear communication. Clear goals, constructive feedback and a culture of listening to new ideas lead to products that grow faster and scale better.\n\n“Ensure that your team has the tools and processes to communicate openly and build consistently — and that those tools and processes are being used. If they’re not, find out why and make adjustments until you establish a solid routine.”\n\nGihub\n\nBEST PRACTICES FOR A COLLABORATIVE SOFTWARE DEVELOPMENT CULTURE\n\nUnderstanding the technology that will be used and putting teams in place with good people skills goes a long way in determining whether a project will grow or become stagnant.\n\nAs a remote-first company, we are keenly aware of the importance of effective communication and organisational structure and work with our clients to structure their organisations and teams around open and constructive communication.\n\nNext steps\n\nThe route to successful digital solutions lies in creating a digital roadmap, working together in a spirit of open communication, empowering and upskilling developers and focusing on software delivery. By implementing a reliable system for delivering effective digital solutions, organisations can break out of the system of silos that blocks so much business progress. Now is the time to create the systems that will align your teams and boost productivity to ensure scalable success into the future." ], "categories": { "primary": "product", "others": [ "frontend", "backend", "data", "cloud", "work" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-bridging-the-employer-employee-divide-on-the-future-of-work": { "href": "https://nearform.com/insights/bridging-the-employer-employee-divide-on-the-future-of-work", "postType": "blog", "slug": "insights-bridging-the-employer-employee-divide-on-the-future-of-work", "date": "2021-08-17", "title": "Bridging the employer-employee divide on the future of work", "authors": [], "content": [ "Companies that mandate a full return to the office are encouraging their talent to leave.\n\nOrganisations and the people they employ are poised at the edge of a new frontier in the world of work. Employers are keen to regain the control they had before the spring of 2020 and return everybody to the office, but employees want to hold on to at least some of their newfound control over their schedules. However, apart from the handful of fully-remote companies that experienced minimal disruption to their work models because of the pandemic, neither employer nor employee really knows where to go from here .\n\nIn this article, we discuss the hazards of dismissing employees’ desires to continue working remotely and provide guidance on how to map an ambitious, inclusive way forward that works for both companies and their people.\n\nWhy the old ways just won’t work\n\nCompanies risk antagonising their staff and encouraging them to leave if they make unilateral decisions to attempt a full return to pre-pandemic work models. For employers, having everybody back in the office would signify a return to normality that just isn’t possible: Employees have had a taste of working from home — and they are prepared to leave any company that won’t allow them to continue doing it indefinitely.\n\nFor knowledge workers in particular, arguments for going back to the office are not persuasive. They have happily abandoned their commutes and embraced the flexibility and the increased productivity of working from home . However, leaders who were not entirely comfortable managing their teams remotely are keen to get back to an office setting to restore the visibility they once had. They have legitimate concerns about communication and collaboration and view a return to the old way of doing things as the solution.\n\nBut the Pandora’s box of remote working is now wide open, and it will be impossible to close. Organisations need to confront the reality that they can’t go back to the way things were. And that’s a good thing: By embracing this unprecedented opportunity, they can build a new model that works for everyone.\n\nHow to find a new way of working\n\nIf business leaders accept that they cannot make the world of work look like it did before the spring of 2020, they can choose to create a new model by working with their people rather than imposing it from above. Close cooperation in a spirit of openness, trust and a willingness to learn will reap rewards for the companies that make the leap.\n\nDon’t pretend to have all the answers now\n\nInstead of mandating how things should be from day one, leaders need to make it clear that the new model is a work in progress. After all, it probably took years to create their pre-pandemic work environment, so it’s likely to take just as long to establish a new model. NearForm has been a remote-first company for ten years, and we are still refining our approach. Returning everyone to the office and expecting everything to run smoothly is unrealistic.\n\nLeaders who are prepared to adopt a new approach will need to investigate how the options available to them will affect their specific employer-employee-client dynamic and make deliberate choices based on these decisions. Through a process of failing fast, they can remedy the current disconnect between them and their employees to create a future-proof, customer-focused, employee-driven working model.\n\nTaking the learnings from the forced work-from-home experiment, they can look at what aspects created the most difficulty and work on addressing them. For example, if communication was a struggle, leaders need to figure out whether face-to-face time is critical and in what context and how to optimise remote communication so that teams can maintain quality relationships with each other and clients.\n\nMake it clear that you are listening\n\nNotwithstanding a justifiable desire to reinstate the pre-pandemic status quo, organisations should make genuine efforts to understand their employees’ concerns about returning to the office. Feigning interest in the learnings from a year of working remotely while driving forward with plans to restore the office as company HQ does little to bolster the spirit of openness and transparency required to instil and maintain staff loyalty.\n\nTruly listening to employees is a process that takes time and commitment. It’s not enough to tell people to contact their manager with any concerns: Forums and spaces must be created where individuals can share their fears, suggestions and feedback in a safe place. Virtual workshops using online whiteboarding tools such as Miro are a great way to elicit targeted feedback from staff on their preferred way to work. Anonymised surveys are also helpful. Channels can be created on Slack or an alternative communication platform to provide a space for discussion and questions.\n\nLeaders need to express genuine interest in their employees’ concerns and opinions and demonstrate that the information gathered will be acted upon. This kind of listening helps to establish a firm footing for the work model that ultimately emerges and ease the workforce through the uncertainty that inevitably accompanies major change.\n\nPrioritise flexibility\n\nOne of the lessons of the pandemic was that nimble organisations fare best in chaotic times. Being able to adapt to unprecedented circumstances at short notice proved invaluable for those companies that had always prioritised agility. As organisations prepare to move on, they should also embrace a flexible mind-set when considering the new workplace.\n\nThis might mean configuring the physical office to accommodate group work. For example, as part of its remote-first working model for employees, Dropbox’s redesigned offices will be tailored for collaboration and teamwork . So-called Dropbox Studios will not contain individual workstations but will emphasise collaborative work, with whiteboards, conference rooms, configurable events spaces and areas where employees can meet for coffee between meetings.\n\nOrganisations whose employees want to continue working from home should consider reserving their physical office space for the kind of relationship-building and collaborative work that is best done in person, while they continue to explore the potential of remote work for everything else. It is unreasonable to assume that 18 months of working from home has uncovered every opportunity that virtual work can deliver.\n\nTools for asynchronous collaboration, digital enablement, security and support are advancing all the time, allowing organisations to design tech ecosystems that will enable their teams to work more efficiently and contentedly wherever they are.\n\nWhy remote-first could be your answer\n\nAlthough nobody is suggesting that every company can embrace virtual work for every context, it has proven to be a remarkably productive model — particularly in sectors such as the knowledge industry. For people who work best where they can control the space, remote work has few drawbacks.\n\nUnderstandably, companies have baulked at the barriers to communication and collaboration that a lack of face-to-face contact can present — but that does not mean they should dismiss the remote-first model as unworkable. In fact, we argue that the remote-first model trumps hybrid working for both companies and their staff.\n\nWith careful consideration, effort and testing, companies can address their reasonable concerns to model a version of remote-first working that suits their specific circumstances. For example, NearForm delivers discovery workshops remotely in a way that gives our clients optimal use of our time because we are not travelling to them and setting up rooms but creating a relaxed virtual environment that feels more collaborative than a formal boardroom.\n\nIt is up to each company to grab this opportunity to investigate and experiment with what works for their specific context and their employees. Leaders have been handed a unique chance to reinvent the future of work. There is no going back." ], "categories": { "primary": "work", "others": [] }, "verticals": { "primary": "none", "others": [] } }, "insights-how-progressive-technology-and-commercial-agility-can-build-digital-advantage": { "href": "https://nearform.com/insights/how-progressive-technology-and-commercial-agility-can-build-digital-advantage", "postType": "blog", "slug": "insights-how-progressive-technology-and-commercial-agility-can-build-digital-advantage", "date": "2021-08-24", "title": "How progressive technology and commercial agility can build digital advantage", "authors": [], "content": [ "Adaptability is the new competitive enabler.\n\nThere was a time when customers were pleased just to be offered a digital solution. However, customer expectations have evolved dramatically, and pressure is growing to deliver increasingly advanced functionality. Companies now face the challenge of maintaining profitability while seeking to fulfil ever-changing customer demands and master a complex landscape of new digital technologies.\n\nThriving in this dynamic and quickly changing landscape will require a shift to a new way of working that combines advanced digital technology with strong commercial awareness. To grasp important opportunities and build a competitive digital advantage, companies must learn how to adapt quickly to do new things — rather than do one specific thing well.\n\nThey must discover how to experiment quickly and often, not only with products and services but also with business models, processes and strategies. In this article, we discuss how digital advantage gives organisations a competitive edge and offer insights into how NearForm combines progressive technologies and commercial awareness to create digital advantage for our clients.\n\nHow digital maturity creates competitive advantage\n\nThe Covid-19 pandemic demonstrated just how little control we have over external events and the changes they can bring, but it also showed how effectively some organisations can navigate those changes if they are equipped to defend themselves against threats and exploit new opportunities.\n\nThe 2021 Deloitte Digital Transformation Executive Survey underlines just how important digital capabilities are for helping companies to leverage accelerated change to their financial advantage. It revealed that digitally evolved companies were about twice as likely as their less digitally mature rivals to post net profit margins and annual revenue growth substantially higher than the industry average.\n\nThe reasons these digitally mature companies are better equipped to leverage volatility to their competitive advantage include the following:\n\nFaster time to market\n\nThe ability to blend masterful data analysis with targeted artificial intelligence (AI) helps companies to identify problems and market opportunities faster than their less capable rivals. Such insights could mean you are working on a solution to a customer issue you have surfaced before your competitors are even aware of the need.\n\nIn addition, technology that facilitates automation frees your teams from manual tasks to focus on more productive work. Rather than devoting their energies to routine operational tasks, they can apply themselves to value-added projects and take the time to experiment with new technologies. The use of cloud platforms and cloud-native development methods offers huge potential for engineers to build once and move on to other more valuable work.\n\nScalability\n\nOne of the main benefits of on-demand cloud computing is that it facilitates ramping up or scaling down demand in response to sudden increases or decreases in demand. This kind of agility is central to creating digital advantage.\n\nProcess mining and robotic process automation (RPA) are other weapons in the digital armoury that can accelerate efforts to understand and automate processes to manage surging transaction volumes. As customer queries rise in line with demand for products and services, chatbots can handle any spikes.\n\nAgility\n\nDigitally mature companies embrace a fail-fast culture to maximise their responsiveness. They also tend to rely on strategic partnerships to get immediate access to skills they need but do not currently possess in-house.\n\nBy adapting their cultures and investing in technologies that leverage real-time data and automate manual processes, companies can pivot fast in response to new threats and opportunities. That means moving from traditional project thinking to the more modern approach of platform thinking, in which multiple services are designed to power multiple solutions.\n\nSilos are broken down, freeing employees to align themselves with business objectives rather than specific technologies and optimising the company’s resources to conquer new markets and opportunities.\n\nHow to gain a digital advantage\n\nAt NearForm, we apply a combination of modern technology and commercial agility to deliver digital advantage to our clients. We have learned how to align our teams and maximise their productivity — and we help our clients do the same, emphasising technology that is cloud native, open source, data-driven and design-led.\n\nCloud native\n\nCustomers demand a consistent user experience, and that’s what cloud native can help you provide. A cloud-native infrastructure enables your web applications to remain highly performant, reliable and personalised. It facilitates constant improvement and allows you to scale automatically and effortlessly as demand dictates — but you pay only for the resources you use, reducing operating costs.\n\nCloud-native applications built on microservices use these small, reusable building blocks to create entire applications, but each microservice remains independent of each other and can be updated or modified individually. This modularity allows you to deploy new features quickly, frequently and dependably — enhancing the experience for both customers and developers.\n\nNearForm uses cloud native infrastructures to create dynamic applications built on open source technologies that prioritise continuous integration and continuous development (CI/CD) in developing your product. You can roll out code changes quickly, easily and with minimal risk.\n\nOpen source\n\nNearForm has close links with the open source community . We believe that open source has a vital role in turning the world into one where digital services make people’s lives easier and more fulfilling. Companies can be more agile and integrate new technologies quickly because the source code is completely accessible, making it easy for teams to connect open source solutions to the tools they normally use.\n\nEmbracing open source also helps organisations to attract elusive tech talent because prospective employees know they can avail of the best modern tools for them to do optimal work. Furthermore, open source platforms provide access to a bank of contributors, where companies can seek advice on resolving issues and getting the most out of the platform. Community members also contribute directly to open source projects.\n\nData-driven\n\nData is among an organisation’s key assets for building a digital advantage, as long as it is managed properly. If you structure and define your data engineering processes well, your operations will be more efficient, and you will be able to extract more value from your data. Data architecture needs to be well defined and performant to provide accurate results in real time.\n\nAt NearForm, our data engineers work closely with our clients’ teams to ensure they understand how the architecture of their data infrastructure works. This means they are equipped with the knowledge and skills to maintain and scale the data warehouse after a product is released.\n\nWe use the open source data query language GraphQL to unify multiple APIs into one convenient gateway, boosting developer productivity and reducing resource consumption by serving only the required data to the application.\n\nDesign-led\n\nNearForm embraces design-led development , a holistic process in which designers and developers work together to ensure that every stage of the development life cycle aligns with the end user’s requirements. This approach builds a solid foundation for scaling design and generally starts with a series of discovery workshops .\n\nHeld remotely over three successive half days, these workshops bring together the project’s key stakeholders on the project and a NearForm senior product designer and senior technical director. Together, they agree on the project objectives, strategy and vision and, at the end of the workshop engagement, the client has a roadmap for product design and development.\n\nThis roadmap includes a comprehensive product prototype, a full architecture overview and a timeline of milestones that allow clients to gauge their progress. With the prototype and product roadmap finalised, the development team have what they need to dive straight into the project. Communication between the NearForm team and the client is paramount throughout the entire process to ensure everything is in place as planned for the product launch.\n\nHarnessing digital for competitive advantage\n\nWe have discovered that embracing a strategy with proven progressive digital technologies at its heart and aligning business goals with digital priorities is what empowers companies to secure an edge over their rivals in a constantly changing world.\n\nBy investing in the kind of technology that makes your organisation highly adaptable and using data to constantly enhance your outcomes and decisions, you can gain that commercial advantage in the market and continue to grow and scale into the future.\n\nKnowing the technologies that work in your specific context, learning how to apply them really well and harnessing them in ways that improve your efficiency and agility can help turn you into a market leader ready to adapt in line with evolving customer needs." ], "categories": { "primary": "cloud", "others": [ "data", "devops", "product" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-an-easy-approach-to-building-kubernetes-operators": { "href": "https://nearform.com/insights/an-easy-approach-to-building-kubernetes-operators", "postType": "blog", "slug": "insights-an-easy-approach-to-building-kubernetes-operators", "date": "2021-08-26", "title": "An easier approach to building Kubernetes Operators", "authors": [], "content": [ "Using Operator-Framework SDK on top of Kubebuilder\n\nKubernetes Operators are quite complex to implement from scratch. They are commonly used to automate managing processes inside and outside of Kubernetes by regularly recurring calls while queued to a control loop.\n\nToday, we will outline an easy way to build an Operator using the Operator-Framework and SDK based on Kubebuilder . We describe how to install and set up a template operator project, which can be built and is deployable into a local Kubernetes cluster. In a later article, we will use that template to implement a real use case that can deploy and run in a production environment.\n\nYou can find all the source code accompanying this article at Github .\n\nRequirements\n\nBefore we can build our first Operator in Go we need to prepare our local environment by installing KinD as a Kubernetes cluster and run a Docker registry locally where we can push and pull our Controller images.\n\nOur KinD configuration defines some essential parameters for our cluster but also containerd plugin configuration to let Kubelet know where to pull Docker images from.\n\nSetup KinD Cluster\n$ cat <> config.yml\nkind: Cluster\napiVersion: kind.x-k8s.io/v1alpha4\nname: dev\nnetworking:\n apiServerAddress: \"127.0.0.1\"\n apiServerPort: 6443\n podSubnet: \"10.244.0.0/16\"\n serviceSubnet: \"10.96.0.0/12\"\n kubeProxyMode: \"ipvs\"\nnodes:\n- role: control-plane\n- role: worker\ncontainerdConfigPatches:\n- |-\n [plugins.\"io.containerd.grpc.v1.cri\".registry.mirrors.\"localhost:5000\"]\n endpoint = [\"http://kind-registry:5000\"]\nEOF\n$ kind create cluster --kubeconfig kind.kubeconf --config config.yml\n$ export KUBECONFIG=$(pwd)/kind.kubeconf\n\nRun Docker registry\n\nOur Docker registry is run as a container and connected to the KinD network.\n\n$ docker run -d --restart=always -p \"127.0.0.1:5000:5000\" --name \"kind-registry\" registry:2\n$ docker network connect \"kind\" \"kind-registry\" || true\n\n\nFinally, we need a Configmap to let Pods such as our Controller know where to find our Docker registry:\n\n$ cat <\n {children}\n
\n);\njsxCopy to clipboard\nSummary\n\nIn this post, we looked at how quickly and easily you can get started theming a React application with Vanilla Extract. We learned how to create themes, apply variables to our page, and access tokens from our styles and components. See the CodeSandbox below for an application created using the examples in this post.\n\nhttps://codesandbox.io/s/vanilla-extract-theming-ci1jq?file=/styles/theme.css.ts\n\nWe've only scratched the surface of what you can do with Vanilla Extract. If you're interested in learning more, head over to the documentation and check out the additional resources below.\n\nAdditional Resources\nVanilla Extract documentation\nSprinkles API\nVanilla Extract GitHub\nRF21 – Mark Dalgleish – Zero-runtime CSS-in-TypeScript with vanilla-extract (YouTube)" ], "categories": { "primary": "frontend", "others": [ "design" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-helping-teams-move-to-collaborative-design-with-figma": { "href": "https://nearform.com/insights/helping-teams-move-to-collaborative-design-with-figma", "postType": "blog", "slug": "insights-helping-teams-move-to-collaborative-design-with-figma", "date": "2021-11-02", "title": "Helping teams move to collaborative design with Figma", "authors": [], "content": [ "Greater potential for collaboration means users can work quickly and efficiently\n\nTELUS is a Canadian multinational that offers products and services in everything from telecommunications and health to safety and security. In this article, we outline how NearForm helped the company transition its design system from Sketch , the leading software design package for the last five years, to Figma. You can learn about how we moved our own design stack in this article on NearForm's transition to Figma.\n\nTime for change\n\nFirst released in 2010, Sketch soon distinguished itself as a powerful tool for user interface/user experience (UI/UX) designers working in the Mac environment. It allows designers to create designs, upload them in JPEGs to InVision and produce prototypes with clickable hotspots for simulating the end product on a device. TELUS's Design System Management (DSM) grew in strength and attracted a large community of users with Sketch at its heart. But the design tools market does not stand still for long, and soon there was a new player attracting attention.\n\nFigma was launched in 2016 as a cross-platform, browser-based design solution targeted at UI designers. It quickly became a a serious contender in a competitive market due to its ability to add new features fast. After a few iterations, it became a stable potential replacement for Sketch — largely due to its strength as a collaborative tool. When the time came for TELUS to supercharge its DSM, Figma's collaborative strengths made it a natural choice. With Figma, separate users could work on the same document at the same time, creating a completely interactive experience.\n\nNearForm was working on a component library for TELUS at the time and had recently transitioned to Figma, so members of the design team were brought in to help TELUS Digital migrate from Sketch .\n\nCreating a structure\n\nWhen the NearForm team began to help TELUS Digital move to Figma, their first priority was to dive deep into the DSM so that they could develop a real understanding of how it worked and make the transition as painless as possible. The system is used by different teams for both web and native experiences. Being involved from the start of the transition meant that NearForm could really get to grips with how the system was used at the time and develop simpler ways to apply it so that both first-time users and experienced ones could feel equally comfortable with it. Given that Sketch and Figma function very differently, this presented a good opportunity to remove any potential areas of confusion.\n\nDeveloping a foundation\n\nOnce the team had got to grips with the TELUS DSM, it was time to work on creating a proper foundation for the file structure and versioning. Before we started creating a library, we discussed best practices and personal preferences with the team and then refined them.\n\nComponents are a powerful feature of Figma. With them, you can reuse UI objects and attributes, and if you want to change an element, you simply make the change once in the original component, and it updates across all your designs. For the TELUS transition to Figma, we divided components into categories using the simple navigation system.\n\nTeams could work easily with the system, which indicated the status of work using a system of traffic lights and allowed for the movement of pages into categories according to their stage of completion. Figma also includes a useful comments tool, so combining this with a platform such as Trello makes it easy to see how projects are progressing.\n\nDesign teams constantly face the challenge of managing design files so that everyone can contribute and also know where everything is. Enabling collaboration while maintaining version control is a constant issue. For the TELUS DSM library, we implemented a versioning system to ensure work was not lost and to keep all users on track. The document we created outlines a clear versioning process that means all users follow a predefined naming convention and give a brief description of what they changed every time they publish a new or additional version of a design.\n\nBuilding the new library\n\nThere is no easy way to convert Sketch components to Figma components — despite the claims of some plugins. Having investigated several options, we decided that the best and most comprehensive way to create the new TELUS library was to redraw each component from scratch. This was a laborious process, but it meant that we would not have to go back and fix components that did not convert consistently. Instead, we created a new, clean structure that allows Figma's Auto Layout, variants and instances to be incorporated in parallel.\n\nIt also means that naming systems can be upgraded if necessary. Naming was extremely important in the transition, both because of its significance for the UX and also because it makes it easier for Figma to analyse components and the connections between the variants and instances.\n\nFollowing discussions with the team, we decided on four discrete but interconnected files for the project:\n\nCore Styles. The first Figma file we created centred on text styles, colours, iconography and logos. The completed file was converted to a library, which could then be linked to multiple files, so that the brand owner/designer could update everything in a central location and those updates would be published automatically on all associated files.\nFoundation. The Foundation files is where all the components are created and stored. It is listed on the left-hand sidebar on different pages and is also published to sync with the Testing area and Guide files below.\nTesting area. This is where components are tested, detached and changed if necessary. Testing does not take place in Foundation to avoid creating issues that would affect the library.\nGuide. The Guide file includes information on how to use Figma and the library, and it also features a list of all the components, together with labels. It is designed not to be edited, working largely as a reference point for all the changes that are made.\n\nAs we worked on creating the components, different opinions surfaced as to how they should be assembled. Figma proved itself to be the ideal tool for this kind of collaboration, offering the flexibility we needed to make decisions that worked well for the majority.\n\nDealing with Figma's bugs\n\nAs Figma matures as a design tool, it becomes increasingly reliable. Any bugs that do arise tend to be fixed as updates are made. Some of the bugs we encountered in our work with TELUS included:\n\na lack of border offsets, which would have been useful for mocking up the outlines for focus states\nsome issues with specs, such as the omission of border size in calculated dimensions, which can confuse developers when they are attempting to interpret a designer's intentions\nno way to publish a single artboard as a prototype\n\nDespite these shortcomings, we found that there was always a way to circumvent any obstacles we encountered within Figma. With a huge and growing community behind it, you will always find advice on dealing with an issue, as well as a range of free components that others have devised.\n\nLooking forward to the future\n\nWorking on the TELUS transition from Sketch to Figma was a complex but rewarding project for NearForm. Collaborating with the TELUS design team revealed just what can be achieved, and we are really looking forward to the next developments as the TELUS team continues to develop their systems in Figma." ], "categories": { "primary": "design", "others": [ "product" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-data-viz-2": { "href": "https://nearform.com/digital-community/data-viz-2", "postType": "blog", "slug": "digital-community-data-viz-2", "date": "2021-11-04", "title": "Adventures with Victory and Canvas", "authors": [ "BECCA BAILEY" ], "content": [ "When it comes to building charts in React, Victory does a lot of work for you. It handles scaling, positioning, rendering, and animations, all while providing a lot of options for customization. It’s easy to get started with Victory by importing a few components and passing in an array of data. From there, Victory is able to traverse your data components in order to determine the type and extent of your data.\n\nVictory’s ability to make inferences about your data based on its child components and provide intelligent fallbacks is one of its superpowers. However, there are some tradeoffs to this behavior, mainly when it comes to performance.\n\nIn Part 1, I wrote about some of the general principles for improving the performance of large data visualizations, including rendering less data, reducing re-paints, and using an alternative rendering API like Canvas. In addition to researching general strategies for high-performance data visualizations, one of my goals in the fellowship I completed was to find some ways to better use these strategies in Victory.\n\nIn this post, I will focus on how we can use the Canvas API to create custom data visualization components that can be used with Victory or as standalone visualizations.\n\nWhat is the Canvas API?\n\nCanvas is a pixel-based drawing API. We can use Canvas by rendering a canvas HTML element in the DOM and using a series of JavaScript commands to get the canvas context and draw shapes inside the canvas container. In React, that process looks something like this.\n\nfunction Chart() {\n const canvasRef = React.useRef();\n\n React.useEffect(() => {\n const ctx = canvasRef.current.getContext(\"2d\");\n // Draw something\n });\n\n return ;\n}\njsxCopy to clipboard\n\nCanvas excels at high-performance data visualizations in the browser. If we are building a chart with many data points, an SVG chart would need to render each data point as a DOM node, while Canvas can use a single wrapper. Check out my first post for an in-depth performance comparison.\n\nMany of us may be familiar with Canvas as a predecessor to SVG, and there are some trade-offs around appearance and developer experience to be aware of.\n\nPixelation\n\nAs a vector-based graphic syntax, one of the great advantages of SVG is the ability to look sharp at any zoom level or screen size. An SVG can be scaled up or down without resolution ever being a concern. This is not the case with Canvas, and I found it helpful to scale up the canvas container for larger views and high-resolution screens in order to avoid pixelation.\n\nZoomed-in view of a Canvas chart\n\nTargeting individual elements\n\nAnother advantage of SVG is the ability to target individual DOM elements. This makes it easier to mount or unmount an individual shape, or move an element from one location to another while keeping its surroundings the same. In order to update a Canvas shape, we either need to “draw over” the existing shape or erase and re-draw the entire canvas. I found this canvas layering technique to be helpful for isolating elements that need to be re-drawn together.\n\nIn this example, there is a separate canvas container for the moving cursor line and points so the lines do not need to be re-drawn when the points re-render.\n\nBuilding a chart with Canvas\n\nLet’s start by using some Canvas functions to build a basic line chart. This will draw a path with a straight line between each of the points.\n\nfunction Line({ lineWidth, color, data, height, width }) {\n const canvasRef = React.useRef();\n\n const draw = React.useCallback(\n (ctx, data) => {\n const [first, ...rest] = data;\n ctx.strokeStyle = color;\n ctx.lineWidth = lineWidth;\n ctx.beginPath();\n ctx.moveTo(first.x, first.y);\n if (rest.length) {\n rest.forEach(({ x, y }) => {\n ctx.lineTo(x, y);\n });\n ctx.stroke();\n }\n },\n [lineWidth, color]\n );\n\n React.useEffect(() => {\n const ctx = canvasRef.current.getContext(\"2d\");\n draw(ctx, data);\n }, [])\n\n return (\n \n );\n}\njsxCopy to clipboard\n\nD3 also provides us with a line function, which is what Victory already uses under the hood. This function gives us more options for defining curves and steps.\n\nfunction Line({ lineWidth, color, data, height, width }) {\n const canvasRef = React.useRef();\n\n const draw = React.useCallback(\n (ctx, data) => {\n const d3Line = d3\n .line()\n .x((d) => d.x)\n .y((d) => d.y)\n .curve(d3.curveNatural)\n .context(ctx);\n ctx.strokeStyle = color;\n ctx.lineWidth = lineWidth;\n\n d3Line(data);\n\n ctx.stroke();\n },\n [lineWidth, color]\n );\n\n React.useEffect(() => {\n const ctx = canvasRef.current.getContext(\"2d\");\n draw(ctx, data);\n }, []);\n\n return (\n \n );\n}\njsxCopy to clipboard\n\nIn order to use this component by itself, we need to do some work with D3 to define our scales. If you're unfamiliar with the concept of scaling data, this is basically the logic that translates x/y data to pixels in the canvas container.\n\nfunction Chart() {\n const data = [\n { x: 1, y: 1 },\n { x: 2, y: 3 },\n { x: 3, y: 2 },\n { x: 4, y: 4 }\n ];\n\n const height = 400;\n const width = 600;\n\n const scaleX = d3.scaleLinear().domain([1, 4]).range([0, width]);\n const scaleY = d3.scaleLinear().domain([1, 4]).range([height, 0]);\n\n const scaledData = data.map(({ x, y }) => ({ x: scaleX(x), y: scaleY(y) }));\n\n return (\nColin Houlihan, VP of Consulting, NearForm”\n\nOur microservices approach to application development accelerates innovation since software updates can be made to individual services as needed—without compromising your entire application.\n\nWhat does this mean for our online retail and e-commerce customers? Increasing the time to market for new products and services, greater agility and an undeniable competitive edge.\n\nLearn More About Our Work in the E-Commerce Sector\n\nView our fact sheet now to find out how we can help your retail or e-commerce organisation enhance performance and flexibility at scale.\n\nGet the Info Sheet[hubspot type=form portal=1964953 id=7345b281-46aa-4877-a3c1-8dab2e577f01]" ], "categories": { "primary": "oss", "others": [ "cloud", "backend", "product" ] }, "verticals": { "primary": "retail", "others": [] } }, "insights-ignite-discovery-process": { "href": "https://nearform.com/insights/ignite-discovery-process", "postType": "blog", "slug": "insights-ignite-discovery-process", "date": "2022-03-24", "title": "Ignite Discovery Process", "authors": [], "content": [ "In 2022 more than half the global economy will be based on or influenced by digital, with 68% of CEOs planning a major investment in data & technology and 61% planning a major new transformation initiative according to a recent study from EY.\n\nOften, taking the first step can be the hardest part for companies looking to build a new digital product or service or modernise a legacy solution.\n\nAt Nearform, we focus on designing and delivering strategic software solutions whilst building client teams' digital culture and capability. The starting point is Ignite - our proven discovery process which has helped major public and private sector companies identify:\n\nThe customer problem they were looking to solve to drive business impact\n\nThe process by which to solve it, factoring in product design and user experience\n\nThe technology required to implement a scalable solution\n\nWe sat down with Kevin Devine, our Design Director, to find out more about how we help clients identify these issues and the benefits that our Ignite discovery process can provide when creating a prototyped solution.", "Kevin, what do you recommend to companies who are in the early phases of planning to build a new digital solution?\n\nCrucially, during the discovery process it is important to understand what it is that you want to build:\n\nWhat problems does the solution aim to solve?\n\nWhat already exists, if anything?\n\nWho will the target users be?\n\nWhat do these users want from a solution?\n\nSecondly, be aware that every organisation has existing business or technical strengths and constraints. Identifying these is critical when designing an optimal solution. Ultimately, no matter how innovative, every solution must be feasible and optimal within the organisation’s context.", "How can companies identify what is the right solution for the problem they are looking to solve?\n\nChoosing the right solution for the problem, and identifying the right way to build and run that solution is often quite a complex process and requires more experience than is available within a single enterprise. Many organisations struggle to get past this stage, often due to a lack of internal alignment or a lack of expertise in choosing the most viable way forwards.\n\nOftentimes, bringing in an external partner who can help with driving alignment on both the problem and the solution can be the missing piece of the puzzle - and a critical accelerator.", "What would you say are three main areas that companies need to look at to minimise risk when creating a new digital product or modernising an existing solution?\n\nFirstly, take the time to make informed choices regarding modern technology platforms and practices. Having a partner with deep expertise and a tech agnostic perspective can de-risk this process.\n\nSecondly, focus on alignment. The internal teams and sponsors need to have an aligned view of the problem to be solved and the proposed solution to ensure success on the journey.\n\nFinally, customer research is not enough to guarantee success. Building a solution that meets customer needs requires actionable insights. Background research is a good input in the preliminary stages, but the real key to success lies in having stakeholders collaborate in defining what the research means and how to apply it to a solution - and critically testing it early and often with users..", "How does Nearform get involved to ensure that the preliminary stages of a product build or modernisation are set up for success?\n\nOur Ignite discovery process is a rapid, product design-led engagement that is proven to:\n\nClose the gap between strategy and delivery\n\nCreate consensus between stakeholders\n\nDeliver tangible assets to accelerate implementation (e.g. user journeys, prototypes, plans, architectures)\n\nValidate and de-risk proposed projects\n\nSet up the delivery phase for success, bringing in momentum from the discovery phase\n\nOur collaborative process is a blend of product, design and technology, where Nearform comes in as an expert external voice to drive and facilitate the discovery process over a series of workshops.\n\nAfter initial workshops, we create high fidelity prototypes and wireframes to ensure that our clients have everything needed to develop the product, whether it be developed in house or by Nearform.\n\nAt its core, we bring a breadth of industry knowledge and experience to the process, producing a large number of outputs in a very short amount of time.", "What does the team enjoy most about the Ignite discovery process?\n\nDigital transformation is shaping our lives, and a lot of enterprise companies are only just catching up with all the new developments. This is exciting for us as we get to be a part of some of the amazing and innovative things being developed by public and private sector companies across the globe." ], "categories": { "primary": "product", "others": [ "design" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-mobile-retail-apps-and-omnichannel-commerce": { "href": "https://nearform.com/insights/mobile-retail-apps-and-omnichannel-commerce", "postType": "blog", "slug": "insights-mobile-retail-apps-and-omnichannel-commerce", "date": "2022-03-29", "title": "How Mobile Retail Apps Are Driving Omnichannel Commerce", "authors": [], "content": [ "Mobile Retail Apps: The Good, the Bad and the Ugly\n\nMobile retail apps have evolved massively in recent years; the best ones achieve must-have status by providing incentives so valuable that users are happy to be identified across online and in-store—whether that’s by account number, location, or by scanning a QR code. The real challenge is building an application flexible enough, responsive enough, and valuable enough to grant access to those precious insights.\n\nA recent Shopify trend report, 'The Future of Commerce' , revealed that a growing number of consumers are returning to in-store shopping. In fact, over the next year alone, 54% of consumers surveyed said they’re likely to look at a product online and buy in-store, while 53% are likely to look at a product in-store and purchase online.\n\nThe report demonstrates that omnichannel shopping is here to stay, with retailers continually seeking new ways to strengthen and link their digital and online presences to compete. As a result, many retailers look to mobile retail apps to bridge the gap between in-store and online and create a seamless experience from research to purchase and beyond.\n\nHowever, for a mobile shopping app to truly take off, ensuring a responsive, end-to-end user experience that provides self-service capabilities is key. Read on to discover some of the key aspects to consider when building an omnichannel mobile retail app, as well as common mistakes to avoid to ensure success.\n\nMobile retail apps: The good, the bad and the ugly\n\nHere are the very best and worst mobile retail app features to look out for.\n\nThe Good\n\nLet’s start with the best shopping app features on offer today. The most effective mobile retail apps on the market can recommend your nearest store(s), check stock levels in real-time, consolidate receipts across online and in-store purchases, deliver tailored offers for loyalty programme members, unlock exclusive access to in-store events and more.\n\nSome of the most advanced mobile apps for retail stores provide a heightened sense of personalisation and even offer open payment options to further streamline the customer experience and remove friction when checking out.\n\nAll of these attributes enable a seamless, omnichannel shopping experience across digital and physical stores.\n\nThe Bad\n\nBad mobile retail apps are generally slow and clunky, with minimal functionality and added value. Lack of integration with third-party tools (for example Apple Wallet for storing loyalty cards) results in a poor user experience. These apps therefore have limited long-term appeal.\n\nThe Ugly\n\nThat brings us to the ugly. In addition to the qualities above, the very worst mobile shopping apps rely on the invasive use of personal data without providing any tangible added benefits to the user. If your mobile application falls into this category, then it’s time to stop what you’re doing and rethink fast.\n\nWhether you’re starting from scratch, modernising or rethinking your mobile retail application, we work with organisations to boost performance and streamline the customer experience.\n\nLearn More About Our Work with Mobile Retail Apps and the E-Commerce Sector\n\nView our fact sheet now to find out how we’ve helped businesses like yours build responsive, customer-centric applications in retail and e-commerce.\n\nGet the Info Sheet\n\n[hubspot type=form portal=1964953 id=7345b281-46aa-4877-a3c1-8dab2e577f01]\n\nOmnichannel retail: It all boils down to the data\n\nWhen it comes to delivering a hyper-personalised shopping experience, it all boils down to the data . As a retailer, creating a mutually beneficial relationship between you and the customer in order to access that data is crucial.\n\nIt works both ways; you want to understand customers’ habits and behaviours better, so that you can better personalise the products and services you offer, and how you communicate with them. This requires you to collect comprehensive end-to-end usage data.\n\nOn the other hand, the customer wants to be rewarded for their loyalty with access to exclusive offers, discounts, and opportunities to self-serve for ultimate convenience.\n\nIf your mobile retail app is able to offer genuine value, then the user is more likely to be happy to consent to processing their data for personalisation and product improvement purposes. This can allow you to map customer behaviour across online and in-store experiences and connect the dots in the customer journey. Related Read: Modernise Your E-Commerce Architecture with Open Source\n\nMobile shopping apps: How NearForm can help\n\nThe Shopify trend report demonstrates that consumers form purchasing decisions over time across multiple channels. As shoppers navigate the return to physical stores, retailers are competing for attention—but there is one way to create clear differentiation.\n\nIf your organisation is seeking to bridge the gap between online and in-store and create a truly omnichannel experience for customers, then a flexible, responsive, value-driven mobile retail app could be the answer.\n\nAt NearForm , we build highly performant retail applications to help our clients create a seamless user experience and deliver exceptional performance on demand. Our solutions operate at the highest levels of scale, security and resilience to create digital advantage for years to come.\n\nLearn More About Our Work with Mobile Retail Apps and the E-Commerce Sector\n\nView our fact sheet now to find out how we’ve helped businesses like yours build responsive, customer-centric applications in retail and e-commerce.\n\nGet the Info Sheet\n\n[hubspot type=form portal=1964953 id=7345b281-46aa-4877-a3c1-8dab2e577f01]" ], "categories": { "primary": "mobile", "others": [ "product" ] }, "verticals": { "primary": "retail", "others": [] } }, "insights-caching-with-fastify-and-aws-cloudfront": { "href": "https://nearform.com/insights/caching-with-fastify-and-aws-cloudfront", "postType": "blog", "slug": "insights-caching-with-fastify-and-aws-cloudfront", "date": "2022-03-30", "title": "Caching with Fastify and AWS Cloudfront", "authors": [], "content": [ "Build an App that Handles Caching with Fastify and AWS CloudFront\n\nWe all want to build blazingly fast applications and one of the most effective ways to speed them up is to use caching.\n\nIn large web applications it's common to adopt a Content Delivery Network (CDN). That introduces many advantages, from reducing latency to decreasing server load, to drastically improving performance by adopting HTTP caching.\n\nWe'll use fastify as a web server and Amazon CloudFront as CDN, in order to optimize HTTP response times via HTTP caching headers.\n\nThe architecture of this case is quite simple: the client -> the CDN -> the server(s).\n\nYou can access the examples referred to in this article at the following link: https://github.com/nearform/blog-fastify-cloudfront-example\n\nHTTP cache\n\nHTTP cache has been defined in the protocol since the beginning. It can be used to reduce server calls and data transfer as well as to avoid repeated operations that have the same results.\n\nTwo core concepts of caching are saving and updating operation results. Saving the results of operations is done to serve them quickly and avoid repeating computations that lead to the same outcome. Updating those saved results when they become stale is essential in a useful cache.\n\nHTTP cache can be time-based or content-based - and of course, some content can’t be cached or is prohibitively difficult to cache.\n\nTime-based caching Time-based caching is quite simple to implement: setting an arbitrary expiration to cache entries, and when that time passes, the content is reloaded from the source. This strategy is the most efficient from the client’s perspective. Once the content is received, no more requests are made for a specific time; at the same time, consistently orchestrating client-side requests is not that easy. Content-based caching Content-based caching is different: the client gets Etag and/or Last-Modified headers that identify the response; the client will provide them to the next requests for the same resource, and the server either responds with new content and updated headers if the resource has changed meanwhile, or with a “304 - not modified” if not, without sending the content again.\n\nThis is just an overview of HTTP caching, for more information see HTTP caching on MDN .\n\nChoosing the right strategy to adopt really depends on many factors, of which the very first is business requirements.\n\nHTTP headers\n\nCache-Control is the main header for caching directives, both for request and response. In this use case, we focus on max-age and s-maxage , respectively, to tell the client and CDN the time-to-live (TTL) for a resource or no-cache to avoid caching. For more information see Cache-Control on MDN\n\nVary Vary response header describes the parts of the request headers that are involved in the cache. For more information see Vary on MDN Etag (entity tag) Etag response header is the identifier of the response. If the server response includes the Etag header, the client should provide the value on the following request to the same resource on the if-Match header. For more information see Etag on MDN Last-Modified Last-Modified is the same concept as Etag but is based on date. If it's contained in the response, the client should send it later as If-Modified-Since. Etag and Last-Modified can be used together. For more information see Last-Modified on MDN\n\nContents\n\nWe can configure different behaviours by combining the caching headers together, but generally speaking, we can categorize contents as public or private, static or dynamic.\n\nWhen we combine them, we get the following content types:\n\ndynamic public Dynamic content usually refers to server-rendered pages or API responses. For example, a home page optimized for client devices (mobile or desktop) or localization by client origin; an API to get the content of an article from the company CMS. dynamic private The same as above, but private, so content is accessible under authorisation, or the user data affects the content. For example, the rendered page may include “welcome ${user.name}”. Because of the many parameters involved, this is the most tricky type of content to cache. Failing to properly define the parameters here can be disastrous such as serving private content to the wrong users. static public This type of content is usually application assets, often served efficiently by storage services like Amazon S3. static private This is for content that is only accessible with authorization, for example, an image sent in a chat app. The approach is similar to dynamic private content.\n\nTo force cache refresh, the simplest way is to remove the cache entries when new content is available (for example, on a new release of the frontend), otherwise, new entries are reloaded because they expire or don't match the content identifier/s Etag and/or Last-Modified .\n\nAmazon CloudFront\n\nAmazon CloudFront is our CDN of choice. The capabilities of CloudFront are wide, including compressing responses, applying Lambda@Edge functions or CloudFront functions to request/response, using streaming capabilities, adding encryption and much more. The feature set is so rich that caching is not even mentioned on the first documentation page.\n\nFor our scope, we'll focus only on caching features, using CloudFront to expose our fastify application as a reverse proxy.\n\nCloudFront allows you to define very fine-grained policies for caching. The main concepts are:\n\nDefine: the “cache key” for paths to identify requests and therefore cache entries. Cache keys always include the url and method, then part or all of the query string. Headers and cookies can be added to identify the request\nUse custom “CloudFront” HTTP headers to get client information such as user device and location (see the full list). for example CloudFront-is-Mobile-Viewer. Having that information ready to use on the server is very powerful!!\nOn client response CloudFront adds an x-cache header, containing information about the use of the cache for the resource. There are four possible responses the client can deliver: “Miss”, “Hit”, “RefreshHit” or “Error”\nIt automatically adopts Etag and/or Last-Modified if present in the server response and manages them with If-Match and If-Modified-Since in further requests.\nFastify\n\nFastify works perfectly with CloudFront because it’s very easy to set HTTP headers and fastify also has the most efficient Etag computation in a tiny, yet amazing, plugin: fastify-etag .\n\nWhen implementing time-based content strategies, Etags are not needed and can be hard to define when a resource is generated and set to Last-Modified . However, since CloudFront manages Etags so efficiently out of the box, it’s very convenient to use them anyway.\n\nThe brilliant part of the Etag plugin is that it uses the fast algorithm fnv1a to hash the response, and also automatically manage If-Match and If-Modified-Since of the request.\n\nIn our case, once the fastify server provides the Etag , CloudFront is able to handle it, serving itself the matching content, or forwarding the request to the fastify server.\n\nconst fastify = require('fastify')\nconst etag = require('fastify-etag')\n\nconst app = fastify()\napp.register(etag)\n\napp.get('/hello', async (req, reply) => {\n // automatic etag generation\n return { hello: 'world' }\n})\n\napp.get('/word', async (req, reply) => {\n // set etag manually\n reply.header('etag', 'foobar')\n return { hello: 'world' }\n})\n\napp.listen(3000)\njsCopy to clipboard\n\nLooking at benchmarks , Etag generation with the fnv1a algorithm is only 10% slower than without it! Considering the benefits of adopting validation based strategy this is an impressively low cost.\n\nExample\n\nLet’s build a cache for a dynamic private API.\n\nThe fastify app has just a simple route with pseudo-authentication that responds with the user info and CloudFront information of request origin.\n\nconst users = {\n 'one': { name: 'Alice', email: 'alice@email.com' },\n 'two': { name: 'Bob', email: 'bob@email.com' }\n}\n\nconst fastify = require('fastify')()\nawait fastify.register(require('fastify-etag'))\n\nfastify.get('/my-info', async (request, reply) => {\n // this \"authentication\" is for educational purposes only!\n const [, token] = request.headers.authorization.split(' ')\n const user = users[token.substr('user:'.length)]\n\n if (!user) {\n return reply.code(403).send('UNAUTHORIZED')\n }\n\n reply.type('application/json')\n // it will be cached on CDN for 30 seconds, and on client for 60\n // the request cache use depends on \"Authorization\" content\n reply.headers({\n 'cache-control': 's-maxage=30,max-age=60',\n vary: 'authorization'\n })\n\n reply.send({\n ...user,\n mobile: request.headers['cloudfront-is-mobile-viewer'],\n country: request.headers['cloudfront-viewer-country'],\n city: request.headers['cloudfront-viewer-city'],\n lat: request.headers['cloudfront-viewer-latitude'],\n lng: request.headers['cloudfront-viewer-longitude']\n })\n})\n\nawait fastify.listen(3000 || process.env.PORT, '0.0.0.0')\njsCopy to clipboard\n\nWe’ll use cdk to set up the CloudFront Distribution named “example”, which uses the CachePolicy and the OriginRequestPolicy . Related Read: Cloud Governance with CDK using Aspects The CachePolicy named “private-dynamic-content” will have min and default TTL at zero, and max at 1 day; the request is identified by the value of the Authorization header and the querystring, if any.\n\nThe OriginRequestPolicy named “forward-all” will forward all the values of cookies, querystring and headers, and also will include the CloudFront headers to identify the client, such as “'CloudFront-Is-Mobile-Viewer”, “'CloudFront-Viewer-Country” and so on.\n\nYou can see the full code in the example repo .\n\nconst cachePolicyPrivateDynamic = new cloudfront.CachePolicy(this, 'private-dynamic-content', {\n cachePolicyName: 'private-dynamic-content',\n defaultTtl: cdk.Duration.seconds(0),\n minTtl: cdk.Duration.seconds(0),\n maxTtl: cdk.Duration.days(1),\n headerBehavior: cloudfront.CacheHeaderBehavior.allowList('Authorization'),\n queryStringBehavior: cloudfront.CacheQueryStringBehavior.all(),\n enableAcceptEncodingGzip: true,\n enableAcceptEncodingBrotli: true\n})\n\nconst originRequestPolicy = new cloudfront.OriginRequestPolicy(this, 'forward-all', {\n originRequestPolicyName: 'forward-all',\n headerBehavior: cloudfront.OriginRequestHeaderBehavior.allowList(\n 'CloudFront-Is-Mobile-Viewer',\n 'CloudFront-Viewer-Country',\n 'CloudFront-Viewer-City',\n 'CloudFront-Viewer-Latitude',\n 'CloudFront-Viewer-Longitude'\n ),\n cookieBehavior: cloudfront.OriginRequestCookieBehavior.all(),\n queryStringBehavior: cloudfront.OriginRequestQueryStringBehavior.all()\n})\n\nnew cloudfront.Distribution(this, 'example', {\n defaultBehavior: {\n origin: new origins.HttpOrigin(SERVICE_HOST),\n allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,\n viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.ALLOW_ALL,\n cachePolicy: cachePolicyPrivateDynamic,\n originRequestPolicy: originRequestPolicy\n }\n})\njsCopy to clipboard\n\nLet’s see them in action.\n\nThe first call is for the user identified by the token “user:one”. The header response “x-cache” says it is missing from CloudFront, so it’s served by the fastify app.\n\ncurl -v -H \"Authorization: token user:one\" http://d1s9xu9rpb6qix.cloudfront.net/my-info\n\n < HTTP/1.1 200 OK\n < Content-Type: application/json; charset=utf-8\n < Content-Length: 122\n < Cache-Control: s-maxage=30,max-age=60\n < ETag: \"qjrpq9\"\n < Vary: authorization\n < X-Cache: Miss from cloudfront\n < Via: 1.1 c275031486c6f7b744b8d30847e98b14.cloudfront.net (CloudFront)\n {\"name\":\"Alice\",\"email\":\"alice@email.com\",\"mobile\":\"false\",\"country\":\"IT\",\"city\":\"Rome\",\"lat\":\"41.90080\",\"lng\":\"12.48740\"}\n\n\nMaking the same request again, CloudFront serves it from its cache using the previous response, without reaching the fastify app.\n\ncurl -v -H \"Authorization: token user:one\" http://d1s9xu9rpb6qix.cloudfront.net/my-info\n\n < HTTP/1.1 200 OK\n < Content-Type: application/json; charset=utf-8\n < Content-Length: 122\n < Cache-Control: s-maxage=30,max-age=60\n < ETag: \"qjrpq9\"\n < Vary: authorization\n < X-Cache: Hit from cloudfront\n < Via: 1.1 82e9051d8d41080bd3028731e0e8677e.cloudfront.net (CloudFront)\n\n\n{\"name\":\"Alice\",\"email\":\"alice@email.com\",\"mobile\":\"false\",\"country\":\"IT\",\"city\":\"Rome\",\"lat\":\"41.90080\",\"lng\":\"12.48740\"}\n\n\nNow let’s call the user “two”. Everything is working fine since it’s responding with the right data from the server.\n\ncurl -v -H \"Authorization: token user:two\" http://d1s9xu9rpb6qix.cloudfront.net/my-info\n\n < HTTP/1.1 200 OK\n < Content-Type: application/json; charset=utf-8\n < Content-Length: 118\n < Cache-Control: s-maxage=30,max-age=60\n < ETag: \"59t9f5\"\n < Vary: authorization\n < X-Cache: Miss from cloudfront\n < Via: 1.1 507b5edb20d0e1a0b73c8687f53defa8.cloudfront.net (CloudFront)\n\n{\"name\":\"Bob\",\"email\":\"bob@email.com\",\"mobile\":\"false\",\"country\":\"IT\",\"city\":\"Rome\",\"lat\":\"41.90080\",\"lng\":\"12.48740\"}\n\n\nMaking the same request again, CloudFront handles it properly, serving the right content for user “two”.\n\ncurl -v -H \"Authorization: token user:two\" http://d1s9xu9rpb6qix.cloudfront.net/my-info\n\n < HTTP/1.1 200 OK\n < Content-Type: application/json; charset=utf-8\n < Content-Length: 118\n < Cache-Control: s-maxage=30,max-age=60\n < ETag: \"59t9f5\"\n < Vary: authorization\n < X-Cache: Hit from cloudfront\n < Via: 1.1 e7e7960d7731a7583cedd8f1ff1aca38.cloudfront.net (CloudFront)\n\n {\"name\":\"Bob\",\"email\":\"bob@email.com\",\"mobile\":\"false\",\"country\":\"IT\",\"city\":\"Rome\",\"lat\":\"41.90080\",\"lng\":\"12.48740\"}\n\nPitfalls & caveats\n\nSince CloudFront manages the request and response between server and client, we must be aware of its behaviour according to HTTP headers.\n\nCloudFront policies control the cache on the CDN over the HTTP directives set on the server: min/max/default CloudFront TTLs values cap Cache-control max-age , s-maxage and even no-cache,must-revalidate . That means, for example, setting minimum TTL = 1 on CloudFront will cache the response for 1 second even on Cache-Control: no-cache,must-revalidate . Cache-Control directive contains information for CloudFront and also for the final client, so they have to be set anyway, and they have to be consistent with the CloudFront settings.\n\nTakeaways\n\nCaching is a powerful yet tricky technique to improve application performance. We should approach it wisely and analyze what and how to cache our applications' data. Using powerful tools like Amazon CloudFront and fastify make it a little easier to implement and to be in control of the outcome." ], "categories": { "primary": "backend", "others": [ "cloud", "perf" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-royal-visit-to-waterford": { "href": "https://nearform.com/insights/royal-visit-to-waterford", "postType": "blog", "slug": "insights-royal-visit-to-waterford", "date": "2022-03-31", "title": "Royal Visit to Waterford", "authors": [], "content": [ "NearForm Praised at Royal Visit in Celebration of Waterford Community & Innovation\n\nLast week, The Prince of Wales and Duchess of Cornwall began their visit to the Republic of Ireland with a trip to County Waterford, NearForm’s hometown.\n\nThe trip is one of several spring tours being undertaken by the royals in celebration of the Queen’s platinum jubilee this year and marks the first royal visit to the Republic of Ireland since 2019.\n\nIn marking the history and achievements of Waterford, our very own founder, Cian O’Maidin, CEO, Ciaran Cosgrave, and Head of Life Sciences, Larry Breen, had the privilege of meeting the senior royals to celebrate the work we have done as a company in building the Irish COVID contact tracing app .\n\n“[...]It is a particular pleasure that we will be meeting so many people throughout the course of today who have helped this city, county and country throughout this dreadful pandemic – from those who have been on the frontline against Covid, to those who have cared for loved ones and through community groups, and indeed to those remarkable Waterford-based innovators whose Covid tracker app has aided your national response, you are owed a great debt of gratitude.
The Prince of Wales
”\n\n“Being invited to this event to meet not only The Prince of Wales and Duchess of Cornwall but also other inspiring local businesses has been an immense privilege and a testament to the incredible work that the team at NearForm have done over the past two years. While we are a remote company, it’s at times like this that I am truly proud to have founded NearForm in my hometown of Waterford,” said Cian O’Maidin.\n\nCiaran Cosgrave, Cian O’Maidin and Larry Breen meeting The Prince of Wales\n\nMade in Waterford, raised globally\n\nWhile NearForm was founded in 2011 in Waterford, we have always been a remote-first company. Today, our HQ remains in NearForm’s home town of Tramore just a stone’s throw away from the beach, but the majority of our team of over 250 work remotely, scattered across 29 countries, and working flexible hours.\n\nFundamentally, we don’t believe that people need to move to “tech hubs” to have a brilliant career. Instead, we bring brilliant careers to wherever we find passionate and talented people.\n\nThis has empowered us to create a highly experienced, multidisciplinary team with a track record of delivery excellence working together to solve complex problems at speed.\n\nCiaran Cosgrave, CEO, speaking with The Duchess of Cornwall\n\nUsing Open Source & engineering excellence to change the face of healthcare and life sciences\n\nOn the afternoon of Sunday, 22 March 2020, HSE contacted NearForm about building a contact tracing app for Ireland.\n\nWithin 3 months, the COVID Tracker Ireland app was built and released. In less than 36 hours of the official launch, the app had more than one million downloads, making it the most successful launch of a contact tracing app in the world. The app has since been used in Scotland, Northern Ireland, Gibraltar, Jersey, and in several US states: New Jersey, Pennsylvania, Delaware and New York, with NearForm subsequently donating all code to the Linux Foundation Public Health under ‘Covid Green’ and managing the central OSS project.\n\n“Even beyond the technical achievements and successful, rapid deployment, the process of developing the COVID Tracker app tells a remarkable story of what’s possible in both the technology and healthcare space when talented, determined people come together to create something valuable and important,” said Ciaran Cosgrave.\n\nFor the team at NearForm, our experience building the COVID app is one of several health & life sciences projects where we have reaped the benefits of Open Source to build critical technologies changing the face of healthcare delivery, diagnostics, and data management in the medical space.\n\nAnother example of our work in the healthcare sector is with Renalytix, for whom our team of experts are building a digital platform for the groundbreaking management of chronic kidney disease.\n\nFind out more about our work." ], "categories": { "primary": "work", "others": [ "oss", "ai", "product" ] }, "verticals": { "primary": "health", "others": [ "government" ] } }, "digital-community-design-generalist": { "href": "https://nearform.com/digital-community/design-generalist", "postType": "blog", "slug": "digital-community-design-generalist", "date": "2022-04-04", "title": "The Rise of the Design Generalist", "authors": [ "RICH LIM" ], "content": [ "Wait. The What?\n\nOftentimes, designers have a tendency to fall into specific niches within design. These days it can be difficult to keep up with all the titles seemingly needed to represent them: UX Designer, Product Designer, Content Designer, Interaction Designer, UI Designer, UX/UI Designer... the list goes on.\n\nEventually, for most designers, a career choice “fork in the road” is inevitable: research, experience, user testing, and UI are just a few areas of expertise that are oftentimes boxed into separate job descriptions. At Formidable, we’ve seen that the broader our experiences get, the better prepared we are. This has led to a different kind of career trajectory. Cue the Design Generalist.\n\nLeading and Learning on the Job\n\nThe fluctuating nature of our work as design consultants provides us with broad experiences that help us in a bevy of ways: we’re able to build more robust design systems, get a far better understanding of user and business needs, and oftentimes enables us to be better partners to our stakeholders. While specialists have narrowed into focused areas of expertise, generalists have a broad understanding of a number of fields. As with most things in the world, there are levels to being a design generalist. On one end of the spectrum it can mean you have a good understanding of the visual design arena; it can also mean you have an advanced perspective on creating solutions for a wide range of problems. Developing this trait allows our consultants to confidently adapt to the business, product, and problems our clients are facing.\n\nAs product design consultants, we're usually asked to bring thought leadership and expertise into complex spaces, mostly through the lens of design and its impact on business. Similarly, the organizations we engage with are solving problems that vary substantially in size and scope. Our internal policy aims to allow our consultants to partner with a client for up to one year, but not exceeding (there are always exceptions, but this is the goal). This recipe makes room for Formidable consultants to encounter a diverse array of problems in a relatively short amount of time.\n\nWith every new client, our designers are evolving their own understanding of a certain skill set— effectively becoming experts in the field. What separates design generalists at Formidable is our ability to seamlessly integrate and adapt with the team tasked to solve the problem. To really leverage this, the following basic skills must constantly be nurtured for a design generalist to thrive.\n\nFocused Communication\n\nThe principle of communication seems like an obvious skill to invest in, but consistently gets overlooked. The bare minimum form of communication can often be counterproductive, while too much information can leave people fatigued. Whether it's the level of detail in a discovery audit, or a discreet note attached to a calendar event, the subtleties of providing thoughtful, useful context should not be undervalued.\n\nAs product designers, we're asked to understand a user's psyche when experiencing a product. This type of understanding can translate into a deeper awareness of human nature and the nuances of effective communication, particularly when our consultants embed themselves into an existing team that may already have strong relationships of their own. Design generalists understand how to utilize communication to help them elevate their existing expertise and gain traction to new ones. This is a necessary process for generalists to thrive and something we ask of all our product designers.\n\nDeliberate Collaboration\n\nFeedback is a foundational element that all designers should be very intimate with. Being an effective product designer hinges on their ability to give and receive feedback; a lever of communication. When the quality of feedback suffers, the potential communication is not realized and products do not succeed in their ability to solve specific issues.\n\nThe ability to successfully integrate to a new team or project oftentimes relies on a designer's propensity to solicit collaboration. Design generalists are able to provide quality feedback and create ego-free forums for inclusive collaboration wherever they go because they’ve experienced where positive iteration leads and felt the resistance when collaboration could’ve been better—because they’ve been there.\n\n\"What separates design generalists at Formidable is our ability to seamlessly integrate and adapt with the team tasked to solve the problem.”\n\nTactful Curiosity\n\nIn the product world, creativity and curiosity sometimes overlap. As product designers, we are trained to bring a level of creativity and curiosity to the table. It’s critical that we’re curious enough to ask the right questions that only strengthen our understanding of how a product threads the needle between user needs and businesses requirements. The inquisitive nature of product design can determine if a product ever makes it to launch.\n\nDesign generalists quickly adapt to new projects by relying on their expertise to ground them, while persistently looking outward to gain broader perspectives. This level of curiosity creates space for other skills to grow.\n\nExperience Equals Preparation\n\nAt Formidable, our product designers are frequently challenged to display a variety of skillsets with a heightened level of thought leadership and direction. It’s this constant layer of experience that provides a wide range of perspectives that only strengthen the skills needed to be a design generalist.\n\nIt's pretty challenging to formulate a well-rounded opinion from one viewpoint. This is why perspective is such an important element of product design. The world is in a perpetual state of change. Design and technology are no different—as this intersection evolves, the role of designer continuously flexes to accommodate it. In an era where specializations are seemingly en vogue, we believe the wider your expertise grows, the better prepared you’ll be for what’s next.", "DESIGN\nObservation as a prerequisite for design\nJOE ALTERIO\n30 JAN 2019\nDESIGN\nREACT\nWhy Have Design Technologists?\nPAULA LAVALLE\n8 APR 2021" ], "categories": { "primary": "design", "others": [] }, "verticals": { "primary": "none", "others": [] } }, "insights-tech-talk-graphql-caching-demystified": { "href": "https://nearform.com/insights/tech-talk-graphql-caching-demystified", "postType": "blog", "slug": "insights-tech-talk-graphql-caching-demystified", "date": "2022-04-06", "title": "Tech Talk: GraphQL Caching Demystified", "authors": [], "content": [ "GraphQL Caching Demystified: How to Improve API Performance\n\nEnsuring your APIs are fast, flexible and developer-friendly is a core aspect of delivering highly performant software—that’s where GraphQL comes in. GraphQL is an open source data query and manipulation language for APIs, and a runtime for fulfilling queries with existing data.\n\nIn this video, our resident Node.js expert and Chief Software Architect, Matteo, reveals how to improve your GraphQL gateway’s performance by 4X using Fastify, Mercurius and AutoCannon. Plus, discover the most common pitfalls to avoid during the caching process to ensure success.\n\nWatch the video below now to find out more.\n\nCatch up on the series Mastering Node.js with Matteo Collina here .\n\nAs Chief Software Architect at NearForm, Matteo Collina consults for some of the top brands in the world. Matteo is a member of the Node.js Technical Steering Committee focusing on streams, diagnostics and http.\n\nHe is also the author of Node.js MQTT Broker, Mosca, the fast logger Pino and Co-Founder of the Fastify web framework.\n\nNeed GraphQL experts for your next project? Contact us today to see how we can help!" ], "categories": { "primary": "backend", "others": [ "data", "cloud", "devops" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-bret-cunningham-americas-gm-head-of-product": { "href": "https://nearform.com/insights/bret-cunningham-americas-gm-head-of-product", "postType": "blog", "slug": "insights-bret-cunningham-americas-gm-head-of-product", "date": "2022-04-07", "title": "NearForm Appoints Bret Cunningham as Americas GM and Head of Product to Drive Rapid Growth Plans", "authors": [], "content": [ "Austin, Texas, March 2022", "NearForm has appointed Bret Cunningham as Americas GM & Head of Product to drive growth and build out the company’s product teams.\n\nIn his new role, Bret will support NearForm’s continued expansion following successful growth investment from Columbia Capital in February 2021. He will focus primarily on accelerating growth for the Americas business, building out NearForm’s product and solutions expertise, and supporting M&A and other strategic growth initiatives.\n\nBased in Austin, Texas, Bret joins NearForm after serving as SVP of Digital Strategy and Solutions and Commercial GM at Cognizant Softvision, where he led the Go-to-Market and market-facing organizations while building out the product community to lead the software product engineering client work. Bret started a company from scratch and grew that through acquisition by Softvision, and has been an operator on both the buy and sell side of corporate development within the digital services space over the past 15 years.\n\n“It’s incredibly energizing to be joining a high-growth, ambitious company like NearForm. I look forward to working with the leadership and client-facing teams to ensure that we create lasting value for our clients, driving business outcomes and empowering them to succeed in a digital world. Enterprises across industries must build the muscle to consistently define, design, and engineer software products that they can bet the future on. I’m excited to build on NearForm’s strong history to bring that unique expertise to market,\" Cunningham said.\n\n“With December 2021 marking 10 years since NearForm’s inception, it is the perfect time to welcome a seasoned industry expert like Bret. His vast experience in building teams who can create digital products that deliver intuitive and personalised user experiences to drive loyalty and revenue makes him the perfect fit as we cater to a wider range of clients and gear up for the next 10 years of high-speed growth both in terms of revenue and headcount” Ciaran Cosgrave, CEO, NearForm.\n\nBret holds an MBA in Marketing & Entrepreneurship from the University of Texas McCombs School of Business, and a BA in Economics from Wake Forest University.\n\nAbout NearForm\n\nWe accelerate business impact by building digital products and developing digital capabilities.\n\nOur community of highly skilled professionals develop the processes, products, and highly skilled teams needed to accelerate our clients’ digital transformation.\n\nAs a leader in the open source movement, we value the positive transformative impact it can have on businesses. Our work in open source guides the collaborative approach to problem-solving we take when making digitisation work for each of our clients.\n\nFind out more about what we are working on ." ], "categories": { "primary": "product", "others": [ "work", "oss" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-e-commerce-microservices-architecture": { "href": "https://nearform.com/insights/e-commerce-microservices-architecture", "postType": "blog", "slug": "insights-e-commerce-microservices-architecture", "date": "2022-04-12", "title": "E-Commerce Microservices Architecture: The Future of Commerce?", "authors": [], "content": [ "E-Commerce Microservices vs Headless Architecture Explained\n\nIn fast moving, hyper-competitive sectors like retail and e-commerce, maximising agility to stay ahead of the curve is a no-brainer. But building agility into your backend systems can be easier said than done, especially if you’re operating a monolithic legacy platform. Here’s how an e-commerce microservices architecture can help.\n\nThere’s no two ways about it; if your organisation is still using the same monolithic e-commerce platform it implemented five to ten years ago, then you’re most likely hindering your ability to adapt fast and move with the market’s ever-changing requirements.\n\nWhether it’s the rate at which your business rolls out standardised updates, more substantial website changes, or releases new products or services into the market, speed matters. Neglect the ability to be nimble for too long, and your business will get left behind.\n\nIn this article, we explain why a microservices architecture approach provides a compelling solution for retail and e-commerce agility, without needing to undergo a complete transformation.\n\nWhy choose an e-commerce microservices architecture?\n\nMicroservices is an increasingly popular approach to software development which allows organisations to loosely group individual services into an application that’s easy to update, move, scale and deploy.\n\nUnlike a monolithic, off-the-shelf e-commerce platform, an e-commerce microservices architecture can provide your organisation with the extensibility to integrate new, purpose-built tools and APIs fast.\n\nFrom a delivery and operations perspective, this equates to greater agility, more frequent deployments, and increased scalability—leading to a more seamless customer experience , faster time to market for new products and services, and a distinct competitive advantage .\n\nMore specifically, an e-commerce microservices architecture could allow you to:\n\nRoll out an existing product in a new territory fast to meet growing demand\nDeploy a critical website update to remove friction when checking out\nLaunch a new online service in a matter of days/weeks instead of months\n\nThe beauty of adopting a microservices approach is that you can continue to use the strengths of your existing proprietary software as you evolve, gradually moving away from vendor lock-in to suit your business’ roadmap.\n\nIf you’re tired of waiting for your existing vendor solution to upgrade and add new features, and your business is seeking the flexibility to pivot fast as your customers’ needs evolve, then an e-commerce microservices architecture can help you get there.\n\nView our retail and e-commerce fact sheet now to find out how we’re helping organisations like yours unleash microservices to unlock flexibility and agility.\n\nDownload Our Free E-Commerce Info Sheet\n\nFind out how we can help you get started with a microservices architecture for speed and agility.\n\nGet the Info Sheet\n\n[hubspot type=form portal=1964953 id=7345b281-46aa-4877-a3c1-8dab2e577f01]\n\nBridging the gap with a headless e-commerce engine\n\nDespite the benefits associated with microservices, jumping straight from a monolithic e-commerce solution to a complete e-commerce microservices architecture is a significant undertaking, requiring new infrastructure, tools and teams. While it requires investment, the right approach can yield massive returns in revenue and business growth.\n\nOne of the most accessible ways to leverage key microservices architecture elements, without having to drastically change your existing systems, is through a headless e-commerce engine.\n\nWith a headless e-commerce platform, your organisation can operate multiple frontends that connect to a single backend system. Like microservices, the software development process is decentralised, meaning updates to one service won’t negatively impact other applications.\n\nA headless approach minimises any organisational disruption associated with going all-in on e-commerce microservices, which can require dedicated teams to develop and maintain. Headless e-commerce is also more cost-effective, allowing your organisation to build up capabilities gradually as needed.\n\n““Moving from a slow, closed, monolithic platform to a fast, open and composable platform equates to greater control, reduced costs, flexibility and purpose-built tools creating strategic differentiation, and an accelerated route to market versus competitors.”
Colin Houlihan, VP of Consulting, NearForm
”\n\nHeadless e-commerce engines provide the best of both worlds: the familiarity of your existing backend system, with the flexibility and agility of a microservices approach built-in. Instead of relying on a monolithic vendor solution, a headless e-commerce solution can help you deliver best-of-breed capabilities to suit your business’ needs—and refine them iteratively as you evolve.\n\nRelated Read:\nHow Mobile Retail Apps Are Driving Omnichannel Commerce\n\nMicroservices architecture for e-commerce: Making it work\n\nAt NearForm, we help retailers and e-commerce organisations deliver highly responsive customer experiences and decrease the time to market for new features and services—but that’s not all.\n\nWith particular expertise in shopping applications, we help our clients move towards more modern and agile ways of working, leveraging a variety of technologies including headless, microservices-based e-commerce architectures to unlock agility.\n\nMaking microservices work for your business requires the right people, processes and skills. We can help your organisation embrace a microservices approach to e-commerce and deliver an omnichannel customer experience.\n\nIf your retail or e-commerce business is looking to unlock the flexibility and agility to compete, view our dedicated fact sheet now to start your journey.\n\nDownload Our Free E-Commerce Info Sheet\n\nFind out how we can help you get started with a microservices architecture for speed and agility.\n\nGet the Info Sheet\n\n[hubspot type=form portal=1964953 id=7345b281-46aa-4877-a3c1-8dab2e577f01]" ], "categories": { "primary": "backend", "others": [ "cloud", "product" ] }, "verticals": { "primary": "retail", "others": [] } }, "digital-community-narrowing-types": { "href": "https://nearform.com/digital-community/narrowing-types", "postType": "blog", "slug": "digital-community-narrowing-types", "date": "2022-04-13", "title": "Narrowing Types in TypeScript", "authors": [ "TREY HOOVER" ], "content": [ "What is Type Narrowing?\n\nType narrowing is just what it sounds like—narrowing down a general type into something more precise. If you've ever dealt with union types, e.g. string | number you've certainly encountered this. In fact, optional types such as x?: number often require narrowing as well, as this typing is equivalent to x: number | undefined. In both of these cases, you'll likely need to handle each case in your code, and for that you'll need to narrow down the type first.\n\nWays to Narrow These Types\n\nTo narrow a union type down to one, we'll need to consider each case. We can do this with good old-fashioned control flow in JavaScript, as the TypeScript compiler is clever enough to infer the narrowing from our conditional logic. Typically, this just means using if or switch statements.\n\nLet's consider a common, real-world example that I'm sure you've all written once or twice: a function that returns the deliciousness score for a given type of candy.\n\ntype Candy =\n | { name: \"Skittles\"; type: \"Regular\" | \"Tropical\" }\n | { name: \"Black Licorice\"; qty: number }\n | { name: \"Runts\"; isBanana: boolean };\n\nfunction rateCandy(candy: Candy): number {\n switch (candy.name) {\n case \"Skittles\":\n return candy.type === \"Regular\" ? 8 : 7;\n case \"Black Licorice\":\n return candy.qty * -1;\n case \"Runts\":\n return candy.isBanana ? 11 : 5;\n default:\n throw new Error(`\"${candy}\" is not a valid candy!`);\n }\n}\njsxCopy to clipboard\n\nBecause these candies each share a common field (name) we can use that to narrow down on a particular type of candy and use unique fields such as type and isBanana without confusing TypeScript.\n\nNaturally, we could write this with if statements as well, but you get the idea. And since our conditional logic is exhaustive, TypeScript actually infers a never type for candy in our default case, which means that error will never throw (unless we go out of our way to trick the compiler).\n\nUsing typeof\n\nLet's imagine we have a double function that accepts a string or number param. When given a string, we repeat it, and when given a number we multiply it by two. For this, we can use the typeof operator to narrow down our input and handle each case in a way that TS can understand.\n\nfunction double(x: string | number) {\n if (typeof x === 'string') {\n return x.repeat(2);\n } else {\n return x * 2;\n }\n}\njsxCopy to clipboard\n\nSo now double(5) returns 10, double('Pop!') returns Pop!Pop!, and TypeScript is perfectly happy.\n\nThe in and instanceof Operators\n\nLet's say we have a function to get the total length of a movie or series.\n\ntype Movie = {\n title: string;\n releaseDate: Date | string;\n runtime: number;\n}\n\ntype Show = {\n name: string;\n episodes: {\n releaseDate: Date | string;\n title: string;\n runtime: number;\n }[];\n}\n\nfunction getDuration(media: Movie | Show) {\n if ('runtime' in media) {\n return media.runtime;\n } else {\n return media.episodes.reduce((sum, { runtime }) => sum + runtime, 0);\n }\n}\njsxCopy to clipboard\n\nThis works because we're able to check for a top-level field that's unique to Movie with the in operator, and handle the only other possible case (a Show type) separately.\n\nBut what if we want to get the year in which a show or movie premiered? We can use getFullYear on a date object, but if it's a date string we'll have to convert it to a Date first. Luckily, TypeScript lets us narrow this down safely using the instanceof operator.\n\nfunction getPremiereYear(media: Movie | Show) {\n const releaseDate =\n \"releaseDate\" in media ? media.releaseDate : media.episodes[0].releaseDate;\n\n if (releaseDate instanceof Date) {\n return releaseDate.getFullYear();\n } else {\n return new Date(releaseDate).getFullYear();\n }\n}\njsxCopy to clipboard\n\nIf you're not familiar with instanceof, it simply evaluates to a boolean representing whether the left-hand side of the expression is an instance of the object on the right-hand side. You can use instanceof to check instances of custom classes as well.\n\nType Predicates\n\nNow for a more advanced case that you may very well have run into already. If we were to ask our users for their favorite foods, but made that information optional, we could end up with some data like this:\n\nconst favoriteFoods = [\n 'Pizza',\n null,\n 'Cheeseburger',\n 'Wings',\n null,\n 'Salad?',\n];\njsxCopy to clipboard\n\nWe can filter out the null values with something like this:\n\nconst validFavoriteFoods = favoriteFoods.filter(food => food != null); // \"!=\" will catch undefined as well\n\n// or if we want to exclude any \"falsey\" values\n\nconst validFavoriteFoods = favoriteFoods.filter(Boolean);\njsxCopy to clipboard\n\nUnfortunately, while that does manage to filter out the null values, TypeScript isn't smart enough to know for sure and will still infer a (string | null)[] type for validFavoriteFoods...\n\nIn cases like these, we can leverage a custom type guard, which is basically a function that returns a boolean determining whether a param is a certain type. We do this by using what's called a \"type predicate\" as that function's return type.\n\nfunction isValidFood(food: string | null): food is string {\n return food !== null;\n}\njsxCopy to clipboard\n\nThis handy type guard lets us safely handle null values, e.g.\n\nfor (const food of favoriteFoods) {\n if (isValidFood(food)) {\n console.log(food.toUpperCase());\n }\n}\njsxCopy to clipboard\n\nNo runtime errors OR compiler errors now—life is pretty good! And for common patterns like this, we can get even fancier with a combination of TS utility types, generics, and type predicates:\n\nconst isNotNullish =name\n\nThis is the name function that showed as a wider block in our last FlameGraph:\n\nfunction name () {\n let result = namesGenerator()\n if (names[result]) {\n result += names[result]++\n }\n names[result] = 1\n return result\n}\njsCopy to clipboard\n\nThe objective of the function is to always return a unique name. Let’s assume that namesGenerator will always return 'rafael' Calling it three times will return:\n\nname()\n> \"rafael\"\nname()\n> \"rafael1\"\nname()\n> \"rafael2\"\nnames\n> { rafael: 3, rafael1: 1, rafael2: 1}\njsCopy to clipboard\n\nThere’s the issue! For every call of name a new property is added to the names object, changing the function to hold only a count reference should fix it gracefully:\n\nfunction name () {\n let result = namesGenerator()\n\n names[result] = names[result] ? \n names[result] + 1 :\n 1\n\n return result + names[result]\n}\njsCopy to clipboard\n\nThe new flamegraph should seem different after that change:\n\nIt looks more reasonable for our small application.\n\nNo wider blocks\nMost of the memory allocation is from dependencies and Node.js internal\n\nYou can also use Clinic Doctor to monitor the memory consumption during the process execution. It will consume way less memory than in the previous version.\n\nUnderstanding memory allocation is essential\n\nMemory is often a source of confusion for engineers. However, once they understand how V8 manages its memory, the information provided by Node.js tools is crucial.\n\nIt’s strongly recommended to understand how a Node.js application manages its memory. The information shown in “ How does Node.js allocate memory ” is a must-read for every Node.js developer. That section gives the knowledge needed to scale up applications with high memory consumption.\n\nThere are several tools in the Node.js ecosystem that give visibility to memory management. For those who want to see how your application behaves over a high load, climem is a great tool. However, once high or suspicious memory consumption is identified it’s essential to reach for more robust tools.\n\nThe Clinic.js package provides a wonderful suite of tools that allows anyone to understand how their application behaves. Please, make sure to try it and give it a star in its repository ."
],
"categories": {
"primary": "backend",
"others": [
"perf",
"devops"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"digital-community-digital-transformation-part-2": {
"href": "https://nearform.com/digital-community/digital-transformation-part-2",
"postType": "blog",
"slug": "digital-community-digital-transformation-part-2",
"date": "2022-04-21",
"title": "Building Teams and Profiling Third Parties",
"authors": [
"SAM REFFITT"
],
"content": [
"Welcome to Part 2 of our series where we deep dive into the findings from our recently published report, The State of Digital Transformation.\n\nIn Part 1, we assessed the importance of staying power and how leaders benefitted from not only commencing Digital Transformation but also committing to an active strategy. So with that clarified, and your trajectory propelling you forwards, Part 2 outlines key findings when considering what type of team structure you should be building to ensure success.\n\nInternal Responsibility vs. Working With a Third Party\n\nUltimately there is no right or wrong way to approach your team setup as every business is different. If you feel you have the team and the relevant skillsets to achieve your goals then why rely on a third party for support? Similarly, if you don’t have the internal skillsets, it may be better to look externally for support. Having said that we’ve been able to identify some significant trends having spoken to industry leaders about their approaches—something we will dissect later in this piece. But first, let’s look at the context of the internal vs. external debate.\n\nLooking Internally?\n\nOver half the businesses we spoke to in this study relied solely on their internal team to implement transformations. The reason? Twenty-five percent of the responses covered a variety of answers such as a lack of trust, a lack of money to hire third parties, or a lack of time needed to get others up to speed. However, the number one reason for using internal resources was they believed their existing team had the knowledge and experience to pull it off.\n\nLooking Externally?\n\nIn Part 1 of the series, we looked at the barriers to digital transformation with ‘a lack of internal expertise’ being a top factor in deciding whether to progress or not. So why not consider third-party support?\n\nNearly half of the businesses in this study used a third-party consultant in some capacity to assist with their transformation. Why is this? Many of the responses revolved around a lack of resources, or a lack of experienced staff; however, the majority of responses focused on the additional guidance and troubleshooting support a consultancy can provide. Digital transformation isn’t a small undertaking, so bringing in specialist consultants, whilst it may be deemed more costly, is certainly highly cost-effective.\n\nThe Benefits of Third Parties\n\nWhen talking to leaders we found that, regardless of the transformation stage, whether it is in progress or completed, those who engaged a third-party consultant were more successful with their transformation than those that relied exclusively on their internal teams. Here are some figures to exemplify the point:\n\nAs demonstrated, when relying on internal teams, 20% of those that were mid-transformation rated their efforts as unsuccessful whereas those that had engaged a consultancy classified their efforts as unsuccessful in 8.7% of cases.\n\nIt’s also interesting to see that 83% of those that had already completed their transformation and involved a third party were the most satisfied segment of all. Taking this a step further, we asked leaders for more insight as to how third parties helped them achieve their goals:\n\nEighty-five percent of businesses that involved a third party had a high level of digital maturity, 11% higher than businesses that used only internal staff.\nIn addition to profitability and online sales, annual revenue and awareness also improved by 4% points over those that focused on internal means.\nThe majority of companies that deemed their transformation to be ‘Highly Successful’ used third parties.\nDespite the widespread success, mid-size businesses were the obvious benefactors of an external strategy; 55% of such companies used a third party and 90% deemed their efforts a great success.\nSpecialized or Large Third Parties?\n\nSo, you’ve committed to a third party, but what type of consultancy do you go for? A large generalist consultancy or a smaller specialist boutique? As it turns out, 100% of companies that hired a highly-skilled boutique, specialist firm as opposed to a larger generalist consultant, categorized success as highly successful. Often the assumption is that smaller boutiques don't have the resources you require when the reality is often the total opposite.\n\nWhat is Right For You?\n\nThere is plenty to digest and ultimately, there are a multitude of factors to consider when planning a transformation. One thing we can say for certain is that everyone who completed a digital transformation, regardless of strategy, saw a greater performance than prior to the transformation.\n\nWhat do our findings tell us is the optimal approach? Simply put, businesses that decided to opt for the support of a third-party consultant with a specialist skillset were most satisfied with business performance post-transformation.\n\nIf it’s a fresh perspective you are looking for, we’d be happy to chat. You can contact us immediately for a complimentary consultation.\n\nPart 3 Preview\n\nIn Part 3, we’ll round out the series by offering our concluding thoughts, contextualizing the core findings, and highlighting why it is critical for businesses to consider a new Digital Transformation strategy to safeguard future success.\n\nIf you missed our webinar with our partners at Hinge Research covering the full research findings, please view it for free in its entirety on our YouTube channel.",
"REACT\nMOBILE\nBACKEND\nDigital Transformation - Driving Success\nSAM REFFITT\n9 MAR 2022\nNew Research: The State of Digital Transformation\nAMY L. DICKSON\n25 JAN 2022"
],
"categories": {
"primary": "work",
"others": [
"product"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"insights-contributing-openssf-alpha-omega-project": {
"href": "https://nearform.com/insights/contributing-openssf-alpha-omega-project",
"postType": "blog",
"slug": "insights-contributing-openssf-alpha-omega-project",
"date": "2022-04-21",
"title": "NearForm Contributing to OpenSSF Alpha-Omega Project",
"authors": [],
"content": [
"NearForm Contributes Security Engineering Resources to Open Source Security Foundation (OpenSSF) Node.js Supply Chain Security Pilot Program\n\nNearForm is proud to announce that it will be contributing security engineering resources to the OpenSSF Alpha-Omega Project , focussing on better supporting open source security standards and practices within Node.js.\n\nAs a highly popular JavaScript project, Node.js faces many of the challenges that community-led initiatives must deal with, namely the lack of time, people, and expertise for comprehensive security measures, exacerbated by the fact that the majority of companies whose products and services rely on Node.js do not contribute back to the project. This project aims to encourage more organisations that use Node.js to give back to the project.\n\nNeed help with Node.js Applications and Performance?\n\nWe are huge proponents of and contributors to Node.js and work with organisations to build best-in-class Node.js applications.\n\nNode.js Development @ NearForm\n\nBy providing security engineering resources to this project, NearForm hopes to help relieve the pressure faced by Node.js project maintainers, some of whom work for NearForm.\n\nThese efforts, alongside Trail of Bits, will support the Node.js Technical Steering Committee , help triage reports, steward security releases, improve security broadly for Node.js and encourage implementing best practices in JavaScript projects across the industry.\n\nAs a company that was built on the belief that web technology and programming languages such as Node.js would enable us to solve real-world problems in the quickest manner possible, it is an honour for us to work on the Alpha-Omega project.\n\nWith our organisation currently receiving 1.2 billion monthly NPM downloads, we remain committed to growing the JavaScript ecosystem through contributions to Open Source.\n\n“I am thrilled about this collaboration, not only as it continues to build the vibrant Open Source community and encourage further collaboration, but also because this new project will enable NearForm to double its Node core team. I can’t wait to see what the future of the Alpha-Omega project brings and the benefits that bolstering Open Source security standards will have on the wider digital ecosystem. Matteo Collina, Chief Software Architect, NearForm.”"
],
"categories": {
"primary": "security",
"others": [
"oss"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"insights-cloud-engineering-end-to-end-velocity": {
"href": "https://nearform.com/insights/cloud-engineering-end-to-end-velocity",
"postType": "blog",
"slug": "insights-cloud-engineering-end-to-end-velocity",
"date": "2022-04-26",
"title": "Engineering End-to-End Velocity in the Cloud",
"authors": [],
"content": [
"Why Your Business Needs a Cloud Engineering Strategy\n\nCloud adoption is often touted as the key to any successful digital transformation. And yet, for the majority of organisations, migrating to the Cloud is just the tip of the iceberg when it comes to driving growth. In this article, we reveal how a cloud engineering strategy can deliver the end-to-end velocity your business needs to evolve at speed and scale.\n\nTraditional companies with legacy IT infrastructure are migrating to the Cloud in growing numbers, and the biggest cloud providers are all competing for their attention. However, beyond the initial hardware and licensing cost savings, simply moving to, or operating in the Cloud seldom delivers dramatically improved business outcomes.\n\nThe ability to deliver highly performant applications and services at speed and scale relies on having a robust cloud engineering approach encompassing architecture, design, code, DevOps, agile processes, and everything in between.\n\nWhile unlocking velocity in the Cloud doesn’t happen overnight, the good news is there are steps your business can take to create the roadmap to get there. Read on to find out why cloud engineering is business-critical in 2022, the key components of a highly performant cloud engine, and how we can help you unlock end-to-end commercial velocity at scale.\n\nWhy cloud engineering is business-critical in 2022\n\nIn today’s fast-moving digital world, customers expect a flexible, speedy and streamlined service across multiple channels. This is leading to a growing number of businesses embracing the Cloud for the agility and scalability it brings.\n\nFrom a technical standpoint, the increased popularity and extensibility of Kubernetes and infrastructure as code (IaC) presents numerous opportunities for businesses, including service discovery and the ability to horizontally scale with ease, driving revenue.\n\nHowever, from a commercial perspective, the shift from on-premise architecture to the Cloud can be a significant adjustment, turning familiar cost, security and ownership models on their heads. The rise of microservices and container orchestration has introduced new challenges, driving changes in traditional site reliability engineer (SRE) responsibilities.\n\nAnd it’s not just different ways of working that are presenting a challenge. When organisations move to the Cloud, they don’t necessarily have the skills to operate in, or make the most of it. Moreover, if skill gaps aren’t promptly addressed, they’ll undoubtedly widen over time, resulting in increased obstacles and complexity.\n\nSuccessful migrations call for not only cloud expertise, but knowledge and experience surrounding container orchestration, Kubernetes and more. But how do you create a strong developer experience and drive productivity so that developers aren’t constantly working on either the infrastructure or platform alone? Many organisations are beginning to consider whether they need a dedicated platform engineering team.\n\nCloud Engineering with NearForm\n\nDiscover how highly performant cloud infrastructure can enable end-to-end commercial velocity across your business’ products and services.\n\nGet in Touch\n\n3 signs you need a cloud engineering team\n\nTo plan and implement your cloud engineering strategy successfully, you need a purpose-built team with the knowledge, skills, and resources to develop and manage your organisation’s cloud environment. From Kubernetes to containers, newfound capabilities require dedicated resources.\n\nWith that said, here are the top three signs your business could benefit from a cloud engineering team:\n\n1. Your organisation has multiple product teams working on similar features.\n\nIf you’ve noticed significant overlap across your product teams, whether they’re working on very similar features, or trying to complete shared tasks, this is one of the most telling signs that your organisation could benefit from a dedicated platform engineering function.\n\n2. Productivity and efficiency isn’t as strong as it could be.\n\nIf you find that you resonate with the above scenario, then it’s highly likely there are productivity and efficiency gains to be made. To deliver above the value line and accelerate delivery and innovation, you need to create a blueprint for scaling in the Cloud that’s entirely unique to your organisation.\n\nHaving a platform engineering team in place can help you achieve this, eliminating duplicate work and freeing up resources to focus on driving velocity across your products and services. This will not only enhance productivity, but improve the overall developer experience (DevEx), which is core to attracting and retaining the top technical talent.\n\n3. Your organisation is migrating to, or has recently migrated to the Cloud.\n\nAnd finally, if cloud adoption is high on your business’ agenda, then you’re going to need a dedicated platform engineering team to manage your cloud environment and drive incremental improvements.\n\nEnsuring you attract the right types of developers with expertise in the specific technologies you’ll be working with is crucial. When considering introducing a platform engineering team, deciding whether to adopt a single or a multicloud approach is a great place to start. This will allow your organisation to define its skill requirements in detail and build the best possible team. Related Read: How Digital Partners Create Competitive Advantage\n\nBuilding a well architected cloud engine: How we can help\n\nWhether your business is implementing a single cloud, multicloud or hybrid cloud environment, getting the fundamentals right from the outset is essential to achieving optimum performance, security, scalability and growth later on.\n\nFrom setting up and integrating your chosen services, to the cloud development and delivery lifecycle, to design-time and run-time cloud management, we can help you get ahead. As consultants and practitioners, we’re well-versed in building highly scalable applications in the cloud for our leading enterprise customers.\n\n““We help organisations build environments in the Cloud and leverage cloud services to release applications easier and faster, while shifting their cost, security and ownership models for greater scalability and agility.”Keith Madsen, Technical Director, NearForm”\n\nOur agile approach and expertise surrounding automation using technologies such as Terraform , as well as Node.js for Kubernetes and microservices, can help you deliver new applications fast while reducing your operational overheads.\n\nSupercharge Your Products and Services\n\nGet in touch to find out how a well-architected cloud infrastructure can help.\n\nGet in Touch" ], "categories": { "primary": "cloud", "others": [ "devops", "backend" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-async-graphql-with-rust-1": { "href": "https://nearform.com/digital-community/async-graphql-with-rust-1", "postType": "blog", "slug": "digital-community-async-graphql-with-rust-1", "date": "2022-04-27", "title": "Async GraphQL with Rust: Introduction", "authors": [ "BRANDON KONKLE" ], "content": [ "Part 1: Introduction\n\nWelcome to the first entry in a new series covering Async GraphQL in Rust! This series is aimed at intermediate Rust developers who have grasped the basics and are ready to build production-ready server applications. I'll cover a variety of topics like:\n\nHandling GraphQL requests\nAccessing the database and pulling in related data\nCreating a GraphQL schema and building resolvers\nAuthenticating and authorizing user requests\nUnit and integration testing\nGraphQL subscriptions and WebSocket events\nBuilds, containers, continuous integration, and deployment\n\nMy demo application through this series will be \"Caster\" — a hypothetical tool to help podcasters, broadcasters, and streamers coordinate show content with their co-hosts and guests. It will be limited to just the API to support front-end applications. I currently have an example API implementation for Caster written in Rust published to Github as bkonkle/rust-example-caster-api. You can use this repository to follow along as the series progresses.\n\nWhy Rust?\n\nRust is a low-level, statically typed, multi-paradigm programming language with a focus on memory safety, high performance, and reliable concurrency. It uses an innovative memory ownership and borrowing system to avoid the need for garbage collection, providing strong memory safety across threads and eliminating latency spikes due to garbage collection sweeps. It solves many of the same problems with mutability and undefined behavior that paradigms like Functional or Object-Oriented Programming do, but in uniquely different ways.\n\nRust doesn't check and collect memory at runtime. It tracks the lifetime of memory and who can read or write to it at compile time, and immediately frees the memory at runtime once it is no longer needed. Functions \"own\" the memory regions that variables represent. The default behavior when they are passed to other functions is to pass-by-value and move the value to the memory region controlled by the new function, which now takes ownership of that variable. If you don't want to hand over ownership of your variable, you can pass-by-reference to the other function and allow it to borrow the value, giving ownership back afterwards. The compiler uses the borrow checker to statically guarantee that references always point to values that haven't been dropped (the equivalent of garbage collected). This prevents problems with null pointer exceptions and undefined behavior.\n\nReferences can be mutable or immutable, but you can only have one mutable reference at a time. This prevents data race issues where multiple memory pointers try to access the same data at the same time, at least one of the pointers is writing to the data, and there is no synchronization method in use. This can cause unpredictable behavior that can be very difficult to troubleshoot at runtime. The safety provided can often rival the protection that languages with dependent types (like Idris) provide, but without the performance hit and extensive source code annotation burden they often come with.\n\nMicrosoft and Google both report that 70% of the security bugs they encounter are memory issues. Rust's goal is to match the freedom of memory access C or C++ provides, while applying sound type safety and enabling high-level abstractions with zero runtime cost (in most cases). It enforces strong memory safety even across threads by providing ways to share ownership with multiple locking methods.\n\nThe end result is a language that is fully compiled without heavy runtime support, has excellent memory safety, provides high-level features that modern developers have come to expect, and delivers spectacular performance while going easy on system resources and preventing chaotic runtime errors.\n\nWhy Async?\n\nAsync Rust is a long-awaited feature that has finally matured, and it was delivered in a way that has allowed a rich ecosystem to grow around the async tools available in the community. The primitive pieces of async support — Futures — can be leveraged a variety of ways and are built upon by a few major competing libraries in the Rust community (like Tokio, async-std, and actix). Rust uses the popular async/await style to apply syntactic sugar to concurrency, presenting a developer experience that is very similar to synchronous code and is easy to work with.\n\nAsync programming allows you to introduce concurrency in a single thread, waiting for multiple tasks to complete at the same time and not blocking execution to wait for each to finish in order. This is distinct from multithreading, which spawns multiple CPU threads to handle computationally expensive tasks in parallel. Async allows you to handle a large number of I/O-bound tasks that would otherwise have to spend a lot of time waiting for responses from other systems, like the filesystem or a network call, on a small number of OS threads. It requires significantly less CPU and memory overhead for systems with a lot of I/O-bound tasks, like the GraphQL API I'm building here.\n\nWhy GraphQL?\n\nGraphQL has been my favorite way to enable client/server communication for a long time now. I was an early adopter within the JavaScript React and Node ecosystems, and I have continued to use it across other language communities because of the numerous benefits it provides over more traditional HTTP REST communication.\n\nThe built-in type system leads to a variety of ways to use it as a source of truth for automatic code generation, and makes it easy to define a contract of inputs and responses that the front and back end can unify on. The query language is very extensible, and the concept of connections to related data is a powerful tool to help the front end craft high-performance queries. The query language also provides the backend rich detail to help optimize queries, providing strong solutions to the N+1 problem with related data. Popular tools like Swagger and Postman aren't necessary, because rich documentation is built right into the schema and tools like GraphiQL make it easy to work with.\n\nRusty Crates\n\nTo present a highly maintainable project structure that has a great developer experience while staying async-first and providing the level of static and runtime safety we've come to expect from high-quality Rust applications, I take advantage of a number of excellent open-source shared community modules. Packages in Rust are called \"crates\", and the crates.io registry provides an excellent index for community crates that work with the popular Cargo package manager.\n\nTokio for Async\n\nThe Rust Future primitive is intended to be used with a runtime executor, which polls the task in order to drive progress. When polled, the Future advances as far towards completion as is possible in that moment, and then goes back into a pending state until polled again. This is where async runtimes come in — they provide an executor that spawns tasks within one or more threads, efficiently polls pending tasks, and synchronizes data between them.\n\nThe Tokio event loop is built on a very efficient multi-threaded scheduler, and it provides safe and reliable APIs that protect against misuse. It supports an easy async/await interface, but also provides a lot of configurability to fine-tune performance for each use case.\n\nTokio's library follows conventions from Rust's standard library \"when it makes sense.\" The async-std library is an alternative to Tokio that aims to more closely mirror the synchronous equivalents from the standard library. I avoided it because it hasn't been around as long, doesn't have as large of an ecosystem, and by most accounts is not as efficient as Tokio.\n\nWarp for HTTP\n\nWarp is built on hyper, which in turn is built on Tokio. Hyper is a fast HTTP client and server library with a focus on high concurrency with non-blocking sockets, and it performs extremely well on Rust server benchmarks. Warp provides a lightweight composable server framework to handle routing, parameters, headers, query strings, form data, WebSockets, logging, and more.\n\nIt integrates well with the async-graphql library I used for GraphQL communication, and it makes it easy to inject things like JWT token payloads into the request context.\n\nGraphQL with async-graphql\n\nThe async-graphql library is a high-performance implementation of GraphQL built from the ground up to support async runtimes like Tokio and actix. Define your schema using Rust structs and automatically derive the GraphQL schema and query code, without needing to extend the Rust syntax and break rustfmt support. It provides many features that the popular alternative Juniper does not.\n\nSeaORM for Database Access\n\nI originally started out with SQLx, a pure Rust SQL toolkit built to support async, which includes a unique compile-time checker that uses an active database connection. When I needed to build out highly dynamic queries I needed to support the flexible GraphQL schema I had designed, I found the fully-static approach of SQLx to be quite challenging and verbose to work around.\n\nSeaORM builds on top of SQLx, providing a full-featured tool to manage dynamic queries with effective unit testing to prove correctness. Similar to async-graphql, it provides traits that can automatically derive the database modeling code and doesn't rely on a domain-specific-language. In many cases you can reuse your async-graphql types as SeaORM models.\n\nThe first-class async support, the dynamic nature of SeaORM's queries, and the avoidance of a domain-specific language are what set it apart from the popular alternative, Diesel.\n\nOso for Authorization\n\nAuthorization decisions are important for almost every API. These decisions can often be tricky, and you may need related data from the database before you can sufficiently decide whether the requesting user should have access to the resources they want to work with. These decisions are often implemented as case-by-case imperative logic implemented in the body of a resolver or a controller, and they can be hard to maintain and keep consistent.\n\nOso is a cross-platform authorization library that provides a declarative policy language called Polar, inspired by the Prolog logic programming language. With the primitives that Oso provides, you can build up sophisticated rules using patterns like RBAC or ABAC and traverse relationships, using concise Polar definitions to express those rules in a tight, declarative format.\n\nIt has first-class support for Node.js, Python, Go, Ruby, and Java, along with early (sparsely documented) support for Rust. The rules engine itself is built as a compiled Rust library, allowing it to be easily embedded in many other languages. There's a hosted service in early-access right now, but using the open-source libraries in your app is \"free for all, forever.\"\n\nOne of the main distinctions that set it apart from the popular OPA alternative is the fact that it is intended to be deployed as an embedded component within a larger application, as opposed to a separate service that sits outside of your API like OPA. In addition, Oso's Polar language is generally easier to understand and maintain than OPA's Rego language, which is also inspired by Prolog but with different design decisions.\n\nProject Structure\n\nMy Rust project structure is influenced by the default project structure for the Nx build tool in the JavaScript ecosystem. It takes advantage of Cargo's workspaces feature to divide code into entry points — called \"apps\" — and business logic divided into library modules — called \"libs\".\n\nIn large organizations, I like to split my source code repositories up by teams and deployables. Projects that are maintained by different teams with separate code review groups should be in separate repositories. In addition, projects that are maintained by the same team but are deployed separately in very different ways (like backend APIs vs. front-end UIs) should be in separate repositories.\n\nEven given those divisions, however, your team will often have projects that have multiple entry points, like an API that has side-processes for task workers or convenience services. Or, you may have a single service that starts out as a monolith but over time breaks apart into multiple related services or sidecar processes. In these cases you will often have a large amount of shared business logic or data access code that would be challenging to refactor if it was initially kept in the same crate and needed to be split apart.\n\nTo mitigate this, any business logic that could conceivably be shared between multiple apps or sidecar processes should be kept in crates within the \"libs\" folder, and entry points within the \"apps\" folder should be limited to code that is entirely application-specific. This keeps things decoupled and flexible, and leads to less refactoring when entry points change.\n\nCargo Workspaces\n\nCargo's workspaces feature does a great job of enabling workflows around the project structure described above. Workspaces share the same Cargo.lock file and output directory, but are split into separate crates with separate Cargo.toml files specifying dependencies. The top-level Cargo.toml can be as simple as this:\n\n[workspace]\nmembers = [\"apps/*\", \"libs/*\"]\njsxCopy to clipboard\n\nEntry-points in the Rust community are typically considered \"binaries\", and shared code modules are considered \"libraries\". In this structure, binaries go in \"apps\" and libraries go in \"libs\". Shared dependencies across the members of the workspace will all use the same version, which saves space and ensures that the crates in the project will all be compatible with each other. Cargo allows you to check, build, and test all crates together using commands at the top level of the repository.\n\nWorkspace members are statically linked into binaries — meaning that they don't require separate lib files when executing the compiled binary. Cargo stores incremental build information about each one, however, speeding up the build process when particular crates haven't been touched in an iteration.\n\nMakefile Madness\n\nWhen you want to go beyond the simple check, build, and test commands that Cargo provides out of the box, you'll likely want to embrace a scripting tool that allows you to add custom commands to your Cargo workflows. My preferred solution here is cargo-make, which uses a Makefile.toml config to add additional workspace-aware build tasks to your Cargo setup.\n\nI use it to enable commands like:\n\ndb-create, db-migrate, db-reset - commands to manage the local database.\ndocker-api - a command to run docker-compose commands to spin up supporting processes.\nintegration - a command to run integration tests with proper flags and environment variables\nLinting with Clippy\n\nClippy gives you a variety of different code quality and linting tools, similar to the popular eslint utility from the JavaScript ecosystem. I use a top-level config file in .cargo/config.toml to configure linting rules, which apply to all crates within the workspace.\n\nConfig with Figment\n\nTo manage hierarchical configuration between environments, I use the Figment library. This library allows you to load and override configuration values from various sources at runtime, and it supports the popular toml format used by tools like Cargo. It easily handles nested configuration values, plays well with serialization tools like Serde, and produces actual Rust structs.\n\nOnward to Implementation\n\nIn my next post I'll cover how I use SeaORM within Services to manage business logic and data access, and how I use Resolvers and Object types to build up a GraphQL schema and handle user requests. After that, I'll cover how I pull authentication and authorization into the request context using features from Warp and async-graphql. I'll follow that up with an exploration of unit and integration testing, both of which are very important to ensure correctness in your deployed application. Then I'll move into the world of \"realtime\" events with GraphQL subscriptions and WebSockets. Finally, I'll cap off my series with a discussion around continuous integration and deployment.\n\nThis content originally appeared at: https://konkle.us/async-graphql-rust-1-introduction/" ], "categories": { "primary": "backend", "others": [ "data", "devops" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-nearform-makes-strategic-appointments-in-north-america-to-bolster-expansion": { "href": "https://nearform.com/insights/nearform-makes-strategic-appointments-in-north-america-to-bolster-expansion", "postType": "blog", "slug": "insights-nearform-makes-strategic-appointments-in-north-america-to-bolster-expansion", "date": "2022-04-28", "title": "NearForm Makes Strategic Appointments in North America to Bolster Expansion", "authors": [], "content": [ "NearForm has appointed Felicia Schwartz as Head of Delivery for North America and Shaun Anderson as Field CTO.\n\nIn their new roles, Felicia and Shaun will be focused on supporting NearForm’s continued US expansion following successful growth investment from Columbia Capital in February 2021.\n\nFelicia and Shaun’s combined years of experience in the world of digital transformation will empower them to lead delivery in the Americas, focussing on helping large enterprises with complex problems, modernize their legacy systems and build new, agile, customer-centric software solutions catered to their business needs. Ultimately, Felicia and Shaun will ensure that NearForm’s rapidly growing portfolio of large, enterprise clients are provided with the expertise to move away from archaic solutions and architectures to remain competitive in a fast-paced digital environment.\n\nBased in New York, Felicia joins NearForm with a wealth of experience creating digital solutions to ensure customer satisfaction across the financial services, healthcare and telecommunications industries. Most recently, Felicia served as Global Director of Application Solutions at VMware Tanzu Labs, formerly known as Pivotal Labs, where she helped clients safely and securely modernize legacy applications to take advantage of modern application architectures and cloud capabilities.\n\nBased in Denver, Shaun also joins NearForm from VMware, where he most recently led the enterprise system and modernization practice. Shaun is the inventor of the Swift Method, a domain-driven design process for quickly understanding the behaviour of complex software systems. Shaun specializes in building enterprise production-grade digital products and modernization strategies for large enterprises, with a breadth of experience in delivering mission-critical systems across the financial, health care, retail and aerospace sectors.\n\n“\"As an Irish founded company that has just celebrated 10 years of incredible growth, we are thrilled to establish a wider presence in the US market. The US market is ripe for growth in the space of digitisation, and welcoming seasoned experts like Felicia and Shaun to our growing US-based team will continue to push forward our expansion efforts at pace.\"
Ciaran Cosgrave, CEO, NearForm”\n\nAbout NearForm\n\nWe accelerate business impact by building digital products and developing digital capabilities.\n\nOur community of highly skilled professionals develop the processes, products, and highly skilled teams needed to accelerate our clients’ digital transformation.\n\nAs a leader in the open source movement, we value the positive transformative impact it can have on businesses. Our work in open source guides the collaborative approach to problem solving we take when making digitisation work for each of our clients.\n\nFind out more about what we are working on ."
],
"categories": {
"primary": "work",
"others": [
"product",
"cloud",
"oss"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"insights-deploying-a-fastify-application-on-azure": {
"href": "https://nearform.com/insights/deploying-a-fastify-application-on-azure",
"postType": "blog",
"slug": "insights-deploying-a-fastify-application-on-azure",
"date": "2022-05-03",
"title": "Deploying a Fastify Application on Azure",
"authors": [],
"content": [
"How to set up infrastructure on Azure and deploy your Fastify application\n\nFastify users have an easy way to deploy their applications on Azure using the Webapp service and set them up using Terraform.\n\nIn this article, we will demonstrate how to:\n\nSet up an Azure Webapp infrastructure as a code\nSet up Github Actions to deploy our application\nTake down the infrastructure\nWhy should I use Azure Webapp?\n\nThe Webapp service is one of the most popular products within Azure. It offers a range of services and tools required to build enterprise-ready apps quickly, accelerating the time to market.\n\nBesides, even though we are working with a PaaS platform, it is possible to scale your infrastructure as needed, and it's simple to do.\n\nAdditionally, it is very easy to create the infrastructure and deploy applications in many languages. In this proof of concept, we will deploy a Fastify app running on Node.js 16.\n\nPrerequisites\nAzure free tier account\nAzure CLI\nTerraform 1.1+\n\nFork and clone the Github repository\n\nhttps://github.com/nearform/azure_webapp\nRepository structure\n\nBefore we proceed with creating the infrastructure, let's understand the structure of the repository and what every important file does.\n\n├── README.md\n├── app \t\t <- application folder \n│ ├── README.md\n│ ├── index.js\n│ ├── package-lock.json\n│ ├── package.json\n│ ├── process.json\n│ └── web.config\n├── main.tf <- primary entrypoint of Terraform\n├── outputs.tf\t\t <- desired outputs\n├── publish.profile.xml\t <- generated Azure publish profile\n├── rg.tf\t\t\t <- resource group and application service plan\n├── state.sh\t\t\t <- script to create storage bucket for tfstate\n├── variables.tf\t\t <- store variables\n└── webapp.tf\t\t <- creation of webapp\n\n\nThere are two important files which are critical to the application described in this article.\n\n1. rg.tf\n\nEvery resource on Azure needs to be in a resource group . This will be created by the rg.tf file with a random name, on azurerm_resource_group block.\n\nresource \"azurerm_resource_group\" \"rg\" {\n name = \"rg${random_integer.ri.result}\"\n location = var.location\n}\njsCopy to clipboard\n\nAnd the application service plan .\n\n# Create the Linux App Service Plan\nresource \"azurerm_app_service_plan\" \"appserviceplan\" {\n name = \"serviceplan${random_integer.ri.result}\"\n location = azurerm_resource_group.rg.location\n resource_group_name = azurerm_resource_group.rg.name\n kind = \"Linux\"\n reserved = true\n sku {\n tier = \"Standard\"\n size = \"S1\"\n }\n}\njsCopy to clipboard\n\nIt is on the service plan that we will define the machine type that will host your application. If you want to deploy this code to production, you can upgrade the machine tier, add multi-zone hosting and enable scaling.\n\nFor a full list of options for the application service plan , look at the Terraform documentation in this module.\n\n2. webapp.tf\n\nFinally, the webapp.tf file creates our Webapp.\n\n# Create the web app, pass in the App Service Plan ID, and deploy code from a public GitHub repo\nresource \"azurerm_app_service\" \"webapp\" {\n name = \"webapp-${random_integer.ri.result}\"\n location = azurerm_resource_group.rg.location\n resource_group_name = azurerm_resource_group.rg.name\n app_service_plan_id = azurerm_app_service_plan.appserviceplan.id\n site_config {\n linux_fx_version = \"NODE|16-lts\"\n }\n provisioner \"local-exec\" {\n command = \"az webapp deployment list-publishing-profiles --resource-group ${azurerm_resource_group.rg.name} --name ${azurerm_app_service.webapp.name} --xml > publish.profile.xml\"\n }\n}\njsCopy to clipboard\n\nIn this sample, we are deploying a Fastify application running on Node.js 16.x. The Node version is defined on option linux_fx_version, this can be changed as needed.\n\nThere is a final block called a local-exec Azure CLI command. This command reads and generates a local publish profile file, that will be necessary to deploy the application.\n\nThe other options are self-explanatory: defining name, location, associated resource group and service plan.\n\nAzure Webapp supports a variety of options like logging and number of workers. In this example, the goal is to keep it simple. View the documentation for a full list of options.\n\nBuilding the infrastructure\n\nAfter forking and cloning the Github repo, go to the cloned repository folder in your favourite terminal app.\n\nNow you need to follow these steps:\n\n1. Login to Azure\n\nThe first thing is to login using Azure CLI. We need to do this in order to run a script to create some objects to store in Terraform tfstate.\n\naz login\n\n\nYou will be redirected to the browser window to complete the current login process. Once logged in, just close the tab and head back to the terminal.\n\n2. Setup Terraform backend\n\nOn the Github repository, there is a script that will create a storage account and a storage container with a random name, which will host our tfstate file.\n\nIt's possible to use a local tfstate file, but this option isn’t recommended, because the management of our infrastructure will depend on a file on your local machine.\n\nRun the script:\n\nsh state.sh\n\n\nAfter the storage container creation, your main.tf file will be automatically populated with the updated information.\n\n# Configure the Azure provider\nterraform {\n required_providers {\n azurerm = {\n source = \"hashicorp/azurerm\"\n version = \"~> 2.65\"\n }\n }\n required_version = \">= 1.0.0\"\n backend \"azurerm\" {\n resource_group_name = \"tfstate\"\n storage_account_name = \"tfstate11111\"\n container_name = \"tfstate\"\n key = \"terraform.tfstate\"\n }\n}\nprovider \"azurerm\" {\n features {}\n}\njsCopy to clipboard\n3. Create Services\n\nTo build everything, just apply the terraform scripts:\n\n$ terraform apply\nAcquiring state lock. This may take a few moments...\n\n\nWhen terraform finishes the plan, review the resources that will be created and confirm by typing yes .\n\nAfter a few minutes, you will receive an output like the following, with a different hostname:\n\nApply complete! Resources: 4 added, 0 changed, 0 destroyed.\n\nOutputs:\n\nhostname = \"webapp-11111.azurewebsites.net\"\n\n\nTake a note because this is the address of our application. To confirm everything is fine, make a quick test accessing https://.azurewebsites.net\n\nYou will see a website like this:\n\nThis means that your infrastructure is up and running, just waiting for an application deployment.\n\nDeploying the application\n\nIn this article, we are deploying a sample hello world Fastify application. The source code is located on the ./app folder of the repository.\n\nYou just need to do two steps on your own Github repository to deploy the app on Azure Webapp service.\n\nUnderstanding Publish Profile\n\nThe application deployment on Azure Webapp depends on the publish profile to authorise access to the service. Every time you create a Webapp, a new publish profile will be created for this app.\n\nIn this case, the publish profile is generated by our webapp.tf terraform file, under the block:\n\nprovisioner \"local-exec\" {\n command = \"az webapp deployment list-publishing-profiles --resource-group ${azurerm_resource_group.rg.name} --name ${azurerm_app_service.webapp.name} --xml > publish.profile.xml\"\n }\njsCopy to clipboard\n\nEvery time you create an infrastructure, a new publish.profile.xml file is created.\n\nSetup secrets\n\nOn Github web, go to your repository, then in Settings -> Secrets click Actions\n\nClick on the New Repository Secret button:\n\nCreate a secret named AZURE_WEBAPP_PUBLISH_PROFILE . The content of this secret will be the content of the file publish.profile.xml , under the infrastructure repository.\n\nFill in the fields like in this sample and click Add secret .\n\nGo to the Actions tab:\n\nAnd click the button to enable actions.\n\nChange webapp name.\n\nIn the repository, there is a file under ./github/workflows called workflow.yml .\n\nWe need to edit this file and change the variable AZURE_WEBAPP_NAME to the name of our app. This name is a prefix of the generated URL on Terraform outputs, where webapp-11111.azurewebsites.net is the full URL and webapp-11111 is the app name.\n\nenv:\n AZURE_WEBAPP_NAME: webapp-11111 # set this to your application's name \n AZURE_WEBAPP_PACKAGE_PATH: './app' # set this to the path to your web app project, defaults to the repository root\n NODE_VERSION: '16.x' # set this to the node version to use\nbashCopy to clipboard\n\nWhen deploying a custom application, feel free to change the NODE_VERSION if needed. This is the Node image that will run the build job.\n\nNow, just push the changes to your repository and let's see the magic.\n\nViewing the workflow's activity\n\nOn the Github web application, go to your repository and click on the Actions tab.\n\nClick on the current workflow to follow up deployment.\n\nCheck to see if all steps are complete.\n\nAccess your application again: https://.azurewebsites.net\n\nAnd see your deployed code.\n\nNow our application is up and running, with CI/CD. When you make any changes, just push into your Github repository and Github Actions deploys it.\n\nBring down the infrastructure.\n\nWhen you don’t need this infrastructure anymore, just go to your local folder containing the infrastructure repository and run:\n\n$ terraform destroy\nAcquiring state lock. This may take a few moments...\n\n\nReview the changes and type yes. When you need to set up everything again, just repeat the steps in this article. Related Read: Getting DevSecOps Right in Azure\n\nConclusion\n\nAzure Webapp is a pretty simple way to host our application with low infrastructure management. You can easily develop your idea using the free tier + Github and stay free until you need to scale up.\n\nUsing Fastify, we have a better handle on the resources of our infrastructure, because it’s a performance-focused framework. This can help developers keep hosting fees at free/low cost tiers."
],
"categories": {
"primary": "cloud",
"others": [
"backend",
"devops"
]
},
"verticals": {
"primary": "none",
"others": []
}
},
"digital-community-data-and-graphs": {
"href": "https://nearform.com/digital-community/data-and-graphs",
"postType": "blog",
"slug": "digital-community-data-and-graphs",
"date": "2022-05-12",
"title": "Async GraphQL with Rust: Data and Graphs",
"authors": [
"BRANDON KONKLE"
],
"content": [
"Part 2: Data and Graphs\n\nWelcome back to my series covering Async GraphQL in Rust! This series is aimed at intermediate Rust developers who have grasped the basics and are ready to build production-ready server applications. Today's entry will cover database access with SeaORM, related data, entity services to make use of the data access code, GraphQL resolvers to connect those services to outside requests, the request context provided by async-graphql, and pulling it all together with Warp to handle HTTP requests.\n\nI'll be approaching the application from the inside out, introducing the different pieces that work together to create a full-featured GraphQL API that is high performance and easily testable. These pieces are intended to work in a multithreaded context, because Warp and Hyper spawn threads to handle multiple requests in parallel. Because of this, I'll touch on Rust's shared ownership and data synchronization tools. The full code for the example project can be found on Github here.\n\nLet's get started!\n\nDatabase Models\n\nAs I mentioned in my previous article, I originally started out with SQLx, a pure Rust SQL toolkit made from the start to support async. It includes a unique compile-time checker based on Rust macros, which is a powerful feature that enables compile-time code generation that is highly flexible and tightly integrated with the build system. The code generated by macros is type-checked along with the rest of your code, and it can even do things like execute build-time routines and make network calls. SQLx uses it to connect to an active SQL database and run a variety of checks based on the SQL queries you write. It is able to check syntax, infer types, and a whole lot more — all during a standard Rust build with warnings and errors that can be easily displayed in your IDE just like other warnings or lint checks. I'm quite comfortable with raw SQL, so this seemed like a great option without the overhead of learning a new ORM and accepting the limitations it would impose.\n\nThis build-time static checking is indeed powerful, but it comes with some drawbacks. The first one is that you need an active database connection in order to build. This can be disabled with an environment variable flag in order to play nicely with CI tests, but it definitely adds an additional hoop to jump through when developing locally. Beyond that minor tradeoff, which wouldn't be a dealbreaker for me on its own, it also makes dynamic queries exceedingly hard. This became the most difficult thing for me to work around as I set out to implement a very flexible GraphQL schema that allows client applications to decide how they want to filter and order the data they are requesting.\n\nA query may want to use different properties for filtering the data that is selected, finding rows with a particular value in a user_id field or with a particular status. For example, because of the way the SQLx queries are statically checked at build time it wasn't easy to include \"where\" clauses in some cases and exclude them in other cases.\n\nSeaORM\n\nTo better support the kind of dynamic queries I want in my GraphQL API I took the plunge into the land of ORMs (object-relational mappers), selecting an up-and-coming library based on SQLx with strong unit testing functionality to make up for the lack of those static checks. The most popular ORM in the Rust ecosystem — Diesel — isn't the one that I chose, however. It doesn't provide the same kind of first-class async support that SQLx does, and it uses a domain-specific language for the model schema. I pulled in SeaORM instead, which is a pure Rust library that derives what it needs based on plain Rust structs.\n\nTo kick things off, I'll start with one of the simpler database entities that I model with SeaORM in my GraphQL API — \"Shows\". In the hypothetical Caster app, a Show has many Episodes that hosts and co-hosts participate in to discuss various topics. This is a simple Model with no foreign keys — Episodes are tied to a Show via the \"show_id\" foreign key field on the Episode model.\n\nDatabase Migrations\n\nTo start with, there are a series of database schema migrations defined in the \"migrations\" folder at the top level of the project. These are SQL files generated by the SQLx CLI:\n\nsqlx migrate add users_and_profiles\njsxCopy to clipboard\n\nAs I mentioned previously I am comfortable with SQL, so instead of using the built-in migrations that SeaORM provides I like to write migrations by hand. I typically use the excellent desktop tool DataGrip, and I like the aligned format that it uses when generating DDL statements:\n\ncreate table users\n(\n id text default gen_random_ulid() not null\n primary key,\n created_at timestamp(3) default CURRENT_TIMESTAMP not null,\n updated_at timestamp(3) default CURRENT_TIMESTAMP not null,\n\n username text not null,\n is_active boolean default true not null\n);\n\ncreate unique index users__username__unique\n on users (username);\n\ncreate trigger sync_users_updated_at before update on users for each row execute procedure sync_updated_at();\njsxCopy to clipboard\n\nMy IDs are text fields, and I use a custom gen_random_ulid() function to generate Universally Unique Lexicographically Sortable Identifiers. I use a sync_updated_at function to keep my updated_at fields up to date with a Postgres trigger.\n\nSee the migrations directory for more examples.\n\nTo run these migrations, I run cargo make db-migrate, which is a build target within the Makefile.toml. This is used by cargo-make, a great build tool to enhance Cargo for more workflows.\n\nThe Show Model\n\nTo define a SeaORM Model, I create a Rust file called show_model.rs, which is held within the libs/shows folder that contains the caster_shows crate. A \"crate\" is a Rust package with its own \"Cargo.toml\" file that defines dependencies. In the Caster application, there is a caster_api crate held in apps/api that uses Cargo's workspaces feature to pull in resolvers, services, models, and more from crates within the libs/ folder.\n\nAt a minimum SeaORM expects a struct called Model for each entity, as well a Relation struct defining relation accessors, and an ActiveModelBehavior trait implementation for the ActiveModel struct that is derived by \"DeriveEntityModel\". The whole file can be viewed on Github here.\n\nHere are the important parts to focus on now:\n\n/// The Show GraphQL and Database Model\n#[derive(DeriveEntityModel, Deserialize, Serialize)]\n#[sea_orm(table_name = \"shows\")]\npub struct Model {\n /// The Show id\n #[sea_orm(primary_key, column_type = \"Text\")]\n pub id: String,\n\n /// The date the Show was created\n pub created_at: DateTime,\n\n /// The date the Show was last updated\n pub updated_at: DateTime,\n\n /// The Show title\n #[sea_orm(column_type = \"Text\")]\n pub title: String,\n\n /// An optional Show summary\n #[sea_orm(column_type = \"Text\", nullable)]\n pub summary: Option