{ "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: \n \n );\n}\njavascriptCopy to clipboard\n\nThis example only scratches the surface of the Hooks API—we could go into far more detail, but the API documentation is incredibly thorough and does a better job of explaining its capabilities than we could in such a short time. For now, we're going to focus on our first impressions.\n\nFirst Impressions\n\n“Whoa. Sweet!” -Jani, probably\n\nYou can call a method in a component function and suddenly that function becomes reactive to updates caused by changes in internal or external state? Rad!\n\nIn many ways Hooks are the most “React-esque” feature we’ve seen in several years—they have that trademark React quality of being simple to use, but extremely clever underneath. Simply by calling a method we can make a function component reactive to changes in internal or external state? Sweet.\n\nOn its face, the Hooks API feels more ergonomic and practical than other common approaches to lifecycle management—even those we’re big fans of like recompose, reselect, and Redux. It lets us avoid massive trees of wrapper components, bundle-bloating third-party libraries, and confusing generator stack traces while debugging, while getting most of the same benefits.\n\nBring Your Own Hooks\n\nAbove we mentioned just two hooks: useState and useEffect. In fact, there are several others, such as useContext (which exposes an interface to the Context API), and useReducer (which lets you manage component state with Redux-style reducers.)\n\nConsidered on their own these are all well and good, but what really excites us is the ability to create what React calls “Custom Hooks”—functions that “package together” invocations of several related hooks for use as an atomic unit elsewhere. For instance, you might combine the useState and useEffect hooks to create your own useAPI hook, which fetches, stores, and manipulates data from an API—all while providing a single, clean interface to users.\n\nThis looks like a clean abstraction for modeling shared functionality in your application, and the the possibilities really explode once you realize that we’ll be able to publish these hooks as open source libraries! Unlike previous iterations of shareable component behaviors, custom hooks are easy to use and easy to compose: just call useMyHook in a component. It seems likely that hooks could solve the problems that mixins, higher-order components, and “render props” tried to solve, but never could because of their lack of composability, ergonomics, or both.\n\nHow does it actually work?\n\nWhile reading the code sample above, you may have noticed something...odd. We never actually defined a state variable anywhere—we simply used it as if it had always existed. What gives?\n\nBehind the scenes, React “knows” that it should associate a given call to Hook functions with the React component it’s rendering, and the order in which those hook functions are called lets React “remember” which hooks are which across several render passes. (One way to visualize this is by imagining each call to useState creating a new “memory cell” to store the actual underlying value.)\n\nTradeoffs\n\nFirst and foremost, hooks can only be used within function components, which creates some amount of friction if you need to share behavior between custom hooks and class components.\n\nSecondly, because React relies on hooks being called in a consistent order on every render pass, there are strict limitations on how they must be called within a function component—namely, the same hooks must be called in the same order, on every render pass, every time. This means that calling hooks within (for instance) conditionals, loops, or try-catch blocks is an explicit misuse of the feature.\n\nAlthough this rule is simple to follow, React has no way to prevent it without the use of out-of-band techniques (although, to its credit, the Hooks API ships with an ESLint plugin to help you remember). Nevertheless, this is an additional, subtle detail to remember, which has the potential to trip up beginners and experts alike, and we can’t help but imagine that bugs related to this behavior are going to be tricky to chase down.\n\nAre function components really functional?\n\nUntil now React’s function components have served as a clear complement to class components—stateless and referentially transparent, where class components were typically stateful and side-effectful. However, with the introduction of hooks (and Suspense), the line blurs—we can no longer identify “stateless, functional components” at a glance. Now it’s necessary to understand the behaviors associated with the hook (or hooks, in the plural) a component uses, and especially the conditions under which those behaviors may cause the component to re-render.\n\nBut, with that said...does it really matter? After all, functional programming doesn’t necessarily dictate that functions must be completely side-effect free, but rather that any side-effects must be managed in a consistent way, which is exactly what the Hooks API does.\n\nBecause React fully controls when your function is called it knows how to associate an invocation of hook functions with its invocation of your “component function”, and defines a strict set of semantics for doing so. Because hooks require us to declaratively define our data dependencies and side effects, they’re still easy to reason about, and even easier for static code analyzers like Flow or TypeScript to validate.\n\nWith this in mind, hooks feel like a pragmatic solution to a tricky problem, but it remains to be seen if this design decision is worth the departure from the widespread, existing mental model.\n\nSummary\n\nWe’re excited about the possibilities the new React Hooks API offers, and we’re looking forward to experimenting with them in the coming days and weeks! We expect that (along with the community at large) we’ll uncover answers to the questions raised here, and we can’t wait to see the new patterns and solutions that shake out.\n\nAll things considered, this feels like a huge step in the direction of a simpler, cleaner API for React components. Although class-based components will continue to be supported for the time being, we have the distinct impression that the community will embrace “Hooked-up” function components, because let’s face it—writing apps is a lot more fun without all the syntax and ceremony!" ], "categories": { "primary": "frontend", "others": [ "design", "product" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-finding-webpack-duplicates-with-inspectpack-plugin": { "href": "https://nearform.com/digital-community/finding-webpack-duplicates-with-inspectpack-plugin", "postType": "blog", "slug": "digital-community-finding-webpack-duplicates-with-inspectpack-plugin", "date": "2018-10-31", "title": "Finding and fixing duplicates in webpack with Inspectpack", "authors": [ "RYAN ROEMER" ], "content": [ "Duplicated code from dependencies is possibly the most needlessly endemic problem confronting modern web application bundles, making them bigger and slower. And, diagnosing how the usual suspects, npm and webpack, conspire together to include more than you need can be incredibly difficult and painful.\n\nIn this post we will do a deep dive into various ways that dependencies can unnecessarily bloat bundles to better understand the problem space. Then, we will introduce the Inspectpack DuplicatesPlugin -- a power tool to help you identify nuanced, actionable information about wasted bytes from dependencies in your webpack bundles.\n\nDependencies, Bundles, and Duplicates\n\nTo begin to understand how duplicated dependencies hurt modern frontend bundles, we need to look at the npm and webpack projects, and how they work together to produce a rising share of the ecosystem's delivered web applications.\n\nDependencies\n\nModern frontend web applications are rarely written from scratch. Most JavaScript-based applications rely on the expansive world of open source libraries, in particular those published as packages to the npm registry. With just a few additions to your package.json file, you can instantly get any number of libraries to help your application with anything from date formatting to full-blown application frameworks like React!\n\nBundles\n\nTransforming your application code and dependencies into a web application capable of running in a browser usually involves a bundling tool, the most popular of which is webpack. Webpack ingests your code and dependencies, and packages all of the necessary files into 1+ \"bundle\" files that together are downloaded to end-user browsers.\n\nDuplicates\n\nUnfortunately, this power and flexibility comes with costs and complexities. Dependencies often have dependencies of their own, which makes analysis difficult for humans trying to optimize bundles and bundling tools trying to efficiently stitch code together.\n\nAll too often bundles suffer from one or more of the following duplication situations:\n\nIdentical code sources from the same package: Your application bundle ends with up 2+ versions of a file included that are byte-for-byte identical. E.g., you have the code from file lodash@4.2.3/get.js literally included twice in your final bundle.\nSimilar code files from different packages: Your application bundles two files with the same package name and file path that function similarly, but are not byte-for-byte identical. E.g., your bundle has code from the files lodash@3.1.0/get.js and lodash@4.2.3/get.js that is functionally the same, but not the actual identical code.\nIdentical code sources from different packages: This time you have different packages, but the specific file included in your bundle hasn't changed across the versions and is byte-for-byte identical. E.g., your bundle has code from the files lodash@3.1.0/get.js and lodash@4.2.3/get.js that is identical (although code in other unused files in the packages may differ).\n\nIn each of these scenarios your bundle ends up with more code than necessary because the same file (identical code or not) should be collapsed to a single version. To see how and why this can happen, it helps to review how npm and webpack work.\n\nUnderstanding npm and webpack\n\nLet's begin with a common frontend build situation wherein npm (or yarn) \"get\" code dependencies from the Internet and webpack then \"puts\" code sources in an application bundle. (Note that npm and webpack have changed how they handle duplicated packages and code, so we're going to cover the mechanics of each over time.)\n\nWe will work through a simple hypothetical application with a lot of different npm and webpack scenarios. You can find all of the discussed examples in a GitHub repository, complete with node_modules and application bundles placed into git source for easier online review.\n\nnpm Dependencies Installation\n\nThe npm tool first reads dependencies from the package.json:dependencies (and devDependencies for development) field. Let's consider an application like this:\n\n// package.json\n{\n \"name\": \"my-app\",\n \"dependencies\": {\n \"lodash\": \"^4.1.0\",\n \"one\": \"1.2.3\",\n \"two\": \"2.3.4\"\n }\n}\njsCopy to clipboard\n\nwith the one and two packages that \"resolve\" to match those dependencies. npm then looks at the resolved packages and recursively resolves the dependencies of each, essentially creating a dependency tree (or even abstractly a graph if there are circular dependencies). Here, we have:\n\n// node_modules/one/package.json\n{\n \"name\": \"one\",\n \"dependencies\": {\n \"lodash\": \"^4.0.0\"\n }\n}\n\n// node_modules/two/package.json\n{\n \"name\": \"two\",\n \"dependencies\": {\n \"lodash\": \"^3.0.0\"\n }\n}\njsCopy to clipboard\n\nSo, what does our dependency tree look like? It's a bit complicated because the first-level dependencies in the root package like \"lodash\": \"^4.1.0\" get resolved to a single package like lodash@4.2.3 and downloaded. Only after this are the resolved package's dependencies read and semver ranges resolved to actual packages recursively. This means that our \"abstract\" dependency tree actually is really a mix of concrete resolutions of files in the resolution at a given point in time.\n\nAside: lodash is a real package with a get method. We will use some fictional implementations in our examples. one and two are fabricated packages. We picked lodash as a fictionalized example because it is so popular that there is a decent chance that a bundle with duplicates has some lodash duplicates.\n\nLet's also define some quick terms that we'll use throughout the rest of this post:\n\n\"resolved\": We start with a package name (lodash) that has a declared version constraint (^4.1.0). During an npm/yarn install, one early step is to take that constraint and resolve it to a single version in the registry that can be downloaded (lodash@4.2.3).\n\"installed\": Resolved packages are downloaded, but not necessarily immediately placed in their final installation paths on disk in node_modules. Both npm and yarn reserve the right to move things around and flattened installed packages to single on-disk versions, etc. Only when npm or yarn finish the installation command do we say a package is actually installed at a given location on disk (e.g., node_modules/lodash).\n\"depended\": We use the term \"depended\" to describe a logical, unique path in the abstract dependency tree that causes a package to be included. In our example above, we have three packages depending on lodash (my-app, one, and two).\n\nFor the present example, our abstract depended tree (with resolved versions in comments on the right) is:\n\n# Depended # Resolved\n# =================== # ========\n- my-app:\n - lodash@^4.1.0 # 4.2.3\n - one@1.2.3: # 1.2.3\n - lodash@^4.0.0 # 4.2.3\n - two@2.3.4: # 2.3.4\n - lodash@^3.0.0 # 3.1.0\nyamlCopy to clipboard\n\nSo, what happens when we install this on disk via npm install or yarn install? Well, the answer depends on which version of npm / yarn you use.\n\nOld npm\n\nOlder versions of npm used to install dependencies exactly as would match the abstract dependency tree, namely:\n\n# Installed # Resolved\n# =================== # ========\nmy-app/node_modules\n lodash # 4.2.3\n one # 1.2.3\n node_modules\n lodash # 4.2.3\n two # 2.3.4\n node_modules\n lodash # 3.1.0\nbashCopy to clipboard\n\nEven though lodash@4.2.3 resolves to a single package version, it is installed twice.\n\nFlattening with modern npm\n\nIn recognition of issues with wasted disk space and bloated frontend bundles, modern versions of npm and yarn implement a scheme of \"flattening\" the installed node_modules dependency tree. Following the Node.js require resolution algorithm, some of these dependencies can be collapsed to one package, within an acceptable semantic version range. (The actual mechanics of flattening and Node.js require resolution are complex and out of scope for this article -- we're just going to gloss over the subject.)\n\nIn the above example, resolved version 4.2.3 of lodash is compatible with both ~/lodash@^4.1.0 and ~/one@1.2.3/~/lodash@^4.0.0. Thus, by using a flattening installer, you could end up with an installed node_modules tree like this:\n\n# Installed # Resolved\n# =================== # ========\nmy-app/node_modules\n lodash # 4.2.3 (for `my-app` _and_ for `one`)\n one # 1.2.3\n two # 2.3.4\n node_modules\n lodash # 3.1.0\nbashCopy to clipboard\n\n~ Note: Following a webpack convention, we use the ~ character to mean the node_modules directory. The two can be used interchangeably.\n\nUn-flattenable dependencies in modern npm\n\nBut, let's not get our hopes up too quickly. Even with modern npm, identical packages may still not be able to be flattened.\n\nIf our abstract dependency tree changes to:\n\n# Depended # Resolved\n# =================== # ========\n- my-app:\n - lodash@^4.1.0 # 4.2.3\n - one@1.2.3: # 1.2.3\n - lodash@^3.0.0 # 3.1.0 (CHANGED!)\n - two@2.3.4: # 2.3.4\n - lodash@^3.0.0 # 3.1.0\nyamlCopy to clipboard\n\nThe root install will be ~/lodash at 4.2.3 with two identical 3.1.0 versions like:\n\n# Installed # Resolved\n# =================== # ========\nmy-app/node_modules\n lodash # 4.2.3\n one # 1.2.3\n node_modules\n lodash # 3.1.0\n two # 2.3.4\n node_modules\n lodash # 3.1.0\nbashCopy to clipboard\n\nTogether, these scenarios outline different ways that npm can place packages on disk in node_modules. Once there, how do depended-on code files end up in your frontend application?\n\nThe answer depends on your bundling tool. In this post, we'll focus on the widely-used webpack project.\n\nWebpack bundling\n\nA Webpack build starts at an entry point, which is typically your application code. It traverses all module imports (require or import) recursively to ingest code from your app or node_modules, process it, and concatenate everything into one or more bundles. (An oversimplification, but bear with us here.)\n\nLet's say we have an application comprising of:\n\n// my-app/index.js (entry point)\nconst { get } = require(\"lodash\"); // lodash@^4.1.0\nconst { getOne } = require(\"one\");\nconst { getTwo } = require(\"two\");\n\nconst OBJ = { one: { two: \"hi\" } };\n\nconsole.log(\"Get from lodash\", get(\"one.two\", OBJ)); // => `\"hi\"`\nconsole.log(\"Get from one\", getOne(OBJ)); // => `{ two: \"hi\" }`\nconsole.log(\"Get from two\", getTwo(OBJ)); // => `undefined`\njsCopy to clipboard\n// node_modules/one/index.js\nconst { get } = require(\"lodash\"); // lodash@^4.0.0\n\nmodule.exports = {\n getOne: (obj) => get(\"one\", obj)\n};\njsCopy to clipboard\n// node_modules/two/index.js\nconst { get } = require(\"lodash\"); // lodash@^3.0.0\n\nmodule.exports = {\n getTwo: (obj) => get(\"two\", obj)\n};\njsCopy to clipboard\n\nWith this setup, we will definitely end up with a bundle that includes the files:\n\nmy-app/index.js\nnode_modules/one/index.js\nnode_modules/two/index.js\n\nBut the big question is: what files from lodash end up in our final webpack bundle?\n\nAnd, of course, the answer is: it's complicated. It depends on how npm installed the packages into node_modules and how webpack behaves.\n\nOld webpack\n\nThe original version of webpack came with the webpack.optimize.DedupePlugin plugin. The plugin replaces subsequent identical sections of an original code source with a pointer reference. Configuring the plugin is as simple as:\n\n// webpack.config.js\nmodule.exports = {\n plugins: [\n new webpack.optimize.DedupePlugin()\n ]\n};\njsCopy to clipboard\n\nand a bundle will conveniently omit all extraneous identical code sources using any version of npm or yarn.\n\nNew webpack\n\nThe DedupePlugin was removed in webpack@3 with an indication that modern npm flattening should be sufficient to collapse duplicates in the installed node_modules folder such that Webpack would no longer have to do anything.\n\n... but is that really the case?\n\nInto the weeds with various duplication scenarios\n\nLet's look at a few scenarios that might arise in bundles using old/new npm and old/new webpack. (See our examples repository for the full inputs and build outputs.)\n\nOld npm\nNew npm flattened\nNew npm unflattened\nNew npm flattened with identical sources\n\nThese scenarios use the application discussed above that imports get() from lodash, getOne() from one, and getTwo() from two. The contrived getOne() and getTwo() methods use another import of lodash at differing versions. Although lodash has a real get() method, instead we will make up two hypothetical versions as follows:\n\nlodash@3.1.0\n\nmodule.exports = {\n // A very, very rough and naive object getter with forEach.\n get: (path, obj) => {\n let memo = obj;\n path.split(\".\").forEach((key) => {\n memo = memo === undefined ? memo : memo[key];\n });\n\n return memo;\n }\n};\njsCopy to clipboard\n\nlodash@4.2.3\n\nmodule.exports = {\n // A very, very rough and naive object getter with reduce.\n get: (path, obj) => path.split(\".\").reduce((memo, key) => {\n return memo === undefined ? memo : memo[key];\n }, obj)\n};\njsCopy to clipboard\nScenario 1 - Old npm\n\nOld npm installs the node_modules folder something like:\n\n# Installed # Resolved\n# =================== # ========\nmy-app/node_modules\n lodash # 4.2.3\n one # 1.2.3\n node_modules\n lodash # 4.2.3\n two # 2.3.4\n node_modules\n lodash # 3.1.0\nbashCopy to clipboard\n\nOn disk, we have identical code sources at:\n\nnode_modules/lodash/index.js (4.2.3)\nnode_modules/one/node_modules/lodash/index.js (4.2.3)\n\nand similar code files at:\n\nnode_modules/two/node_modules/lodash/index.js (3.1.0)\n\nLet's look at how old and new webpack bundle these:\n\nScenario 1.a - Old npm + old webpack\n\nOld webpack's DedupePlugin deduplicates the identical code sources so that only 1 code instance remains in our bundle. Looking at these lines of the bundle:\n\n/* 3 */\n/*!*****************************************!*\\\n !*** ./old-npm/~/one/~/lodash/index.js ***!\n \\*****************************************/\n1,\njsCopy to clipboard\n\ninstead of real code, there is an integer 1 which points to the full identical source at index 1 in the bundle which corresponds to node_modules/lodash/index.js.\n\nAssessment: Examining our potential duplication problems, our bundle stacks up as follows:\n\nIdentical code sources from the same package: None. The plugin deduplicates.\nSimilar code files from different packages: Duplicates. The deduplicated file lodash@4.2.3/index.js is similar in functionality to the different file lodash@3.1.0/index.js. If only one of the two files were chosen we would save the other file's byte size.\nIdentical code sources from different packages: N/A. Our example doesn't have identical sources across different packages. But if it did, the plugin would deduplicate them.\nScenario 1.b - Old npm + new webpack\n\nModern webpack doesn't deduplicate, so our bundle contains the following full code sources:\n\nnode_modules/lodash/index.js (4.2.3)\nnode_modules/one/node_modules/lodash/index.js (4.2.3)\nnode_modules/two/node_modules/lodash/index.js (3.1.0)\n\nAssessment:\n\nIdentical code sources from the same package: Duplicates. No webpack plugin deduplication.\nSimilar code files from different packages: Duplicates. Same as scenario 1.a.\nIdentical code sources from different packages: N/A. Our example doesn't have identical sources across different packages. But if it did, they would still remain as duplicates because modern webpack doesn't deduplicate identical sources.\nScenario 2 - New npm flattened\n\nLet's upgrade to a modern npm version or any version of yarn. Both package managers now inspect the entire dependency tree and \"flatten\" dependencies to single packages higher up in node_modules whenever they can.\n\nAs mentioned above, this translates to an installed layout of:\n\n# Installed # Resolved\n# =================== # ========\nmy-app/node_modules\n lodash # 4.2.3 (for root _and_ for `one`)\n one # 1.2.3\n two # 2.3.4\n node_modules\n lodash # 3.1.0\nbashCopy to clipboard\n\ncollapsing the dependencies for lodash@4.2.3 to a single on-disk location.\n\nThus, we end up with no identical code sources and two similar code files:\n\nnode_modules/lodash/index.js (4.2.3)\nnode_modules/two/node_modules/lodash/index.js (3.1.0)\n\nLet's turn to webpack and bundling this installation.\n\nScenario 2.a - New npm flattened + old webpack\n\nOld webpack's DedupePlugin doesn't have anything to do this time, as there are no identical duplicate code sources.\n\nAssessment: Our bundle has the following issues:\n\nIdentical code sources from the same package: None. npm was able to flatten away our identical sources by collapsing lodash@4.2.3.\nSimilar code files from different packages: Duplicates. The different files lodash@4.2.3/index.js and lodash@3.1.0/index.js waste bytes if a single file could be used instead.\nIdentical code sources from different packages: N/A. Same as scenario 1.a.\nScenario 2.b - New npm flattened + new webpack\n\nAs the old DedupePlugin never came into play in this scenario, modern webpack has pretty much exactly the same substantive bundle as in scenario 2.a with the same advantages and disadvantages.\n\nScenario 3 - New npm unflattened\n\nUnfortunately, modern npm and yarn cannot flatten all semver-compatible packages because they are ultimately bound by the rules of the Node.js require resolution algorithm. Thus, if we have a slight change in dependencies (the one package now depends on lodash@3.1.0.), we end up with an installed on-disk layout of:\n\n# Installed # Resolved\n# =================== # ========\nmy-app/node_modules\n lodash # 4.2.3\n one # 1.2.3\n node_modules\n lodash # 3.1.0 (Cannot be collapsed)\n two # 2.3.4\n node_modules\n lodash # 3.1.0 (Cannot be collapsed)\nbashCopy to clipboard\n\nThus, we have identical code sources:\n\nnode_modules/one/node_modules/lodash/index.js (3.1.0)\nnode_modules/two/node_modules/lodash/index.js (3.1.0)\n\nand similar code files:\n\nnode_modules/lodash/index.js (4.2.3)\nScenario 3.a - New npm unflattened + old webpack\n\nOld webpack's DedupePlugin is able to deduplicate the identical code sources across one and two's lodash@3.1.0. The code from two is collapsed to a reference integer 3 in these lines.\n\nAssessment: Our bundle stacks up as follows:\n\nIdentical code sources from the same package: None. The plugin deduplicates.\nSimilar code files from different packages: Duplicates. The deduplicated file lodash@3.1.0/index.js is similar to lodash@4.2.3/index.js, but both remain in the bundle.\nIdentical code sources from different packages: N/A. Same as scenario 1.a.\nScenario 3.b - New npm unflattened + new webpack\n\nModern webpack doesn't deduplicate, so we end up with full code sources of:\n\nnode_modules/lodash/index.js (4.2.3)\nnode_modules/one/node_modules/lodash/index.js (3.1.0)\nnode_modules/two/node_modules/lodash/index.js (3.1.0)\n\nin our bundle pretty much analogously to scenario 1.b. Ultimately, modern npm that cannot flatten is equivalent to old npm that didn't even try.\n\nScenario 4 - New npm flattened with identical sources\n\nWe return to our original package version setup, but introduce a different twist: now lodash@3.1.0/index.js and lodash@4.2.3/index.js are identical code sources. Both use the reduce version of our get function.\n\nWe end up with the same installed layout as scenario 1:\n\n# Installed # Resolved\n# =================== # ========\nmy-app/node_modules\n lodash # 4.2.3 (for root _and_ for `one`)\n one # 1.2.3\n two # 2.3.4\n node_modules\n lodash # 3.1.0\nbashCopy to clipboard\n\ncollapsing the dependencies for lodash@4.2.3 to a single on-disk install.\n\nSo now we end up with no similar code files and 2 identical code sources at:\n\nnode_modules/lodash/index.js (4.2.3)\nnode_modules/two/node_modules/lodash/index.js (3.1.0)\n\nLet's see how different webpacks handle this final scenario:\n\nScenario 4.a - New npm flattened with identical sources + old webpack\n\nOld webpack's DedupePlugin is able to deduplicate the identical code sources across the flattened lodash@4.2.3/index.js (for root and one) and the different package (but identical code source) of lodash@3.1.0/index.js from two. The identical code source from two's dependency is collapsed to a reference integer 1 in these lines.\n\nAssessment: Our bundle has no duplicates anywhere!\n\nIdentical code sources from the same package: None. New npm / yarn takes care of this.\nSimilar code files from different packages: N/A. The scenario has no similar-but-not-identical code sources.\nIdentical code sources from different packages: None. The old webpack DedupePlugin is now able to collapse these, even across different packages.\nScenario 4.b - New npm flattened with identical sources + new webpack\n\nAlthough modern npm / yarn take care of the flattened packages of lodash@4.2.3/index.js, there is a missed opportunity for the identical code source in lodash@3.1.0/index.js.\n\nAssessment: Our bundle now has different types of duplicates from previous scenarios:\n\nIdentical code sources from the same package: None. npm was able to flatten away our identical sources by collapsing lodash@4.2.3.\nSimilar code files from different packages: N/A. The scenario has no similar-but-not-identical code sources.\nIdentical code sources from different packages: Duplicates. Without old webpack deduplication, we end up with identical code across the two lodash versions in our bundle.\nFinding and fixing duplicates in real applications\n\nIt takes a surprisingly large amount of background to dig into even the most common cases of duplicate dependency creep in your bundle. We have reviewed how old and modern npm and webpack together transform source code into a full application bundle. We've investigated just a few of the many, many scenarios that demonstrate how unnecessary dependency duplicates can produce a larger bundle than you need. And, we've identified some of the things that influence duplicates, namely:\n\nWhere dependencies are coming from;\nHow npm has placed the dependencies on disk;\nHow webpack has included code from dependencies into the bundle.\n\nThe tough part here is that so far, we've only analyzed a truly trivial application via human inspection of the actual application bundle. Nearly all real applications will be significantly larger and more complex, all but foreclosing such manual analysis.\n\nHow do we apply this for reals?\n\nReal-world development and production workflows all but require some baseline of programmatic tooling support for these issues.\n\nOn the positive side, there are a multitude of different webpack analysis tools that break down the various parts of the webpack compilation process. A good starting point is SurviveJS' dedicated page for build analysis with a subsection on duplicates analysis.\n\nNonetheless, while many of these projects can together provide a lot of information about every part of webpack compilation and your bundle, finding a dedicated report that is specifically actionable for reducing duplicates can remain challenging.\n\nIntroducing the Inspectpack DuplicatesPlugin\n\nThe Inspectpack project has been analyzing Webpack innards for quite some time. It's the information engine behind the popular webpack-dashboard, which provides a captive terminal display with a NASA-like control center. Inspectpack also provides a powerful CLI tool that consumes a Webpack stats object from disk to report on size, duplicates, and package version information in a variety of formats (text, TSV, JSON).\n\nAt its core, the Inspectpack library can efficiently discover code duplicates as well as inspect installed node_modules directories and infer how both npm and webpack impact a final production application bundle. We're very pleased to announce that we have taken this power and concentrated it into a new easy-to-use webpack plugin -- the Inspectpack DuplicatesPlugin.\n\nWebpack integration\n\nFollowing the online guide, first install the plugin and add it to your development dependencies:\n\n$ npm install --save-dev inspectpack # OR\n$ yarn add --dev inspectpack\nbashCopy to clipboard\n\nThen, integrate the plugin into the plugins field of your webpack configuration file:\n\n// webpack.config.js\nconst { DuplicatesPlugin } = require(\"inspectpack/plugin\");\n\nmodule.exports = {\n plugins: [\n new DuplicatesPlugin({\n // Emit compilation warning or error? (Default: `false`)\n emitErrors: false,\n // Display full duplicates information? (Default: `false`)\n verbose: false\n })\n ]\n};\njsCopy to clipboard\n\nOur options are as follows:\n\nemitErrors: By default (false), the DuplicatesPlugin emits duplicate issues to compilation.warnings. If this value is true, then the plugin will emit issues to compilation.errors which will fail typical modern webpack builds.\nverbose: By default (false), the report only shows package information for packages that have files that end up duplicated somewhere in a given bundle. Setting this value to true additionally displays information for duplicated files, including file size and type (identical (I) or similar (S)).\n\nAnd that's pretty much it. It's worth noting that the plugin supports every version of webpack (currently 1-4) and is fully tested on each version!\n\nDiscovering and understanding duplicates\n\nNow that we have integrated the plugin, let's try it out!\n\nThe README documentation provides a guide to understanding plugin reports, but it's probably easier to just see it in practice. Picking an exemplary situation, we return to scenario 3.b, which uses modern npm with unflattened dependencies.\n\nDefault report\n\nRunning webpack with the default options (DuplicatesPlugin()) produces the following report:\n\nOur report is a bit terse, but contains a summary of the information from our previous, manual analysis:\n\nFor duplicate files, we have 2 similar and 3 similar or identical code sources. We also get a summary of the total number of bytes at issue. For us here, that's 703 for 3 code sources, which we could presumably roughly cut to a third the size if we fix the duplicates.\nFor packages, we have 1 unique package (lodash) with 2 resolved versions (3.1.0, 4.2.3), 3 installed paths on disk(~/one/~/lodash, ~/two/~/lodash, ~/lodash), and 3 depended abstract paths (starting from root application, one, and two).\n\nWe then get a per-asset report (just bundle.js in our case) with a per-unique-package drill-down of the form:\n\n{PACKAGE_NAME} (Found {NUM} resolved, {NUM} installed, {NUM} depended. Latest version {VERSION}.)\n {INSTALLED_PACKAGE_VERSION NO 1} {INSTALLED_PACKAGE_PATH NO 1}\n {DEPENDENCY PATH NO 1}\n {DEPENDENCY PATH NO 2}\n ...\n {INSTALLED_PACKAGE_VERSION NO 1} {INSTALLED_PACKAGE_PATH NO 2}\n ...\n {INSTALLED_PACKAGE_VERSION NO 2} {INSTALLED_PACKAGE_PATH NO 3}\n ...\njsCopy to clipboard\n\nOur report contains a package summary for lodash as it is the only duplicate-producing package in the scenario. Then we drill down into each installed version / path, and further drill down into each depended graph.\n\nThat's all of the package information we manually figured out before! But what if we want a bit more information about the duplicate code sources?\n\nVerbose report\n\nEnter the verbose report. Configuring the option DuplicatesPlugin({ verbose: true }) will additionally produce duplicate code source information:\n\nNow, in addition to our dependency graphs, we get a report of each duplicated code source path, a note indicating if it is identical (I) to some other file in the bundle or merely similar (S), and the file byte size (e.g., 249 and 205 bytes respectively). As discussed previously, we have:\n\nIdentical code sources from the same package: Duplicates. We have ~/one/~/lodash/index.js and ~/two/~/lodash/index.js from separate lodash@3.1.0 installations.\nSimilar code files from different packages: Duplicates. Both of these lodash@3.1.0 files are similar to ~/lodash/index.js from lodash@4.2.3 in the bundle.\nAssessing duplicates\n\nWith DuplicatesPlugin added to our webpack configuration file, we now have a detailed assessment of how npm dependencies are installed and what webpack ends up placing in the bundle. More specifically, we can answer these important questions:\n\nWhat package versions were resolved?\nWhere were the resolved packages installed on disk in node_modules?\nWhat parent packages depended on a given package to cause it to be resolved and installed?\nWhich duplicate files from a package ended up being included in the final application bundle?\n\nNote - DedupePlugin: The DuplicatesPlugin does not specifically detect that old webpack's DedupePlugin has programmatically collapsed a duplicate code source. Given that very few folks use a pre-webpack@3, we chose to omit a special case report (although we could if there was community demand).\n\nFixing duplicates\n\nSo, now that we can automatically report on duplicate dependencies, how do we fix them? How do we smash our duplicates?\n\nStaying true to our running theme, the answer is: it's complicated.\n\nThe Inspectpack documentation has an introductory guide discussing how to fix bundle duplicates.\n\nSummarizing these for convenience, we first look to meta-level tips on prioritization and focus:\n\nLook first to identical code sources: When choosing what to do first, a good bet is to focus on literally identical code duplicated in your bundle and dependencies. Although not guaranteed to be collapsible (due to considerations like other depended-on code), it's a great first stop.\nChange dependencies in your root package.json: Anything you can change directly in your applications package.json is likely to have the least unintended consequences.\nCritically examine and scrutinize your dependencies: An easy win is always to just have less code. Look at your dependency tree. Do you really need all of the bundled packages? Keep a critical eye out for packages that have lots of transitive other dependencies, prioritize based on total size brought in by a package (using tools like the awesome webpack-bundle-analyzer), and see if you can live without the dependency or find a smaller, equivalent replacement.\n\nUnfortunately, many times you won't be able to harmonize and collapse your abstract dependency graph / installed node_modules tree easily. The next step is to potentially force packages and code sources to collapse to single entities, even if the normal rules of npm/yarn/webpack would prevent it.\n\nSet resolve.alias in your webpack configuration: Direct webpack to use a single package when resolving dependencies that would follow normal (multi-package) resolution.\nSet the resolutions field with yarn: Direct yarn (not available on npm) to resolve packages to a single version, overriding what is normally considered an allowed resolution and node_modules installation.\n\nThese are essentially sledgehammer approaches for otherwise intractable duplicate situations, but because they can violate the assumptions and rules of semantic versioning, your application is potentially at risk for breaking behavior and bugs.\n\nAll in all, like most web application optimization work, reducing duplicate dependencies is more of an art than science. The above tips are just starting points for an overall effort that digs deep into why your bundle is so large and how to most effectively leverage this information to reduce its size.\n\nConclusion\n\nAfter our (rather lengthy) deep dive, we have now uncovered more of how and why duplicates can occur in your application bundles. Although we only discussed a few hundred wasted bytes to keep our build scenarios comprehensible, it is easy to extrapolate an impact of several orders of magnitude for more complex, real-world web applications.\n\nWe hope you find the new Inspectpack DuplicatesPlugin to be a useful, actionable tool in finding and squashing duplicate dependencies in your webpack builds. Do your application bundles a favor and give it a whirl today!" ], "categories": { "primary": "frontend", "others": [ "cloud", "oss" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-nodeconf-eu-2018-app-now-available-for-conference-attendees": { "href": "https://nearform.com/insights/nodeconf-eu-2018-app-now-available-for-conference-attendees", "postType": "blog", "slug": "insights-nodeconf-eu-2018-app-now-available-for-conference-attendees", "date": "2018-11-04", "title": "NodeConf.EU 2018 App now available for conference attendees!", "authors": [], "content": [ "[caption id=\"attachment_300002070\" align=\"aligncenter\" width=\"433\"]\n\nThe sign-in screen of the NodeConf.EU 2018 App [/caption] This year we are really excited to launch the NodeConf EU App!\n\nWe have put together a Progressive Web App ( PWA ) to enhance the NodeConf.EU conference attendance experience. The application is built with two users in mind - the conference attendees and the conference organisers. It is designed to help bridge the gap between both of these users.\n\nWhat features does it have?\n\nThe App lets you get the most up-to-date conference schedule synced to your personal devices. It also continues to work when offline; so conference attendees can still interact with and see the timetable even if there is poor Wifi. [caption id=\"attachment_300002057\" align=\"aligncenter\" width=\"461\"]\n\nThe timetable within the App [/caption] The conference organisers can also send out notifications to attendees from the App when there is a change in schedule or when something important is happening. For example, a last minute talk change or update, a workshop location change or a change to the evening entertainment!\n\nThe App allows organisers to send important updates to conference attendees; as long as they have installed the App! [caption id=\"attachment_300002071\" align=\"aligncenter\" width=\"539\"]\n\nThe notifications feed within the App [/caption]\n\nHow we built it\n\nWe built the App using a design-led approach; this gives it a great look and feels out of the box. Our main concern was making this a great conference experience for all attendees and the attention to usability shines through in the App! [caption id=\"attachment_300002072\" align=\"aligncenter\" width=\"766\"]\n\nDesign screens for the App showing the carefully designed user flow to bring the best experience to our attendees [/caption] The App has been built using the technology Node.js developers have come to love, as it’s Javascript all the way down. With a React frontend and a Fastify Node.js backend; even using some of the same technology that’s powering the npm registry, (couchdb!) it is something that developers attending the conference can understand and appreciate.\n\nWhy build this?\n\nThis is a demonstration of some of the latest App development technology. You can create Web applications with the tools you know and love, like React, Vue and so on. These Web applications can be \"installed\" on mobile devices (both Android and Apple IOS devices) and behave similarly to native applications. There are of course limitations since this is a newer technology that is not as mature as native application development. However, it is expected that over time as more users adopt the technology and feature support is added, this can become one of the many commonplace tools in the Web developer or full stack developer toolbelt.\n\nThe benefit of building a PWA over a regular native app is that you can get a native experience very easy and the barrier for entry for creating one (at least for Web developers) is much lower. A PWA does not need to be installed via an App Store, so there is no need for publishing licences from the various vendors. There is no need to worry about vendor lock-in either as this is written for the Web it is cross-platform out of the box.\n\nFinally...\n\nA special thank you to everyone involved in the development, design, deployment and management of this App including...Nigel Hanlon, Joy Burke, Jeff Simons, Ivan Frantar, Alex Knol, Jack Clark, Jhey Tompkins, Arur Daschevici, Brian Mullan, Eduardo Barredo, Will Gross, Conor O Neill and Helene Haughney.\n\nI’d like to thank NearForm for providing us with the resources to create the App and the Marketing and Events teams for being a brilliant and patient customer!\n\nAs a final note, we want to let the Community know we plan to open source the App after the conference. Everyone can have the opportunity to leave feedback and potentially reuse this App for their own conference!\n\nFor more information on PWAs check out our Blog series on PWAs .\n\nAlex Kotliarskyi" ], "categories": { "primary": "mobile", "others": [ "frontend", "oss" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-the-nodeconf-eu-2018-digital-badge-is-here-and-its-fabulous": { "href": "https://nearform.com/insights/the-nodeconf-eu-2018-digital-badge-is-here-and-its-fabulous", "postType": "blog", "slug": "insights-the-nodeconf-eu-2018-digital-badge-is-here-and-its-fabulous", "date": "2018-11-04", "title": "The NodeConf EU 2018 Digital Badge is here and it's fabulous", "authors": [], "content": [ "If you were at NodeConf EU 2017, you know just how blown away everyone was by the digital badge we created. Powered by the Espruino JavaScript interpreter and full of Bluetooth goodness, it really made a mark. This year we figured we could do even better.\n\nAnd here it is, the NodeConf EU 2018 Digital Badge:\n\nGorgeous, isn't it? The first time I saw one lit up, it silenced me. The badge surround is, to quote one of our NearFormers 'a work of art'. Many of us are already planning to mount it somewhere at home where we can smile every time we see it.", "Hardware Features\n\nThe heart of the badge is the same as last year's NRF52832-based badge and its follow-up, the Pixl.js . We also added some new features:\n\nRGB LEDs (of course!)\nRGB back-lit screen\n2 vibration motors for alerts\nLiPo battery for all those LEDs and motors\nBattery charging circuit\nUSB port for charging\nAn LSM303DLHC accelerometer and compass\nHoles for an optional ESP8266 ESP-01 Wifi module\n\nThe focus this year was on the software, and specifically making more use of Bluetooth for features/fun. We were also very interested in up-skilling across more Azure services to add to our DevOps expertise around it, so this seemed like the perfect opportunity.", "Software Requirements\n\nThe core set of requirements we started with were:\n\nShow people's name on badge (obviously!)\nUse badge Bluetooth broadcasts to anonymously estimate number of people in room and generate heatmaps\nUse accelerometer on badge to measure clapping at sessions and broadcast that anonymously\nReceive and display information messages and alerts on badge\nReceive and display basic schedule information on badge\nAdd whatever other fun code we have time to do (Compass, Map, Backlights)\nEnable people to program the badge themselves using the Espruino IDE in Chrome over Web Bluetooth\n\nThe heatmaps are more than just fun. They can potentially help anyone who suffers from social anxiety and they can also help with smoothing out the lunch rush.\n\nThe aim of the alerts is to work around phone-alert-fatigue where many of us don't bother checking our constantly buzzing phones. A buzzing alert on the badge only means one thing - this is important and you should read it...for example 'The buses are leaving now!'.", "Raspberry Pis love Node.js\n\nTo achieve everything we wanted we clearly needed more than just the badges.\n\nEnter 20 Raspberry Pis with built-in Bluetooth and Wifi running our Node.js code. These are our relays scattered around the event venue. They can broadcast to all the badges over Bluetooth and they can also listen for what the badges are broadcasting. Naturally we used Sandeep Mistry's brilliant Noble and Bleno Node.js libraries to implement this.", "Microsoft Azure loves Node.js\n\nBut where will all that data go to/from and how? Microsoft Azure!\n\nAzure gave us the following functionality:\n\nAccess to the schedule backend created by the NodeConf EU PWA team that runs on AKS\nSend schedule info to the badges\nSend Info/Alert info to the badges from the Events team, originating in the PWA backend\nAggregate the badge data\nGenerate heatmap and clap-o-meter visualisations and display on a giant screen\nSend/Receive all of the data over MQTT to/from the Pis via IOT Hub\n\nAnd to do that we used the following:\n\nAKS for the PWA back-end\nIOT Hub\nFunctional Apps\nStream Analytics\nEvent Grid\nApplication Insights\nEvent Hub\nCosmosDB\nPower BI\nazure-iot-device Node.js module\nazure-iot-device-mqtt Node.js module\nAzure IoT Toolkit for VS Code\n\nWe'll do a deep dive blogpost on the architecture of all of this after the event, when we'll also be Open Sourcing everything - hardware and software.\n\nBut for the moment, I'd just like to mention the immense pleasure it was to discover that the Azure MQTT Node.js modules rely on NearForm legend Matteo Collina's MQTT.js library !", "Privacy\n\nWe took privacy very seriously from day one and rejected many cool ideas as they could have (even theoretically) impinged on attendee privacy. Some of the relevant features/approaches we implemented include:\n\nOpt-out of badge broadcasts on first use or any time after\nOpt-out of clap-o-meter broadcasts on first use or any time after\nOpt-out of receiving any notifications on first use or any time after\nNo record kept of who received which badge\nNo badge information is persisted on Raspberry Pis\nBadge Bluetooth Mac addresses are hashed before sending to Azure\nNo triangulation of badges - best guess on count of badges in event rooms is based on measured power\nHeatmap room counts are ranges only\nAll Pi-to-badge messages are broadcasts; never 1-1\nNo recording of badge data outside of range of Pis in public areas\nNo recording of data from non-badge Bluetooth devices\nBadges reject data from all devices except from event Pis or if attendees own code allows it\n\nPlease contact any NearFormer working at NodeConf EU if you feel there is anything we have missed or anything that you are uncomfortable with. They'll put you in touch with me.", "A Work In Progress\n\nThis work is not complete by any means. We have so many things we'd like to have done but were time and resource limited. Many aspects were done in people's spare time or in small gaps between customer projects, for example testing was done on 9 Pis and 15 real and pseudo-badges in my house via ngrok :-) So please be gentle with us if things glitch or break. But let us know if you spot anything, particularly anything important.\n\nOnce we Open Source it all, you can fix anything you don't like.", "Thank You\n\nLike so many NearForm projects this is a multinational effort and we have a lot of people to thank:.\n\nGlobal - All of the NearFormers who submitted ideas and helped out on the 2018 badge in any way\nIreland - Glen Keane, Nigel Hanlon and Helene Haughney for initiating the NodeConf EU App project and working on it throughout\nGlobal - All of the NearFormers who worked on the NodeConf EU App\nUK - Gordon Williams for the always brilliant hardware and software design of the badge\nIreland - Agata Surgot for the stunning badge surround design\nItaly - Matteo Collina for MQTT.js\nCanada - Luca Maraschi for recommending we go with Azure, IOT Hub and MQTT\nCroatia/UK - Mihovil Rister and Shaun Baker for the first version of the Azure code\nFrance - Nicolas Morel for the core Azure implementation\nLithuania - Edvinas Barthkus for all of the Raspberry Pi Node.js code and lots of other things\nIreland - The NearForm Marketing and Events Team for all their support and help\nUSA - Ron Litzenberger for the notification system and many aspects of Azure\nBrazil - Mehdi Avdi for getting the heatmap and clap-o-meter visualisation over the line\nSpain - Alex Knol and the rest of our DevOps team for all of their Azure expertise and help\nIreland - Antoine Marin for the lovely design of the visualisation\n\nI'd also like to give a shout-out PD Signs in Cork Ireland who did a great job manufacturing the badge surrounds. We used a *lot* of laser time! And finally to Pimoroni who also did a great job manufacturing the badges in the UK.\n\nWatch out for several more posts in the next few days and weeks about the software and hardware." ], "categories": { "primary": "oss", "others": [ "cloud", "devops", "backend" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-how-to-integrate-security-into-devops": { "href": "https://nearform.com/insights/how-to-integrate-security-into-devops", "postType": "blog", "slug": "insights-how-to-integrate-security-into-devops", "date": "2018-11-13", "title": "How to integrate security into DevOps", "authors": [], "content": [ "NearForm and Sqreen are delighted to come together to share their insights on DevOps and security integration.\n\nSome topics covered during the discussion:\nWhat is the biggest challenge around DevOps and Security?\nWhat hinders better security today?\nHow do you detect attacks in production today?\nHow can DevOps help secure other parts of the organization: employees, emails etc.?\n\nNeed help with DevOps? Contact us today to see how we can help!" ], "categories": { "primary": "devops", "others": [ "security" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-static-analysis-of-docker-image-vulnerabilities-with-clair": { "href": "https://nearform.com/insights/static-analysis-of-docker-image-vulnerabilities-with-clair", "postType": "blog", "slug": "insights-static-analysis-of-docker-image-vulnerabilities-with-clair", "date": "2018-11-13", "title": "Static Analysis of Docker image vulnerabilities with Clair", "authors": [], "content": [ "Clair tutorial: analyzing a Docker Image\n\nIn a previous article, we described how to build a Docker Registry in Kubernetes .\n\nToday we look at Clair - a tool that does static analysis of vulnerabilities in a docker image.\n\nWhat is Clair?\n\nClair is a popular open source vulnerability scanning solution for docker images made by CoreOS .\n\nClair is also integrated with quay.io public docker registry and Quay Enterprise, both products of CoreOS.\n\nAs a source of vulnerabilities, it uses CVE (Common Vulnerabilities and Exposures) data sources like NIST NVD as well as security bug trackers of the specific Linux distributions supported by Clair.\n\nClair doesn’t have a web UI or even a command-line tool; so the only way to work with it is via its REST API or a third-party CLI tool.\n\nClair is distributed as docker image:\n\ndocker pull quay.io/coreos/clair\ntextCopy to clipboard\n\nIt can also be compiled from the source code here: https://github.com/coreos/clair .\n\nHow Clair works\n\nClair scans docker images by doing static analysis, which means it analyzes images without a need to run their docker container.\n\nA docker image is composed of 1+n layers (also called intermediate images) and each layer is stored in a docker registry as a tar file blob.\n\nGive Clair a HTTP URL to an image layer tar file and it analyses it. To analyse an entire docker image, we need to give Clair all the image layers.\n\nClair has a couple of API endpoints listed here: https://coreos.com/clair/docs/latest/api_v1.html We use two of them:\n\nPOST /layers - push a docker image layer to Clair for an analysis\nGET /layers/:name - retrieve info about a docker layer with found vulnerabilities\n\nClair also has protobuf API v3, but we will be using API v1 as we want to communicate with Clair via HTTP.\n\nArchitecture and Clair components\n\nClair is composed of 2 components:\n\nClair\nREST API server\nCVE Updater which takes care of updating database of vulnerabilities\nList of CVE data sources\nPostgreSQL 9.4+\nStorage of vulnerabilities database and results of analysis of uploaded docker image layers\nLocal setup of Clair\n\nWe won't go into detail about how to deploy Clair as it isn't the focus of this post.\n\nInstead, let’s focus on how Clair works and for that, we use the official docker-compose setup and make it run on our local machine.\n\nWe need to create just 2 files:\n\nclair_config/config.yaml (download)\ndocker-compose.yaml (download)\n\nAdd password=password parameter into clair_config/config.yaml PostgreSQL connection configuration.\n\nI also recommend changing the default postgres:latest docker image by arminc/clair-db which already contains the CVE database. Otherwise, we need to wait roughly 30 minutes before the database gets downloaded.\n\nLet's start our local Clair:\n\ndocker-compose up\ntextCopy to clipboard\nAnalyzing a docker image in a few steps\n\nIn the rest of the post, we use the docker registry V2 built in the previous article with the same pseudo domain name registry.mydomain.com and same Basic Auth credentials admin:admin123 .\n\nStep 1\n\nFirst, we need to have an image in our registry to be able to perform an analysis of it.\n\nSo let’s pick up, for example, a debian:9.5 image and push it to our registry.\n\ndocker pull debian:9.5\ndocker tag debian:9.5 registry.mydomain.com/debian:9.5\ndocker login https://registry.mydomain.com -u admin -p admin123\ndocker push registry.mydomain.com/debian:9.5\ntextCopy to clipboard\nStep 2\n\nWith the image in the registry, let’s get the HTTP URLs of its layers in tar format. To do that, we need to get its manifests:\n\ncurl -u admin:admin123 https://registry.mydomain.com/v2/debian/manifests/9.5\ntextCopy to clipboard\n\nin a JSON response, a field fsLayers contains all the image layers identified by blobSums.\n\n\"fsLayers\": [\n {\n \"blobSum\": \"sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4\"\n },\n {\n \"blobSum\": \"sha256:05d1a5232b461a4b35424129580054caa878cd56f100e34282510bd4b4082e4d\"\n }\n ]\ntextCopy to clipboard\n\nEach docker image is always composed by one or more empty layers generated by commands from Dockerfile like CMD, EXPOSE etc. which don't modify the content of the image, so we don't need to scan them.\n\nBecause these layers are empty they always have the same blobSum:\n\nsha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4\ntextCopy to clipboard\n\nTherefore we can easily identify them and exclude them from Clair analysis.\n\nStep 3\n\nKnowing that we want to analyze only the second layer with blobSum sha256:05d1a5232b461a4b35424129580054caa878cd56f100e34282510bd4b4082e4d to get its content, we need to call a different API endpoint:\n\ncurl -u admin:admin123 https://registry.mydomain.com/v2/debian/blobs/sha256:05d1a5232b461a4b35424129580054caa878cd56f100e34282510bd4b4082e4d\ntextCopy to clipboard\n\nIn response, we get a tar file representing the delta of the layer. That is what we need to provide Clair to let it do its analysis.\n\nStep 4\n\nNow let’s tell Clair to analyze our docker image composed by only one \"scannable\" layer.\n\nTo do that we call the API POST https://localhost:6060/v1/layers which requires a few parameters:\n\nName - we can use blobSum of a layer. Here we need to keep in mind that the name field has to be unique, that means we have to avoid pushing empty layers as they have the same blobSum. That’s also a reason why we decided to exclude it from the analysis.\nPath - URL to tar file of a layer\nHeaders - has to contain Authorization header to make Clair able to reach Docker Registry. In our case, it’s Basic Auth. (We can generate a Basic Auth token like this: echo -n \"admin:admin123\" | base64)\nFormat - Clair supports both Docker and Rkt formats of container images.\nParentName - this field is optional and has to be used if we want to analyze a docker image with more than one layer. In such case we need to push these layers in the right order by referencing its parent layer; otherwise, Clair will not be able to provide us with results of the entire docker image.\n\nLet Clair do its magic:\n\nPOST https://localhost:6060/v1/layers

{\n \"Layer\": {\n \"Name\": \"sha256:05d1a5232b461a4b35424129580054caa878cd56f100e34282510bd4b4082e4d\",\n \"Path\": \"https://registry.mydomain.com/v2/debian/blobs/sha256:05d1a5232b461a4b35424129580054caa878cd56f100e34282510bd4b4082e4d\",\n \"Headers\": {\n \"Authorization\": \"Basic YWRtaW46YWRtaW4xMjM=\"\n },\n \"Format\": \"Docker\"\n }\n}\ntextCopy to clipboard\n\nWhen finished, we are immediately able to get a result of found vulnerabilities in the layer by calling the endpoint:\n\nGET https://localhost:6060/v1/layers/sha256:05d1a5232b461a4b35424129580054caa878cd56f100e34282510bd4b4082e4d?features&vulnerabilities\ntextCopy to clipboard\n\nIn response, we get a list of all features present in a filesystem which could indicate a vulnerability.\n\nOne of the features in our tested debian:9.5 docker image is for example systemd where Clair found some vulnerabilities listed below:\n\n{\n \"Layer\":{\n \"Name\":\"sha256:05d1a5232b461a4b35424129580054caa878cd56f100e34282510bd4b4082e4d\",\n \"NamespaceName\":\"debian:9\",\n \"IndexedByVersion\":3,\n \"Features\":[\n {\n \"Name\":\"systemd\",\n \"NamespaceName\":\"debian:9\",\n \"VersionFormat\":\"dpkg\",\n \"Version\":\"232-25+deb9u4\",\n \"Vulnerabilities\":[\n {\n \"Name\":\"CVE-2017-1000082\",\n \"NamespaceName\":\"debian:9\",\n \"Description\":\"systemd v233 and earlier fails to safely parse usernames starting with a numeric digit (e.g. \\\"0day\\\"), running the service in question with root privileges rather than the user intended.\",\n \"Link\":\"https://security-tracker.debian.org/tracker/CVE-2017-1000082\",\n \"Severity\":\"Negligible\"\n },\n {\n \"Name\":\"CVE-2013-4392\",\n \"NamespaceName\":\"debian:9\",\n \"Description\":\"systemd, when updating file permissions, allows local users to change the permissions and SELinux security contexts for arbitrary files via a symlink attack on unspecified files.\",\n \"Link\":\"https://security-tracker.debian.org/tracker/CVE-2013-4392\",\n \"Severity\":\"Negligible\"\n },\n {\n \"Name\":\"CVE-2017-18078\",\n \"NamespaceName\":\"debian:9\",\n \"Description\":\"systemd-tmpfiles in systemd before 237 attempts to support ownership/permission changes on hardlinked files even if the fs.protected_hardlinks sysctl is turned off, which allows local users to bypass intended access restrictions via vectors involving a hard link to a file for which the user lacks write access, as demonstrated by changing the ownership of the /etc/passwd file.\",\n \"Link\":\"https://security-tracker.debian.org/tracker/CVE-2017-18078\",\n \"Severity\":\"Negligible\"\n },\n {\n \"Name\":\"CVE-2018-1049\",\n \"NamespaceName\":\"debian:9\",\n \"Description\":\"In systemd prior to 234 a race condition exists between .mount and .automount units such that automount requests from kernel may not be serviced by systemd resulting in kernel holding the mountpoint and any processes that try to use said mount will hang. A race condition like this may lead to denial of service, until mount points are unmounted.\",\n \"Link\":\"https://security-tracker.debian.org/tracker/CVE-2018-1049\",\n \"Severity\":\"Medium\"\n },\n {\n \"Name\":\"CVE-2018-6954\",\n \"NamespaceName\":\"debian:9\",\n \"Description\":\"systemd-tmpfiles in systemd through 237 mishandles symlinks present in non-terminal path components, which allows local users to obtain ownership of arbitrary files via vectors involving creation of a directory and a file under that directory, and later replacing that directory with a symlink. This occurs even if the fs.protected_symlinks sysctl is turned on.\",\n \"Link\":\"https://security-tracker.debian.org/tracker/CVE-2018-6954\",\n \"Severity\":\"High\"\n }\n ],\n \"AddedBy\":\"sha256:05d1a5232b461a4b35424129580054caa878cd56f100e34282510bd4b4082e4d\"\n }\n ]\n }\n}\ntextCopy to clipboard\n\nWhat we must pay attention to are 2 fields:\n\nSeverity - telling you how critical is the vulnerability\nFixedBy - telling you there is a newer version of a feature which fixes the vulnerability. The field doesn’t exist if there isn’t a fix yet.\nConclusion\n\nWe have learned how to use Clair without using any third-party client which helped us to understand how Clair works.\n\nNow with this in mind, we can look at popular third-party clients like klar , clairctl , reg and many others that simplify the work with Clair. With them, you don’t need to care about layers as you provide only a docker image name and the client does the rest for you.\n\nSo what was the reason for writing this article you might ask? Well, let me cite one paragraph from official Clair documentation: \"Clair can be integrated directly into a container registry such that the registry is responsible for interacting with Clair on behalf of the user. This type of setup avoids the manual scanning of images and creates a sensible location to which Clair's vulnerability notifications can be propagated. The registry can also be used for authorization to avoid sharing vulnerability information about images to which one might not have access.\" And that's something that we will look at in next article.\n\nStay tuned!\n\nRead more about NearForm’s services and how we assist businesses in product design and modern application development or contact us to discuss how we can help you accelerate your projects using modern tools, processes and platforms. MILKOVI" ], "categories": { "primary": "security", "others": [ "oss", "devops" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-node-js-meetup-node-clinic-from-nearform": { "href": "https://nearform.com/insights/node-js-meetup-node-clinic-from-nearform", "postType": "blog", "slug": "insights-node-js-meetup-node-clinic-from-nearform", "date": "2018-11-20", "title": "Node.js meetup - Node Clinic from NearForm", "authors": [], "content": [ "We had another great crowd at our Node.js Dublin meetup in September. Hosted in the Microsoft building in Leopardstown, Matteo Collina featured a profile of Node Clinic, a new set of diagnostic tools to help diagnose and address application and platform performance issues and Dara Hayes giving an introduction to GraphQL with a live demo.\n\nIf you didn't make it along to the meetup, get an overview of Node Clinic and what it can do at the recording below (remember you can see recordings of all Node.js meetups if you subscribe to our YouTube channel .) Matteo Collina walks us through the ability of the Clinic tools -- including Clinic Doctor, Clinic Bubble Prof and Clinic Flame -- to help answer questions from the business about why apps are slow or underperforming.\n\nThe Clinic tools are just what the doctor ordered if you have an application in development or in production that’s underperforming because they accelerate and simplify the process of pinpointing bottlenecks. Is it an internal bottleneck with a Node.js process? Or something external, possibly a database? Matteo demonstrates how each part of the Clinic toolset moves you through the process (though you’ll need to take the first step by reproducing the performance problem on staging, outside your production environment).\n\nCheck the video below to see the following:\nClinic Doctor, which assesses system health using heuristics, generates graphs and uses AI to make recommendations that may help resolve the issue\nClinic Flame, which uses CPU sampling to track the frequency of the issue and generates helpful visualizations\nClinic Bubble Prof, which collects metrics using async_hooks (a new diagnostic feature from Node 8.5) and lets you track latency between operations, presenting the most detailed visuals of all to help diagnose the root cause of performance problems.\n\nhttps://www.youtube.com/watch?v=YCJHa03kDz4&t=32s\n\nTry Node Clinic and see more about the September meetup\n\nIf you’d like to experiment with Node Clinic, go ahead and visit https://clinicjs.org/ . We were also happy to have a second speaker at the September meetup, Dara Hayes, with a light-hearted introduction to GraphQL. You can see both Matteo and Dara’s presentations on our Node.js meetups playlist.\n\nCome along to Node.js Dublin: pizza, skills sharing and more!\n\nOur monthly Node.js Dublin meet-ups are a great place to meet like-minded folks from the Irish dev community, hear directly from the NearForm team, and get comfortably numb with pizza and beverages. Why not come along next time or better still, get in touch if you would like to speak!\n\nHave a look at all our Node.js Dublin meetups past and present here." ], "categories": { "primary": "backend", "others": [ "perf", "devops" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-writing-reusable-terraform-modules": { "href": "https://nearform.com/insights/writing-reusable-terraform-modules", "postType": "blog", "slug": "insights-writing-reusable-terraform-modules", "date": "2018-11-22", "title": "Writing Reusable Terraform Modules to Facilitate Code Reuse Across your Infrastructure", "authors": [], "content": [ "Writing reusable terraform modules to facilitate code reuse across your infrastructure\n\nNote: all the code samples in this article are written using Terraform v0.11.7 and for an AWS based infrastructure, but these patterns can be applied to any of the cloud providers that Terraform supports. One of the standard infrastructure architectural patterns for web applications - that we also apply here at NearForm - is to split the infrastructure into multiple logical environments. The most common ones are dev, staging and production.\n\nThey use the same type of resources (load balancers, instances, databases, etc), but they differ in scale and public accessibility: while dev will use a low number of small instances and will be password or VPN protected from the Internet, production will use a high number of instances and will be accessible by anyone.\n\nBecause we apply DevOps best practices , these types of infrastructures are deployed from the beginning as infrastructure-as-code. This gives us the ability to easily reproduce the infrastructure and version the code via Git or any other VCS. And for that, one of the tools of choice is Terraform .\n\nYou can see the example code in this repository if you want to have a full overview of how it all ties in: https://github.com/nearform/tf-modules-example\n\nThe problem: Updating Complex Architectures in Terraform\n\nWhile Terraform is a great tool and a great time-saver, when it gets to more complex architectures like the ones described above, things can get unwieldy.\n\nLet's assume the current directory structure for this kind of infrastructure looks like this (and this is a directory structure we would recommend for such projects):\n\n+-- environments\n¦ +-- dev\n¦ ¦ +-- main.tf\n¦ +-- production\n¦ ¦ +-- main.tf\n¦ +-- staging\n¦ +-- main.tf\n+-- main.tf\n+-- provider.tf\n\n\nWe mentioned that each environment uses the same type of resources.\n\nThis means that if the application requires a new resource, for example, Redis via AWS's Elasticache, an engineer will first introduce the resource into the dev environment, by adding the following code to environments/dev/main.tf:\n\nresource \"aws_elasticache_replication_group\" \"elasticache-cluster\" {\n availability_zones = [\"us-west-2a\", \"us-west-2b\"]\n replication_group_id = \"tf-rep-group-1\"\n Replication_group_description = \"Dev replication group\"\n node_type = \"cache.m3.medium\"\n number_cache_clusters = 1\n parameter_group_name = \"default.redis3.2\"\n port = 6379\n}\n\n\nWhat happens after the new features are introduced and tested? Before deploying the code to staging and then production, the same code will have to be copy-pasted (and modified) to both environments/staging/main.tf and environments/production/main.tf.\n\nAnd this pattern will repeat itself with every new resource added, making the code-base bigger and harder to read and especially to modify because any change to how a resource is being used will mean the change has to be applied to every environment.\n\nThis also makes things prone to configuration drift: if a quick change is required to justify the production environment, a lot of times it will quickly be added to environments/production/main.tf while forgetting to add it to the other environments, thus making the dev environment more and more different to the production one, defeating the purpose of having environments like dev and staging that truly mimic production so tests can be run on them without affecting live traffic and users.\n\nThe solution: Create Reusable Terraform Modules\n\nOne of the ways to mitigate these issues is to create reusable and configurable Terraform modules. Let's break this down and start of first with:\n\nReusable Terraform Modules\n\nUsing the Elasticache example from above, we will create another directory in the root of our codebase, called elasticache. The directory structure will look like this:\n\n.\n+-- elasticache\n¦ +-- main.tf\n+-- environments\n¦ +-- dev\n¦ ¦ +-- main.tf\n¦ +-- production\n¦ ¦ +-- main.tf\n¦ +-- staging\n¦ +-- main.tf\n+-- main.tf\n+-- provider.tf\n\n\nTerraform's way of creating modules is very simple: create a directory that holds a bunch of .tf files. That module can be called in each of the environment modules. You can think of this module as an object in OOP, which you can instantiate in other parts of the code.\n\nThe module's main.tf file will have the same piece of code, the Terraform resource, which we used above and in each environment:\n\nresource \"aws_elasticache_replication_group\" \"elasticache-cluster\" {\n availability_zones = [\"us-west-2a\", \"us-west-2b\"]\n replication_group_id = \"tf-rep-group\"\n node_type = \"cache.m3.medium\"\n number_cache_clusters = 1\n Parameter_group_name = \"default.redis3.2\"\n port = 6379\n}\n\n\nWe can now add in environments/dev/main.tf:\n\nmodule \"dev-elasticache\" {\n source = \"../../elasticache\"\n}\n\n\nNote that source parameter needs to call the module with its path as relative to the module it is being called from.\n\nYou can continue by adding the same piece of code to both environments/staging/main.tf and environments/production/main.tf, the only thing that you will need to modify in each file is the module name: each instance of a module needs to have a unique name (ex: instead of module dev-elasticache use module staging-elasticache).\n\nConfigurable Terraform Modules\n\nNow that we have our reusable module in place, we will hit another problem: each environment might have its own requirement from a certain resource.\n\nTo continue to use our example, in dev we might need just one cache.m3.medium node in our Elasticache cluster, but in production, we might need 3 cache.m3.large nodes in the cluster.\n\nThe solution to this is to make the module configurable by using input parameters. These are basically variables that are available only in the module's scope and can be passed to the module upon instantiating (calling) it.\n\nYou can add these variables directly in the module's main.tf file, but one of the cleaner ways - especially if the number of input parameters grows - is to have a separate variables.tf file in the module's directory.\n\nAfter adding that, our final directory structure looks like this:\n\n.\n+-- elasticache\n¦ +-- main.tf\n¦ +-- variables.tf\n+-- environments\n¦ +-- dev\n¦ ¦ +-- main.tf\n¦ +-- production\n¦ ¦ +-- main.tf\n¦ +-- staging\n¦ +-- main.tf\n+-- main.tf\n+-- provider.tf\n\n\nThe variables.tf file will hold the variables that configure the module.\n\nIn our case, we want to be able to configure the number of nodes in the cluster, the type of nodes, the cluster's description (so it is easy to know in which environment it runs) and the availability zones in which it runs:\n\nvariable \"environment\" {}\nvariable \"node_count\" {}\nvariable \"node_type\" {}\nvariable \"availability_zones\" { type = \"list\" }\n\n\nOf course, the module needs to know where to use these variables, so the elasticache/main.tf file will look like:\n\nresource \"aws_elasticache_replication_group\" \"elasticache-cluster\" {\n availability_zones = [\"${var.availability_zones}\"]\n replication_group_id = \"tf-${var.environment}-rep-group\"\n replication_group_description = \"${var.environment} replication group\"\n node_type = \"${var.node_type}\"\n number_cache_clusters = \"${var.node_count}\"\n parameter_group_name = \"default.redis3.2\"\n port = 6379\n}\n\n\nIn each of the environment main.tf files, the module now needs these variables defined and passed to it. In our example, environments/dev/main.tf will look like:\n\nmodule \"dev-elasticache\" {\n source = \"../../elasticache\"\n environment = \"dev\"\n node_count = 1\n node_type = \"cache.m3.medium\"\n availability_zones = [\"us-east-1a\", \"us-east-1b\"]\n}\n\n\nAnd environments/production/main.tf will look like:\n\nmodule \"production-elasticache\" {\n source = \"../../elasticache\"\n environment = \"dev\"\n node_count = 3\n node_type = \"cache.m3.large\"\n availability_zones = [\"us-east-1a\", \"us-east-1b\"]\n}\n\nWrapping up\n\nAt this point all that is left to do, is to call the environments modules in the main.tf file of the root:\n\nmodule \"dev\" {\n source = \"environments/dev\"\n}\n\nmodule \"staging\" {\n source = \"environments/staging\"\n}\n\nmodule \"production\" {\n source = \"environments/production\"\n}\n\n\nRunning terraform plan and terraform apply should bring up an Elasticache cluster in each environment, configured the way it is needed.\n\nConclusion: Clean, Readable, and Scalable Terraform code\n\nWith a relatively small amount of effort, Terraform code can be structured in such a way from the beginning that growing the code base won't bring with it growing pains. Configurable, reusable modules are one of the basic building blocks of clean, readable and scalable Terraform code.\n\nRead more about NearForm’s DevOps & Platform Engineering services and how we assist businesses to create and deploy high-performance software or contact us to discuss how we can help you accelerate your projects using modern tools, processes and platforms. Ian Simmonds" ], "categories": { "primary": "cloud", "others": [ "devops" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-better-http-testing": { "href": "https://nearform.com/digital-community/better-http-testing", "postType": "blog", "slug": "digital-community-better-http-testing", "date": "2018-11-27", "title": "YesNo: Better HTTP Testing", "authors": [ "IAN WALKER-SPERBER" ], "content": [ "YesNo is a new library for Node.js that simplifies how we write tests asserting the actual behavior of our HTTP requests. YesNo intercepts the requests your app makes, then either forwards the request to its original destination or responds with a user defined mock.\n\nMany Node.js apps include some sort of API integration. Especially when working within a microservices architecture, the entire behavior of our app may be dependent on the correctness of our HTTP requests. So it's critical that our tests capture this behavior.\n\nThe problem is that HTTP requests are the kind of thing we normally need to mock out in our unit tests, since they're dependent on an external service. But once we're mocking these requests it becomes difficult to guarantee our tests reflect the real behavior of the app. What happens when our mocks become stale? Or what if we build our mock HTTP response according to incorrect documentation, then later discover the response has a completely different shape? When you're juggling several different APIs in a evolving ecosystem these issues occur regularly, and they're often the source of real bugs.\n\nWe've tried to address this problem in YesNo by reimagining the best features of several existing HTTP testing libraries to accommodate the lessons we've garnered having to maintain complicated test suites that use them.\n\nYesNo makes it easy to generate fixtures that have a strong guarantee of reflecting real requests. You can use it in integration tests against a live service or in your offline unit tests. Moreover, it includes a few utility methods to access and manipulate intercepted requests without additional boilerplate.\n\nFeatures\n\nSpy on live requests\n\nyesno.spy()\n\nawait myApi.updateUser(1, 'invalid-token')\n\n// Select the intercepted POST request \nand assert its response code\nexpect(yesno.matching(/user\\/1/).response())\n.to.have.property('statusCode', 401)\njavascriptCopy to clipboard\n\nMock requests\n\nyesno.mock(await yesno.load({ \n filename: './my-mocks.json' \n}))\n\nconst users = await myApi.getUsers() // Responses are mocked\njavascriptCopy to clipboard\n\nEdit and record requests\n\nconst recording = await yesno.recording({ \n filename: './update-user-sanitized.json' \n})\n\n// Auth requests with sensitive data...\nconst token = await auth.getToken()\nawait myApi.updateUser(1, token)\n\n// Redact auth data so that our credentials don't \n// end up in source control!\nyesno.matching(/auth/).redact('response.body.token')\nyesno.matching(/user\\/1/).redact('request.headers.authorization')\n\nawait recording.complete()\njavascriptCopy to clipboard\nTesting Philosophy\n\nYesNo is built to support a simple testing approach that plays well with a TDD-based mindset, which one could divide into the steps Validate, Persist, Mock. This allows us to first validate our test against a live API, secondly persist the intercepted requests, and thirdly mock our test with the new fixtures. By the end we have a unit test whose mocked behavior closely resembles the unmocked behavior, using a workflow we can repeat whenever we need to refresh our fixtures.\n\nLet's look at an example. We'll use YesNo's convenient recording method to write a test that can spy, record or mock requests according to an environment variable we set at runtime. This way the same test can support each step of our workflow, with our assertions remaining valid throughout.\n\n// Begin a recording. Load mocks if in \"mock\" mode, otherwise spy.\nconst recording = await yesno.recording({ \n filename: './get-users.json' \n})\n\n// Make our HTTP requests\nawait myApi.getUsers() \n\n// Run assertions\nexpect(yesno.intercepted()).to.have.lengthOf(1)\nexpect(yesno.matching(/users/).response()).to.have.property('statusCode', 200)\n\n// Persist intercepted requests if in \"record\" mode, otherwise no-op\nawait recording.complete()\njavascriptCopy to clipboard\n\nOur first step is to validate the real HTTP behavior of our test, so we run our tests unmocked against live services.\n\nYESNO_RECORDING_MODE=spy npm test\nbashCopy to clipboard\n\nIf our assertions pass, we know we received the expected request & response format. If not, we'll need to identify and fix our errors, then repeat this step.\n\nNow that we know the test behaves correctly against live services, we're ready to generate fixtures so that we can run our tests offline. To persist these requests to disks we simply run the test again in record mode.\n\nYESNO_RECORDING_MODE=record npm test\nbashCopy to clipboard\n\nDepending on the test it may be helpful to look at the generated JSON file. Sometimes you'll notice values that you ought to be asserting on, or you'll find sensitive credentials which should be redacted from the fixtures.\n\nWith the fixtures saved to disk we can run our test with mocks, so that all our intercepted requests resolve with mocked responses.\n\nYESNO_RECORDING_MODE=mock npm test\nbashCopy to clipboard\n\nOnce the test passes we can commit the test and generated fixtures to version control. We have to commit the fixtures to version control so that we can continue to run our tests in mock mode going forward. Whenever our application or an external API changes, we'll repeat these steps to update the fixtures.\n\nFollowing this methodology we're able to validate API behavior with the same code as our unit tests. This means we can use our tests to drive discovery and development, where otherwise we might have to write scripts or one off curl requests to independently validate APIs. This is why I find this approach so conducive for TDD, because it encourages us to write our tests first.\n\nRemember that while this is our preferred workflow for writing tests, you're free to use whatever approach you'd like. You can always choose to manually define your mocks or skip mocking altogether.\n\nChallenges of existing approaches\n\nAs previously discussed, there are already lots of libraries available to help you test HTTP requests in Node. Here are some of the challenges we've encountered using them that YesNo tries to address.\n\n1. They assert the behavior of an HTTP library, not the HTTP request.\n\nYesNo intercepts the HTTP requests at a low level, so our tests aren't tied to any library.\n\n2. They require hand crafting fixtures.\n\nWe want to avoid writing fixtures by hand whenever possible. It's time consuming and unreliable.\n\n3. They force us to write test specific configurations.\n\nAnother approach we've encountered is to stand up a local test server that responds to requests. However this requires us to modify our app configuration to point toward the test server, still necessitates manual mocking, and generally adds overhead.\n\n4. They're difficult to manipulate.\n\nA few libraries do provide some sort of \"record\" functionality to save mocks to disk from generated HTTP requests. But those libraries lack a syntax for editing the mocks or selecting results, which hinders maintaintability.\n\n5. They're a pain.\n\nPerhaps all the drawbacks should be summarized here — the existing libraries could all be easier to use!\n\nGive it a shot\n\nIf you're still reading at this point then we likely share a passion for robust testing strategies. Go check out the README for YesNo and let us know what you think!" ], "categories": { "primary": "test", "others": [ "backend" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-protecting-node-js-from-uncontrolled-resource-consumption-headers-attacks": { "href": "https://nearform.com/insights/protecting-node-js-from-uncontrolled-resource-consumption-headers-attacks", "postType": "blog", "slug": "insights-protecting-node-js-from-uncontrolled-resource-consumption-headers-attacks", "date": "2018-11-28", "title": "Protecting Node.js from uncontrolled resource consumption headers attacks", "authors": [], "content": [ "Fixing Denial of Service vulnerabilities in Node.js\n\nAs part of the security release of the 27th of November 2018 , we fixed several Denial of Service vulnerabilities related to headers processing. You should upgrade your Node.js versions to v6.15.0, v8.14.0, v10.14.0, v11.3.0. This blog post is an in-depth explanation on how those attacks were fixed.\n\nA long-time advice in the Node.js community is to deploy Node.js protected by a full a web server, like NGINX. As of the 27th of November, we fixed some critical Denial of Service vulnerabilities (Uncontrolled Resource Consumption - CWE-400 ) that makes Node.js safer when deployed without a web server.\n\nTwo headers-related vulnerabilities are fixed in that security release:\n\nthe maximum size of HTTP/1 headers is now 8KB (before it was 80KB); CVE: CVE-2018-12121\nthe maximum time that the HTTP/1 headers could be received is now limited to 40 seconds by default, a.k.a. Slowris; CVE: CVE-2018-12122.\nCVE-2018-12121: Maximum size of headers attack\n\nNode.js uses http_parser to parse the incoming HTTP/1 request. By default, the maximum amount of headers that could be sent prior to the fix was 80 KB, while most web servers limit this to 6 or 8 KB. This difference could be easily exploited to create a memory exhaustion attack on a Node.js server by creating a large amount of HTTP requests, and never terminate the headers block with ‘\\r\\n’.\n\nNote that there is a default timeout for inactivity set at 2 minutes, but this is still a long amount of time: as an example, with 25.000 pending requests, it will allocate 1.9 GB of memory on the heap (200MB with the fix). This is normally not a problem, but on specific conditions, it was possible to cause the Node.js process to crash due to memory exhaustion. This type of attack requires a huge amount of bandwidth to pull off.\n\nThere is no security revert flag for this check, i.e. it cannot be disabled or configured.\n\nCVE-2018-12122: Prevent Slowris-style attack on HTTP headers\n\nThis is a Node.js-flavor of a common attack to web servers, known as Slowris . In this attack, a client sends data at the slowest possible throughput to not trigger an inactivity timeout on the HTTP/1 server (2 minutes in Node.js by default).\n\nA Slowris attack could happen for both the headers and the body. Parsing the body is left to the ecosystem, however, Node.js should not be vulnerable to potential slowris attacks for parsing the headers themselves.\n\nThis is fixed by a new server setting server.headersTimeout, that sets the maximum amount of time to receive the headers to 40 seconds by default. This could be tweaked according to your application requirements.\n\nThe real challenge to fix this attack was to not compromise Node.js throughput and speed, as initial prototypes had a significant drop in throughput, up to 50%. The reason for this drop was the use of a timer to control when to expire the connection. Instead, we settled on a different approach: whenever a data chunk is received, we are checking if the maximum amount of time for parsing the headers has elapsed. Generating this timestamp is already cached for each second to generate the HTTP response timestamp, so it does not introduce a new bottleneck for high-speed servers.\n\nConclusions\n\nWe still recommend deploying Node.js behind a Web server to protect against Denial of Service attacks. However, Node.js just become a bit safer if you decide not to do so. Remember to upgrade your Node.js deployments to v6.15.0, v8.14.0, v10.14.0, v11.3.0.\n\nYou may find this video helpful where I talk about choosing which version of Node.js you should use Image: Sylwia Bartyzel" ], "categories": { "primary": "security", "others": [ "backend" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-sharing-media-in-progressive-web-apps": { "href": "https://nearform.com/insights/sharing-media-in-progressive-web-apps", "postType": "blog", "slug": "insights-sharing-media-in-progressive-web-apps", "date": "2018-11-30", "title": "Sharing Media in Progressive Web Apps", "authors": [], "content": [ "What are Progressive Web Apps (PWAs)?\n\nWith the widespread adoption of HTML5 standards, the lines between native and web applications are becoming more blurry. Now, increasing native features have become available for the browsers, making it difficult to decide whether to build a native or web application.\n\nHere at NearForm we love pushing the boundaries of disruptive technology, and in a sense, this is what Progressive Web Apps (PWAs) are.\n\nFor more info see our other articles on Progressive Web Apps :\n\nBuilding Progressive Web Apps\nPayment Request API for online purchase in PWAs\nUsing Web Notifications to increase engagement in PWAs\n\nLet’s remind ourselves what Progressive Web Apps are:\n\nProgressive: they make use of the functionality that is available on your device. If the functionality is not available they provide a sensible fallback\nWeb: they are built with the web in mind so they are available for your device if it is web-ready.They run in a browser and the code base is essentially a web page\nApp: and last but not least, it is an App because it allows you to add it as a standalone bookmark to your website. It appears and opens as an App would but, unlike native Apps, the step of going to the App store and downloading the App is not required making it a more seamless and frictionless user experience\nBuilding a Progressive Web App for Image Sharing\n\nGiven that the APIs available for web applications are very close to what the native version has to offer we decided to build a Progressive Web App that can take pictures and then share them via the native device methods. Demo - Source In order to take the actual picture, we made use of the HTML5

// create our material ui theme using up to date typography variables\nconst theme = createMuiTheme({\n typography: {\n useNextVariants: true\n }\n});

// Let's convert App from class to function to get into the mood!\nfunction App() {\n return (\n \n { /* our demo form will go here */ }\n \n );\n}

export default App;\ntextCopy to clipboard\n\nThe above code sets up a new MaterialUI theme object using `createMuiTheme`, which we pass as a prop to ThemeProvider. Now it is accessible to all subcomponents of ThemeProvider.\n\nNext, create a basic Form component called `Form.js` in a `/components` subfolder with the following code (explained below):\n\n// import built in hook for functional component state

import React, { useState } from \"react\"; \n// material-ui hook functions\nimport { makeStyles, useTheme } from \"@material-ui/styles\";\n// import material-ui components\nimport { Paper, TextField, Typography } from \"@material-ui/core\";\n//create a custom material-ui hook to access class styles\nconst useStyles = makeStyles(\n theme => ({\n root: {\n padding: theme.spacing.unit * 3\n }\n }),\n { withTheme: true }\n);

function Form() {\n // use of custom hook to bring in styles (usually done with HOC and prop)\n const classes = useStyles();\n // we can also use a hook to access the theme object (as above)\n const theme = useTheme();\n // create and init state variable and state mutator with useState React hook\n const [data, setData] = useState(\"\");

// create memoised event handler for input field onChange event\n // similar to this.handleChange in class component

const handleChange = useCallback(e => {\n setData(e.target.value);\n }, []);

return (\n \n NearForm Hooks Demo\n \n Theme primary color = {theme.palette.primary.main} (obtained from\n useTheme hook)\n \n \n Data: {data}\n \n );\n}\nexport default Form;\ntextCopy to clipboard\nThe first thing we do here is call `makeStyles` to create a material-ui custom hook and assign it to `useStyles`, which we call in the component function to get a reference to the `classes` object. We can then use `classes` as normal. The usual way to do this is to wrap a given class component with a HOC (withStyles), and access the `classes` object via props.\nIn this step, we also pass in `withTheme` option, in order to provide access to the `theme` object within the `makeStyles` function. This allows us to use the `theme` object to define custom styles, in this example, we access the base spacing unit of the theme and multiply by 3.\nMaterialUI has provided a custom hook called useTheme to get access to the theme within the component.\nNext, we call useState to set up a state variable called data, and a setter function called setData and we initialise the value of data to empty string with the useState function call parameter. This would not have been possible in a standard functional component, and if using a class we would have had to create and initialise the state object in a constructor, and set the state using this.setState.\nNext, we create a memoised handler for the onChange event of the TextField component, using another react hook called useCallback, and call setData within the handler to update the state variable, data. This is similar to using this.handleEvent in a class component.\nFinally, we render using some material ui components, most notably the TextField component which is bound to the state using the value field, and invokes the handleChange event to set state from onChange.\n\nNow import and render within the App.js to try it out.\n\nHooks, < Lines and Simpler!\n\nOne of the most compelling features of hooks is that custom hooks can be created that utilize the built-in react hooks. Remember, they are normal javascript functions, which can take objects or functions as parameters and can return complex objects etc. and so elegant hooks can be created to manage the state and props of components, separating logic from rendering concerns.\n\nFor example, imagine we wanted a hook for an input component that manages its state, it’s validation onChange or onBlur, we could write a hook called useInput as follows:\n\nexport function useInput(name, defaultValue) {\n // set up the state for the inputs value prop and set it to the default value\n const [value, setValue] = useState(defaultValue);\n //set up state for the inputs error prop\n const [error, setError] = useState(null);

// set up the event handler for onChange event\n function handleChange(e) {\n // set the state no matter what\n setValue(e.target.value);\n // cancel any error\n setError(null);\n }

// set up event handler for onBlur, if value is not set, setError to true\n function handleBlur() {\n if(!value) return \n setError(true)\n }

// return object \n return {\n name,\n value,\n onChange: handleChange,\n onBlur: handleBlur,\n error\n };\n}\ntextCopy to clipboard\nWe name the function useInput. The convention use[CustomHookName] is suggested by the react team when creating custom hooks for linting purposes.\nThe function creates two state variables and corresponding mutators for the components value and error state\nIt then creates handlers for onChange and onBlur, onChange to set the value, and onBlur to validate\nFinally, we return an object with everything set up\n\nNow if we go back to our render method, we can call our new customHook towards the top of our modules as follow\n\nconst test = useInput(\"test\", \"\");\n//We can then apply the custom hook directly to our input control as follows:\ntextCopy to clipboard\n\nNow the custom hook and TextField are linked together. The state and events are managed within the hook, and the object returned by the hook passes the state and handlers to the TextField object using the spread operator to pass in as props.\n\nThe function for providing input state and functionality can be put in a library for future use and the logic is kept completely separate from the visual rendering and is managed in an intuitive way.\n\nThe custom hook can be reused then for multiple inputs if necessary e.g.\n\nconst email = useInput(\"email\", \"\");\nconst age = useInput(\"age\", \"\");\ntextCopy to clipboard\n\nAnother advantage of this is that unit tests can be written effectively around the custom hook function, and the logic for handlers and state are managed in one place in a straightforward way.\n\nLet’s take the example forward a little bit and make it a little more useful, adding in simple validation function and a custom hook for form submit. Create a /hooks folder and create a file called form.js within with the following evolution of our custom handler code:\n\nimport { useState } from \"react\";

// custom hook for input elements\nexport function useInput(name, defaultValue, validate, regex) {\n // set up the state for the input item and error\n const [value, setValue] = useState(defaultValue);\n const [error, setError] = useState(null);

// handle the onChange event\n function handleChange(e) {\n // set the state no matter what\n setValue(e.target.value);\n setError(null); \n }

// handle onBlur event\n function handleBlur() {\n handleValidate();\n }

// call validate if supplied and set error appropriately\n function handleValidate() {\n const valid = validate && validate(value, regex)\n setError(!valid);\n return valid;\n }

return {\n props: {\n name,\n value,\n onChange: handleChange,\n onBlur: handleBlur,\n error\n },\n validate: handleValidate\n };\n}\ntextCopy to clipboard\n\nIn the code above, we pass in a reference to a callback function, which takes the value and a regular expression as arguments. The user must create a validation function in this example but a library of validations could easily be created for common validations or a third party validation library could be used. The returned object also groups props into a sub-object and provides access to `validate` in order to allow an external caller to validate the value represented by the instance of the hook. We do this to allow the submit button to validate before form submission.\n\nFollowing is a custom hook for form submission, which takes an array of items returned from then custom input hooks and performs validation across all inputs on submit. If successful, it will call back to a success callback function passed as a parameter, whereby the containing component might send the data to a server.\n\nexport function useSubmit(inputs, success) {\n // set up the state for the inputs causing errors\n const [errorItems, setErrorItems] = useState(null);

// handle submit\n function handleSubmit(e) {\n e.preventDefault(); //prevent page refresh\n //validate every input (in case there was no blur event)\n const errorItems = inputs.filter(input => !input.validate());\n //persist the error items to state\n setErrorItems(errorItems);\n // if no errors, call success with name, value pairs as parameter\n if (errorItems && errorItems.length === 0) {\n success &&\n success(\n inputs.map(({ props: { name, value } }) => ({\n name,\n value\n }))\n );\n } \n }

return {\n props: {\n onSubmit: handleSubmit\n },\n errorItems\n };\n}\ntextCopy to clipboard\n\nThe main action above happens in handleSubmit:\n\nFirst, we prevent the default action to prevent a page refresh onSubmit\nWe then cycle through the inputs, calling to their individual validation handlers\nIf there are any invalid inputs, these are stored in errorItems state (and returned)\nIf there are no invalid items it calls back to the success call back function passing in the valid data, which would typically send the data to a server for persistence\n\nTo complete the demo, consider the final implementation of Form.js\n\nimport React, { useState } from \"react\";

import { makeStyles, useTheme } from \"@material-ui/styles\";\nimport {\n Paper,\n Button,\n Typography,\n Table,\n TableRow,\n TableCell,\n TextField,\n TableBody,\n TableHead\n} from \"@material-ui/core\";\nimport { useInput, useSubmit } from \"../hooks/form\";

//create a hook for classes objects\nconst useStyles = makeStyles(\n theme => ({\n root: {\n padding: theme.spacing.unit * 3\n },\n form: {\n marginTop: theme.spacing.unit * 3\n },\n input: {\n marginBottom: theme.spacing.unit * 3\n }\n }),\n { withTheme: true }\n);

// regular expression constants for validation \nconst validations = {\n // eslint-disable-next-line\n EMAIL: /^(([^<>()[\\]\\\\.,;:\\s@\\\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\\\"]+)*)|(\\\".+\\\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/,\n NUMBER: /^\\d*$/\n};

function Form() {\n // use of hooks to bring classes style sheet in (usually done with HOC)\n const classes = useStyles();\n // we can also use a hook to access the theme\n const theme = useTheme();

// our custom validation function, which the hook calls back to\nfunction handleValidation(value, regex) {\n // we could get fancy here with validations based on type of input\n // could be put in a form hook library and imported\n if (value && regex && value.match(regex)) return true;\n return false;\n }

const email = useInput(\"Email\", \"\", handleValidation, validations.EMAIL);\n const age = useInput(\"Age\", \"\", handleValidation, validations.NUMBER);\n // the data we're going to submit, just using a standard useState hook to display\n const [data, setData] = useState(null);

// our success handler when all items are validated\n function handleSuccess(data) {\n // we're just setting the state here, but typically this would\n // be sent to the server for further validation and persistence\n setData(data);\n }

//the custom hook that is called onSubmit, taking our two input hooks return values\n //as parameters, this means the state from the two inputs is available to this hook\n const submit = useSubmit([email, age], handleSuccess);

// our render method, which displays our form, text fields with error labels\n // hooked up to the custom hooks, it also renders data that has been successfully\n // validated by the form\n return (\n \n NearForm Hooks Demo\n \n Theme primary color = {theme.palette.primary.main} (obtained from\n useTheme hook)\n \ntextCopy to clipboard\n \n {email.props.error && (\n \n Invalid Email address\n \n )}

\n {age.props.error && (\n \n Invalid age\n \n )}

\n Submit\n \n {submit.errorItems && submit.errorItems.length > 0 && (\n \n {`Please fix ${submit.errorItems && submit.errorItems.length} form\n field error(s)`}\n \n )}\ntextCopy to clipboard\n {data && (\n \n \n \n Input Field\n Validated Input\n \n \n \n {data.map((item, index) => (\n \n {item.name}\n {item.value}\n \n ))}\n \ntextCopy to clipboard\n )}\n \n );\n}

export default Form;\ntextCopy to clipboard\nUseEffect\n\nThere are other hooks that are well worth investigating. I’ll give a brief example of useEffect, which can be used to set up and shut down correctly as part of a component’s lifecycle. With class based components there are some lifecycle methods, and again this can get confusing as some are deprecated.\n\nTypically, the most commonly used lifecycle methods are componentDidMount, componentDidUpdate and componentWillUnmount to perform actions on addition to the DOM, updates and removal respectively. Typically things like registering and deregistering from events are done here.\n\nConsider the following custom hook:\n\nimport { useState, useEffect } from \"react\";\nexport function useClock() {\n // set up our time state variable, mutator and initialize\n const [time, setTime] = useState(new Date().toTimeString().split(\" \")[0]);\n // timer callback handler\n function tick() {\n setTime(new Date().toTimeString().split(\" \")[0]);\n }

useEffect(\n () => {\n // set up timer to callback to tick\n // same as componentDidMount\n const timer = setInterval(tick, 50);\n return () => clearInterval(timer); // same as componentWillUnmount\n },\n [] // set up once, i.e. no re-register on update\n );\n return time;\n}\ntextCopy to clipboard\n\nA lot is happening in here in just a few lines of code:\n\nFirst, we call useState hook to set up the time state variable and setter function, we also initialise the time variable as a string (hh:mm:ss)\nWe then set up a tick function, which will be our timer callback function on interval expiration\nNext, we call useEffect, which sets up the timer interval, this is the same as componentDidMount and componentDidUpdate in a standard react class. The return of this removes the timer and is the same as componentWillUnmount\nThe second argument here [] ensures we only setup and tear down the timer once.\nFinally, we return the time state object, which we can use in our app to display the time\n\nE.g.\n\nconst time = useClock();\nreturn (\nCurrent Time: {time}\n)\ntextCopy to clipboard\n\nAs well as giving us the ability to do all of this within a function instead of a class, this really tidies up where code resides keeping the logic in one place for registering and tidying up, as well as managing state related to the hook\n\nThis could be used for creating hooks to interact with browser events like resizing, mouse movement or with apis centrally.\n\nE.g. to create a custom hook to capture browser mouse position\n\nfunction useMousePosition() {\n // set up pos state object, and initialize\n const [pos, setPos] = useState({x: 0, y: 0});\n useEffect(() => {\n // handler updates the state\n const handler = ({ clientX, clientY }) => setPos({ x: clientX, y: clientY });\n // create handler on mount, update\n window.addEventListener(\"mousemove\", handler);\n //perform cleanup\n return () => window.removeEventListener(\"mousemove\", handler);\n }, []);\nreturn pos;\n}\ntextCopy to clipboard\nOther Hooks\n\nThere are a few other hooks in the API including\n\nuseContext(): which takes a context object as an argument, when the context changes a re-render occurs with the value returned. This can be very useful for global updates to a site like language changes or currency update, or maybe global filters.\nuseReducer(): this behaves like useState, except the state is passed through a reducer dispatch function, which takes the state and action as parameters (anyone used to redux will understand the benefits of this).\nuseCallback(): creates a memoized function that is only called if inputs change\nuseRef(): used to create an object can be assigned to a ref prop on react components so that we can perform things like setFocus\nuseImperativeMethods(): used with nested refs so parent ref can select correct ref\nuseLayoutEffect(): this is the same as useEffect only it runs synchronously after the DOM is finished updating (favour useEffect).\nESLint Plugin\n\nReact have provided an eslint plugin tool to enforce some of the rules required regarding hooks. The main rule is that they must appear at the top of a module and should not exist within conditional statements because the order of creation is important.\n\nThe convention for creating custom hooks is to put the word ‘use’ at the front of your hook function name e.g. useTimer, useWindowPosition, useInput and so on.\n\nTo install the eslint plugin, ensure you first have eslint installed and saved as a development dependency npm install eslint --save-dev Then install the hooks linting plugin as a developer dependency npm install eslint-plugin-react-hooks@next --save-dev Then add the following to your esLink config section of package.json\n\n\"eslintConfig\": {\n \"extends\": \"react-app\", //should be already in present\n \"plugins\": [\n \"react-hooks\"\n ],\n \"rules\": {\n \"react-hooks/rules-of-hooks\": \"error\"\n }\n },\ntextCopy to clipboard\n\nFinally, add the following line to your scripts section in package.json\n\n\"lint\": \"eslint src/**/*.js\"\ntextCopy to clipboard\n\nSave and you can now run npm lint from the terminal and the hooks rules will be checked.\n\nTo try it out and verify if installed correctly, enclose a hook within an if statement and run the lint command.\n\nObservations\n\nI think in the very near future we will see lots of new useful libraries using hooks for many common tasks that were previously cumbersome to separate from component logic. One that immediately comes to mind is a set of hooks that abstract browser events. Typically, developers register and unregister listeners for common tasks like mouse position, keyboard strokes, window sizing, drag/drop and so on, and knowledge of these browser events is required and often being directly called within multiple components’ lifecycle events. As per the demo above, a couple of these are implemented as custom hooks and using them is as simple as calling a single function e.g. useResize. All of this logic can now be contained within a custom hook, which could greatly simplify many components. This could be done previously nesting components into HOCs or creating render props etc., but it would become a nesting nightmare, whereas with hooks a developer can simply pull in all the hooks necessary one-by-one at the top of the component making it exceptionally flat, clean and readable.\n\nA concern I have would be for future developers learning the technology. I think hooks will greatly simplify React development, which is fantastic, however for those new to the technology, it may lull them into a false sense of security in terms of their full understanding of the framework. For example, if they learn and become comfortable using React in this way and are then given the task to maintain code built using the mechanisms mentioned above, such as mixins, render props, HOCs etc., they may face challenges. This is no reason not to embrace hooks however, it’s just that experienced developers should be understanding when less seasoned react developers assist in the maintenance of such code.\n\nConclusion\n\nReact hooks are a fantastic addition to the React js Framework that will:\n\ngreatly simplify React components,\nmake code more easily testable,\nmake code more atomic (living up to the logo),\nreduce complexity,\nfacilitate simpler creation of shareable stateful logic,\nnaturally, organize code that is tightly related (e.g. registering and deregistering from events using useEffect),\nmake component lifecycle easier to manage,\nmake it easier to profile and debug,\nmake it more readable: no more this.state, this.props\nreduce the number of ways of doing things, making it quicker to learn\nResources and Links\n\nReact Hooks Demo Link\n\nReact Hooks Demo Github Repo\n\nReact Hooks Documentation\n\nExcellent article by Dan Abramov At NearForm, we have vast experience in building solutions across a broad tech stack to deliver reduced complexities and overcome common hurdles. If you are creating modern applications and leveraging web technologies, contact us to learn more about how we can help.\n\nYou might also like some of our previous blog posts on React:\nManaging React state with Render Props\nExploring React Portals\nSharing React components with Lerna\n\nImage credit: Robson Hatsukami Morgan on Unsplash" ], "categories": { "primary": "frontend", "others": [ "design", "product" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-design-observation": { "href": "https://nearform.com/digital-community/design-observation", "postType": "blog", "slug": "digital-community-design-observation", "date": "2019-01-30", "title": "Observation as a prerequisite for design", "authors": [ "JOE ALTERIO" ], "content": [ "Observation as a discipline is difficult to summarize, and sometimes even harder to express—it is a talent that takes practice. When performed well, design seems to be obvious, to be the natural state of things. However, only when a piece of work speaks to us in a language we understand do we fully engage. Noticing the world around you and allowing those observations to inform your work is the prerequisite to being a designer.\n\nUnlike more obvious talents, like shooting a basketball, the habits that often go hand in hand with becoming a designer—training your eye to notice the small affordances that turn something simply functional into something that speaks to a fellow human—are frustratingly undefinable. A lifetime spent noticing small placements in the world, when colors speak to you a certain way, or when items in a certain arrangement evoke a sense of harmony—these are interior, subrosa experiences. To allow this experience the interior nature of its magic is to allow that it it is sometimes exceedingly difficult to “Show Our Work”.\n\nI hesitate to label it innate, but for some, the talent of observation comes more naturally. I am the father of two little boys—one clearly has the innate design eye, and one does not. This is not a judgement or critique, just a fact. I can observe the younger one watching the shadows play on the walls as the sun sets; the other child is too busy with Lego engineering. The talent of design starts with a patience that comes from pausing and watching the planet turn. Designers are the shepherds of this lifetime of observations that may have been ignored or forgotten by others. Designers, especially the experienced ones, are rigorous in their insistence upon attention to detail, thinking through the meaning of these details, and allowing the process to develop that allows these details to inform the right solutions.\n\nStarting to think like a designer requires three essential steps: slowing down and observing a pattern in the world, recognizing the way that pattern makes you feel, and then attempting to replicate that feeling in another person by deploying that pattern. It’s the same process, be it an album cover, teapot, or digital product. In its most basic form, it is a trick of reflective experience. The best designers are practitioners of communicating the things that they themselves sense when they picture an ideal experience. In a field that relies heavily on empathy, communicating that empathy is the core component.\n\nObservation in itself is only the first step in the process. Design as a tool must be frequently wielded to be used deftly. However, it can be sharpened through the practice of taking the time to observe the world, how it moves, and how it affects people. While the base experience behind these moments is universal, applying the observations gleaned is what a good designer does." ], "categories": { "primary": "design", "others": [] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-fast-node-testing-mongodb": { "href": "https://nearform.com/digital-community/fast-node-testing-mongodb", "postType": "blog", "slug": "digital-community-fast-node-testing-mongodb", "date": "2019-02-06", "title": "Blazing Fast Testing in Node with MongoDB", "authors": [ "STEVEN MUSUMECHE" ], "content": [ "Look ma, no mocks!\nWhat is MongoDB?\n\nMongoDB is a document-based NoSQL database, and is a popular choice for applications in the Node ecosystem. In a traditional relational database, such as MySQL, data is stored as rows and columns within tables. MongoDB, however, stores documents, such as BSON objects (binary JSON), which live inside a collection.\n\nThere are many benefits to this model, such as high performance, availability, and dynamic schemas. There are also challenges, such as slow joins across collections, and a lack of simple transactions. This post is about testing in Node with MongoDB, however, and not about why you should or should not use MongoDB, so I’ll leave it to the pundits on Hacker News to hash that out.\n\nAutomated testing\n\nAutomated testing involves breaking down a program into smaller pieces, and subjecting each piece to a series of tests, which are themselves programs. Tests are usually run periodically, often after every change to the source code. A few benefits include the following:\n\nReduces production bug density 40% - 90%. Fewer bugs in production result in a dramatic decrease in maintenance time and costs.\nEnsures your code continues to work as the system grows and is modified–tests reduce future cost.\nImproves team velocity by establishing a fast-feedback loop. Passing tests provide multiple levels of confidence and will allow all members of the team to fearlessly develop, refactor, and merge code.\nEnsures that the code does what it says it does.\nProvides “Living Documentation” of how the system works.\n\nWhile automated tests can add 15-35% in initial development time, in the long run, they provide an inexpensive way to test your entire system after every change, and before involving your QA team (if you are lucky enough to HAVE a QA team). I highly recommend a robust test suite for any production application.\n\nUnit testing & mocks\n\nUnit testing is a particular type of automated testing that focuses on small pieces of your program (the “System Under Test”), as opposed to other systems it may interact with, but which are not being explicitly tested.\n\nTo isolate the behavior of the SUT, mocks are used in place of the real dependencies to simulate (“mock”) the behavior of its dependencies. This is useful because the real objects are often impractical to incorporate into the test—they may require extensive setup or significantly increase the test’s run time. Network requests and database queries are often great candidates for mocks, but they come with a few tradeoffs.\n\nWhat if you want to test code that is database-centric, such as a data model whose primary purpose is to interact with the database?\n\nYou could mock the database and make assertions on how you call it, but the level of confidence that provides is very low. Alternatively, you could use a real database in your tests, but that will be slow and require more infrastructure to manage, such as bringing up the database in a separate Docker container or cloud-hosting environment.\n\nNeither feels like a great option.\n\nmongodb-memory-server\n\nSay hello to mongodb-memory-server. This wonderful package programmatically downloads and spins up a real MongoDB server and holds the data in memory directly from Node, which is much more convenient than using an external Docker container or cloud-hosted database. This allows your tests to use a real database, but without suffering the usual downsides of slow connection speeds and more infrastructure.\n\nBecause the MongoDB server it creates has such a low memory footprint (each instance takes about 7MB of memory), you can simultaneously spin up multiple, independent databases and run your tests in parallel. Though subsequent runs will be very fast, the first time you run this package, it will be slow because it downloads the MongoDB binaries to a local cache.\n\nSystem Under Test (“SUT”)\n\nThe following is an example data model from an application that uses MongoDB. We’ll use it as our “SUT” for the remaining examples.\n\nexport default class Product {\n constructor(db) {\n this.db = db;\n this.collectionName = \"products\";\n this.collection = db.collection(this.collectionName);\n }\n\n /**\n * Find a specific product document by ID\n * @param {ObjectID} productId\n */\n findById(productId) {\n return this.collection.findOne({ _id: productId });\n }\n\n /**\n * Find a list of product documents by IDs\n * @param {ObjectID[]} ids\n */\n findByIds(ids) {\n return this.collection.find({ _id: { $in: ids } }).toArray();\n }\n\n /**\n * Find a list of product documents with the provided brand\n * @param {string} brandName\n * @param {MongoSort} [sort]\n */\n findByBrand(brandName, sort = {}) {\n return this.collection\n .find({ brand: brandName })\n .sort(sort)\n .toArray();\n }\n\n /**\n * Return a custom serialized product object\n * @param {ObjectID} productId\n */\n async serialize(productId) {\n const product = await this.findById(productId);\n const relatedIds = product.relatedProducts.map(({ _id }) => _id);\n const relatedProducts = await this.findByIds(relatedIds);\n\n return {\n id: product._id.toString(),\n model: product.modelNum,\n sku: `${product.brand}-${product.modelNum}`,\n title: product.name,\n brandName: product.brand,\n price: product.salePrice,\n listPrice: product.msrp,\n discount:\n product.salePrice > product.msrp\n ? product.salePrice - product.msrp\n : null,\n relatedProducts: relatedProducts.map(relatedProduct => ({\n id: relatedProduct._id.toString(),\n title: relatedProduct.name,\n brandName: relatedIds.brand\n }))\n };\n }\n}\njsCopy to clipboard\n\nBefore we write any code, let’s think about what we want to test.\n\nThe first two methods, findById and findByIds, are fairly straightforward. We want to verify that they return the document(s) associated with the provided ID(s).\n\nThe third method, findByBrand, is a little more complicated. It searches the product collection for documents with the “brand” property matching the provided brand name. It also allows an optional sort object, so we should exercise the code with and without a sort.\n\nFinally, the serialize method returns a “serialized” version of a product document. It renames a few properties, adds a few dynamic properties, and makes additional database queries so that it can return nested related products. We should test that the returned object has the properties and values that we expect, as well as the related products.\n\nTesting algorithm\n\nNow that we have an idea of WHAT we want to test, let’s figure out HOW to test it.\n\nIdeally, each test should run against a real database with real data, and run independently from any other test, even those that are running in parallel (thanks to the delightful Jest). We can accomplish that by following these steps:\n\nBefore each test suite (a grouping of related individual test cases):\n\na. Start up an independent MongoDB instance\n\nb. Create a connection to it\n\nBefore each test case:\n\na. Instantiate a new Product model (SUT from above)\n\nWithin each test case:\n\na. Insert the desired documents and collections into the database\n\nb. Call the method under test (for example, findByBrand) with the parameters needed for your desired outcome\n\nc. Make assertions on the result\n\nAfter each test case:\n\na. Remove any documents, collections, and indexes created in the test case\n\nAfter each test suite:\n\na. Close the connection to the database\n\nb. Stop the MongoDB instance\n\nAs you can see, a number of these steps are repeated many times, so we can create a shared library to help us.\n\nNow we have a game plan! Let’s write some code.\n\nHelper library\n\nWe’ll start with the helper library. We can import and use this library in all of our test suites.\n\nimport { MongoClient } from \"mongodb\";\nimport { MongoMemoryServer } from \"mongodb-memory-server\";\n\n// Extend the default timeout so MongoDB binaries can download when first run\njasmine.DEFAULT_TIMEOUT_INTERVAL = 60000;\n\nexport default class TestDbHelper {\n constructor() {\n this.db = null;\n this.server = new MongoMemoryServer();\n this.connection = null;\n }\n\n /**\n * Start the server and establish a connection\n */\n async start() {\n const url = await this.server.getConnectionString();\n this.connection = await MongoClient.connect(\n url,\n { useNewUrlParser: true }\n );\n this.db = this.connection.db(await this.server.getDbName());\n }\n\n /**\n * Close the connection and stop the server\n */\n stop() {\n this.connection.close();\n return this.server.stop();\n }\n\n /**\n * Delete all collections and indexes\n */\n async cleanup() {\n const collections = await this.db.listCollections().toArray();\n return Promise.all(\n collections\n .map(({ name }) => name)\n .map(collection => this.db.collection(collection).drop())\n );\n }\n\n /**\n * Manually insert a document into the database and return the created document\n * @param {string} collectionName\n * @param {Object} document\n */\n async createDoc(collectionName, document) {\n const { ops } = await this.db\n .collection(collectionName)\n .insertOne(document);\n return ops[0];\n }\n}\njsCopy to clipboard\nTest suite\n\nSweet! Now that we have our helper library, let’s move on to our test suite. Remember that we already mentally mapped out what we want to test and the testing algorithm to be used. All that’s left to do is implement it in code.\n\nWe’re going to use Jest as our test runner, but if you use another test runner (such as Mocha or tape), the same concepts apply.\n\nBefore and after hooks\n\nLet’s setup an outline, following the algorithm from above.\n\nimport TestDbHelper from \"../testUtils/testDbHelper\";\nimport Product from \"./Product\";\n\nconst dbHelper = new TestDbHelper();\n\nbeforeAll(async () => {\n await dbHelper.start();\n});\n\nafterAll(async () => {\n await dbHelper.stop();\n});\n\nlet product;\nbeforeEach(async () => {\n product = new Product(dbHelper.db);\n});\n\nafterEach(async () => {\n await dbHelper.cleanup();\n});\n\n// we'll write our tests here...\njsCopy to clipboard\n\nWe use Jest’s beforeAll and afterAll methods to start and stop the database server, respectively. We use Jest’s beforeEach to instantiate a new Product model, and afterEach to remove any documents, collections, and indexes created in the test case. This outline handles steps 1, 2, 4, and 5. Now, our individual tests cases only need to implement step 3.\n\nTesting findById and findByIds\n\nRecall from earlier that we want to verify that these methods return the document(s) associated with the provided ID(s). Since we have our before and after hooks already setup, we can focus on step 3:\n\nInsert the desired documents and collections into the database\nCall the method under test (findById in this case) with the parameters needed for the desired outcome\nMake assertions on the result\n// ...all previous code\n\ndescribe(\"findById\", () => {\n test(\"should return the correct document by ID\", async () => {\n // 1. Insert the desired documents and collections into the database\n const { product2 } = await createSampleProducts();\n\n // 2. Call the method under test with the parameters needed for the desired outcome\n const result = await product.findById(product2._id);\n\n // 3. Make assertions on the result\n expect(result).toMatchObject(product2);\n });\n\n test(\"should return null if a document with the provided ID could not be found\", async () => {\n const result = await product.findById(\"123456789123\");\n expect(result).toBeNull();\n });\n});\n\ndescribe(\"findByIds\", () => {\n test(\"should return the correct documents by ID\", async () => {\n const { product1, product3 } = await createSampleProducts();\n const result = await product.findByIds([product1._id, product3._id]);\n expect(result).toMatchObject([product1, product3]);\n });\n\n test(\"should return empty array if documents with the provided IDs could not be found\", async () => {\n const result = await product.findByIds([\"123456789123\"]);\n expect(result).toEqual([]);\n });\n});\n\n/**\n * Insert set of sample products into the database\n */\nasync function createSampleProducts() {\n const product1 = await dbHelper.createDoc(product.collectionName, {\n name: \"PLUS Sewing Quilting Machine\",\n modelNum: \"B880\",\n brand: \"Bernina\",\n salePrice: 349.99,\n msrp: 329.99,\n relatedProducts: []\n });\n const product2 = await dbHelper.createDoc(product.collectionName, {\n name: \"Mechanical Sewing Machine with Foot Pedal\",\n modelNum: \"10\",\n brand: \"Alphasew\",\n salePrice: 79.99,\n relatedProducts: []\n });\n const product3 = await dbHelper.createDoc(product.collectionName, {\n name: \"L460 Overlocker\",\n modelNum: \"L460\",\n brand: \"Bernina\",\n salePrice: 189.99,\n relatedProducts: []\n });\n const product4 = await dbHelper.createDoc(product.collectionName, {\n name: \"Sewing & Embroidery Machine\",\n modelNum: \"NQ3600D\",\n brand: \"Brother\",\n salePrice: 219.99,\n msrp: 249.99,\n relatedProducts: [product1._id, product3._id]\n });\n\n return { product1, product2, product3, product4 };\n}\njsCopy to clipboard\n\nVoila!\n\nTesting findByBrand\n\nThis method searches the product collection for documents with the “brand” property matching the provided brand name. It also allows an optional sort object, so we should exercise the code with and without a sort.\n\n// ...all previous code\n\ndescribe(\"findByBrand\", () => {\n test(\"should return matching documents with no sort\", async () => {\n const { product1, product3 } = await createSampleProducts();\n const result = await product.findByBrand(\"Bernina\");\n expect(result).toEqual([product1, product3]);\n });\n\n test(\"should return matching documents with custom sort\", async () => {\n const { product1, product3 } = await createSampleProducts();\n const result = await product.findByBrand(\"Bernina\", { salePrice: 1 });\n expect(result).toEqual([product3, product1]); // sorted by sale price, ascending\n });\n\n test(\"should return empty array if there are no matches\", async () => {\n const { product1, product3 } = await createSampleProducts();\n const result = await product.findByBrand(\"Unknown\");\n expect(result).toEqual([]);\n });\n});\njsCopy to clipboard\nTesting serialize\n\nThis is the most complex method in our Product model, so we’ll need to write a few more tests to make sure we cover all the edge cases.\n\n// ...all previous code\n\ndescribe(\"serialize\", () => {\n test(\"should return correct shape\", async () => {\n const { product4 } = await createSampleProducts();\n const result = await product.serialize(product4._id);\n\n expect(result).toMatchObject({\n id: String(product4._id),\n model: \"NQ3600D\",\n title: \"Sewing & Embroidery Machine\",\n brandName: \"Brother\",\n price: 219.99,\n listPrice: 249.99,\n // we'll test these in more detail in another test\n sku: expect.any(String),\n discount: expect.any(Number),\n discountPercent: expect.any(Number),\n relatedProducts: expect.any(Array)\n });\n });\n\n test(\"should return the correct SKU\", async () => {\n const { product4 } = await createSampleProducts();\n const { sku } = await product.serialize(product4._id);\n expect(sku).toBe(\"Brother-NQ3600D\");\n });\n\n test(\"should return the correct discount if msrp is higher than sale price\", async () => {\n const { product4 } = await createSampleProducts();\n const { discount, discountPercent } = await product.serialize(product4._id);\n expect(discount).toBe(30);\n expect(discountPercent).toBe(13);\n });\n\n test(\"should return a zero discount if msrp is lower than sale price\", async () => {\n const { product1 } = await createSampleProducts();\n const { discount, discountPercent } = await product.serialize(product1._id);\n expect(discount).toBe(0);\n expect(discountPercent).toBe(0);\n });\n\n test(\"should return a zero discount if msrp is not set\", async () => {\n const { product2 } = await createSampleProducts();\n const { discount, discountPercent } = await product.serialize(product2._id);\n expect(discount).toBe(0);\n expect(discountPercent).toBe(0);\n });\n\n test(\"should return the correct related products\", async () => {\n const { product1, product3, product4 } = await createSampleProducts();\n const { relatedProducts } = await product.serialize(product4._id);\n\n expect(relatedProducts).toEqual([\n {\n id: String(product1._id),\n title: \"PLUS Sewing Quilting Machine\",\n brandName: \"Bernina\"\n },\n {\n id: String(product3._id),\n title: \"L460 Overlocker\",\n brandName: \"Bernina\"\n }\n ]);\n });\n\n test(\"should return an empty array if there are no related products\", async () => {\n const { product1 } = await createSampleProducts();\n const { relatedProducts } = await product.serialize(product1._id);\n expect(relatedProducts).toEqual([]);\n });\n});\njsCopy to clipboard\nIn conclusion\n\nYou’ve now created a robust test suite for the Product model that uses a real database to exercise the code in a way that more closely resembles your production environment (no database mocks). And still, it runs very quickly. On a recent client engagement, we used this technique to run over 700 tests in a little under eight seconds.\n\nIsolating the system under test allows you to write unit tests that focus on small pieces of your program, as opposed to other systems not directly being tested. This enables you to carefully scrutinize the behavior of your SUT.\n\nBut in cases where the SUT is database-centric, such as a data model, we have to make a few concessions. We discussed several options available to us, but each comes with tradeoffs of increased runtime, complexity, or confidence.\n\nWe then examined mongodb-memory-server, a package that programmatically downloads and spins up a real MongoDB server that holds data in memory, directly from Node. This allows us to write our isolated unit tests with a real database, without the tradeoffs mentioned before.\n\nAnd most importantly, we can modify and refactor our code with the confidence that our test suite has our backs!\n\nAll of the code described in this post can be found in the [companion repository on GitHub.] (https://github.com/FormidableLabs/mongodb-testing)" ], "categories": { "primary": "test", "others": [ "backend", "data" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-utility-first-css-with-tailwind": { "href": "https://nearform.com/insights/utility-first-css-with-tailwind", "postType": "blog", "slug": "insights-utility-first-css-with-tailwind", "date": "2019-02-06", "title": "Utility-first CSS with Tailwind", "authors": [], "content": [ "An introduction to Tailwind\n\nUtility-first CSS is the notion of composing many small utilitarian classes together. With this, the aim is to allow you to create robust, scalable and responsive user interfaces for the web. Tailwind is a CSS framework that provides a suite of utility classes out of the box. It also allows you to compose and add your own classes where required.\n\nTailwind doesn’t prescribe any specific look or feel. You’re free to build to your desired design without having to undo anything the framework offers up front.\n\nA customisable config file drives the look and feel of your UI and provides default rules that you can tweak to suit your needs.\n\nIn this article, we’ll go into more depth on how you can use Tailwind to build a feature-rich user interface. We’ll also touch upon some of the more advanced features Tailwind has to offer.\n\nSetup\n\nAlthough Tailwind is available to use directly from a CDN it’s recommended to install it from npm . This allows you to take advantage of the full customisability Tailwind provides.\n\nFirst, install Tailwind as a development dependency;\n\nnpm install tailwindcss --save-dev\ntextCopy to clipboard\n\nOnce installed you need to initialise Tailwind’s configuration setup;\n\n./node_modules/.bin/tailwind init [custom filename]\ntextCopy to clipboard\n\nThis command generates a config file called tailwind.js (or the custom filename provided). This file contains all the predefined rules for colours, breakpoints, fonts, margins and more. The idea is that you remove a lot of the boilerplate and leave only the config required to build your UI. The file contains comments with an overview of each rule.\n\nFor example, the default responsive breakpoints provided by Tailwind are;\n\nscreens: {\n 'sm': '576px',\n 'md': '768px',\n 'lg': '992px',\n 'xl': '1200px',\n},\ntextCopy to clipboard\n\nThese are the minimum widths used to generate CSS media queries.\n\nIf desired you could adjust these to be ergonomic breakpoints and even add your own;\n\nscreens: {\n 'wrist': '576px',\n 'palm': '768px',\n 'lap': '992px',\n 'desk': '1200px',\n 'wall': '2560px'\n},\ntextCopy to clipboard\n\nTailwind uses PostCSS to generate CSS output from the directives and config provided. This means integrating a build step into your current development process is necessary. Integration is possible via various build tools such as Webpack , Gulp and more. Being built on PostCSS means you’re able to leverage the ecosystem of plugins to adapt to your build process.\n\nThe simplest solution to get up and running is to create a CSS file and use the @tailwind directive to include all Tailwind’s utilities.\n\n/* provides a set of base styles */\n@tailwind preflight;

/* injects in any component classes created via plugins, place custom component classes below this */\n@tailwind components;

/* injects in all Tailwind's utility classes, place custom utility classes below this */\n@tailwind utilities;\ntextCopy to clipboard\n\nYou can use the Tailwind npm module to build the CSS;\n\n./node_modules/.bin/tailwind build [input file path] -o [output file path]\ntextCopy to clipboard\n\nYou can then reference this output file path in a tag in your HTML;\n\n\ntextCopy to clipboard\nUtility Classes\n\nTailwind provides utility classes for a wide array of needs. This allows you to build a responsive, bespoke UI without necessarily needing to write any new CSS.\n\nFor example .text-lg by default is 1.5 rem of the base font size. .bg-dark-red will apply a dark red background based on the settings in your config file.\n\nThe values set in rules are configurable from your config file. This means if you want .text-lg to be twice the size of your base font you can customise it to be.\n\nYou can apply state variants such as hover or focus in the same way as responsive styles. .hover:bg-blue will turn the background blue when hovering over the desired element.\n\nTo combine both responsive and state variants at the same time make sure you prefix the responsive variant first. .xl:hover:bg-blue will mean the background is only blue on hover at the xl breakpoint.\n\n[caption id=\"attachment_300002593\" align=\"aligncenter\" width=\"2000\"]\n\nAnatomy of a Tailwind class[/caption]\n\nBelow is an example of a card component with dark and light variations adapted from an example in Tailwind’s documentation .\n\nThis markup uses no custom CSS, just utility classes from Tailwind:\n\n

\n
\n
\n \"Sunset\n
\n
A Warm Sunset
\n

\n A large drop of sun lingered on the horizon and then dripped over and\n was gone, and the sky was brilliant over the spot where it had gone,\n and a torn cloud, like a bloody rag, hung over the spot of its going.\n And dusk crept over the sky from the eastern horizon, and darkness\n crept over the land from the east.\n

\n
\n
\n #photography\n #sunset\n #summer\n
\n
\n
\n
\n
\n \"Sunset\n
\n
A Cold Sunset
\n

\n A large drop of sun lingered on the horizon and then dripped over and\n was gone, and the sky was brilliant over the spot where it had gone,\n and a torn cloud, like a bloody rag, hung over the spot of its going.\n And dusk crept over the sky from the eastern horizon, and darkness\n crept over the land from the east.\n

\n
\n
\n #photography\n #sunset\n #winter\n
\n
\n
\n
\ntextCopy to clipboard\n\nView example on CodeSandbox. One of the most powerful features we’re using here is the ability to create responsive grids with just a few classes. Flexbox powers this functionality under the hood.\n\nBy applying an outer .flex class we’re able to add classes to inner elements which dictate their widths. For example, w-full lg:w-1/2 xl:w-1/2 will create a full-width element at all breakpoints other than lg and xl , where the width will be half.\n\nWith this, you can create complex layouts by composing utility classes. You’re also free to create a grid layout that works for you rather than being prescribed one.\n\nGenerally, the utility class name syntax may take a while to get used to due to its shorthand nature. The comments within the generated config file and detailed website documentation are helpful.\n\nComponent Classes\n\nAs you may have noticed in the example above you can get to a point where you’re applying lots of utility classes to a single element. Use the same element in many places and you’re now having to update each one every time you need to make a tweak. This isn’t scalable.\n\nLuckily Tailwind has a solution to reduce this in the form of component classes.\n\nComponent classes allow you to extract many utility classes as well as custom CSS into new classes. This will provide you with a single source of truth for a specific piece of functionality.\n\nUsing Tailwind’s @apply directive we can create component classes to abstract these rules.\n\nHere’s the exact same design as the card example above built using component classes where deemed necessary:\n\n
\n
\n
\n \"Sunset\n
\n
A Warm Sunset
\n

\n A large drop of sun lingered on the horizon and then dripped over and\n was gone, and the sky was brilliant over the spot where it had gone,\n and a torn cloud, like a bloody rag, hung over the spot of its going.\n And dusk crept over the sky from the eastern horizon, and darkness\n crept over the land from the east.\n

\n
\n
\n #photography\n #sunset\n #summer\n
\n
\n
\n
\n
\n \"Sunset\n
\n
A Cold Sunset
\n

\n A large drop of sun lingered on the horizon and then dripped over and\n was gone, and the sky was brilliant over the spot where it had gone,\n and a torn cloud, like a bloody rag, hung over the spot of its going.\n And dusk crept over the sky from the eastern horizon, and darkness\n crept over the land from the east.\n

\n
\n
\n #photography\n #sunset\n #winter\n
\n
\n
\n
\ntextCopy to clipboard\n\nAnd here’s the newly created classes:\n\n.heading {\n @apply font-bold text-xl mb-2;\n}

.card {\n @apply overflow-hidden shadow-lg;\n}

.pill {\n @apply inline-block rounded-full px-3 py-1 text-sm font-semibold mr-2 cursor-pointer;\n}

@variants hover {\n .pill-light {\n @apply text-grey-lighter bg-grey-darker;\n }\n .pill-dark {\n @apply text-grey-darker bg-grey-lighter;\n }\n}

.pill-light {\n @apply bg-grey-lighter text-grey-darker;\n}

.pill-dark {\n @apply bg-grey-darker text-grey-lighter;\n}\ntextCopy to clipboard\n\nThis approach reduces the number of classes in the markup whilst delivering the exact same design. We’ve moved reused patterns to new classes allowing a single source of truth.\n\nYou’ll also see that we’re still composing utility classes alongside component classes. It’s not a choice between one or the other meaning you can have the best of both worlds.\n\nFor example, there’s no need to create a .card-dark class as that’d end up being @apply bg-grey-darkest; . You can use the .bg-grey-darkest class alongside the .card class in the markup.\n\nThis is one of the core concepts that gives Tailwind its power. While utilitarian at first glance Tailwind doesn’t force that pattern upon you.\n\nDirectives\n\nTailwind comes with a suite of predefined directives, we’ve come across three in this article already:\n\nthe @tailwind directive which allows you to import the core of Tailwind\nthe @apply directive which allows you to create new classes by composing other classes\nand the @variants directive, which we’ll take a deeper look at now\n\nIn the card example above we’re using the @variant directive to merge our pill hover styles into a single class. This is a powerful way of creating stateful variants of your own utility or component classes. You can use the @variant directive to create focus, active or group-hover specific classes.\n\nHere’s how we used the @variants rule in the example above to create hover variants for our custom component classes:\n\n@variants hover {\n .pill-light {\n @apply text-grey-lighter bg-grey-darker;\n }\n .pill-dark {\n @apply text-grey-darker bg-grey-lighter;\n }\n}\ntextCopy to clipboard\n\nThe @responsive directive will create a suite of responsive classes for any new classes you wrap within it;\n\n@responsive {\n .blur {\n filter: blur(30px);\n }\n}\ntextCopy to clipboard\n\nThis will generate classes prefixed with your responsive breakpoint names. For example, .sm:blur will only apply a blur to images at the small breakpoint.\n\nFinally, the @screen directive allows you to target the already defined breakpoints. This avoids rewriting media queries and having to keep them in sync.\n\n@screen md {\n .blur {\n filter: blur(20px);\n }\n}

@screen lg {\n .blur {\n filter: blur(10px);\n }\n}\ntextCopy to clipboard\n\nThis example will provide stepped levels of blurriness depending on the breakpoint to any images with the blur class applied to it.\n\nDirectives are another powerful way to extend custom classes. They can help provide all the features you get from Tailwind’s utility classes to your own custom classes.\n\nCSS-in-JS Integration\n\nHere at NearForm , we use a variety of solutions to build user interfaces. We tailor solutions to the specific needs of clients and their projects.\n\nCSS-in-JS libraries such as Styled Components or Emotion as well as frameworks such as Material-UI are amongst our arsenal. Given this, it’s worth investigating how Tailwind integrates with these tools.\n\nHere’s an example of usage with Styled Components and React ;\n\nimport React from \"react\";\nimport styled from \"styled-components\";\nimport tw from \"tailwind.macro\";\nimport sunsetWarm from \"./sunset-warm.jpg\";

const Container = styled.div`\n ${tw`p-6 w-full lg:w-1/2 xl:w-1/2`}\n`;

const Card = styled.div`\n ${tw`overflow-hidden shadow-lg`}\n`;

const Image = styled.img`\n ${tw`w-full`}\n`;

const InnerContainer = styled.div`\n ${tw`px-6 py-4`}\n`;

const Text = styled.div`\n ${props => props.type === \"heading\" && tw`font-bold text-xl mb-2`}\n ${props =>\n (props.type === \"paragraph\" || !props.type) &&\n tw`text-grey-darker text-base`}\n`;

const Pill = styled.span`\n ${tw`inline-block bg-grey-lighter rounded-full px-3 py-1 text-sm font-semibold text-grey-darker cursor-pointer hover:text-grey-lighter hover:bg-grey-darker`}

&:not(:last-child) {\n ${tw`mr-2`}\n }\n`;

export const App = () => (\n \n \n \"Sunset\n \n A Warm Sunset\n \n A large drop of sun lingered on the horizon and then dripped over and\n was gone, and the sky was brilliant over the spot where it had gone,\n and a torn cloud, like a bloody rag, hung over the spot of its going.\n And dusk crept over the sky from the eastern horizon, and darkness\n crept over the land from the east.\n \n \n \n #photography\n #sunset\n #summer\n \n \n \n);\ntextCopy to clipboard\n\nIn the example above we’re using the Babel Macro babel-plugin-tailwind-components . This plugin exposes the tw`` tagged template literal function to convert Tailwind classes into style objects.\n\nThis example works well and allows further abstraction via Styled Component’s visual primitives.\n\nThere are some caveats worth highlighting when trying to integrate Tailwind into a CSS-in-JS toolchain;\n\nYou’re still going to need to amend your toolchain to accommodate a build step for Tailwind\nYou’ve now got two places you can write styles. How do you ensure consistency?\nThe component style of a library like React feels somewhat at odds with the component style of Tailwind. You’re now able to componentise either via Tailwind with the @apply directive or in React with a component. A decision is now required on where any abstractions live.\n\nIf CSS-in-JS is your jam then there are ways to integrate the two workflows. However, you may end up not gaining the full benefits of either solution when used together.\n\nProduction Builds\n\nBy default Tailwind clocks in at around 36kb in size without any customisation, once minified and gzipped.\n\nOnce you begin to configure Tailwind to suit your UI look and feel you’ll be able to remove a lot of the predefined configuration Tailwind provides.\n\nFor example, if you trim the colour configuration down from the 73 colours provided by Tailwind to 25 colours you’ll reduce the bundle size down to 18kb. Similarly, if you reduce down the breakpoints from 5 to 3 you’ll shave 14kb off the bundle size.\n\nFinally, by integrating a tool like PurgeCSS into your workflow you can remove any unused classes at build time. This means you’re only ever serving the classes your application uses.\n\nFinal Thoughts\n\nTailwind takes the benefits of CSS utility classes and extends upon them. By allowing composability and extensibility Tailwind provides an impressive developer experience. One where you can be productive straight away whilst not being tied to a predefined look and feel.\n\nThe lack of prescribed visual styles can be a huge boost to productivity. The speed with which you can compose a complex, responsive UI with its own look and feel is staggering.\n\nIf you looking for a team to deliver a rapid prototype using tools like Tailwind then don’t hesitate to get in touch. Cover image credit" ], "categories": { "primary": "frontend", "others": [ "design" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-say-hello-to-react-browser-hooks": { "href": "https://nearform.com/insights/say-hello-to-react-browser-hooks", "postType": "blog", "slug": "insights-say-hello-to-react-browser-hooks", "date": "2019-02-07", "title": "Say Hello to React Browser Hooks", "authors": [], "content": [ "React Browser Hooks\n\n‘React Browser Hooks’ is an Open Source library containing several custom hooks that integrate with common browser functionality.\n\nThe Problem & Our Motivation\n\nOften browser events and functions are directly added to components, which can:\n\nAdd significantly to a component’s footprint\nDilute the core functionality and purity of the component leading to less readable code\nCreate disjointed code where related logic ends up apart, leading to less maintainable code\nRequire the use of lifecycle events or state to manage, meaning a React class component must be used instead of a stateless functional component\nTake some investigation for a developer to figure out (especially if there are nuances), resulting in lost time / inaccurate estimations of tasks\nBe non-standard between browsers, meaning developers have to research cross-browser support and register multiple events / call multiple functions e.g. WebKit, Microsoft, opera and Mozilla versions of events.\nLead to memory leaks if the lifecycle is not managed correctly\nSometimes require throttling (for rapid-fire events like scrolling or mouse position to minimise the impact on performance)\nLead to re-inventing the wheel\n\nWe did some rudimentary research on common browser events and, from a basic search, found that there are over 150,000 modules on GitHub that add event listeners directly, tens of thousands of which are specific browser events including ‘mousemove’, ‘fullscreen’, ‘resize’ and many others. These are typically registered in component lifecycle event ‘componentDidMount’ and deregistered or removed in the ‘componentWillUnmount’ event. Our initial research revealed that up to 25% of registered events may not be deregistered. It also highlighted that the same browser integration code is being repeated over and over, and so it’s a real case of developers re-inventing the wheel.\n\nInternally within our projects, we have often implemented listeners directly within components, and so we felt a library of hooks would be useful to standardise and simplify the re-use of these types of browser events.\n\nWhy Hooks?\n\nReact Hooks are a new addition to React.js , that makes it much easier to create and use libraries of application logic that are made up of complete vertical slices of a component. Previous methods for separating application/presentation logic sometimes lead to ‘nesting hell’, and often developers didn’t bother creating/importing libraries for very simple functions as a result.\n\nCheck out Dan Abramov’s article on what should and shouldn’t be a hook.\n\nExample Before Hooks\n\nImagine you wanted to create a button component, for a video player, that when clicked opened the browser in fullscreen mode. You might implement something like the next example.\n\nimport React from 'react'\n\nclass FullScreenButton extends React.Component {\n constructor(props) {\n super(props)\n this.state = {\n fullscreen: false\n }\n }\n\n handleFullscreenChange = (e) => {\n let fullscreen = false\n if (document.fullscreenElement ||\n document.mozFullScreenElement||\n document.webkitFullscreenElement ||\n document.msFullscreenElement ||\n document.fullscreen ||\n document.mozFullScreen ||\n document.webkitIsFullScreene ||\n document.fullScreenMode ) {\n fullscreen = true\n }\n this.setState ({fullscreen})\n }\n\n handleToggle = (e) => {\n const el = document.documentElement\n if(!this.state.fullscreen) {\n if (el.requestFullscreen) {\n el.requestFullscreen()\n } else if (el.mozRequestFullScreen) {\n el.mozRequestFullScreen()\n } else if (el.webkitRequestFullscreen) {\n el.webkitRequestFullscreen()\n } else if (el.msRequestFullscreen) {\n el.msRequestFullscreen()\n }\n } else {\n if (document.exitFullscreen) {\n document.exitFullscreen()\n } else if (document.mozCancelFullScreen) {\n document.mozCancelFullScreen()\n } else if (document.webkitExitFullscreen) {\n document.webkitExitFullscreen()\n } else if (document.msExitFullscreen) {\n document.msExitFullscreen()\n }\n }\n }\n\n componentDidMount() {\n document.addEventListener('webkitfullscreenchange', this.handleFullscreenChange, false)\n document.addEventListener('mozfullscreenchange', this.handleFullscreenChange, false)\n document.addEventListener('msfullscreenchange', this.handleFullscreenChange, false)\n document.addEventListener('MSFullscreenChange', this.handleFullscreenChange, false) //IE11\n document.addEventListener('fullscreenchange', this.handleFullscreenChange, false)\n }\n\n render() {\n return {\n \n )\n }\n\n componentWillUnmount() {\n document.removeEventListener('webkitfullscreenchange', this.handleFullscreenChange)\n document.removeEventListener('mozfullscreenchange', this.handleFullscreenChange)\n document.removeEventListener('msfullscreenchange', this.handleFullscreenChange)\n document.removeEventListener('MSFullscreenChange', this.handleFullscreenChange)\n document.removeEventListener('fullscreenchange', this.handleFullscreenChange)\n }\n}\n\nexport default FullScreenButton\njsCopy to clipboard\n\nAs you can see from above, there can be a lot of events for multiple browsers and code mucking up a component that could be much purer. All of this ends up in the component before any further logic is added.\n\nConsider the same component using a custom fullscreen hook from a library like react-browser-hooks:\n\nimport React from 'react'\n\nimport { useFullScreen } from '@nearform/react-browser-hooks'\nexport default function FullScreenButton () {\n const {toggle} = useFullScreen()\n return (\n \n \n )\n}\njsCopy to clipboard\n\nIn this example, the entire vertical slice of full-screen functionality has been stripped from the component. All of the logic that deals with activating full-screen mode and discovering fullscreen status, is now in its own tidy library that can be used by any future component that requires this functionality. In this case, a button component might even be unnecessary as the hook could be used directly within the video player component, whose main element could be passed indirectly to the hook and toggle could be fired from a doubleClick event.\n\nThere are other nuances with full-screen functionality, that often developers may not consider until they have to implement it (adding unknown time to an estimated task), e.g. is the application full screen because of the browser menu full-screen option or is it because an element was made full-screen from within an application. These are the kinds of things a developer shouldn’t have to worry about solving. It’s something a library like react-browser-hooks should take care of.\n\nAll of these initial hooks were developed with passion, care and interest by developers who always strive to write good code.\n\nThe first version of react-browser-hooks contains hooks for various common tasks including:\n\nOnline/Offline hook: Determine if the browser has an Internet connection.\nOrientation hook: Determines the angle of orientation of the screen\nGeoLocation hook: Gets the user’s current location and keeps it updated as they move, very handy for mapping applications.\nMouse Position hook: Gets the current mouse coordinates\nScroll hook: Gets the current browser scroll left and top positions\nResize hook: Gets the width and height of the page\nFull-Screen hook: Determines if the screen or an element is in full-screen mode, a second hook exists to check if the browser is full screen (e.g. F11 on menu)\nPage Visibility hook: If you browse away or back to a tab, this hook will let your component know (maybe hibernate some activity or set the tab title to something to entice them back).\nMedia Controls hook: Provides access to media controls like play, pause, seek and volume for controlling audio/video elements.\n\nWe can put together hooks, like in this demo using several of the hooks above to render a video. It uses media controls, mouse position, screen resize as well as fullscreen hooks together. Check the \"Babel\" tab to see how quickly you can create something powerful with react browser hooks. The play and pause buttons use media controls hook, the fullscreen icon in the bottom corner uses the fullscreen hook, and try set different sizes using the codepen toolbar and move the mouse around to see it respond accordingly.\n\n[codepen_embed height=\"443\" theme_id=\"0\" slug_hash=\"dajZBd\" default_tab=\"result\" user=\"donovanh\"]See the Pen Browser hooks example: video by Donovan Hutchinson ( @donovanh ) on CodePen .[/codepen_embed]\n\nWe plan on adding more over time as demand dictates. We also see this library as a handy base library for building some more complex libraries on top and we invite others to use it for such purposes.\n\nTesting\n\nOur goal is to have an extremely solid set of hooks that work seamlessly across as many browsers as possible. In terms of testing, as part of our continuous integration process, we have unit tests and coverage analysis in place. We also use netlify to deploy our demo on every branch submitted so reviewers can test out code that is undergoing a pull request.\n\nWe appreciate feedback from the community should any errors be found in this early version of react-browser-hooks.\n\nSee our demo (which doubles as our documentation), for more information on each of these custom hooks and to see them in action.\n\nTo install the package into your project use ‘ react-browser-hooks ’\n\nThen import a hook and use it within a functional component. You can literally integrate them in seconds.\n\nIf you would like to contribute to this project or raise an issue/request, please visit our GitHub project page At NearForm, we have vast experience in building solutions across a broad tech stack to deliver reduced complexities and overcome common hurdles. If you are creating modern applications and leveraging web technologies, contact us to learn more about how we can help. Learn more about React User Interface design at NearForm.\n\nYou might also like some of our previous blog posts on React:\nForget everything you learned about React - Hooks rocks! \nManaging React state with Render Props\nExploring React Portals\nSharing React components with Lerna\n\nImg Credit: PixaBay" ], "categories": { "primary": "frontend", "others": [ "oss" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-five-ways-node-js-benefits-todays-digital-enterprise": { "href": "https://nearform.com/insights/five-ways-node-js-benefits-todays-digital-enterprise", "postType": "blog", "slug": "insights-five-ways-node-js-benefits-todays-digital-enterprise", "date": "2019-02-08", "title": "Five Ways Node.js Benefits Today's Digital Enterprise", "authors": [], "content": [ "Download our E-book on how Node.js benefits today's enterprise\n\nFrom speed to market and modern architectures to developer skills and the Open Source community, discover how Node.js benefits today's enterprise. Prior to the cloud, software was built and delivered as single monolithic units requiring dedication of significant resources capable of running for months, or even years, without restart. Building cloud-native projects requires a shift in paradigm to a model of continuous delivery and continuous evolution of decomposed microservices that the previous generation of runtimes was not designed for. Node.js is now one of the fastest growing runtimes in the cloud and this eBook takes a look at the reasons why many global brands are adopting it. As of today, Node.js has been used to develop all kinds of user-facing applications, whether these are net new projects or involve the modernisation of existing applications. In the eBook you will learn:\n\nHow Node.js is improving developer productivity\nSome of the ways in which you can use Node.js to reach optimum performance of your applications\nWhy Node.js has fuelled both microservices-based and serverless architectures\n\nNeed Node experts for your next project? Contact us today to see how we can help!\n\nSubmit the form below to download our E-book" ], "categories": { "primary": "backend", "others": [ "cloud", "oss" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-animation-in-react": { "href": "https://nearform.com/insights/animation-in-react", "postType": "blog", "slug": "insights-animation-in-react", "date": "2019-02-14", "title": "Animation in React", "authors": [], "content": [ "Animating your React apps doesn't have to be a hassle. With these helpful components and prebuilt animation keyframes, you'll be adding animation to your apps in no time.\n\nAnimating is difficult\n\nWe often forget about how animation is going to feature into our web projects. It's easy to let this happen - designs tend to take shape in the form of flat images, and when we're coding we're thinking about browser compatibility, screen sizes, and the implementation of features. How UI moves often finds itself thrown in as an afterthought.\n\nThis can cause issues. Sometimes parts of our UI need to move. They need movement to smooth the transition between states or to draw attention to the most important action or newest content.\n\nFor example, we might want to add a little animation when a price changes so that people don’t miss it, as in this little example:\n\n[codepen_embed height=400 theme_id=1 slug_hash='aXGmpR' user='donovanh' animations='run'] See the example on CodePen [/codepen_embed]\n\nIt can become a problem when we leave this to last and put together quick solutions as needed, we can create situations where our animations aren't consistent, applied to the wrong things, or even forgotten entirely.\n\nIntroducing React Animation\n\nWe've been working on ways to make adding UI animation to React projects quicker and easier, including releasing a new package called React Animation . React Animation is a helpful package of wrapper components along with pre-built animations you can apply to projects easily.\n\nWhy not just use something else? That's a fair question. There are lots of good ways of building animations into our React UI. React Transition Group offers a handy approach to adding and removing classes so that we can then apply animations to it. Unfortunately though, React Transition Group doesn't bring any animations, you still need to handle that part yourself. On the other hand, projects like React Spring offer advanced animation tools for handling large sets of animated elements.\n\nWhat we needed was something in between - something that made it easy to apply animation to elements and offered a consistent set of pre-built animations we could apply to our projects knowing that the results would be reliable and consistent. It had to be easy to install and use, and offer enough flexibility that we could customise the animations to suit the project. It also gave us an opportunity to build using React hooks !\n\nLet's take a look at what React Animation can do, starting with the helper components.\n\nAnimateOnChange\n\nThe repo includes components you can wrap around your content and they'll apply animation as needed. The first is AnimateOnChange .\n\nSometimes you want to have a little movement on screen to let people know when some content has changed. Writing this functionality for lots of small pieces of UI can quickly become a hassle, so instead you can simply wrap your content in the AnimateOnChange component.\n\nWe can get started by running npm install react-animation . Then the component is used as:\n\nimport { AnimateOnChange } from ‘@nearform/react-animation’\n\n Your content, components etc here\n</AnimateOnChange>\ntextCopy to clipboard\n\nThis component will respond to any change in the \"children\" content by applying a simple fade-out then fade-in animation with the new content. We can see the effect on this example:\n\n[codepen_embed height=400 theme_id=1 slug_hash='exEKgV' user='donovanh' animations='run'] See the example on CodePen [/codepen_embed]\n\nThere's more we can do with this component. We can pass in properties to control how the animation works. One option is to supply a durationOut value (a number of milliseconds). This “durationOut” is the time the “out” animation will take (when the old content is animated away). We can set this to a larger or smaller number to change the feel of the fade animation. Here’s a slower example with a durationOut value of 1,500:\n\n[codepen_embed height=400 theme_id=1 slug_hash='omeMyY' user='donovanh' animations='run'] See the example on CodePen [/codepen_embed]\n\nBy passing in animationIn and animationOut properties, we can have other animations apply when the content changes. These take the name of one of the included animations in the package. You can find a full list of these animations at the end of this post.\n\n\n Your content, components etc here\n</AnimateOnChange>\ntextCopy to clipboard\n\nThis makes use of the built-in bounce animations. Here it is in action:\n\n[codepen_embed height=400 theme_id=1 slug_hash='PVKdZy' user='donovanh' animations='run'] See the example on CodePen [/codepen_embed]\n\nIf we need even more control, we can set any properties we like on the component using the style property. This is just like the “style” property in React, and accepts an object containing style rules in the normal way.\n\nCustom animations\n\nIf you want to create your own custom animations for the AnimateOnChange component, there are two ways do to so. First, you can create your own keyframes and pass in your own animation string to both the animationIn and animationOut properties.\n\n\n Your content\n</AnimateOnChange>\ntextCopy to clipboard\n\nThis will run the animation keyframes “my-anim-out” when hiding the content, and “my-anim-in” on the when showing the new content. We could define these keyframes like so:\n\n@keyframes custom-animation-in {\n from {\n transform: rotateX(140deg) scale(32);\n }\n to {\n transform: none;\n }\n}

@keyframes custom-animation-out {\n from {\n transform: none;\n }\n to {\n transform: rotateX(-270deg) scale(0);\n }\n}\ntextCopy to clipboard\n\nThis would result in a 3D rotating zoom effect, as seen here:\n\n[codepen_embed height=400 theme_id=1 slug_hash='MLBmJX' user='donovanh' animations='run'] See the example on CodePen [/codepen_embed]\n\nA second approach is to use classes . If you have a situation where you need to animate an element’s pseudo-element, or some element’s children, you might want to have a top left class applied for when the animation is in the “in” or “out” state. You can do this by specifying className.\n\n\n Your content\n</AnimateOnChange>\ntextCopy to clipboard\n\nThis will apply the classes “foo-in” and “foo-out” for each stage. Here’s an example of it in action.\n\n[codepen_embed height=400 theme_id=1 slug_hash='pGdzQw' user='donovanh' animations='run'] See the example on CodePen [/codepen_embed]\n\nHaving parts of your UI animate can be very useful for making sure people notice when information changes. You could use it to update a value in a live-streamed data set such as stock prices, or to call attention to when an item has been added to a shopping basket. The possibilities are endless.\n\nHideUntilLoaded\n\nSome components make use of a background image, or some other featured image that can be dynamic and so potentially a large file size. We wouldn’t want the component to display before we know that the image has loaded as this could result in showing partially-loaded images. Sometimes, instead, you want a component to stay hidden until an image has completed loading. This is where HideUntilLoaded helps.\n\nYou can use this in a similar way, wrapping your content and in this case telling it which image to wait for.\n\n\n Your content here\n\ntextCopy to clipboard\n\nYou can see this in action here:\n\n[codepen_embed height=400 theme_id=1 slug_hash='pGrBvM' user='donovanh' animations='run'] See the example on CodePen [/codepen_embed]\n\nWe can even go further and pass in our own Spinner component that will show when loading is taking place.\n\n\n Your content here\n\ntextCopy to clipboard\n\n[codepen_embed height=400 theme_id=1 slug_hash='ErvJqo' user='donovanh' animations='run'] See the example on CodePen [/codepen_embed]\n\nFinally, we can also specify an animationIn for when the content has loaded. In this case we'll use the popIn animation (find these and more example animations on this demo page ).\n\n\n Your content here\n\ntextCopy to clipboard\n\n[codepen_embed height=400 theme_id=1 slug_hash='KJvLyq' user='donovanh' animations='run'] See the example on CodePen [/codepen_embed]\n\nThe HideUntilLoaded component could be useful if you have a component that relies on a large background image - this could be product images with drop shadows and text overlays, or media components with photos and text information. These can be held back until ready and then animated in together.\n\nPrebuilt keyframes\n\nThe package also includes some helpful pre-built animations you can use. You can even bring them into your project without using either of the above helper components. To import them, you'll also need the associated keyframes, like so:\n\nimport 'react-animation/dist/keyframes.css'\nimport { animations } from 'react-animation'\ntextCopy to clipboard\n\nWith the keyframes imported, we can use the animations object in our component styles. An example might be when you want a component to pop in on first load. We could make use of the animation like so:\n\nconst style = {\n animation: animations.popIn\n}

const MyComponent = () =>

My Component
\ntextCopy to clipboard\n\nIn this example, animations.popIn evaluates to pop-in 500ms cubic-bezier(0.19, 1, 0.22, 1) forwards . You can use any of the built-in animations:\n\nfadeIn\nfadeOut\nfadeInUp\npopIn\npopOut\nbounceIn\nbounceOut\nslideIn\nslideOut\nGive it a go\n\nCan you think of situations where animation could help your UI? Maybe you want to draw attention to an important button, or fade-in new items in a list. If so, feel free to try React Animation. You can get started using:\n\nnpm install react-animation\ntextCopy to clipboard\n\nFrom there you can import the components:\n\nimport { AnimateOnChange, HideUntilLoaded } from 'react-animation'\ntextCopy to clipboard\n\nThey will automatically bring in the needed keyframes definitions, so you can then use the components in your app!\n\nI hope you find this a helpful and easy way to add animation to your projects.\n\nAt NearForm, we have vast experience in building solutions across a broad tech stack to deliver reduced complexities and overcome common hurdles. If you are creating modern applications and leveraging web technologies, contact us to learn more about how we can help. Learn more about React development at NearForm.\n\nYou might also like some of our previous blog posts on React:\nForget everything you learned about React – Hooks rocks! \nManaging React state with Render Props\nExploring React Portals\nSharing React components with Lerna" ], "categories": { "primary": "frontend", "others": [ "design" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-some-useful-terms-to-know-when-working-with-a-developer": { "href": "https://nearform.com/insights/some-useful-terms-to-know-when-working-with-a-developer", "postType": "blog", "slug": "insights-some-useful-terms-to-know-when-working-with-a-developer", "date": "2019-02-18", "title": "Some useful terms to know when working with a developer.", "authors": [], "content": [ "Here’s a handy list of commonly-used terms, acronyms and buzzwords that you’ll need to know if working with or within the world of software development, digital design and open source. Whether you are a business-user needing to understand the meaning of the tools, technologies & methodologies used by your IT department or a developer exploring new topics, tutorials & documentation, this will help you get there faster!\n\nAgile\n\nA technical project management methodology with a philosophy centred on enabling rapid product iteration to improve both time-to-market and market responsiveness.\n\nWhile a significant industry has grown around Agile with instituted norms, conventions and disciplines the Agile philosophy only describes four binary prioritizations:\n\nIndividuals and interactions over processes and tools\nWorking software over comprehensive documentation\nCustomer collaboration over contract negotiation\nResponding to change over following a plan\n\nThe antithesis to Agile is Waterfall, in fact, Waterfall implicitly reverses the above prioritizations. Enterprise organisations undergoing Digital Transformation typically adopt an Agile planning approach in isolation to pre-existing Waterfall strategies.\n\nHere is a Glossary of Agile Terms.\n\nApache Kafka\n\nApache Kafka is an open-source, stream-processing, software platform written in Scala and Java. The project aims to provide a unified, high-throughput, low-latency platform for handling real-time data feeds. Its storage layer is essentially a \"massively scalable pub/sub message queue designed as a distributed transaction log,\" making it highly valuable for enterprise infrastructures to process streaming data\n\nAPIs\n\nAn acronym standing for Application Programming Interface. An API is essentially a contract. Systems are composed of groups of logic. Whenever a group of logic has a discrete boundary, a predefined way to interact with that group of logic must be exposed. These logic groupings may be in the form of Components, Services, Classes, Modules, Lambdas, Middleware, Plugins, Functions, or Servers. These words can also mean different things in different contexts, but they are always groups of logic. In every case, an API is required to allow for coordination between logic groups. In an Enterprise engagement context, developers would need to know relevant API’s in order to integrate a solution against pre-existing technologies in the business.\n\nAPI access controls and gateways\n\nEssential technical security layers that are responsible for allowing or denying access based on authorized identity, quotas, geographical origin and any other aspects as specified by business or legal policy.\n\nBack end\n\nGenerally the server-side. Depending on the context, may also refer to the logic that is further back than logic close to the front. For instance, Back end could refer to a Node.js implementation when spoken of in the context of a React + Node implementation, whereas it may refer to a legacy system when spoken of in the context of a Node implementation built atop a clients Legacy API.\n\nBI\n\nBusiness Intelligence. A key focus for Enterprise organisations undergoing Digital Transformation. Requires the integration of tools, processes, workflows and cultural changes in order to provide a technology backbone that allows for the collection, analysis and reporting of Big Data such that it informs the decision-making and strategic outcomes.\n\nCommit\n\nIn order to allow collaboration with minimal conflict, developer teams use a Version Control System. A commit can be thought of as a snapshot of development work that a developer creates in order to add code to a project. These snapshots are linked together so that the entire development history of the project is available. This allows for a project to be distributed across people, all one needs to do is keep the commits synchronized. A remote repository is typically the source of truth for all commits, developers will push their commits to this repository and pull others commits from it.\n\nContributor\n\nSomeone who regularly commits to a remote repository. See Commit.\n\nContainer\n\nAn isolated environment which provides a discrete boundary around code. Containers support the decomposition of functionality into Microservices by providing a light-weight way to isolate each service - essentially sandboxing it from other services to reduce risk. Services could be deployed on multiples Virtual Machines or on multiple Bare Metal machines to achieve the same effect but this would be vastly more expensive. Enterprise organisations undergoing Digital Transformation will typically use Containers to deploy their Microservices. Docker is the tool of choice for Container development while Kubernetes is the winning platform for the deployment of Containers.\n\nCI/CD\n\nContinuous Integration/Continuous Deployment. When used in a discussion this acronym relates to the tooling required to enable incremental changes to a code base (integration) and incremental deployments of that code base. This tooling is essential for projects that have adopted an Agile approach.\n\nDistributed System\n\nA system which has been carved up into logical pieces which are independently deployed. These lead to the need for communication between parts of the system over a network, and the need to think differently as to how state is managed. The Microservices architecture is a common example of a distributed system.\n\nDistributed Tracing\n\nIn a Distributed System there must necessarily be communication between parts of that system. In order to effectively manage a system diagnostic tooling is essential. A centralized system (often referred to as a Monolith) can be inspected with relative ease, whereas a decentralized system is communicating state and causing chain reactions over a distance. Distributed Tracing provides holistic insights into the interactions of different parts of a Distributed System.\n\nDesign-Thinking\n\nAs a basic level, integrating an awareness of User Experience (UX) into every aspect of the business. The idea behind Design-Thinking is to inject design intelligence into an organisation by connecting the organisation more closely with user feedback, design principles and prototyping. Design-Thinking closely aligns with Agile planning. Enterprises undergoing Digital Transformation my move their culture towards Design-Thinking in order to improve their understanding of the market and build more valuable products.\n\nDesign Sprint\n\nA methodology arising from the intersection of multiple cultures, primarily UX and Agile development. Part of the Design-Thinking movement, Design Sprints follows the same methodology as a typical Agile Sprint at a holistic planning level whilst mandating a five-phase process that centres around rapid exploration and iteration on user feedback within each sprint. The term “Design” here has less to do with visual design, and far more to do with Product Design and UX.\n\nDevOps\n\nA portmanteau of Development and Operations. A person in the DevOps role is responsible for automating, configuring and managing the deployment of a system. DevOps are important to Agile development because traditional Operations (or SysAdmins) are geared towards the more traditional Waterfall workflows. That is, they are used to Big Bang deployments rather than the incremental iteration required by Agile development. The only way to keep up with the speed of development that Agile produces is to automate Operations, but automation tends to require a developer mindset, hence DevOps .\n\nDevSecOps\n\nOnce Operations has been automated, due to a lack of context Security teams typically become the next bottleneck in Enterprise operations. While DevOps seeks to remove the logistical barriers typically caused by traditional Operations (or SysAdmin) workflows, DevSecOps also represents a restructuring away from a siloed Security Team and instead puts the security onus on DevOps.\n\nDocker\n\nA Container management tool.\n\nFront end\n\nDepending on the reference point, this can either refer to the code used to build the UI (client-side code), or to the code that runs at the “front of the back”, that is server-side code that is public facing. More commonly the former, but Enterprise clients can sometimes use it to refer to the latter. To further explain by association, the client-side code would be built in React, whereas server-side would be built in Node.js.\n\nFull Stack\n\nConcerns core competencies with all (or most) parts of an application stack. For instance, one who is proficient in both Back end and Front end programming (in the sense of client and server side) may be referred to as Full stack. The term is subjective however, client/server ability may not be enough to be considered Full stack by some, who may throw in DB admin, DevOps or CSS requirements in order to be considered “real” Full stack.\n\nInnersource\n\nInnerSource is the use of best practice open source methods inside your organisation to get some of the advantages of the collaborative way of building open source software. It brings a change of culture to the business allowing employees to free up their work through transparency and cross-collaboration. Speed, quality and typically much happier developers result.\n\nJavaScript - (JS)\n\nA dynamic programming language that is used for both Browser programming and Node.js programming . Dynamic here means it can understand code straight away and run it (that is, it can read and act out a script), whereas Compiled languages must first go through a transformational process that turns them binary code that is executed independently. This dynamic aspect allows for a rapid development feedback loop vs compiled languages.\n\nKubernetes\n\nAn extremely popular Container deployment platform . The DevOps juggernaut that is Kubernetes seems unstoppable. We’ve been using it longer than most and it’s our de-facto standard for customer deployments, whether stock, AKS, EKS or OpenShift. However, it’s not the solution to every problem and there are many use cases where a Serverless approach may be more appropriate.\n\nKeras\n\nKeras is a high-level neural networks API, written in Python and capable of running on top of TensorFlow, CNTK, or Theano. It was developed with a focus on enabling fast experimentation.\n\nMiddleware\n\nA portmanteau of Middle and Software. Every technical product has a Software Stack. Middleware is an independent piece of logic that is designed to be inserted somewhere in the middle of that stack. In a Node.js context, Middleware is typically associated with Web Frameworks and supply generic/shared functionality for Web-facing products.\n\nMicroservices\n\nA distributed architectural approach centring around the division of logic into business domains that correspond to logic deployed in individual processes. This is opposed to centralizing all logic into one process (Monolith) or a small number of processes (Service Oriented Architecture/Coarse-Grained Services). One reason for using Microservices is to isolate risk. If functionality is grouped into one process, the risk of 100% malfunction is high. If functionality is divided across many independently deployed services, failure is isolated only to a small portion of the product. Another reason is it allows for an organisational transformation through de-siloing. By grouping functionality into domains, Enterprise organisations can gradually restructure a few very homogenous teams into many small cross-discipline specialists teams.\n\nFor these (and other) reasons, Enterprise organisations undergoing Digital Transformation typically choose a Microservices architecture. The trade-off of Microservices is in exchange for reducing development maintenance overhead it adds Operational complexity, which drives a need for DevOps.\n\nMVP\n\nMinimum Viable Product. When following an Agile methodology the goal is to get the product to the market as soon as possible and then use market feedback to iterate upon the product. In order to find the fastest path to market, the product must be defined with the minimum amount of functionality and features required for it to meet the business case. Due to stakeholder politics, enterprise companies tend to find it challenging to commit to an MVP, so there is usually pressure on the design and development teams to extend the scope of the product. This, in turn, causes delays which then causes friction between design/developers and the business.\n\nNode.js\n\nA server-side programming platform that uses JavaScript. One of the key qualities of Node is that it provides concurrent operations by decoupling I/O (operations such as reading files or responding to a web site request) from the programming paradigm. This allows for a mental model that ignores some of the complexity of parallel programming, allowing Node to work well as a mediator. Using JavaScript as the programming language this also causes parity with Web UI development which means the teams have interchangeable skills between the Front end and Back end. A huge amount of people know JavaScript because it’s the language of the browser. All of this together makes Node.js an appealing candidate for innovation projects in Enterprise companies.\n\nOpen Innovation\n\nOpen innovation is a term used to promote a progressive mindset toward sustainable innovation that runs counter to the ‘not invented here’ silo mentality of traditional corporate R&D. Embracing and adopting open innovation is to build from open and in the open - building from open source software (OSS) and hardware; being open to new ideas; with open collaboration across the organisation and with external parties; and with a more open approach to continuous user-centric development.\n\nThroughout the years several factors have emerged that paved the way for open innovation:\n\nThe increasing availability and mobility of skilled workers\nThe growth of the venture capital market\nExternal options for ideas sitting on the shelf\nThe increasing capability of external suppliers\n\nThese four factors have resulted in a new market of knowledge. Knowledge is not anymore proprietary to the company. It resides in employees, suppliers, customers, competitors and universities.\n\nOpen-Source Software (OSS)\n\nA competing philosophy against Proprietary Software. Popularized by the Linux Operating System, one of the first OSS projects, this is an approach to development where Intellectual Property is publically developed. While this seems counterintuitive, it allows for alternative business models, encourages pro-bono collaboration from industry-leading engineers and when properly wielded can have powerful marketing value. Enterprises undergoing Digital Transformation typically adopt an OSS consumption strategy because it allows them to quickly use free, publicly available IP to rapidly grow their product. The trade-off is that if the organisation's in-house talent does not have the skill level to modify every part of the OSS products they are using, it can cause maintenance friction and potentially lead to security vulnerabilities.\n\nPWAs\n\nProgressive Web Apps are web applications that conform to the PWA checklist ( https://developers.google.com/web/progressive-web-apps/checklist ). Essentially an offline-first responsive web application that can be also added as a native application on mobile and desktop . Adding applications natively can be good for branding, whilst developing one web application (rather than one web app and one native app) drastically cuts the costs of a dual approach.\n\nReact\n\nA very popular Front end (UI) framework.\n\nServerless\n\nA hosted application environment, using the Function as a Service (FaaS) paradigm. It requires logic to be broken into isolated single functions (the smallest feasible unit of functionality, smaller than Microservices) that are then independently deployed into a ready-made Distributed System. The operational overhead for Serverless deployment is very low since it’s entirely managed by the Serverless provider. However, fees are calculated on resource usage, and the compute cost is higher relative to managed deployments. Serverless can provide an even higher level of development iteration speed, however, it lacks some of the flexibility of self-managed deployments and almost always needs to work in tandem with a more traditional solution due to the stateless quality of Serverless functions. Enterprise organisations may consider adopting Serverless hosting as a counter-option to training/hiring System Admin/Operations/DevOps staff.\n\nSprint\n\nA Sprint is an Agile term. It is a reoccurring block of time where development work is done. Prioritization of tasks for the next Sprint and a retrospective of the current Sprint is performed at the end (or beginning) of each Sprint.\n\nTwelve-factor application technology\n\nAn application (or system, or product) that he been built using conventions that cover the twelve technical areas of product development, as specified by the Twelve-factor App document ( https://12factor.net/ ). All modern development should broadly comply with the Twelve-factor methodology.\n\nUI - (User Interface)\n\nIn a web development context, the visual pieces of the site that we click, touch or otherwise interact with.\n\nUX - (User Experience)\n\nConcerns the ergonomics of user interaction with an application, the behaviour of an application. UX is applied to both make it easy for a user to achieve their objectives and to guide the user into fulfilling business objectives. Due to the complexity of predicting human behaviour, UX starts with basic assumptions and is then continuously iterated upon and improved based on analysis of user interaction.\n\nVersion Control\n\nA workflow whereby a code base is developed in many tiny phases, called Commits, which can be thought of as snapshots, or versions. The code base can be returned to any former version of itself due to this approach. Version Control requires a Version Control System. Git is the VHS of Version Control Systems.\n\nVirtual Machine (VM)\n\nA machine that is simulated using software. This allows one “real” machine (known as Bare Metal), to run many Virtual Machines. Cloud offerings such as AWS and AZURE consist of thousands of Virtual Machines.\n\nVue.js\n\nA Front end (UI) framework that is rising in popularity.\n\nWireframe\n\nAn outline of a page/application structure for a particular part of the user journey. These are typically used in storyboarding user journeys and to convey layout/semantic structure to the development team.\n\nWaterfall\n\nA traditional technical project management methodology. It involves abstractly defining the entire product up-front and has several phases which are executed in sequential order. For instance, full analysis and documentation of business rules and state management must be defined before designing an architecture. While this seems intuitive, it’s a seductive oversimplification of the real world and leads to rigidity that can stifle innovation and lead to friction and overhead. Waterfall also tends to propagate the misconception that a product can be “finished”, whereas Agile acknowledges and supports the notion that competing in the market requires constant evolution.\n\nWe hope you find this list useful and if you have any questions, please feel free to get in touch or reach out to us on Twitter. \n\nAnnie Spratt" ], "categories": { "primary": "work", "others": [ "oss", "product", "devops", "design" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-upgrade-styled-components": { "href": "https://nearform.com/digital-community/upgrade-styled-components", "postType": "blog", "slug": "digital-community-upgrade-styled-components", "date": "2019-02-20", "title": "Upgrading styled-components from v3 to v4", "authors": [ "BRIAN MATHEWS" ], "content": [ "The v4 release of styled-components comes with a lot of features and performance wins that we were excited about. Here are the release highlights:\n\nSmaller and much faster, going from 16.1kB to less than 15kB, and speeding up mounting by ~25% and re-rendering by ~7.5%\nA brand new createGlobalStyle API, the hot-reloadable and themable replacement for the old injectGlobal\nSupport for the \"as\" prop, a more flexible alternative to .withComponent()\nRemoval of Comp.extend, with an automatic codemod to move your entire codebase to the unified styled(Comp) notation\nFull StrictMode compliance for React v16, which also means we had to drop support for React v15 and lower (you may be able to use polyfills to get v15 working with styled-components v4)\nNative support for ref on any styled component, no more innerRef thanks to React v16\n\nIf you're like me, you might look at the official v3 to v4 migration guide, see the codemod, and feel pretty confident that the migration should take you less than a day! Welp, I was wrong. Here are a few gotchas I ran into:\n\nGotcha #1: Replacing the deprecated YourComp.extend with styled(YourComp) and how that affects .withComponent\n\nWhen you run the codemod, it replaces all of the deprecated YourComp.extend code with styled(YourComp). If you use .withComponent on something created with .extend before the codemod, it won't work as intended. For example:\n\nimport styled from 'styled-components'\nimport { space, width } from 'styled-system'\n\nconst Base = styled('div')`\n ${space}\n ${width}\n`\n\nconst Heading = Base.extend`\n font-weight: bold;\n border-bottom: 2px solid #333;\n`\n\nconst Title = Heading.withComponent('h1')\njsxCopy to clipboard\n\nIn v3, Title would get the styles from Heading and Base, then render as an h1 element. 🆒\n\nAfter running the codemod, you'd get:\n\n...\n\nconst Heading = styled(Base)`\n font-weight: bold;\n border-bottom: 1px solid black;\n`\n\nconst Title = Heading.withComponent('h1')\njsxCopy to clipboard\n\nThat .withComponent will no longer behave as intended. Rather than Heading wrapping Base, Heading will now only wrap the h1. You won't get any of the styles from Base.\n\nInstead, use attrs and the new as prop. This will properly merge all the styles together and only swap out what gets rendered:\n\nconst Title = styled(Heading).attrs(() => ({ as: 'h1' }))``\njsxCopy to clipboard\nGotcha #2: .attrs evaluation order\n\nIf you have multiple components folded together using styled(), be aware that the order in which attrs are evaluated starts from the base component outwards.\n\nFor example, in v3 we had a base Icon component that relies on a name prop to add the desired svg path as children:\n\nconst Icon = styled('svg').attrs({\n children: ({ name }) => \n})``\njsxCopy to clipboard\n\nElsewhere we had an EditIcon that extended the Icon and provided that name prop:\n\nconst EditIcon = Icon.extend.attrs({\n name: 'pencil'\n})``\njsxCopy to clipboard\n\nThis worked in v3, but after swapping out that .extend for styled(), we got a runtime exception when the EditIcon is rendered.\n\nconst Icon = styled('svg').attrs({\n children: ({ name }) => // EXCEPTION THROWN HERE\n})``\n\nconst EditIcon = styled(Icon).attrs({\n name: 'pencil' \n})``\njsxCopy to clipboard\n\nWe got \"Cannot read property path of undefined\" because the attrs for Icon are evaluated before the attrs for EditIcon are provided, and the name prop is undefined at that point. The fix here was to use defaultProps which makes that name available to the base Icon component sooner.\n\nconst EditIcon = styled(Icon)``\nEditIcon.defaultProps = {\n name: 'pencil'\n}\njsxCopy to clipboard\nGotcha #3: Casing of css attrs\n\nIn v4, we ended up with css values with px units added where we didn't expect. If you're returning an object with css rules, make sure the keys are camel-cased and not dash-cased. In v4, the detection of 'unit-less' rules assumes you're providing camel-cased keys:\n\nIn v3 we had a shorthand helper returning an object with dash-cased css rules, e.g., something like:\n\nconst shortHand = props => {\n return {\n 'line-height': props.lh\n }\n}\n\nconst Base = styled('div')`\n ${shortHand}\n`\n\n...\n\n\njsxCopy to clipboard\n\nIn v3, the resulting css was: line-height: 1.4 (expected) In v4, the resulting css was: line-height: 1.4px (unexpected)\n\nThe solution is to return camel-cased rules:\n\nconst shortHand = props => {\n return {\n lineHeight: props.lh\n }\n}\njsxCopy to clipboard\n\nThat's it!\n\nWith the official v3 to v4 migration guide and these few gotchas in mind, the upgrade should be relatively quick and straight forward. The smaller bundle size, faster performance, and improved API of v4 are worth the effort!" ], "categories": { "primary": "design", "others": [ "frontend" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-5-tips-approaching-open-innovation": { "href": "https://nearform.com/insights/5-tips-approaching-open-innovation", "postType": "blog", "slug": "insights-5-tips-approaching-open-innovation", "date": "2019-02-20", "title": "5 Tips for Approaching Open Innovation in your Company", "authors": [], "content": [ "Want a high performing culture? Make way for open innovation!\n\nAre today’s enterprises approaching innovation in the healthiest and most efficient way? If enterprises are to stay relevant, it’s time to retire outdated approaches to product & service development and embrace open innovation - by which we mean opening up the innovation process to open source solutions and a collaborative approach rather than in siloed environments behind closed doors. So where are you on the innovation continuum? Across industries and across the globe, enterprises are coming under unprecedented pressure to innovate. And innovation works: new products, unique delivery models and novel concepts in customer service can deliver profits, new revenue streams, and media attention for the companies who get innovation right.\n\nThe pressure to deliver new ideas runs right through the organization, from the CEO’s office through IT and beyond, but it is up to the company leadership to ask itself the hardest question of all: is the organization getting innovation right? If product & service development has always been an aspect of the enterprise’s activities, is the approach it follows still the best approach as the world races toward 2020?\n\nLet’s take a look at how this race to innovate has picked up the pace and 5 ways you should approach open innovation in your organisation to help make it happen.\n\nWhy do enterprises need to innovate?\n\nHowever it delivers on its innovation agenda, the enterprise must bring new ideas to market. Here are some macro pressures that turn up the heat even further on the enterprise and its IT team:\n\nGartner says global IT spending in 2019 will total $3.8 trillion, with spending on enterprise software in particular increasing by 8.3%. Companies are betting on IT to deliver their vision, which pressures IT, teams, to innovate better.\nCustomers’ service expectations are high and growing, and enterprises are winning (and losing) on the basis of their customer experience. They’re hoping technology will enable not just better experiences, but better insights and data, to facilitate a more personalised service.\nThe average lifespan of a company listed on the S&P 500 index has decreased by more than 50 years in the last century, and it is estimated that the average tenure will shrink to just 12 years by 2027. Enterprises must do more to stay relevant.\nDon’t let ‘Not Invented Here’ kill your Innovation\n\nTraditionally, innovation within the enterprise happened behind sealed doors, masterminded by R&D teams who were themselves siloed within the organization. Think about the traditional R&D “division” – even the wording is divisive.\n\nThis feeling of separateness pervaded the entire ideation process. Those siloed teams quietly built proprietary intellectual property portfolios that were considered the organization’s crown jewels, protected in many cases by patent and presented as a fully formed piece of brilliance that both colleagues and the market would love. The ‘Not Invented Here’ mindset was also a way of protecting the organizational ‘immune system’ against the threat of ideas from the outside, avoiding risk.\n\nExcept it hasn’t always worked out that way. Open innovation comes to the fore partly due to the gradual realization that a swollen patent portfolio does not always equal profitability . Open innovation is, in IT terms, about embracing open source software, open standards, and collaborative processes, but it is more than that. It’s about recognizing that valuable new ideas emerge through open interactions, partnerships, and conversation -- not solely with IT and product development colleagues, but with other divisions, with customers, with suppliers & partners.\n\nA pioneering set of experiments looking at innovation in textiles, plastics, and food carried out by Paul Lawrence and Jay Lorsch in the 1960s examined the extent to which differences between functions had an influence on how long it took to get new products to the marketplace. Those groups with multiple integration mechanisms fared better, sharing ideas, defusing tensions, and working together towards the common goal.\n\nMuch has been written about the importance of having an open or learning culture in the enterprise, and open innovation fits directly into that. Think of organisations who find innovation most difficult: they are likely to be those where the culture punishes risk-taking. From its leadership down, that kind of organization sends a strong signal that failure is unacceptable and ideas from the outside are unwelcome.\n\nThe organization that embraces open innovation feels and operates in a more creative, empowering way, acknowledging that great ideas can come from anywhere. This open culture is about mindset as much as anything, and the signal sent from leadership is one of encouragement, collaboration and support. Google famously empowers its developers to devote 20% of their time to projects they’re curious about, which led to Gmail, Google Maps and more – but Twitter, Groupon and countless other game-changing concepts also sprang from side projects that some developer, somewhere, was simply curious about.\n\n5 ways to think about open innovation\nAccess to new IT skills\n\nBravely call out your technology skills gaps ASAP, regardless of how much you’re already investing in plugging those gaps. You may need to skill up faster than you think. This can come through training or by bringing in outside specialists, but it needs to be addressed as soon as it spotted. If open source software has never been part of your innovation process, there’s a wealth of code, developer talent, and community goodwill out there ready to help your IT team tackle the software aspects of transformation initiatives you’re considering which you will have access to if you embrace open innovation.\n\nAccess to new perspectives\n\nIf your development teams are brainstorming and delivering on business requirements, co-creating with others can bring not only new product ideas but new ways of thinking, new approaches and new toolsets. And don’t forget open innovation's secret power: it expands your perspective without expanding your costs. There is real value in the insights you gain from professionals who bring their own set of experience and skills - often from other industries and from industry disruptors who already think differently. There’s only so much insight your team can get from listening to themselves: expose them to new ideas, approaches and methodologies, and you may just find your next Eureka moment.\n\nFocus on performance\n\nFocus not on the speed but on the effectiveness of your innovation work. When you take an open innovation approach your innovation activity is more effective, that allows you to do other things faster (like bring new products to market). Taking small steps toward a bigger vision can often translate into better performance. Taking small steps can also help to make the transition more comfortable for existing teams.\n\nRetain the talent you have\n\nCo-creation and collaboration are one of the most satisfying experiences you can give your IT team, which means your most valuable technical staff may be more likely to stay with you. One reason Microsoft is once again said to be a great place for developers to work is its approach to open innovation, with its hackathons, Garage and so on. Personally, I’ve found co-creation projects incredibly rewarding, seeing the code I've written be used in amazing ways that I could never have anticipated. Let your developers be creative (not just among themselves, but with colleagues – even in other industries) and the results may surprise and please you both.\n\nTake Risks\n\nDistinguish the areas where risk should be and where it is not. Risks in discovery, in developing new solutions to customer problems, for example, are risks worth taking and should be regarded as a safe zone for innovation unlike those that have a significant & immediate financial impact.\n\nOpen innovation: this is how we do it\n\nAt NearForm we are often brought in to help organizations tackle thorny problems with software aspects of business transformation programs. We’ve worked with developers all over the world, literally in every time zone, across a wide selection of industries.\n\nIt’s not always a comfortable position to be in at first, either for ourselves or the developer team we meet: how can we collaborate and tackle the problem at hand without leaving anyone, on either side, feel sidelined or undervalued? I suppose the secret of how we’ve managed to help so many companies get significant transformation projects over the line is that we truly don’t think in terms of “sides.”\n\nA good case in point is a technology company we have worked with extensively. While their technical team has deep domain knowledge relating to what their core product is designed to do, they were bumping up against the edges of their ability to implement at scale. This limited their ability to deliver new features as fast as customers want, and competitors were threatening to lure those customers away. The NearForm team stepped in to help, partnering and openly collaborating with the technical team to fill those gaps. Be sure to take a look at our case studies , to see in more detail, some of the companies we've helped.\n\nTo ensure success, we cannot enter an engagement with the attitude that we are the experts and we know all. We have as much to learn from our customers as they do from us, and only through establishing a functional collaborative partnership can we truly drive things forward.\n\nTo establish such a relationship, it is critical to demonstrate competency immediately, but in a respectful way that helps upskill the customer’s team. We listened to the customer, we took the time to learn their domain and identify the issues they were facing. We didn’t just parachute in with a one-size-fits-all miracle cure. We began co-creating together, optimising the architecture and implementation to first give a solid foundation upon which to build before starting to expand their product’s features.\n\nTruly, the companies we work with are in such a range of industries that we could never hope to have the domain knowledge they possess. We do quite a lot of listening – more than talking – and recognise that the ideal final result is if we can help expand the skills base of the technical teams we work with so they can continue to add more value.\n\nThis means we’re also helping expand the population of talented open source developers who will, in turn, contribute usefully to the well of knowledge everyone draws value from, NearForm included. It really is a win all around.\n\n\tClosed Innovation\tOpen Innovation\nPlace of Innovation \twithin the company\tInside & outside the company\nPhilosophy\tInnovations emerge from the company's internal resources\tConscious import and export of knowledge to improve and accelerate your own innovations.\nSource of skill-sets\tClosed Innovation places very high demands on a fixed set of employees - the company should always strive to hire highly qualified employees.\tThe company works with bright minds inside and outside the organisation. There is less emphasis on hiring but having access to qualified skillsets.\nRole of Customer\tPassive recipients\tActive co-innovators\nProduct development bias\tUniqueness\tAction, Speed\nCompetitive advantage\tTo lead the competition, it is necessary to offer the best ideas. The winner is who brings the innovation to market first\tMaking the most of internal and external ideas gives a competitive advantage. The winner is who delivers a scalable sustainable model, a user-centric approach and can adapt to change.\nIntellectual Property\tThe own know-how is treated confidentially in order to protect it and to avoid free rides by competitors.\tThe shared know-how is available to build on by third-party contributors.\n\nWe partner with organisations across the globe to help them achieve sustainable, open innovation through the design & delivery of open software, methodologies and technologies. If you’d like to understand how we can help you stay relevant & scale to demand, contact us for an exploratory review and feel free to connect with James on LinkedIn.\n\nImage credit: Andrew Palmer" ], "categories": { "primary": "oss", "others": [ "product", "cloud" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-the-journey-to-open-source-a-leading-thinkers-discussion-with-nearform": { "href": "https://nearform.com/insights/the-journey-to-open-source-a-leading-thinkers-discussion-with-nearform", "postType": "blog", "slug": "insights-the-journey-to-open-source-a-leading-thinkers-discussion-with-nearform", "date": "2019-02-27", "title": "The Journey to Open Source: A Leading Thinkers’ Discussion with NearForm", "authors": [], "content": [ "We caught up with some of the leading thinkers, contributors and users of Open Source at NodeConf EU to discuss the role of Open Source & Node.js in digital transformation when it’s right for enterprises to join the evolution and why we believe the time is now to get involved.\n\nPaul Savage, COO, NearForm\nGordon Suttie, Director in EY\nTodd Moore, IBM VP for Open Technology & Opensource, also Node.js Board Chairperson\nAhmad Nassri, Chief Architect, TELUS Digital\nLet’s talk a little about the growth of enterprise adoption of Open Source?\n\nPaul : We’ve been involved in Open Source and Node.js for over 7 years or so. Everybody in the community was deep into it but now a lot of enterprises are coming into space. What was a small group 5 or 6 years ago where contributors, users and maintainers were all same people has now expanded? Now we have users and enterprises that are not directly connected with people who are building and maintaining. Getting these groups connected is one of the key challenges for Open Source this year in order to benefit from the great opportunity as Node and Open Source mature. There are some big signs of that in the industry and amongst some of the big players with changes that are driving adoption of Open Source. If you look at Azure : Open Source is one of the biggest drivers behind Azure and Node.js is one of the biggest drivers behind Open Source on Azure = that's a fantastic shift. Open Source has truly arrived and in a big way. We now need to help it become sustainable by connecting those that build and maintain Open Source with Enterprises looking to use Open Source. Gordon : We are working with more and more clients that are using Open Source to deliver digital transformation projects. Node.js is a big part of our technology stack when we’re developing what are highly customer-focused customer-centred design products. Todd : We’ve seen the benefit and power Open Source can bring to the world. It's a pivotal point in what's going on in hybrid-cloud and multi-cloud. About 20% of folks have figured out how to get into cloud, oftentimes moving existing systems into the cloud as their first steps...but there's 80% left to go. I’m very excited about it. Open Source is something that's in IBM’s DNA from early days. Since we made a billion dollar investment in Linux this has really kicked things off in making Open Source available to the enterprise. It then continued to snowball as we saw the benefit and power of what Open Source could bring to the world. Ahmad: In today's world, the adoption of Open Source software in the enterprise is a key growth and transformational factor for a lot of companies. There are so many facets changing from where we were as an industry 10-15 years ago to where we are today. The biggest leading indicator of why Open Source is valuable to enterprises is in the areas of team members. You’ve much opportunity to scale and grow your business when your own developer community has a bigger community umbrella around it.\n\nWhat value does it bring to the enterprise?\n\nTodd : We’ve learned as an industry now that we don’t need to compete on plumbing but on the services and at least create interoperability to protect clients from vendor lock-in. The client feels it is much safer as they have freedom of action. We feel strongly about open governance, we want to see projects be truly open and provide the ability for any contributor to be a maintainer, to commit the code and to be part of the decisions that happen with it too. Often times we see single vendors control everything that goes on but that’s not a way to have long-lived projects. We believe in truly Open Source and operating collaboratively. Gordon : From a technology perspective, we’re working with clients co-creating and designing web applications, platforms and solutions at scale - and Node fits. We need something very much attuned to a lean agile production process, we need a team that is able to be highly productive and so it’s part of that ecosystem. The projects we have done with this new technology stack and that also use newer architectural approaches have been very successful. Ahmad : You also have a better opportunity for hiring people because the Open Source community is a lower barrier of entry for people to get in and be productive on Day 1. In today's world, the open source adoption of software in the enterprise is a key growth factor for a lot of companies based on this. There is also the cost factor & long-term outlook. Within the proprietary software application world, you need professional training and certification which carries a cost, And you need a licensed software to build upon. That is not sustainable for fast-growing industries we have today where all businesses must be technology-focused. Needing developers to drive evolution is key. The reality is the value you get from contributing and adapting to Open Source in business: lower cost, higher trust along with greater society and community impact.\n\nWhat factors do organisations need to consider - how do they know if it’s right for them?\n\nPaul: If you look at some of the early entrants like Netflix and Paypal, they changed how they did things completely. It wasn’t just bringing in Node or talented developers, they changed the way they were building the code, the process around it, the architecture, the systems. So we try and help enterprises with that change as it’s a big thing to take on, and it’s not a one size fits all. What works in Netflix doesn’t work for the average enterprise - there are differences in scale and in what they are dealing with in terms of industry. But we are helping more and more businesses with those challenges in a way that they can deliver their vision and make their efforts sustainable.\n\nSo that gives us a sense of the value that Open Source brings to the enterprise. What value does enterprise bring to Open Source?\n\nTodd: Enterprises really contribute quite a bit of the resource that goes into Open Source these days. That contribution to the community really is making a difference. The community get additional resources that they need. Ahmad: For TELUS, one of the key foundational messages is we give where we live. We enable our team members to volunteer time to the community. In terms of the software industry, the Open Source aspect is key. Enterprises can enable their people to contribute, to become community members and active participants. The first step is that organisations need to realise their business relies on this.\n\nThe idea of companies having a moral obligation and individuals having a professional responsibility to be adopters and contributors to Open Source is central to the future software industry. A lot of these companies have more resources at their disposal to help evolve the Open Source ecosystem and the community itself. It can surface in many different ways but what Open Source needs the most are contributors and collaborators.\n\nBut there are challenges right?\n\nTodd : Right now, clients are struggling with how do I consume Open Source, how do I contribute to it and what kind of programme can I set up internally. Developers are central to this, it’s an exciting time for them! Paul : Many enterprises don't yet have a way of getting to grips with all these new technologies and changes and all that is expected of them. With Open Source, the main challenge is in how enterprises approach it. Often, they give a relatively junior developer the toolkit to play with, given its low barrier to entry. That developer can typically outperform a large java or .net team: they have no technical debt to deal with and they have a massive amount of Open Source modules to work with and plug together. They can move really fast and look like a genius. However, this early success leads to spaghetti architecture, difficult to maintain code and issues in production systems.\n\nSo how do they overcome these challenges?\n\nPaul: The answer is to leverage in-house expertise that understands the enterprise domain and build a team based on a core of experienced Open Source engineers. The community is a great way to find this core talent - alternatively working with a company like NearForm can also help kick start this digital transformation process. There is typically an inflection point when a system reaches about a million users, it tends to require a bit of perform-tuning so, in many cases, we help folks with things like that. We work with them on their architecture set-up. They’ve typically come from a world where they had a reference architecture, a blueprint they could touch and feel and use, and now they have to work in a microservices world. We help people adapt to this world and make the right decisions at all different levels including the cultural change and process change that goes with it.\n\nWhat advice would you give to Enterprises starting out with Open Source?\n\nTodd : First thing is to overcome fears about being part of Open Source. The licensing and work that’s being done to make it safe to participate is important to look at. You're relatively safe in what you are going to do, contribute to and maintain. Your people need to get in there and start small - make small contributions: ‘chopping wood, carrying water’ as I like to call it, Become involved. Work with one of the main contributors to get your work recognised. It's a lot of fun and a good community to work in. Paul : Yes, start with something small, one bite at a time. And remember it’s more than the software itself. You’re going to have a cloud strategy, and hopefully trying to make your development process more agile and lean. This will involve building really short feedback loops so that business can actively take part and inform development., To achieve this you need to shorten the time to get an idea from code on a developer’s laptop into a staging environment. This way the product owner and business owner can actually see and give feedback quickly so development is guided the right way - that's how you win. So do this with something small first, get it all working and get the skill sets involved early. To get the most out of these technologies, you need someone who understands how to structure a front-end, back-end, render server side, set up continuous delivery pipelines and get the environment in place properly. If you don’t have the people that know this, get some help because it can be quite painful if you get it wrong. At NearForm, we are one of the largest, international contributors to Node Core and home to some of the world’s thought leaders in Node.js, We are perfectly positioned to offer exceptional, commercially supported Open Source services. \n\nPaul Savage is available on LinkedIn - connect with him today to talk about O pen Source for your enterprise.\n\nPhoto credit: Chris Lawton" ], "categories": { "primary": "oss", "others": [] }, "verticals": { "primary": "none", "others": [] } }, "insights-javascript-promises-the-definitive-guide": { "href": "https://nearform.com/insights/javascript-promises-the-definitive-guide", "postType": "blog", "slug": "insights-javascript-promises-the-definitive-guide", "date": "2019-02-28", "title": "Javascript Promises - The Definitive Guide", "authors": [], "content": [ "The single-threaded, event-loop based concurrency model of JavaScript, deals with processing of events using so-called “asynchronous non-blocking I/O model. ” Unlike computer languages such as Java, where events are handled using additional threads, processed in parallel with the main execution thread, JavaScript code is executed sequentially. In order to prevent blocking the main thread on I/O-bound operations, JavaScript uses a callback mechanism where asynchronous operations specify a callback - the function to be executed when the result of an asynchronous operation is ready; while the code control flow continues executing.\n\nWhenever we want to use the result of a callback to make another asynchronous call, we need to nest callbacks. Since I/O operations can result in errors, we need to handle errors for each callback before processing the success result. This necessity to do error handling and having to embed callbacks makes the callback code difficult to read. Sometimes this is referred to as “ JavaScript callback hell ”.\n\nIn order to address this problem, JavaScript offers a mechanism called a Promise. It is a common programming paradigm (more about it here: https://en.wikipedia.org/wiki/Futures_and_promises ) and TC39 introduced it in ECMAScript 2015. The JavaScript Promise is an object holding a state, which represents an eventual completion (or failure) of an asynchronous operation and its resulting value.\n\nA new Promise is in the pending state. If a Promise succeeds it is put in a resolved state otherwise it is rejected . Instead of using the original callback mechanism, code using Promises creates a Promise object. We use Promises typically with two callback handlers - resolved invoked when the operation was successful and rejected called whenever an error has occurred.\n\n// Converting a callback based method to a method that returns Promise\nconst fs = require('fs')\n\nconst readTextFromFile = () => new Promise((resolve, reject) => {\n fs.readFile('file.txt', (err, data) => {\n if (err) {\n return reject(err)\n }\n\n resolve(data)\n })\n})\n\n// Usage of a method that returns Promise\nreadTextFromFile()\n .then(data => console.log(data))\n .catch(e => console.log(e))\njsCopy to clipboard", "Process.nextTick(callback)\n\nTo understand how Promises work in Node.js, it is important to review how process.nextTick() works in Node.js, as the two are very similar. Process.nextTick() is a method that adds a callback to the “next tick queue”. Tasks in the queue are executed after the current operation in the event loop is done and before the event loop is allowed to continue. Simply said, there’s another queue beside the event loop that we can use to schedule events. This queue is even faster than the event loop and it may be drained several times in a single event loop tick.\n\nconst log = msg => () => console.log(`NEXT TICK ${msg}`)\n\nconst timeout = (time, msg) => {\n setTimeout(() => {\n console.log(`TIMEOUT ${msg}`)\n }, time)\n}\n\nprocess.nextTick(log('ONE'))\ntimeout(0, 'AFTER-ONE')\nprocess.nextTick(log('TWO'))\ntimeout(0, 'AFTER-TWO')\njsCopy to clipboard\n\nIn the example above we can see how process.nextTick works in practice. We have 2 setTimeout calls, with callbacks immediately scheduled in the event loop. We also have 2 process.nextTick methods with callbacks scheduled in the “next tick queue”. This is what we see in the console:\n\nNext TICK ONE\nNext TICK TWO\nTIMEOUT AFTER-ONE\nTIMEOUT AFTER-TWO\njsCopy to clipboard\n\nSince we know that “next tick queue” is separate from event loop and can be drained multiple times in a single event loop tick, this makes sense. Two nextTick callbacks are executed immediately and the other two setTimeout callbacks, set in the event loop, are executed after.\n\nPutting so many callbacks in the “next tick queue” may block the event loop and prevent any I/O operation. That’s why we have process.maxTickDepth that represents the maximum number of callbacks in the queue that can be executed before allowing the event loop to continue. Its default value is 1000.\n\nHow Do Promises work?\n\nPromises are a new and nice way to handle async code, but how do they really work? For understanding the benefits and the performance characteristics of Promises we need to understand how they are implemented and what really happens when we return new Promise() .\n\nPromises use the Microtask queue and they are executed independently from regular tasks (setTimeout callback for example). What does this really mean? In JavaScript, we have three queues: (1) event loop, (2) nextTick queue and (3) Microtask queue. All those queues work independently. Macrotasks are regular tasks that are going into the event loop and in one event loop tick, only one Macrotask is executed. Microtasks have an independent queue and in one event-loop tick the whole microtasks queue can be drained. This gives us a really good performance benefit. Basically, we use microtasks when we need to do stuff asynchronously in a synchronous way, as fast as possible. Promises are executed as Microtasks . This means that they are executed sooner than Macrotasks . They are never executed concurrently. Microtasks are always executed sequentially, so talking about parallelism with Promises is wrong. They work like process.nextTick , independently from event loop in their own microtask queue. Macrotasks: setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, UI rendering Microtasks: process.nextTick, Promises, Object.observe, MutationObserver (read more here )\n\nconst fetch = require('node-fetch') // only when running in Node.js\n\nconst fetchData = () => \nfetch('https://api.github.com/users/nearform/repos')\n .then(() => console.log('Hi from fetch!'))\n .catch(e => console.error(e))\n\nconsole.log('Hi!')\n\nsetTimeout(() => {\n console.log('Hi from setTimeout')\n}, 0)\n\nfetchData()\njsCopy to clipboard\n\nIn the example above, the code in the Promise will be scheduled in the Microtask queue, but since that action requires the network, it will only be resolved after the data is received. In this example, we’ll see this output:\n\nHi!\nHi from setTimeout!\nHi from fetch\njsCopy to clipboard\n\nWe also need to mention that the timing of callbacks and Promises can vary significantly depending on the environment (browser or Node.js).\n\nPromise methods\nPromise.all(iterable)\n\nIt takes an array of Promises and returns a Promise that either fulfils when all of the Promises in the iterable argument have fulfilled or rejects as soon as one of the Promises rejects. If the returned Promise fulfils, it's fulfilled with an array of the values from the fulfilled Promises in the same order as defined in the array argument. If the returned Promise rejects, it is rejected with the reason from the first Promise in the array that got rejected. This method can be useful for aggregating results of multiple Promises.\n\nThe biggest confusion about Promise.all is that Promises passed in the iterable are executed concurrently. Promise.all doesn’t provide parallelism! The function passed in the Promise constructor is executed immediately and Promise is resolved in the microtask queue. Microtasks are always executed in sequence.\n\nThis method is useful when we want to wait for multiple Promises to resolve (or reject) without manually chaining them. The most common use case is mapping through an array and returning a Promise for every element:\n\nconst results = await Promise.all(\n\n items.map(item => generateResultFromItem(item))\n\n)\njsCopy to clipboard\n\nThe first rejection of a Promise will cause Promise.all() to reject, but other constituent Promises will still be executing. This can be harmful as we will be using resources for generating results that won’t be used.\n\nconst util = require('util')\nconst sleep = util.promisify(setTimeout)\n\nPromise.all([\n sleep(1000).then(() => console.log('b')),\n Promise.reject('a')\n]).catch((err) => console.log(err))\njsCopy to clipboard\n\nIn the example above, we’re passing 2 Promises in the Promise.all(). The first one is waiting one second and then logging letter b in the console. The second one is rejected with the letter a . Since the second one is rejected, we would expect to see only a in the console, but you’ll see a and b . That’s because you can’t cancel the Promise. Every scheduled Promise will be executed and Promise.all just helps us to ignore the result if one of the Promises in the iterable is rejected, and gives us a rejected Promise as a result.\n\nPromise.race(iterable)\n\nIt takes an array of Promises and executes them in the same way as Promise.all, the difference being it returns a Promise that fulfils or rejects as soon as one of the Promises in the iterable fulfils or rejects, with the value or reason from that Promise. As an example, Promise.race can be used for building a timeout functionality, where the first Promise will be an HTTP request to some service, and a second one will be a timeout function. If the second one fails first, the resulting Promise from Promise.race() will be rejected and the data from the first Promise won’t be available. The rejection of one Promise from the iterable won’t cancel others, they will be still be executed, as in the Promise.all method case.\n\nconst fetch = require('node-fetch') // only when running in Node.js\n\nconst getUserRepos = () =>\n fetch('https://api.github.com/users/nearform/repos')\n\nconst timeout = delay =>\n new Promise((resolve, reject) => {\n setTimeout(() => reject(new Error('request timeout')), delay)\n })\n\nPromise.race([getUserRepos(), timeout(300)])\n .then(repos => console.log(repos))\n .catch(e => console.error(e))\njsCopy to clipboard\n\nPromise.reject( reason ) Returns a Promise object that is rejected with the given reason as an argument. It is mainly used to throw an error in the Promise chain.\n\nPromise.resolve(value)\n\nReturns a Promise that is resolved with the given value as an argument. It is mainly used to cast a value into the Promise, some object or array, so we can chain it later with other async code.\n\nAsync/Await\n\nIn ECMAScript 2017 async / await semantics were added, allowing programmers to deal with Promises in a more intuitive way. The word “async” before a function means one simple thing: a function always returns a Promise. If the code has return in it, then JavaScript automatically wraps it into a resolved Promise with that value. The keyword await , which can only occur inside an async function, makes JavaScript wait until the Promise has been settled and returns its result.\n\nBelow is a function waiting on a Promise that is resolved after one second using async / await keywords:\n\nlet promise = new Promise((resolve, reject) => {\n setTimeout(() => resolve(\"done!\"), 1000)\n})\n\nasync function f() {\n let result = await promise // wait till the Promise resolves\n alert(result) // \"done!\"\n}\njsCopy to clipboard\nCommon mistakes with Promises\n\nPeople always say that whatever you write in JS it will be executed and it will work. That’s almost true, but not always the correct way to do things. At the end of the day, when you’re making quality products, it should be fast and bug-free. By using Promises, you can make some really bad mistakes really easily, just by forgetting to put some part of the code or by using them incorrectly. Below is a list of the common mistakes with Promises that a lot of people make every day.\n\nMistake #1: Nested Promises\n\nCheck the code below:\n\nloadSomething().then(something => {\n loadAnotherThing().then(another => {\n doSomething(something, another)\n }).catch(e => console.error(e))\n}).catch(e => console.error(e))\njsCopy to clipboard\n\nPromises were invented to fix the “callback hell” and the above example is written in the “callback hell” style. To rewrite the code correctly, we need to understand why the original code was written the way that it was. In the above situation, the programmer needed to do something after results of both Promises are available, hence the nesting. We need to rewrite it using Promise.all() as:\n\nPromise.all([loadSomething(), loadAnotherThing()])\n .then(([something, another]) => {\n doSomething(something, another)\n })\n .catch(e => console.error(e))\njsCopy to clipboard\n\nCheck the error handling too. When you use Promises properly, only one catch() is needed.\n\nA Promise chain also gives us a finally() handler. It’s always executed and it’s good for cleanup and some final tasks that will always be executed, no matter if the Promise was resolved or rejected. It was added in the ES2018 version of ECMAScript and implemented in Node.js 10. It is used like this:\n\nPromise.all([loadSomething(), loadAnotherThing()])\n .then(([something, another]) => {\n doSomething(something, another)\n })\n .catch(e => console.error(e))\n .finally(() => console.log('Promise executed'))\njsCopy to clipboard\nMistake #2: Broken Promise Chain\n\nOne of the main reasons Promises are convenient to use is “promise-chaining” - an ability to pass the result of a Promise down the chain and call catch at the end of the chain to catch an error in one place. Let’s look at the below example:\n\nfunction anAsyncCall() {\n const promise = doSomethingAsync()\n\n promise.then(() => {\n somethingElse()\n })\n\n return promise\n}\njsCopy to clipboard\n\nThe problem with the code above is handling somethingElse() method. An error that occurred inside that segment will be lost. That’s because we didn't return a Promise from the somethingElse() method. By default, .then() always returns a Promise, so in our case, somethingElse() will be executed, the Promise returned won’t be used and .then() will return a new Promise. We just lost the result from the somethingElse() method. We could easily rewrite this as:\n\nfunction anAsyncCall() {\n return doSomethingAsync()\n .then(somethingElse)\n .catch(e => console.error(e))\n}\njsCopy to clipboard\nMistake #3: Mixing sync and async code in a Promise chain\n\nThis is one of the most common mistakes with Promises. People tend to use Promises for everything and then to chain them, even for async code. It’s probably easier to have error handling on one place, to easily chain your code, but using Promise chains for that is not the right way to do. You’ll just be filling your memory and giving more job to the garbage collector. Check the example below:\n\nconst fetch = require('node-fetch') // only when running in Node.js\n\nconst getUsers = () => fetch('https://api.github.com/users')\nconst extractUsersData = users =>\n users.map(({ id, login }) => ({ id, login }))\nconst getRepos = users => Promise.all(\n users.map(({ login }) => fetch(`https://api.github.com/users/${login}/repos`))\n)\nconst getFullName = repos => repos.map(repo => ({ fullName: repo.full_name }))\n\n

const getDataAndFormatIt = () => {\n return getUsers()\n .then(extractUsersData)\n .then(getRepos)\n .then(getFullName)\n .then(repos => console.log(repos))\n .catch(error => console.error(error))\n}\n\ngetDataAndFormatIt()\njsCopy to clipboard\n\nIn this example, we have mixed sync and async code in the Promise chain. Two of those methods are getting the data from Github, the other two are just mapping through arrays and extracting some data and the last one is just logging the data in the console (all 3 are sync). This is the usual mistake people make, especially when you have to fetch some data, then to fetch some more per every element in the fetched array, but that’s wrong. By transforming getDataAndFormatIt() method into async/await, you can easily see where the mistake is:\n\nconst getDataAndFormatIt = async () => {\n try {\n const users = await getUsers()\n const userData = await extractUsersData(users)\n const repos = await getRepos(userData)\n const fullName = await getFullName(repos)\n await logRepos(fullName)\n } catch (error) {\n console.error(error)\n }\n}\njsCopy to clipboard\n\nAs you see, we’re treating every method as async (that’s what will happen in the example with Promise chain). But we don’t need Promise for every method, only for 2 async methods, other 3 are sync. By rewriting the code a bit more, we’ll finally fix the memory issue:\n\nconst getDataAndFormatIt = async () => {\n try {\n const users = await getUsers()\n const userData = extractUsersData(users)\n const repos = await getRepos(userData)\n const fullName = getFullName(repos)\n logRepos(fullName)\n } catch (error) {\n console.error(error)\n }\n}\njsCopy to clipboard\n\nThat’s it! It’s now written properly, only methods that are async will be executed as Promises, other ones will be executed as sync methods. We don’t have a memory leak anymore. You should avoid chaining async and sync methods, that will make a lot of problems in the future (especially when you have a lot of data to process). If it’s easier for you, go for async/await, it will help you understand what should be the Promise and what should stay sync method.\n\nMistake #4: Missing catch\n\nJavaScript does not enforce error handling. Whenever programmers forget to catch an error, JavaScript code will raise a runtime exception. The callback syntax, however, makes error handling more intuitive. Every callback function receives two arguments, error and result . By writing the code you’ll always see that unused error variable and you’ll need to handle it at some point. Check the code below:\n\nfs.readFile('foo.txt', (error, result) => {\n if (error) {\n return console.error(error)\n }\n\n console.log(result)\n})\njsCopy to clipboard\n\nSince the callback function signature has an error , handling it becomes more intuitive and a missing error handler is easier to spot. Promises make it easy to forget to catch errors since .catch() is optional while .then() is perfectly happy with a single success handler. This will emit the UnhandledPromiseRejectionWarning in Node.js and might cause a memory or file descriptor leak. The code in the Promise callback takes some memory and cleaning of the used memory after Promise is resolved or rejected should be done by the garbage collector. But that might not happen if we don’t handle rejected promise properly. If we access some I/O source or create variables in the Promise callback, a file descriptor will be created and memory will be used. By not handling the Promise rejection properly, memory won’t be cleaned and file descriptor won’t be closed. Do this several hundred times and you’ll make big memory leak and some other functionality might fail. To avoid process crashes and memory leaks always finish Promise chains with a . catch() .\n\nIf you try to run the code below, it will fail with the UnhandledPromiseRejectionWarning :\n\nconst fs = require('fs').promises\n\nfs.stat('non-existing-file.txt')\n .then(stat => console.log(stat))\njsCopy to clipboard\n\nWe’re trying to read stats for a file that doesn’t exist and we’re getting the following error:\n\n(node:34753) UnhandledPromiseRejectionWarning: Error: ENOENT: no such file or directory, stat 'non-existing-file.txt'\n\n(node:34753) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block or by rejecting a promise which was not handled with .catch(). (rejection id: 1)\n\n(node:34753) [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.\n\nIf you don’t handle your errors properly, you’ll leak a file descriptor or get into some other denial of service situation. That’s why you need to clean up everything properly on Promise rejection. To properly handle it, we should add a .catch() statement here:\n\nconst fs = require('fs').promises\n\nfs.stat('non-existing-file.txt')\n .then(stat => console.log(stat))\n .catch(error => console.error(error))\njsCopy to clipboard\n\nWith a .catch() statement, when the error happens we should log it in the console:\n\n{ [Error: ENOENT: no such file or directory, stat 'non-existing-file.txt']\n errno: -2,\n code: 'ENOENT',\n syscall: 'stat',\n path: 'non-existing-file.txt' }\njsCopy to clipboard\n\nWe recommend checking out this blog post from Matteo Collina that will help you understand this issue and learn about the operational impact of unhandledRejection.\n\nMistake #5: Forget to return a Promise\n\nIf you are making a Promise, do not forget to return it. In the below code, we forget to return the Promise in our getUserData() success handler.\n\ngetUser()\n .then(user => {\n getUserData(user)\n })\n .then(userData => {\n // userData is not defined\n })\n .catch(e => console.error(e))\njsCopy to clipboard\n\nAs a result, userData is undefined. Further, such code could cause an unhandledRejection error. The proper code should look like:\n\ngetUser()\n .then(user => {\n return getUserData(user)\n })\n .then(userData => {\n // userData is defined\n })\n .catch(e => console.error(e))\njsCopy to clipboard\nMistake #6: Promisified synchronous code\n\nPromises are designed to help you manage asynchronous code. Therefore, there are no advantages to using Promises for synchronous processing. As per JavaScript documentation: “The Promise object is used for deferred and asynchronous computations. A Promise represents an operation that hasn't yet completed, but is expected to in the future.” What happens if we wrap synchronous operation in a Promise, as below?\n\nconst syncPromise = new Promise((resolve, reject) => {\n console.log('inside sync promise')\n resolve()\n})\njsCopy to clipboard\n\nThe function passed to the Promise will be invoked immediately but the resolution will be scheduled on the microtask queue, like any other asynchronous task. It will just be blocking the event loop without a special reason. In the above example, we created an additional context, which we are not using. This will make our code slower and consume additional resources, without any benefits. Furthermore, since our function is a Promise, the JavaScript engine will skip one of the most important code optimizations meant to reduce our function call overhead - automatic function inlining .\n\nMistake #7: Mixing Promise and Async/Await\nconst mainMethod = () => {\n return new Promise(async function (resolve, reject) {\n try {\n const data1 = await someMethod()\n const data2 = await someOtherMethod()\n \n someCallbackMethod(data1, data2, (err, finalData) => {\n if (err) {\n return reject(err)\n }\n\n resolve(finalData)\n })\n } catch (e) {\n reject(e)\n }\n })\n}\njsCopy to clipboard\n\nThis code is long and complicated, it uses Promises, Async/Await, and callbacks. We have an async function inside a Promise, a place where it is not expected and not a good thing to do. This is not expected and can lead to a number of hidden bugs. It will allocate additional Promise objects that will be unnecessarily wasting memory and your garbage collector will spend more time cleaning it.\n\nIf you want to use async behaviour inside a Promise, you should resolve them in the outer method or use Async/Await to chain the methods inside. We can refactor the code like this:\n\nconst somePromiseMethod = (data1, data2) => {\n return new Promise((resolve, reject) => {\n someCallbackMethod(data1, data2, (err, finalData) => {\n if (err) {\n return reject(err)\n }\n\n resolve(finalData)\n })\n })\n}\njsCopy to clipboard\nasync function mainMethod() {\n try {\n const data1 = await someMethod()\n const data2 = await someOtherMethod()\n return somePromiseMethod(data1, data2)\n } catch (e) {\n console.error(e)\n }\n}\njsCopy to clipboard\nMistake #8: Async function that returns Promise\nasync function method() {\n return new Promise((resolve, reject) => { ... })\n}\njsCopy to clipboard\n\nThis is unnecessary, a function that returns a Promise doesn’t need an async keyword, and the opposite, when the function is async, you don’t need to write `return new Promise` inside. Use the async keyword only if you’re going to use await in the function, and that function will return a Promise when invoked.\n\nfunction method() {\n return new Promise((resolve, reject) => { ... })\n}\njsCopy to clipboard\n\nor\n\nasync function method() {\n const data = await someAsyncMethod()\n return data\n}\njsCopy to clipboard\nMistake #9: Define a callback as an async function\n\nPeople often use async functions in places where you shouldn’t expect them, like a callback. In the example below, we’re using async function as a callback on the even from server:\n\nserver.on('connection', async stream => {\n const user = await saveInDatabase()\n\n console.log(`Someone with ID ${user.id} connected`)\n})\njsCopy to clipboard\n\nThis is an anti-pattern. It is not possible to await for the result in the EventEmitter callback, the result will be lost. Also, any error that’s thrown (can’t connect to the DB for example) won’t be handled, you’ll get unhandledRejection , there’s no way to handle it.\n\nWorking with non-Promise Node.js APIs\n\nPromises are a new implementation in ECMAScript and not all Node.js APIs are made to work in that way. That’s why we have a Promisify method that can help us generate a function that returns a Promise from a function that works with a callback:\n\nconst util = require('util')\n\nconst sleep = util.promisify(setTimeout)\n\nsleep(1000)\n .then(() => console.log('This was executed after one second'))\njsCopy to clipboard\n\nIt was added in Node.js version 8. and you can find more about it here.\n\nConclusion\n\nEvery new feature in a programming language makes people excited but eager to try it. But no one wants to spend time trying to understand the functionality; we just want to use it. That’s where the problem arises. The same goes with Promises; we were waiting for them for a long time and now they are here we’re constantly making mistakes and failing to understand the whole point around using them.\n\nIn my opinion, they’re a cool feature but also quite complicated. In this post we wanted to show you what’s happening under the hood when you write return new Promise() and what are some common mistakes that everyone makes. Write your code carefully or one day it may come back to you with some unhandled promise rejections or memory leaks.\n\nIf you get into bigger problems with Promises and need some assistance with profiling, we recommend using Node Clinic - a set of tools that can help you diagnose performance issues in your Node.js app.\n\nSafe coding!" ], "categories": { "primary": "frontend", "others": [ "backend" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-new-spectacle-lander": { "href": "https://nearform.com/digital-community/new-spectacle-lander", "postType": "blog", "slug": "digital-community-new-spectacle-lander", "date": "2019-03-01", "title": "New Spectacle Lander", "authors": [ "EMMA BRILLHART" ], "content": [ "Formidable and the Spectacle team are excited to announce the launch of the new Spectacle lander on the Formidable website! We've updated the branding and brought the lander more in line with our company's overall brand.\n\nAll documentation on our lander is now in line with the documentation in Spectacle's GitHub README as well. Parity between the two should help cut down on confusion and make the Spectacle development experience much more pleasant.\n\nWe hope you check it out, and, as always, we're interested to hear your feedback." ], "categories": { "primary": "oss", "others": [ "design" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-virtual-coffee-with-nearform-senior-product-designer-antoine-marin": { "href": "https://nearform.com/insights/virtual-coffee-with-nearform-senior-product-designer-antoine-marin", "postType": "blog", "slug": "insights-virtual-coffee-with-nearform-senior-product-designer-antoine-marin", "date": "2019-03-01", "title": "Virtual Coffee With NearForm Senior Product Designer, Antoine Marin", "authors": [], "content": [ "A conversation with Senior Product Designer Antoine Marin\n\nAntoine Marin, Senior Product Designer at NearForm, is based in Kilkenny, Ireland and is working on a range of client engagements across the globe. We began our discussion talking about drone technology, where he’s been focusing much of his time lately.\n\nWhat is your area of speciality?\n\nAs part of the product team, I facilitate workshops to answer Why, How and What we’re building. This approach helps with aligning stakeholders, capturing requirements and kicking-off the project. I then map the user experience, prototype the interface, and design a visual language or design system.\n\nWhat project are you currently working on?\n\nWe’re working with a drone data company to design their platform. The platform is used by civil engineering companies to survey construction sites. They’re asking, “How does the progress on site compare to the original plans?” and they send up autonomous drones to survey huge swaths of land.\n\nThe operator chooses the area to survey and the drones then fly autonomously, taking all the photos required. Data captured is then uploaded and processed on the platform. My specific role here is to design the interface that shows this data. I work with the product team to design tools that empower our users.\n\nHow exactly is your work helping the drone data company‘s strategic ambitions?\n\nIn short, my work enables operations managers to analyse faster and make more informed decisions on the ground.\n\nDrones are transforming the way civil engineering projects and farming are done. Companies are getting ground data faster and more accurate. But the main challenge with drone technology is treating the huge volume of data captured and making sense of it.\n\nWhen they engaged us, our client’s platform did not serve their business ambitions. Some of the technology was not scaling for that huge amount of data. They wanted to be able to release features faster.\n\nWe’ve completed a whole system audit and we’re rebuilding the architecture. On my side, I designed a system that can support scalability and fast paced development. User experience is focused on key tasks people are trying to achieve. My goal is to make it frictionless.\n\nWhat process do you go through, with customers, to find the best product design?\n\nGood design is a collaborative effort. Business and technical decisions have a huge impact on customer experiences. Hence, the role of product designers is to communicate the impact on users of these decisions (cost and benefits).\n\nWe kick-off projects with a design workshop including key stakeholders from business and technology groups. It’s a series of team exercises that shape the product. It ends with the creation of a high fidelity prototype everyone can relate to. The goal of the week is to define what is getting built, how, and why.\n\nWhat parts of the design process are most important?\n\nPeople often underestimate the mindset differences between the product designer, developer and the business person. If you just write documents, people will interpret them differently based on their own perspective. That’s why, during our design workshops, we create something concrete that people can discuss so that a visual language becomes the universal language of the team.\n\nMost people would struggle to focus on a 100-page requirements document so it’s important to have something visual - a prototype - that we can collaborate on.\n\nIf you can use technology to complete a task much faster, that’s what will disrupt industries.\n\nWhere is the biggest risk of failure?\n\nOne of the main reasons projects fail is because of people. Lack of communications, not seeing the bigger picture, working in silos. These are all big risks for a project. When we do a workshop with a customer at the beginning of the engagement, we try to expose the project from many different perspectives.\n\nThere are always three types of goals – technical, business, and end-user goals - and these must align. Sometimes you want to build a product and you think it will be amazing for business – but if it takes 2 years to build, well, it’s not as viable as it seems. Another aspect is knowing who you’re working for. The better you know what users are trying to achieve, the more successful and effective you’re going to be.\n\nWhere did you work before NearForm?\n\nI worked with a company called Kitman Labs in Dublin. The Kitman system empowers professional sports clubs across the globe to optimise their players’ performance. The team is at the forefront of sport science research and uses technology to minimize injuries and optimise performance.\n\nI designed, with the team, the mobile applications and AR experiences that captured and prepared the required data: a mix of subjective information (perceived sleep quality, appetite, etc.) and biomechanical data (external shoulder rotation, countermovement jump height, etc.). Clubs using the system had about 60% less end-season injuries.\n\nWhere are you from?\n\nI’m from Nantes in Western France.\n\nI was so impressed when I went to Nantes – it’s an amazing place, the La Galerie des Machines and the giant robotic elephant is one of the most remarkable combinations of art and science that I’ve ever seen.\n\nYes, Les Machines des L’ile is one of our city's most famous attractions. Of course, when you mention the combination of art and science, it's what I do for a living! The product design process very much follows a scientific approach. We form a lot of assumptions around what people need, how they will use the product and so on and we use continuous data to refine those assumptions. That’s the science bit that then feeds into the art of designing the product's identity or to refine the user experiences.\n\nAs for Nantes as an amazing place, we also love the culture there. There are many reasons to go back and visit. The city hosts wonderful festivals such as the Blues and Jazz Festival and they work hard to bring art and culture into every level of society.\n\nSo you’re from Nantes in France, how did you end up in Ireland, with NearForm?\n\nI met my wife on holiday and decided to come here to live. After working in Dublin, I was looking for a product role offering remote options and NearForm came up. NearForm really helps employees at every level, we really feel cared about. At our headquarters in Tramore, we have a chef that cooks really great food, and they offer great health and wellbeing activities like pilates and yoga classes. Although I spend more time in the kitchen than the classes!\n\nSocially there is a lack of ego in the company – and it’s refreshing. There are people with 20+ years of experience, but they never look down on you. We’re all learning and striving to be better at what we do.\n\nDoes that ongoing ambition show, to the customers? Is that why they hire NearForm?\n\nPeople come to us because we impact businesses in record times. We know that technology is not the end but a means to an end. Our clients value that. The majority are going through some form of digital transformation and they like our open approach to innovation, the methodologies we use and the breadth of our technical expertise.\n\nWhat kind of technology disruptions do you see happening right now?\n\nIf you can use technology to complete a task much faster, that’s what will disrupt industries.\n\nThe better you know what users are trying to achieve, the more successful and effective you’re going to be.\n\nWhat’s your career ambition?\n\nTo positively impact people through design. Whether it’s the people using the product or the team building it. It’s a real reward to see someone seamlessly using a product I designed. I aim to make sure business, technology and design stakeholders are aligned. If something will affect the quality of the product, it needs to be exposed at an early stage in the process. Successful digital transformation isn’t so much about technology, as it is about people.\n\nAny other ambitions that you have?\n\nOne company I admire is Ideo and the way they work in so many different areas of social impact. I especially remember some of their work done in Zambia. They designed beauty centres that delivered contraception and family planning information to young women while they were getting their nails done.\n\nThe medical field is an easy one to relate to and a field I’d love to work in more. It touches every one of us. I believe we are at a time where the patient-practitioner relationship needs to be reinvented. People expect a more personalised and on-demand approach in some cases (prescription renewal). A more human one in others (accidents, long term sickness). Technology can help but will only get adopted if it doesn’t get in the way. And I believe a patient-focused design can bring the best of technology.\n\nHow do you stay relevant as a product designer? Are there podcasts you recommend? Other sources of learning?\n\nOur design team joined a three-day course at NN/g London last year. It was a deep dive into facilitating workshops, usability and leadership. It gave us the ideal occasion to learn best practices and meet other product designers.\n\nIn terms of podcasts. The Futur is the most recent one I've been listening to. There's some great content focused on the value of design. Medium is full of case studies and design discussion .\n\nAnd I also like dissecting my own customer experiences: Banks, airlines, coffee shops...\n\nWhat do you think has changed about CX / UX over the past five or ten years?\n\nSelf-service has become the norm. People expect brands to provide the same service at their fingertips that they would do in a store or on a phone:\n\nPurchasing a product, subscribing to a service, paying a friend, ordering a taxi, sending back a package, getting a medical diagnosis via video call.\n\nThe fast pace of this big shift, that is still ongoing, forces established companies to re-invent themselves. We see national banks being challenged by upcoming players. Feature parity is not good enough anymore. Successful companies tailor their services to very specific user needs. And who better than product designers to shape these experiences? Design is more than ever a competitive advantage. As a consequence, product designers are now seen as business enablers, rather than artists.\n\n*** Many thanks to Antoine for giving us some fascinating points to ponder – about how companies can differentiate themselves on the basis of design, and about how product designers, with their impact on the bottom line, are taking a rightful place around the boardroom table." ], "categories": { "primary": "product", "others": [ "design" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-matteo-collina-cost-of-logging-nodejs": { "href": "https://nearform.com/insights/matteo-collina-cost-of-logging-nodejs", "postType": "blog", "slug": "insights-matteo-collina-cost-of-logging-nodejs", "date": "2019-03-04", "title": "The Cost of Logging & Node.js Performance: Tech Talk Video", "authors": [], "content": [ "A journey into the world of Node.js performance\n\nAt 10am on Black Friday, your phone rings: the new JS application you deployed came under too much load, and the site has gone down! Your employer is losing sales opportunities... your employer is losing money! But you don’t lose your cool. You log into your cloud provider and tweak your autoscaling settings. Now the deployment can handle the load spike but with four times the number of servers, which is four times the cost.\n\nThe next day, you try to analyze what happened and begin to optimize your application to prepare for future load spikes. This talk is a journey into the world of Node.js performance, taking a look at the available tools and optimization techniques inspired by insight gained from glimpsing under the hood of Node and V8.\n\nMatteo is a code pirate, mad scientist and part of the Node.js Technical Steering Committee. As a Principal Architect at nearForm, he consults for the top brands of the world. He authored Node.js MQTT Broker, Mosca, the fast logger Pino and the Fastify web framework.\n\nNeed Node experts for your next project? Contact us to see how we can help!\n\nJSConf.Asia - Capitol Theatre, Singapore - 25 January 2018\n\nSource: https://2018.jsconf.asia/ License: For reuse of this video under a more permissive license please get in touch with us. The speakers retain the copyright for their performances." ], "categories": { "primary": "perf", "others": [ "backend", "cloud" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-virtual-coffee-with-nearform-senior-product-designer-kevin-devine": { "href": "https://nearform.com/insights/virtual-coffee-with-nearform-senior-product-designer-kevin-devine", "postType": "blog", "slug": "insights-virtual-coffee-with-nearform-senior-product-designer-kevin-devine", "date": "2019-03-11", "title": "Kevin Devine is part of the design team at NearForm who creates digital solutions for clients in industries ranging from retail to travel to financial services.", "authors": [], "content": [ "A conversation with Kevin Devine, Senior Product Designer\nKevin Devine is part of the design team at NearForm who creates digital solutions for clients in industries ranging from retail to travel to financial services.\n\nHe sat down for a virtual coffee to discuss everything from booking flights on your mobile phone to the latest app craze in China.\n\nWhat does a typical day as a Senior Product Designer include?\n\nWe’re there from the beginning of the customer relationship. We conduct design kick-offs for client projects, from ideation to three-day workshops. We get to work with lots of key stakeholders from innovation officers to technical directors, data analysts to customer marketing representatives. We brainstorm ideas and get to the crux of the customer problem they are trying to solve. We mock up prototypes of the design and test them.\n\nWhat tools help you? For example, do you use the principles of Design Thinking?\n\nWe use the principles of Design Thinking - ideation, prototyping, customer-first mentality - but maybe not in such a prescriptive way as others do. There is no right or wrong methodology and we often use a combination of more than one, whatever suits the client, their operational requirements and their desired outcomes. We started using Design Sprints from Google Ventures but have since tweaked and evolved it for our own needs. But the stages we work through for our design workshops are typically the same.\n\nWhat form does the three-day workshop take?\n\nDay One, we learn as much as we can about the client’s business. This is after doing a due diligence process where I try to learn as much as possible about their industry in advance. On Day Two, we formulate ideas about what their prototype will look like, and we’ll usually mock up a prototype into the evening on that day. On Day Three we review the prototype and start to think about what an MVP will be.\n\nIt’ll then take weeks to design, build, test and tweak the 'go-to-market'-ready solution – we always show it and test it with groups of stakeholders – so this is the lengthier part of the process.\n\nWhere did you work previously?\n\nI was at Ryanair and helped design their first native mobile apps – starting everything from scratch. I was the lead designer on the iOS and Android apps. It was both a great opportunity and challenge for me, because of the number of users who would be using these apps and the high-pressured turnaround times.\n\nWhat’s the best thing about working at NearForm?\n\nI used to spend two hours per day in the car, commuting to Dublin. Now I can work remotely, in the countryside, and chase my daughter around the house and garden when my working day is up. There’s no beating that.\n\nThe people are great too, all at the top of their game. It’s always great when we get together at meetups, workshops or down at HQ in Tramore.\n\nWhere is your home office?\n\nI work remotely from Tara in County Meath.\n\nIn banking, startups like Starling, N26 and Monzo are examples of the new trend towards digital-only banking. It’s making other banks take note.\n\nWhat’s best about working in design?\n\nOne of the things I really enjoy is learning about all different areas. Previously, I was on a project in the travel sector, now it’s banking, I have done some projects in data. In design, you’re always on the front line and you’re learning new things. I then get to share these learnings, and carry them over, with new clients across multiple industries.\n\nDo you meet your team face-to-face?\n\nAs a design team, we try to meet face-to-face at least every four months at NearForm’s HQ. For our product teams, when we’re in the middle of a project, we tend to meet every eight weeks in places including London, Munich, New York, Dubai, Toronto, etc. We go wherever the clients are.\n\nWhat are the big technology trends you’re encountering?\n\nIn banking, startups like Starling, N26 and Monzo are examples of the new trend towards digital-only banking. It’s making other banks take note. In travel, Airbnb has shaken up everything, even though they don’t own property.\n\nInstead of throwing everything at the customer, companies are being more empathic today.\n\nEarly on people thought you’d never buy things on your phone, but now mobile acquisition and commerce is going up all the time.\n\nWhat’s new in customer experience (CX)?\n\nThe days of trying to satisfy shareholders are gone – instead of throwing everything at the customer, companies are being more empathic. They’re keeping the customer in mind always. Companies are getting feedback more from customers so that requirements aren’t always fed from the top down. From a design standpoint, we are constantly thinking from the customer’s point of view.\n\nAny other trends you see?\n\nAccessibility is always one that should be at the forefront of a designers mind. Addressing an area like colour, making sure as many people as possible can read the text, even people with colour-blindness, can make a huge difference to peoples’ experience. With the emergence of voice technology, our products and tools can reach and help a wider audience if implemented with accessibility in mind.\n\nWhat’s the secret to success in digital design?\n\nYou can’t stand still. There’s always new skills and technologies to learn.\n\nLike what?\n\nMotion lately is a huge thing. Incorporating animation and interactivity into a digital service or tool is becoming more important. Ten years ago, sites were more rigid and static. Now there are enhancements like animation and micro-interactions, such as an added-to-basket animation, that all lead to a richer experience.\n\nWhat foundations do you need, as a designer?\n\nIt’s key to have a solid understanding of design. Colour theory, the principles of typography, layout and grid – those things don’t change. You have to know the tools, but you can’t use the tools unless you have that solid grounding.\n\nHow do you stay relevant?\n\nYou have to have an understanding of business. I always deep dive for a couple of weeks before a client project kicks off. I do a lot of reading and research – I look into their competitive landscape.\n\nDo you use podcasts in your research?\n\nYes, I subscribe to a few. I often listen to the 99% Invisible Design Podcast. It looks at everything, not just the digital world. One week, they might be looking at how shipping containers are designed.\n\nI also listen to Debbie Millman’s Design Matters – and the Maker’s Channel. As a designer, I like to think about the world around us – bridging that gap with the physical world.\n\nDo you do any design outside of your job?\n\nEvery year I try to do something different – last year I did a screen printing course while this year I’m tinkering with a physical IOT project. It’s good to flex those muscles away from the computer.\n\nWhat did you study at university?\n\nI did my degree in business but I’ve always had a real appetite for art. I went to DCU for a Masters in Multimedia. There, I found that I loved front-end design and building my first website.\n\nHow do you know if a project has been a success?\n\nIf people are achieving tasks using the digital service, then you can measure quantifiable numbers to prove that it’s working.\n\nEarly on people thought you’d never buy things on your phone, but now mobile acquisition and commerce is going up all the time.\n\nHas design paved the way for the mobile revolution?\n\nSome companies were slow to move to mobile, and now they’re playing catch up. Early on people thought you’d never buy things on your phone, but now mobile acquisition and commerce is going up all the time. From a company’s perspective, if you give a solid design experience, you’re opening yourself up to make a lot more revenue.\n\nWhat’s good in mobile design?\n\nWhen apps have a seamless experience from desktop to mobile – such as Slack.\n\nWhat’s disruptive in mobile?\n\nBanking is really getting shaken up in Ireland with companies like N26 and Revolut. Traditional banks need to look outwards and learn from these startups. You have to be forward thinking, and think why are people flocking to these services.\n\nAlso, AI is disruptive when it’s a good experience. Chatbots can be executed well but I think it has a way to go.\n\nIn terms of business, the emerging markets are disruptive – Africa is mostly untapped. The bandwidth isn’t there so they’re going to mobile first, skipping over desktop apps. It’s the same with India. In China there are a lot of interesting technologies, for instance, the WeChat app – it’s like WhatsApp on steroids, with all the big companies on the platform, so you can do your banking over messaging. Something like that could be huge when it takes off here.\n\n***\n\nThanks to Kevin for this sneak peek into the world of cutting-edge design. We’ll be waiting for the day of WhatsApping our bank to make a transfer!" ], "categories": { "primary": "design", "others": [ "product", "mobile" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-introducing-graphql-hooks": { "href": "https://nearform.com/insights/introducing-graphql-hooks", "postType": "blog", "slug": "insights-introducing-graphql-hooks", "date": "2019-03-13", "title": "At NearForm we love React, and since the release of React Hooks we’ve been busy building cool new things with them.", "authors": [], "content": [ "GraphQL and React: a perfect match\n\nAt NearForm we love React , and since the release of React Hooks we’ve been busy building cool new things with React Hooks .\n\nWe also love GraphQL , its declarative API is perfect to marry up with React components.\n\nIntroducing graphql-hooks:\n\nGraphQL Hooks is a super lightweight GraphQL client for React with first-class support for hooks. It supports custom cache plugins, server-side rendering and requires minimal configuration to get up and running quickly. On top of that, it’s tiny - weighing in at 5.2KB (1.9KB gzipped).\n\nExample:\n\nLet’s walk through how we would get started with `graphql-hooks` by building a small demo application. In this example, we’re using create-react-app to bootstrap the React application and GraphCool to bootstrap the GraphQL API.\n\nWe’re going to cover:\n\n`GraphQLClient` & `ClientContext` - how to create a client instance using the Context API\n`useQuery` - send a GraphQL query\n`useMutation` - send a GraphQL mutation\nRefetching data\n\nIn the following snippet, we configure a new `GraphQLClient`, letting it know where to find our GraphQL API. We then pass our client into React’s context using the provided `ClientContext`, making it available throughout our application.\n\nimport { GraphQLClient, ClientContext } from 'graphql-hooks'\n\nconst client = new GraphQLClient({\n url: 'https://api.graph.cool/simple/v1/cjs4qo29b2w0c0130tfx6maca'\n})\n\nfunction App() {\n return (\n \n {/* children */}\n \n )\n}\n\nuseQuery\n\nNow we will create a new component called `Posts`. This will send a query to fetch the posts from our GraphQL API using `useQuery` and render them in a list.\n\nimport React from 'react'\nimport { useQuery } from 'graphql-hooks'\n\nexport const allPostsQuery = `\n query {\n allPosts(first: 20) {\n id\n title\n url\n }\n }\n`\n\nexport default function Posts() {\n const { loading, data, error } = useQuery(allPostsQuery)\n\n return (\n <>\n

Posts

\n \n \n ) \n}\n\nfunction PostList({ loading, error, data }) {\n if (loading) return 'Loading...'\n if (error) return 'There was an error loading the posts :('\n if (!data || !data.allPosts || !data.allPosts.length) return 'No posts'\n\n return (\n
    \n {data.allPosts.map(post => (\n
  • \n {post.title}\n
  • \n ))}\n
\n )\n}\n\nRefetching\n\nLet’s include the `CreatePost` component inside `Posts` and make use of the `refetch` function from `useQuery` once the mutation is complete.\n\nexport default function Posts() {\n const { loading, data, error, refetch } = useQuery(allPostsQuery)\n\n return (\n <>\n

Add post

\n \n

Posts

\n \n \n )\n}\n\n\nHere we’re using graphql-hooks-memcache , an in-memory cache.\n\nWhat about Server Side Rendering?\n\nYup - you guessed it, graphql-hooks-ssr has you covered. Check out its documentation for a step by step guide.\n\nWhat else can graphql-hooks do?\nPagination\nManually trigger a query\nCustomise fetch options per query/mutation\nFine-grained error handling\n...and lots more! For a full list of features, see the README.\n\nIf you’d like to see some more examples you can check out our Fastify SSR and Next.js examples. We’d love for you to try it out yourselves and, as always, we welcome any feedback and contributions !\n\nAt NearForm, we have vast experience in building solutions across a broad tech stack to deliver reduced complexities and overcome common hurdles. If you are creating modern applications and leveraging web technologies, contact us to learn more about how we can help.\n\nPhoto by Clint Adair on Unsplash" ], "categories": { "primary": "frontend", "others": [ "backend" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-locking-down-aws-serverless-applications-the-right-way": { "href": "https://nearform.com/digital-community/locking-down-aws-serverless-applications-the-right-way", "postType": "blog", "slug": "digital-community-locking-down-aws-serverless-applications-the-right-way", "date": "2019-03-14", "title": "Locking down AWS Serverless applications, the right way", "authors": [ "RYAN ROEMER" ], "content": [ "Since the debut of AWS Lambda in 2014, the Functions-as-a-Service (or \"Serverless\") platform for backend services, has soared in popularity. At the forefront of this rise is the Serverless Framework, which offers exceptional development and operational ergonomics, especially when targeting AWS Lambda. However, crafting secure, locked-down cloud infrastructures around these applications remains an often overlooked challenge.\n\nIn this post, we will review the basics of IAM permissions in AWS Serverless Framework applications, tour some existing solutions, and then present the terraform-aws-serverless collection of modules. We will explore how to integrate the terraform-aws-serverless project to provide specialized roles for your development team, isolate and lock-down application privileges, and support many commonly-encountered development scenarios.\n\nThe problem\nExisting privilege approaches\nIntroducing the terraform-aws-serverless project\nHow to integrate terraform-aws-serverless\nConfiguration\nHow to provision the Terraform stack\nAttaching groups to AWS IAM users\nHow to create the Serverless Framework application as an admin\nHow to develop everything else as a developer/CI\nAutomating deployments with CI\nCustomizations, submodules\nConclusion\n\nThe problem\n\nGetting a Serverless Framework up and running in AWS is straightforward and well documented. Essentially, you write your code, add a few fields to serverless.yml, and you're up in the cloud with just some CLI commands!\n\nBut, beneath this happy, seemingly \"zero configuration\" world lies potential pitfalls and hidden complexity. The question we really need to ask is this:\n\nIs my Serverless Framework deployment secure?\n\nUnder the hood, the Serverless Framework creates many AWS resources beyond just the expected Lambdas and API Gateways. A large number of different permissions are required to deploy these resources. Consequently, many developers will feel pressure to take a shortcut and deploy Serverless Framework applications with an AWS superuser -- a potentially dangerous practice. If those credentials are compromised, every AWS resource in the same account could be at risk ranging from sensitive customer datastores to production web applications. Scary!\n\nExisting privilege approaches\n\nThere are number of ways to potentially lock down Serverless Framework applications on AWS. Let's review a few of the most common:\n\nSingle account, AWS superuser:\n\nThis is the easiest and riskiest option. You have one account and a superuser that controls all AWS resources (production databases, apps, etc.) is used to deploy Serverless Framework applications. If something goes wrong, everything everywhere is at risk.\n\nMultiple accounts, AWS superusers:\n\nFor a Serverless Framework application this usually means a different account for each stage (e.g., development, staging, production) of each separate application project (e.g., everything controlled within one serverless.yml file). If a given AWS superuser is compromised, the damage is limited to just the Serverless project at that specific stage. Much, much better security!\n\nBut, this creates an infrastructure hassle when applications need to share resources or communicate across a project or stage boundary. Just maintaining multiple accounts and superusers can be an operational burden. Accordingly, we'll sometimes see tradeoffs of security vs. maintainability with intermediate schemes such as single accounts handling all applications and resources for a single stage, so that, e.g., a compromise of development doesn't threaten the production environment.\n\nSingle account, limited AWS IAM users:\n\nThis approach entails setting up IAM policies tailored to exactly what an AWS IAM user needs for Serverless Framework development and nothing more. Ideally, in this scenario IAM policies isolate resource references distinctly for each of the following factors:\n\nService: A single Serverless Framework project (e.g., all the resources defined in one serverless.yml configuration file). Loosely, this corresponds to the service field in a serverless.yml file.\nStage: The deployment environment, corresponding to the provider.stage entry in a serverless.yml file. Usually, something like development, staging, and production.\nRole: Some notion of different \"types\" of users to distinguish ones who can create and delete the entire Serverless Framework application from those who can merely update existing applications.\n\nBy way of a little backstory, as Formidable became more and more involved with Serverless Framework applications, we scoured the community ecosystem for resources that might allow us to set up permissions along these lines. Unfortunately, we came up empty. While a few noble projects and articles attempted to provide guidance for limited Serverless Framework IAM privileges, we typically found some combination of the following shortcomings:\n\nFailing to lock down each IAM resource to the maximum extent possible. Most existing projects/articles in this area have some number of overly-permissive wildcards (\"*\") on AWS resources that could be locked down to at least service and stage.\nNot handling all Serverless Framework-specific variations (e.g., a Serverless Framework application has a potentially truncated S3 deployment bucket name).\nProviding only one set of all-or-nothing permissions rather than offering more nuanced roles along boundaries of creating/deleting vs. merely updating Serverless Framework resources.\n\nSo, after double-checking that none of the off-the-shelf solutions met our needs, we decided to write our own.\n\nIntroducing the terraform-aws-serverless project\n\nOver the past year our team has conducted extensive research to distill a collection of the absolute minimum IAM privileges that can support the Serverless Framework. With this set of IAM privileges, we've been able to achieve strong application isolation without hindering development velocity for a number of Formidable's clients.\n\nWe are thrilled to bring this work to the community with the terraform-aws-serverless project, providing battle-tested and locked-down privileges for Serverless Framework applications running within a single AWS account. We have scrutinized all applicable IAM resources in a Serverless Framework deployment, andfully documented exactly how and why each resource limitation / allowance exists in the project.\n\nHow to integrate terraform-aws-serverless\n\nThe high-level integration process starts with an AWS superuser who creates a support cloud infrastructure that can assign limited privileges to IAM users for developers and automation contexts. The IAM users can then appropriately deploy, modify, and introspect Serverless Framework applications. As the terraform-aws-serverless project is a collection of Terraform modules, you will need some familiarity with setting up Terraform stacks.\n\nA good first stop in your integration journey is to review our sample reference application that integrates everything we will discuss today into a fully production-ready \"hello world\" Lambda application. In the remainder of this post we will work through an abbreviated example in the following steps:\n\nConfigure your Terraform and Serverless Application projects.\nProvision the Terraform stack with an AWS superuser.\nAttach IAM groups to appropriate IAM users for the Serverless Framework project.\nDeploy the Serverless Framework and perform any other lifecycle commands.\n\nAside: Why Terraform?: Terraform is a bit of learning/technology burden over and above the normal expectations for a Serverless Framework application in AWS. In fact, our original version of the project was written in CloudFormation. However, we decided to port our work to Terraform for a few reasons, the main one being that Terraform modules/submodules allow easy packaging of distinct features and scenarios. Additionally, we have found Terraform stacks to be a bit more maintainable and extensible in practice over the lifetime of our client projects, and there is a large, vibrant open source ecosystem of Terraform modules to help kickstart your specific infrastructure project. All that said, if a strong community desire for a CloudFormation version of the project emerges, we could investigate releasing that as well.\n\nConfiguration\n\nThe purpose of the terraform-aws-serverless project is to support Serverless Framework applications, so configuration is mostly governed by the Serverless Framework. Thus, we'll start configuring our Serverless Framework project with the two relevant naming choices:\n\nservice: The project service field, usually something like a single word or phrase. One best practice for pairing with the Terraform module is to prefix the service name with sls- in serverless.yml. This allows an AWS administrator viewing cloud resources to easily distinguish between those created by the Serverless Framework from those created by Terraform. And, since we love weird, yet oddly cute tapirs, let's put this all together and name our Serverless Framework application sls-tapir.\nstage: The provider.stage field in serverless.yml. This is an arbitrary, user-defined list of different deployment target names in AWS. Our example will configure a reasonably typical list of development, staging, and production. For this exercise, we'll deploy to the development environment.\n\nLet's turn these choices into a serverless.yml configuration:\n\n# **`terraform-aws-serverless` integration note**:\n# Should be `sls-` + `service_name` parameter *or*\n# be specified directly as param `sls_service_name`.\nservice: sls-tapir\n\nprovider:\n name: aws\n runtime: nodejs8.10\n region: \"us-east-1\"\n stage: ${opt:stage, \"development\"}\n\nfunctions:\n function1:\n # ...\n function2:\n # ...\nyamlCopy to clipboard\n\nNow, let's configure a Terraform stack to support this Serverless Framework project:\n\n# variables.tf\nvariable \"stage\" {\n description = \"The stage/environment to deploy to.\"\n default = \"development\"\n}\n\n# main.tf\nprovider \"aws\" {\n region = \"us-east-1\"\n}\n\n# Core `serverless` IAM support.\nmodule \"serverless\" {\n source = \"FormidableLabs/serverless/aws\"\n\n region = \"us-east-1\"\n service_name = \"tapir\"\n stage = \"${var.stage}\"\n\n # (Default values)\n # iam_region = `*`\n # iam_partition = `*`\n # iam_account_id = `AWS_CALLER account`\n # tf_service_name = `tf-SERVICE_NAME`\n # sls_service_name = `sls-SERVICE_NAME`\n}\nhclCopy to clipboard\n\nOur configuration parameter service_name = tapir will produce AWS resources prefixed by default with tf-tapir and infers a Serverless Framework service field name of sls-tapir for assigning IAM privileges, which matches what we configured above in serverless.yml. (All service name-related fields can be customized, if desired.) The stage parameter corresponds directly to the provider.stage field in serverless.yml. The remaining input parameters are documented further in the project's integration notes.\n\nHow to provision the Terraform stack\n\nNow that we've ironed out our configurations, it's time to provision the Terraform support stack with an AWS superuser (or user with a lot of IAM privileges). Let's assume that an AWS user user-super has these permissions and we've configured a similarly named AWS profile, so we can use it in Terraform and Serverless via the AWS_PROFILE environment variable.\n\nTo create the Terraform support stack, we follow the usual Terraform sequence of init and apply:\n\n$ AWS_PROFILE=user-super \\\n terraform init -var stage=development\n\n$ AWS_PROFILE=user-super \\\n terraform apply -var stage=development\nshCopy to clipboard\n\n... and we have our support stack!\n\nAttaching groups to AWS IAM users\n\nThe Terraform stack outputs three IAM groups that can be attached to IAM users in our AWS account. Notice below that each group name corresponds to the level of isolation of service/Serverless Framework project, stage, and then our customized \"role\":\n\nAdministrator (tf-tapir-development-admin): AWS users assigned to the admin group can create/update/delete a Serverless application and do pretty much anything that the Serverless Framework permits out of the box.\nDeveloper (tf-tapir-development-developer): AWS users can update a Serverless application and do other things like view logs, perform rollbacks, etc.\nContinuous Integration (CI) (tf-tapir-development-ci); Presently the same privileges as the developer group, intended for automation.\n\nThe division into these three groups is an opinionated creation of the terraform-aws-serverless project. In practice, we have found that many projects don't typically require a developer or CI to be able to create / delete Serverless Framework resources, and thus we can get an extra level of security from segregating those privileges. This further allows us to put nearly all of the elevated AWS IAM permissions that only support a wildcard (\"*\") into the administrator group.\n\nOn the other hand, many Serverless Framework projects do have developers or automation creating new AWS resources quite often. In such a scenario, the appropriate solution may be to route everything through the admin IAM group. This at least provides security isolated to the Serverless Framework project and stage.\n\nContinuing with our example, let's assume we end up with the following users:\n\nuser-admin assigned to tf-tapir-development-admin group\nuser-developer assigned to tf-tapir-development-developer group\n\nWith these users, we're now ready to deploy the Serverless Framework application!\n\nHow to create the Serverless Framework application as an admin\n\nAn IAM admin user can perform all actions offered by the serverless CLI tool. A typical starting point is creating a Serverless Framework application with the first deploy, which then creates the necessary CloudFormation resources in addition to deploying the code to Lambda:\n\n$ AWS_PROFILE=user-admin \\\n serverless deploy --stage development\nshCopy to clipboard\n\nAfter this first deploy, assuming no underlying AWS resources change in the Serverless Framework application, a developer/CI user can perform additional deploys.\n\nSome other commands that are limited to the admin group include the following:\n\nserverless remove: Delete the Serverless Framework application and AWS resources.\nserverless metrics: View application cloud metrics. It's worth noting that the rationale for this action being in the admin group is that the underlying IAM resource must be a wildcard due to AWS limitations and can see information for other unrelated stages and applications.\n\nHow to develop everything else as a developer/CI\n\nAfter the Serverless Framework application is deployed by an admin, users assigned to the developer / ci IAM groups can perform most of the other Serverless CLI commands, including the same deploy command for an existing Serverless Framework application:\n\n$ AWS_PROFILE=user-developer \\\n serverless deploy --stage development\nshCopy to clipboard\n\nSome other useful commands:\n\nserverless info: View deployment information including service endpoints.\nserverless logs --function {FN_NAME}: View logs for a deployed function.\nserverless rollback: View available states to rollback a deploy to and perform the rollback.\n\nAutomating deployments with CI\n\nThe ci IAM group is intended for use in a CI/CD process, such that a CI-targeted AWS IAM user can deploy the Serverless Framework application at various stages. In Formidable's client work, we have set up successful CI/CD systems supporting scenarios like branch merges triggering staged deploys all the way to production automatically!\n\nAs mentioned above, if you expect that normal Serverless Framework project development will need to create or delete AWS resources (e.g., regularly adding new functions) then you may be better off using the admin IAM group for CI instead of ci. If such an occurrence is relatively rare, you can likely get away with the ci group in automation backed by a human admin performing some occasional, privileged manual commands before automation kicks in.\n\nCustomizations, submodules\n\nThe terraform-aws-serverless core IAM module should get most Serverless Framework applications off the ground. But, as applications grow, chances are you will need more functionality from the AWS ecosystem. This usually means bespoke Terraform extensions and/or integrating additional modules from the Terraform registry (both of which should be straightforward alongside the terraform-aws-serverless project).\n\nFor the Serverless Framework specifically, there are some enhancement scenarios that are so common that the terraform-aws-serverless project supports or will support them directly via Terraform submodules! We presently have one implemented submodule:\n\nX-ray: Brings IAM support for the fantastic AWS X-ray performance tracing tool to your Lambdas. After the submodule is deployed, you can enable X-ray support in your serverless.yml configuration or via a Serverless plugin.\n\nWe have an open source roadmap for additional terraform-aws-serverless submodules (most of which we've already implemented internally):\n\nVPC: Create an AWS VPC suitable for Serverless Framework integration for functions in VPC with 2 private subnets, 2 public subnets, a NAT gateway, and hot failover support.\nKMS: Create a AWS KMS key for service + stage specific encryption / decryption. Lambda execution role can decrypt at runtime.\nSecretsManager: Create and manage secrets tied to service + stage using AWS Secrets Manager. Lambda execution role can decrypt at runtime.\nCloudWatch Dashboards / Alarms: Create alarms and metrics in CloudWatch Dashboards customized to each service + stage. Tunable thresholds for alarms.\n\nFinally, we are interested in any additional submodule suggestions from the community for better Serverless Framework support!\n\nConclusion\n\nThe terraform-aws-serverless project has helped us bring role, stage, and service isolation to our AWS Serverless Framework applications. We hope that the project helps your team enhance the security and maintainability of your cloud infrastructure and Serverless applications as well. We encourage you to give it a try and share how well the project is working! Any comments or suggestions are most welcome to help us improve and focus our future development efforts.\n\n_Many thanks to the following folks for their invaluable post feedback: Alex DeBrie, Ian Walker-Sperber, Kevin Stephens, Tyler Thompson, and Amy Dickson _" ], "categories": { "primary": "cloud", "others": [ "devops", "security" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-virtual-coffee-with-nearform-delivery-architect-mark-ireland": { "href": "https://nearform.com/insights/virtual-coffee-with-nearform-delivery-architect-mark-ireland", "postType": "blog", "slug": "insights-virtual-coffee-with-nearform-delivery-architect-mark-ireland", "date": "2019-03-20", "title": "Virtual Coffee With NearForm Delivery Architect, Mark Ireland", "authors": [], "content": [ "A conversation with Mark Ireland, Delivery Architect\n\nFor each client engagement, Mark Ireland leads a team of up to ten developers, designers and DevOps engineers. He spoke to us about everything from remote working and financial strategy, to the disruption of open banking APIs.\n\nWhat’s the nature of your client projects at NearForm?\n\nThey’re digital transformation projects. We’re usually adding something new and exciting to what clients already have. I like to compare what we do in software to buildings architecture - in many cases today, we are working with enterprises on extending, rebuilding and renovating programs and sometimes an entirely new building is needed. We design and develop their structures to modernise them, improving their stability, accessibility, security, usability.\n\nWhat’s the secret to being a successful delivery architect?\n\nMost people come to this role from a developer role. The key thing is to recognise you can’t carry on just doing what you did before. You have to focus on the things that don’t come so easy. I have found that the softer skills are almost more important – like people management, conflict resolution and stakeholder management. Crucially, it’s about getting the most out of everyone on the team.\n\nWhat’s the secret to that?\n\nYou have to give everyone just the right amount of responsibility and just the right amount of work, to achieve and grow.\n\nI start each morning with a 1-to-1 with a team member. We then kick-off with a daily standup with the whole delivery team. We use agile methodology – so there are regular checks on how everyone is doing – and that makes my job easier.\n\nDo you meet in person?\n\nWe’re specialists in digital working, so our meetings happen over Zoom or Google Hangouts. My most recent project had team members spread across 7 different European countries and India, as widely spread as Ireland, the Czech Republic, Mumbai and Mallorca. Combined with the client also working from 5 different locations on 3 continents, we were truly a distributed team!\n\nWe always start a project with an in-person kick-off meeting and workshops with the client. This gives everyone a chance to build relationships as well as giving focused attention to the project so it gets off to a good start.\n\nWe then get together from time-to-time (not too frequently!) to work on critical pieces of work and ensure those relationships continue to flourish.\n\nWe work to critical success factors and KPIs that have been set with the client from the get-go. Typical KPIs are delivery on-time and on-budget but we also work to more commercially strategic goals around end-user engagement and satisfaction.\n\nWhere do your skills and expertise lie?\n\nI have been in software development for my whole working life, always trying to improve and add skills to my toolbox. I’ve had various roles across development, architecture, team leading and project management, working both within an organization and on the service provision side.\n\nI love the feeling when you create something new and exciting and it’s exactly what someone needs.\n\nCurrently, I’m really enjoying being in the mobile and internet space – making new products and bringing new capabilities to customers.\n\nWho are your clients?\n\nAt NearForm I’ve had various client engagements, with my major projects being with a top global management consultancy and with News UK , owners of The Times, Sunday Times and the Sun.\n\nWhat did that project entail?\n\nFor News UK, we created a back-end for their mobile news app, pulling data from existing diverse systems and consolidating content that is presented across multiple platforms. The goal was getting data into a form that can be loaded easily and transparently to the user, with resized images, etc and visually presented in the most optimum way.\n\nI know that for a news publisher, a CMS (content management system) is their lifeblood.\n\nWe’re effectively making news stories and articles from their CMS available seamlessly, scaling it up and out, and ensuring end users can access it even while they’re offline. We’ve also taken a long-term view in designing the solution to cater for today’s inputs but also tomorrow’s unknowns. The media industry is going through massive disruption, transforming how they distribute their content across multiple channels. Data is by far their most valuable asset. It’s great to be a part of such a dynamic time in that industry.\n\nHow do you know when a project is successful?\n\nWe work closely with all our clients and make sure we are constantly getting feedback. We work to critical success factors and KPIs that have been set with the client from the get-go. Typical KPIs are delivery on-time and on-budget but we also work to more commercially strategic goals around end-user engagement and satisfaction.\n\nWhat have you built for the global consultancy business you’ve mentioned?\n\nWe created a very powerful application for their specialised global financial strategy. The application crunches and charts data in lots of different ways, eliminating Excel and massively reducing the building time to create reports. We enabled all the data to be accessed securely via the cloud. It’s SAAS and the company is adopting it for use by their consulting teams as well as rolling it out to their own customers.\n\nFrom the sounds of things, your team built something special. Was that a career highlight for you?\n\nI’m very proud of the efforts of our team! We delivered over and above what anyone could expect and we have a very happy customer, which is the ultimate indicator of success.\n\nAt my previous job with Visa in the UK, I also worked on the technical strategy for card processing in Europe – that was also a highlight for me.\n\nWhat do you see as the trends that banks need to be on top of?\n\nOpen banking APIs are of great interest. They lead to the ability to combine data from multiple, disparate sources and apply intelligence on behalf of the end user. I can see these leading to a wide variety of new products and services, especially allowing people to subscribe to services that can do some of the work for them in managing their finances.\n\nHow many users will access the digital assets you create? I suppose the answer varies a lot if you’re talking about B2B versus B2C apps.\n\nIt does. The corporate financial strategy application will be used by hundreds of highly specialised users. The end user for the News UK app is a regular person who’s reading the content so the number of users will be many thousands and potentially could run into the millions.\n\nFrom your perspective, what trends have been & continue to be the most disruptive in IT?\n\nAcross the industry, it’s not necessarily about what’s new, but what’s vastly shaping business strategy. Most companies are still adapting to the big changes that cloud and mobile computing have brought. Those are the bases from where disruption comes.\n\nThere are many opportunities that digital brings and new possibilities appearing all the time as new services come online and leading-edge technologies such as machine learning become mainstream.\n\nOn the technical side, Node.js was massively disruptive – and backing that was good for NearForm. Because we’re seen as experts in JS, that wins us client contracts. Node.js is no longer the new kid on the block and has really grown up - enterprises are truly beginning to see the value world-over.\n\nWe work to critical success factors and KPIs that have been set with the client from the get-go. Typical KPIs are delivery on-time and on-budget but we also work to more commercially strategic goals around end-user engagement and satisfaction.\n\nAre your clients in Ireland or across the globe?\n\nThey’re all over – Dubai, in the US, around the EU – they’re diverse and distributed.\n\nHow much has NearForm grown in the three years since you joined?\n\nWe’ve doubled from around 70 people to around 120 since I’ve been here. That’s a real sign of how organisations are now approaching software development. Leveraging the talent, expertise and experience of a company like ours just makes sense. It's a perfect marriage of our extensive capabilities & deep technical knowledge with their business’ domain expertise and digital transformation opportunities.\n\nWhat’s the number one recommendation you give to clients undergoing digital transformation?\n\nHave a clear roadmap in place. Don’t take it in a piecemeal fashion. The whole idea is making sure you’re not disrupted – that you’re ahead of everyone else. Think like a disruptor. Focus on the outcomes. Look at your IT estate holistically, and recognize the capability that you need to reach your business objectives.\n\nYou mentioned your personal life helped make the decision to move to Ireland. How?\n\nIt’s a better way of life for me and my family. It’s a great environment here. Working for NearForm , you get the benefits of being with a dynamic company. Giving your employees a good lifestyle is a key differentiator in attracting talent. If they have the opportunity to work on cool, challenging projects, while also working from home – that’s a huge draw. It’s also a great way to retain the talent you have.\n\nHow do you stay relevant as a remote worker?\n\nIt’s generally a continual thing – continually reading on your interest area – as well as talking to others in the company, taking advantage of the fact that our client teams are always mixed up and there are always good people to meet.\n\nWhat’s the best thing about life in Tramore?\n\nThe Comeragh Mountains, surfing, horse riding, the Copper Coast, the creativity – my kids go to a great music school, for instance. We’ve got a very good life here.\n\n***\n\nThanks to Mark for giving us a good overview of disruption and how digital transformation projects can help customers stay ahead of the game. It was an interesting point about how by embracing remote working, NearForm has given itself an edge in recruiting talented staff." ], "categories": { "primary": "devops", "others": [ "work", "cloud", "backend" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-react-codegen-part-1": { "href": "https://nearform.com/digital-community/react-codegen-part-1", "postType": "blog", "slug": "digital-community-react-codegen-part-1", "date": "2019-03-26", "title": "The New React Native Architecture Explained", "authors": [ "LORENZO SCIANDRA" ], "content": [ "Part One: React and Codegen\n\nFirst announced in 2018, the React Native re-architecture is a massive effort Facebook undertook to address some long-standing issues of this cross-platform mobile solution.\n\nIn this series we will give an overview of the main elements that comprise React Native’s new structure. We will avoid showing code, to keep this explanation as accessible as possible, and will share our excitement regarding this new implementation.\n\nIn this first post we discuss the aspect of the re-architecture that will actually affect the code you may write—the new React features and a tool called Codegen.\n\nBefore we dive in, let’s review the basics: React Native is an open-source cross-platform solution that easily allows you to use React (and JavaScript) to create fully native mobile applications. It is widely used, not only by Facebook (which develops it with the help of the surrounding dev community), but also by both enterprise companies like Amazon and Microsoft, and startups alike.\n\nTo help visualise how React Native works, we have prepared this basic graph:\n\nAs you can see, there are four core sections: the React code you write (which is very similar to its web counterpart), the JavaScript that gets interpreted from what you write, a series of elements collectively known as “The Bridge,” and the Native side.\n\nThe key aspect of the current architecture is that the two realms, JavaScript and Native, are not really “aware” of each other. This means that, to communicate, they rely on asynchronous JSON messages transmitted across The Bridge. These are sent to the native code with the expectation (but not a guarantee) that they will elicit a response some time in the future.\n\nWhile an intuitive approach to start, and one that has served React Native well for years, the team at Facebook wants to rethink this async message approach to overcome its limitation: to enable this, they are working on a new architecture for React Native. We can describe their strategy as such: to take each of the four core sections of React Native and improve them individually. In this article we’ll explain how the team approached improving the first block, React.\n\nThe React Native team largely leverages the work done by their colleagues on the core React library. This means the new React Native will be able to rely on all the new features announced last year at ReactConf 2018 (you can find a comprehensive recap here). In particular, Andrew Clark showcased the concepts of concurrent mode and synchronous event callbacks—available from React 16.6—which, as we’ll see in the third post, enable some important low-level implementation.\n\nThe new React feature parity is, for the foreseeable future, the only change of the re-architecture that will affect the code most React Native developers write—by using Suspense to let components “wait” for something before rendering, and Hooks to use state and other React features without writing a class.\n\nThe React Native team is also doubling down on the presence of a static type checker (either Flow or TypeScript) in the code. In particular, they are working on a tool called CodeGen to \"automate\" the compatibility between JS and the native side. By using the typed JavaScript as the source of truth, this generator can define the interface files needed by Fabric and TurboModules (elements of the new architecture that will be showcased in the third post) to send messages across the realms with confidence. This automation will speed up the communication too, as it’s not necessary to validate the data every time.\n\nIn conclusion, if we were to replace this first block of the architecture with its new counterpart, the change would look like this:\n\nThis ends the first part of our exploration of the re-architecture. Over the next few weeks we’ll release more posts diving into the other elements. In the meantime, remember to share this article with your fellow developers or reach out for follow up questions over on Twitter (DMs are open).\n\nAs you can imagine, these changes open the door to many more improvements in the other blocks, and we hope they spark excitement regarding how these powerful changes will impact your codebases, without requiring you to rewrite (basically) anything.\n\nAll aboard the hype train!\n\nOther installments:\n\nPart 2 | Part 3 | Part 4" ], "categories": { "primary": "mobile", "others": [ "frontend" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-jsi-jsc-part-2": { "href": "https://nearform.com/digital-community/jsi-jsc-part-2", "postType": "blog", "slug": "digital-community-jsi-jsc-part-2", "date": "2019-04-02", "title": "The New React Native Architecture Explained: Part Two", "authors": [ "LORENZO SCIANDRA" ], "content": [ "Part Two: JSI and JSC\n\nFirst announced in 2018, the React Native re-architecture is a massive effort Facebook undertook to address some long-standing issues of this cross-platform mobile solution.\n\nIn this series we will give an overview of the main elements that comprise React Native’s new structure. We will avoid showing code, to keep this explanation as accessible as possible, and will share our excitement regarding this new implementation.\n\nIn this second post we will dive into how React Native consumes the code you write, and how the re-architecture changes it.\n\nBecause of the nature of JavaScript, the React Native team has to rely on an engine to interpret it so that it can run in a native mobile application. In the current architecture, the team chose to use JavaScriptCore (JSC) directly, as per Apple’s iOS guidelines rule “to use the appropriate WebKit framework and WebKit JavaScript” (JSC is the one used by WebKit).\n\nTo enhance this element, (second block of the current React Native architecture) they decided to properly separate the bundled and minified JavaScript produced from the written code, and the engine that would “digest it”. This was made possible by introducing a third element between the two, unequivocally called JavaScript Interface (JSI).\n\nThe JSI is not part of React Native per se—it is a unified, lightweight, general-purpose layer for (theoretically) any JavaScript engine. But, when inserted in the broader puzzle of the new architecture, it allows for a few truly important improvements.\n\nThe first one is fairly intuitive—potentially, the JSC could now be swapped out more easily for other engines (or newer versions of the JSC, as recently happened in RN 0.59). Other options you may know are ChakraCore by Microsoft and V8 by Google.\n\nThe second improvement—arguably the cornerstone of the whole re-architecture—is that “by using JSI, JavaScript can hold reference to C++ Host Objects and invoke methods on them.” This means that, finally, we are tackling the core issue explained in the previous article: the two realms of JavaScript and Native will be really aware of each other, and there won’t be any need to serialize to JSON the messages to pass across, removing all congestion on the bridge (we’ll explore this more in the next article).\n\nThis is a very exciting change because C++ has long been one of the few ways to share code between Android and iOS without relying on JavaScript; Android’s native code is written in C\\C++ (Java and Kotlin gets “translated down” via a Java Native Interface) and similarly iOS supports it by default (Objective-C is none other than a strict superset of C).\n\nSo this re-architecture step of React Native both enables massive changes to the current structure and opens the door to write more C++ for your apps, also enabling easier brownfield approaches.\n\nIf we were to replace the second block of the architecture with its new counterpart (you can find the full graph in the first article), the change would look like this:\n\nThis concludes the second part of our exploration of the re-architecture. Over the next few weeks we’ll release more posts diving into the other blocks. In the meantime, remember to share this article with your fellow developers or reach out for follow-up questions over on Twitter (DMs are open).\n\nAs you can imagine, these changes open the door to many more improvements in the next block, and we hope they spark excitement regarding how they will impact your codebases, without requiring any rewrites.\n\nAll aboard the hype train!\n\nOther installments:\n\nPart 1 | Part 3 | Part 4" ], "categories": { "primary": "mobile", "others": [ "frontend" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-no-build-step": { "href": "https://nearform.com/digital-community/no-build-step", "postType": "blog", "slug": "digital-community-no-build-step", "date": "2019-04-04", "title": "Don’t Build That App!", "authors": [ "LUKE JACKSON" ], "content": [ "React apps without a build step: no node_modules, no webpack, no babel, no worries. Scalable architecture for free using the platform.\n\nI’ve been a web developer for nearly a decade now and recently felt a certain contempt toward a platform I once truly adored. This has led me on a journey of discovery, which has altered my outlook on the future of web development.\n\nSaying no to the status quo\n\nFor too long we, as web developers, have been in contention with web browsers and with JavaScript the language itself. But this need not be the case anymore. ES6 was a major update to JavaScript that included dozens of new features and inspired browser vendors to get together in order to manifest an evergreen world. A promised land where we can all build out our dreams and live happily ever after.\n\nI ask that you forget what you know and take a few minutes to read this post in the hope that you too can be persuaded to liberate yourself from a toolchain conglomerate that once helped us be more productive, but is now almost certainly introducing unnecessary complexity, limitations, and overhead to our web apps and dev environments.\n\nI am going to pick on two parts of the de facto build chain that have historically proven somewhat a bane to the development cycle of most projects. Not surprisingly, I am going to propose alternatives. But not some shiny new tools. Rather, that you try using nothing at all instead.\n\nThe minimalist approach\n\nStarting from scratch is what we, as developers, love to do, so that is what we are going to do here. I want to demonstrate how to build up a modern dev environment (like create-react-app) just by using \"the platform\" and squeezing out every drop of potential from the latest language features.\n\nAs a child I used to say to my mother “Can I have this?” to which her response was always “Do you need it?”\n\nI love create-react-app (so much so I redesigned the welcome screen for it) and have encouraged many people to use it over the years. It is indeed a best-in-class starter that is great for:\n\nLearning React in a comfortable and feature-rich development environment\nStarting new single-page React applications\nCreating examples with React for your libraries and components\n\nBut it is not so great for (and I quote the create-react-app repository here):\n\nTrying React without hundreds of transitive build tool dependencies\n\nWhich is exactly what I wanted to do. I’m the kind of person who, rather than checking in luggage on a flight, will try squeeze everything I need into my hand baggage allowance. It’s easier like that, fewer dependencies, fewer worries.\n\nI try to take a similar approach with my apps. I do a lot of prototyping in my day job and have found pulling in 1044 separate dependencies, which amounts to around 200MB on disk, (a grim side effect of running npx create-react-app) for every demo is just not sustainable; my hard drive is only 128GB!\n\nHow to develop an app without Babel and Webpack\n\nI said we were going to pick on two tools in particular in this post and now is when you get to find out what those two things are and why:\n\nWebpack because of a new language feature called ES Modules that allow JavaScript to import other JavaScripts at run time.\nBabel because ES6 is well supported now and we can rely on tagged template literals, which enable embedding non-standard JS syntax.\n\nOk. So, you are telling me we can have all the nice things we like–such as bundling, JSX, the latest language features, live reload etc., all for free, from the platform?\n\nYes, you can... and in essence, this is what it looks like:\n\nimport { React, ReactDOM } from ‘https://unpkg.com/es-react';\nimport htm from ‘https://unpkg.com/htm'\nconst html = htm.bind(React.createElement)\n\nconst Route = {\n ‘/’: React.lazy(() => import(‘./routes/home/index.js’)),\n ‘*’: React.lazy(() => import(‘./routes/lost/index.js’)),\n}\n\nReactDOM.render(\n html`\n <${React.Suspense} fallback=${html`
`}>\n <${Route[location.pathname] || Route[‘*’]} />\n \n `,\n document.body\n)\njsCopy to clipboard\n\nWhat's more, with this architecture there are no node_modules, and no package.json is required by default either. So, let’s step through the example code and determine exactly how this all works.\n\nModularising your application without a bundler\n\nWe all dream of our app fitting into a single file. When you come up with an idea you immediately think “How hard can this be? It is probably only 1,000 lines of code or something... that will fit into a single file, no problems.”\n\n\"Good authors divide their books into chapters and sections; good programmers divide their programs into modules.\" –Preethi Kasireddy\n\nUnfortunately the reality is that nothing is as simple as it might first appear. Eventually you will want need to break up your code into separate files. Until now Webpack (or perhaps Rollup) has done the heavy lifting in this regard by \"bundling\" your code for you.\n\nBut whilst we have all been busy—maintaining bundler config files and debugging broken builds—some clever people over at ECMAScript have been baking this behavior into JavaScript the language itself.\n\nEven better than that—browser vendors have actually gone and implemented it!\n\nScreenshot from https://caniuse.com/#search=modules\n\nES modules are a super powerful concept—a monumental breakthrough for front-end development. Imports come in two different forms:\n\nStatic import is preferable for loading initial dependencies, and can benefit more readily from static analysis tools and tree shaking.\nDynamic import is useful in situations where you wish to load a module conditionally, or on demand; also known as lazy loading.\n\nIf we look at the example code we can see both dynamic and static imports are being used to load different dependencies:\n\nimport { React, ReactDOM } from ‘https://unpkg.com/es-react';\njsCopy to clipboard\n\nFirst, a static import is used to import React and ReactDOM straight from unpkg.com (which, if you didn’t know already, is a CDN that mirrors the NPM registry 1-to-1). This kind of import is synchronous and will block execution until the script has been resolved. It works with both relative paths—for example ./pages/home.js, and absolute paths like this one.\n\nTo make this work with React specifically, I created the package es-react (as currently Facebook doesn’t export a ES module build), which is hand-crafted but is absolutely synonymous with React 16.8.3.\n\nReact.lazy(() => import(‘./routes/home/index.js’))\njsCopy to clipboard\n\nSecond, a dynamic import is used to pull in pages appropriate to the current window location. It seems the React team saw this language feature coming and have implemented React.Suspense and React.Lazy components to aid with code splitting at run time like this.\n\nEmploying a combination of static and dynamic imports like this gives you absolute control of what is loaded and when. You can read more about this approach in the React documentation.\n\nUsing the latest ES6 syntax and JSX without Babel\n\nSo we have modularised (bundled) our app, essentially for free, just by using the new import syntax (that was easy), and we live safe in that all evergreen browsers support imports (static at least; you will need to shim dynamic imports for Firefox and Edge).\n\nBut the create-react-app build chain does a lot more than that; it passes the contents of each file Webpack finds into Babel, whose (primary) job is to transpile any new ES6 syntax into ES3/5 syntax so the all browser family can parse it without error.\n\nBut guess what? While we have been busy waiting for our projects to build (transpilation is quite intensive and is probably taking up at least a few second of your life every time you hit save), clever people at Google, Microsoft, and Firefox have been busy baking in support for all the latest syntax into browsers.\n\nScreenshot from https://kangax.github.io/compat-table/es6/\n\nNowadays, it is fair to assume that anywhere you can use ES modules, you can use most other ES6 syntax without transpilation. That includes cool stuff like const and let, async and await, array and object spread operators.\n\nBut what about JSX?! Surely that is not natively supported yet? No. You are right. That would be ridiculous because JSX is not real JavaScript. It is a domain-specific language created and maintained by Facebook. There are alternatives but it has proven popular enough for someone to go figure out how to make it work without a build step.\n\n\"I wanted to use Virtual DOM, but I wanted to eschew build tooling and use ES Modules directly.\" –Jason Miller\n\nThat person was Jason Miller who works for Google. He created a package called htm. The implementation takes advantage of another new language feature called Tagged Template Literals and you can use them in your project like this:\n\nimport htm from ‘https://unpkg.com/htm?module'\nconst html = htm.bind(React.createElement)\n\nReactDOM.render(\n html`
Hello World
`,\n document.body\n)\njsCopy to clipboard\n\nFirst, htm (a function) is imported from unpkg.com using a static import—just like es-react was. Then it is bound to React.createElement as to create the factory function html, which can create virtual dom nodes in a shape that ReactDOM can comprehend. It will do all of this in a blink of an eye, at runtime.\n\nYou can read more about how it compares to transpiled JSX in the project repo.\n\nServing up static files with live reload\n\nSo we have our script but to bring it to life we are going to need something else—a development server! Historically create-react-app has provided a solid localhost static file server with livereload behaviors. So let’s try to replicate that (without introducing a node_modules folder):\n\n$ npx servor\njsCopy to clipboard\n\nRun this command from the root directory of a create-es-react-app clone or any directory containing an index.html for that matter. The app should open in your preferred browser and will stay in sync with the codebase when changes occur. Magic.\n\nI created the servor package to do this one job specifically. It is tiny and dependency free; it takes advantage of an ordinary keep-alive connection in combination with node fs.watch and an injected EventSourceAPI script listening on the client. The source is very approachable and I encourage you to go check it out!\n\nThe start of a revolution\n\nSo there you have it, a react app starter template with lazy loading routes and views written in JSX, and a live development server. All without node_modules, Webpack, or Babel. It turns out most of what we need to build scalable apps is achievable just by using the platform, which really puts the power firmly back into your hands and lightens your life (each create-es-react-app clone weighs 50KB).\n\nNow, before you get your Webpack, Babel, or create-react-app sticker-coated pitchforks out, let me try to outline a few shortcomings of this approach. Some reasons why you might want to stick to the status quo (along with counter points):\n\nThere is no TypeScript or Flow support (could use comment types)\nServer-side rendering is untried (give it a go if you are interested)\nES modules builds for packages are not as common (make a PR)\nFirefox still doesn’t support dynamic import (use a ponyfill)\nReact suspense and lazy APIs are not final (but they will be soon)\nImporting scripts from the Internet can be dangerous (be careful)\nThere is still no official way of modularising styles (we could use fetch)\nMissing minification of styles or scripts (gzip works on unminified code too)\nNo centralised record of package versions (could employ static analysis)\nNo chunking could lead to many requests being made (http2 is here already)\nSyntax highlighting within tagged template literals could be better\n\nIf you can think of any more, then let me know on twitter!\n\nThe landscape is changing\n\nOf course whenever there is a fundamental shift in paradigms there is going to be resistance and people are going to find edge cases where the application of an idea is inappropriate. However, I have seen a lot of different architectures in my time as a developer and firmly believe that the simplicity of an ES module architecture is revolutionary and will be sufficient for the majority of use cases.\n\nIn the not-too-distant future\n\nI predict we are going to see smarter servers that perform production-ready optimizations—perhaps bundle, transpile, minify then cache—at request time, or perhaps at deploy time.\n\nThat's all, folks!\n\nThanks for taking the time out of your day to read this and thank you to my employer Formidable for allowing me to spend time researching, experimenting, and writing about interesting topics like this.\n\nFeel free to follow me on twitter @lukejacksonn" ], "categories": { "primary": "frontend", "others": [ "product", "devops" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-podcast-different-perspectives-with-nearform-smart-cx-new-thinking-for-the-digital-customer-experience": { "href": "https://nearform.com/insights/podcast-different-perspectives-with-nearform-smart-cx-new-thinking-for-the-digital-customer-experience", "postType": "blog", "slug": "insights-podcast-different-perspectives-with-nearform-smart-cx-new-thinking-for-the-digital-customer-experience", "date": "2019-04-05", "title": "Podcast: Different Perspectives with NearForm Smart CX - New Thinking for the Digital Customer Experience", "authors": [], "content": [ "According to industry analysts such as Forrester, enterprises need to be doing a lot more to ensure their digital CX transformation efforts don't stall. In this interview with NearForm's Design Director James Malone and Technical Director Damian Beresford we discuss what makes a great digital customer experience model, what sets the disruptors apart from the laggards and what enterprises need to do to make big gains." ], "categories": { "primary": "design", "others": [ "product" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-virtual-coffee-with-cian-foley-full-stack-developer-at-nearform": { "href": "https://nearform.com/insights/virtual-coffee-with-cian-foley-full-stack-developer-at-nearform", "postType": "blog", "slug": "insights-virtual-coffee-with-cian-foley-full-stack-developer-at-nearform", "date": "2019-04-08", "title": "Virtual Coffee with Cian Foley, Full Stack Developer at NearForm", "authors": [], "content": [ "Cian Foley has combined two passions in life – healthy eating and developing clean and tidy code. As NearForm’s latest superfan of React Hooks, Cian is the person to speak to about emerging technologies. We started the discussion talking about food – but it all links back to building great tech, in the end.\n\nWhere are you based and what’s your role at NearForm?\n\nI’m a Full Stack Developer, based in Waterford, and work with clients across the world. Full Stack Developers are expected to roll up the sleeves and jump in at any level in the stack, from the database to front end.\n\nSo you’re near enough to headquarters to work either from there or from home?\n\nYes, and there’s a big incentive to go into the office because the food is amazing. I am not sure if our chef, Mark Lanigan, has a Michelin star but the food is Michelin star quality: fresh fish, fresh produce, freshly cooked and it’s so tasty.\n\nI’ve noticed your background in food and dieting - and even body-building. Tell me about that.\n\nI wrote a book called Don’t Eat for Winter and published my thoughts on how to eat differently. Our modern-day diet is heavily loaded with a 1:1 ratio of fat to carbs. In nature, these are foods that natural beings would consume in Autumn to fatten up for Winter, such as a squirrel eating acorns. I used to weigh 256 pounds, several years ago, as a sedentary software engineer. I lost 90 pounds through a new form of dieting - I even entered a national male physique competition last year and came away with a bronze medal so I was very pleased with that.\n\nSuch an interesting sideline that you have. Back to the day job though – what projects are you working on at NearForm?\n\nI’m currently on a short-term project for a large telecoms customer – we’re basically extending their online catalogue of products and services over their high-speed networks. We’re adding new features, improving accessibility and so on, in order to provide a more unified and streamlined user experience. Due to confidentiality, I can’t say too much, but it will be a publicly-facing service to a lot of customers in a large country. On completion, it should result in an improved uptake of services.\n\nWhat is trendsetting for developers right now?\n\nI recently trained up on React Hooks , and I think it’s a game-changer, from a developer point of view.\n\nWhy is that?\n\nReact (the open source Javascript library started by Facebook) is a powerful tool, and React Hooks is a way of making code tidier and more readable. In one concrete example, we had a component that had lots of browser-specific code associated with making a window go full screen. This secondary feature of the component took from its readability. React Hooks makes those types of problems go away by extracting such code into testable modular libraries. It means features like this can be added faster, more efficiently and in a more standardised and testable way in future. An example of such a library can be found on https://github.com/nearform/react-browser-hooks , which we created at NearForm.\n\nDevelopers are mostly thought of as keyboard warriors, hammering away at a screen in a darkened room. How do you get into the zone to write code?\n\nI start the day by checking in – check emails, check in with my team, look at what’s shared on Slack. We work to an agile process – there are stories in a sprint that we’re working on for typically 2-week blocks. We work to tasks under these stories that have come out of the planning session, complete them and mark them as done. Typically, tasks are taken on by team members who are best suited, most experienced in a particular area.\n\nWhen I sit down to write code it’s almost like being hypnotised, getting into the detail of solving a complex puzzle. It’s all about problem-solving and getting into a flow. When we run into a hurdle we check documentation or Google the problem to quickly find a solution. It’s really important for me to have a very quiet environment, so working from home is good in that respect.\n\nOne criticism I have for the agile process is kudos during demos/retros. Sometimes stakeholders get involved in this and often developers working deep in the stack can be excluded as their work isn’t as visible as a cool front-end feature that everyone can appreciate. I think kudos is best left between peers on a team and if stakeholders wish to give kudos it should for the entire team. The last thing you want is developers competing for a rub on the belly.\n\nBy embracing open source and remote working, NearForm’s culture ensures its developers are constantly upskilling.\n\nYou’re characterising your work as very collaborative with the community of developers – not just at NearForm, but those around the world.\n\nThe key thing about being a developer is not how to solve a problem, but how to find a solution. We don’t waste time reinventing the wheel. You don’t need to know or solve every single thing yourself - because someone else will have shared a useful solution on GitHub or other forums.\n\nAre you self-taught or do you have a degree in CS?\n\nI studied at the Waterford Institute of Technology, and after my degree, I spent eight years there in the TSSG as a researcher.\n\nWhat’s new in software development?\n\nTechnology changes all the time. In my career I’ve used C++, Visual Basic, Java, PHP and various frameworks for each – you have to pick things up as you go along. There’s always a learning curve. Now, Node.js and React are what I use mostly, and I’ve found them to be the most enjoyable to work with, because of all the open source tools and support available.\n\nIs developing more progressive nowadays than it was before?\n\nThe cloud changes everything. Serverless computing as well. Just to get up and running is much cheaper. Front-end development has switched entirely to web and mobile, and it has matured. The front end is far superior to even three or four years ago. Now a lot of tools are free, and a lot of the grunt work of developing code has been taken away.\n\nWhat has changed for enterprises?\n\nI worked at an internship in a bank 20 years ago, building Windows applications. That was in Visual Basic 6. In that time period, applications were very heavy and OS specific. Now, things can be light and run on any platform. Highly-tested code is available for agile development. It’s a different world.\n\nIs that the point at which companies tend to approach NearForm: when they’re seeing the dangers of not embracing that new world?\n\nA lot of companies are living in the old world. They’ve gone on for years with the same technology – because, in their minds: ‘Why fix what’s not broken?’ Even these companies are coming to the realisation that if they don’t modernise and keep up, they will quickly become obsolete.\n\nCustomers are coming to us because they recognise that we have experts in every aspect of this new world. We have experts in software processes, architecture, DevOps, databases, web front-end, native apps, design, online marketing and analytics, literally all aspects of software development – if a customer needs it, it’s there and available and we have the breadth of expertise to understand how best to do it and avoid the pitfalls.\n\nCompanies we work with tend to quickly reap the benefits of the new world. Freeing up time is one key outcome. Using developments in technology to run things faster or to replace slower, outdated processes allows for that time to be spent on more useful pursuits.\n\nHow does the culture in NearForm lend itself to excellence in your work?\n\nBy embracing Open Source and having a highly collaborative team. All our code is reviewed before merging with a system or library, there’s always a stage where we get feedback from other NearFormers. These constructive reviews keep us on our toes and make us write better code. Our skills are constantly kept up-to-date because of that sharing mentality – because of Open Source and collaboration.\n\nWe also are practitioners of Inner Source: when a company takes the Open Source, collaborative mentality – sharing modules, and the agile way of doing things – and brings this way of working in-house.\n\nDoes the younger generation of developers have it easier?\n\nThe younger generation has more tools than we had when we started our career. My advice to a young coder would always be to look at Open Source code to learn your trade. All companies should look at exposing code that can be used by others, that people can benefit from. There’s no point in reinventing the wheel. Facebook is built in React – that’s Open Source. Paypal is putting a lot of Open Source code out – Google embraces Open Source – the biggest and best companies are going that way, and I think smaller companies should embrace Open Source too – there are so many benefits when individuals and companies put out useful reusable software as it improves the library for everyone including the creators, which ultimately improves the quality of the solutions they’re embedded in.\n\nAny other technology trends you’re seeing now?\n\nMaterial-UI. It’s a really elegant way of theming an application. It’s a really well implemented React styling and component framework using Google’s material design guidelines. We used this to create a complex MVP in a recent project for a large multinational - it was great to use and the customer was delighted with the results. Next.js is another tool that’s helping developers build multi-paged React websites, hooking in with web servers like Fastify for server side rendering. And I’ve already mentioned that React Hooks is a gamechanger for simplifying react development – you can read my latest blog post about it. Writing code is an artistic feat as well as technical. There’s a certain amount of creativity that goes into it. I don’t think computers can replace developers – not for a long time anyway.[\n\nWhat are some common failures or problems that you see a lot of companies facing?\n\nSometimes people get too used to one way of looking at things – and then when something new is introduced, two camps can form on either side of a debate setting up a “them and us” scenario. This can cause internal and external politics and drive mistrust between people, I guess it’s natural, but I think being curious to new ways of doing things and be as open-minded as possible as a culture circumvents this quite a bit. It’s also important to understand developers get anxious with FOMO when there is excitement about a new technology. There’s so much going on, it’s impossible for developers to be an expert in everything, and so continuous upskilling should be a priority to alleviate this. Thankfully NearForm is sensitive to this.\n\nI see the same in the dietary world – when people are too sold on a particular methodology and can’t judge others clearly for their merits. There are lots of things that are true when looking at them from different angles, but maybe there’s just one truth?\n\nAny other trends to look out for?\n\ngRPC – a remote-calling procedure initially developed by Google – is a more structured way of creating and consuming microservices. It’s an inter-service communication protocol that enables someone to write code on a local machine and call server-side APIs as if the service was on the same machine. It’s a bit like CORBA if anyone remembers that? We have done some work integrating gRPC with Fastify , an extremely fast and flexible web server, to connect to services implemented with gRPC from web clients easily.\n\nWhat are your thoughts on AI? Will it change the world dramatically for developers?\n\nWriting code is an artistic feat as well as technical. There’s a certain amount of creativity that goes into it. I don’t think computers can replace developers – not for a long time anyway. An AI algorithm has its place, for instance, enabling a machine to sift through a million photographs of fingerprints to catch a criminal – but the nuance of problem solving still has to be done by humans.\n\nAny parting words about working for NearForm?\n\nNearForm has been a challenge for me, but it’s an amazing place. It’s rare to see so many developers who are so passionate, and it’s rare to see our development process in other companies. It’s modern, efficient and it embraces Open Source and remote working. Remote working alone has made NearForm attractive for some really talented developers around the world.\n\nIt’s like a good football team – if you get a really great midfielder on board, then other talented players find out about it, and want to join up because being on their team improves everyone’s game!\n\n*** Thanks so much to Cian Foley for opening up about your worlds – both as a developer, as well as your passions outside of work in fitness and dieting.\n\nYou can also connect with Cian on LinkedIn ." ], "categories": { "primary": "backend", "others": [ "frontend", "devops", "cloud" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-fabric-turbomodules-part-3": { "href": "https://nearform.com/digital-community/fabric-turbomodules-part-3", "postType": "blog", "slug": "digital-community-fabric-turbomodules-part-3", "date": "2019-04-09", "title": "The New React Native Architecture Explained: Part Three", "authors": [ "LORENZO SCIANDRA" ], "content": [ "Part Three: Fabric and TurboModules\n\nFirst announced in 2018, the React Native re-architecture is a massive effort Facebook undertook to address some long-standing issues of this cross-platform mobile solution.\n\nIn this series we will give an overview of the main elements that comprise React Native’s new structure. We will avoid showing code, to keep this explanation as accessible as possible, and will share our excitement regarding this new implementation.\n\nIn this post we’ll dive into the “meaty” part of the re-architecture, the one that every React Native developer has probably heard about: Fabric and TurboModules.\n\nAs we previously explored, the new React allows for the concept of queuing, and the JSI enables JavaScript code to be aware of the Native code “on the other side”.\n\nFor the sake of accessibility and easy comprehension, we’ll “oversimplify” what the bridge block of the old architecture is:\n\nThis group of elements is basically responsible for two different behaviours: defining how the UI should look and behave (via the Shadow Tree) and managing the native side (via Native Modules). As mentioned, these communications happen via asynchronous JSON messages that get batched and sent, back and forth, over one communication channel, which, as you may expect, can get congested and lead to suboptimal experiences.\n\nThe Facebook team decided to split this massive bridge into two separate actors: Fabric, which is the re-architecture of the UI manager, and the TurboModules, which is the “new gen” implementation of the interaction with native side.\n\nFabric aims to modernize the rendering layer of React Native. In the current implementation all the UI operations are handled by a series of cross-bridge “steps” (React -> Native -> Shadow Tree -> Native UI). The new implementation, however, allows for the UI manager to create the Shadow Tree directly in C++, which greatly increases the swiftness of the process by reducing the number of “jumps” across realms. Basically, this greatly improves the responsiveness of the User Interface.\n\nAlso, by using the JSI, Fabric exposes the UI operations to JavaScript as functions: the new Shadow Tree (which determines what to really show on screen) is shared between the two realms, allowing straight interaction from both ends.\n\nAnd, if that wasn’t already a great improvement, this direct control from the JavaScript side allows to have the priority queues from the new React (mentioned in the first article) for the UI operations, in order to have opt-in synchronous executions where it benefits performance. This foundation will allow for improvements in common pitfalls like lists, navigation, and gesture handling.\n\nIn the current implementation, the Native Modules used by JavaScript code (e.g. Bluetooth) need to be initialized when the app is opened—even when they’re not used—because of the “unawareness” between the realms mentioned in the first article. The new TurboModules approach allows the JavaScript code to load each module only when it’s really needed, and to hold direct reference to it, meaning no more need to communicate using batched JSON messages on the old bridge. This will significantly improve startup time for applications with lots of Native Modules, along with the direct communication mentioned in the other articles.\n\nAll changes to the third block, as mentioned, rely on the JavaScript Interface explored in the previous article. If we want to sum up how the new Facebook team’s architecture looks like up to this step, it would look something like this:\n\nThis concludes the third part of our exploration of the re-architecture. Next week we’ll release the final post in this series. In the meantime, remember to share this article with your fellow developers or reach out for follow-up questions over on Twitter (DMs are open).\n\nWe hope we’ve sparked excitement on how these powerful changes will impact your codebases, without requiring any rewrites.\n\nAll aboard the hype train!\n\nOther installments:\n\nPart 1 | Part 2 | Part 4" ], "categories": { "primary": "mobile", "others": [ "frontend" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-react-testing-library": { "href": "https://nearform.com/digital-community/react-testing-library", "postType": "blog", "slug": "digital-community-react-testing-library", "date": "2019-04-11", "title": "Lightweight Client-Side Tests with React-Testing-Library", "authors": [ "EMMA BRILLHART" ], "content": [ "I have a confession to make: I usually dread writing tests. I especially dread writing them early on in a project, when components are still subject to rapid change and iteration. A few weeks ago, I found myself in that position—I had written new components that needed test coverage, but I knew there were several iterations of both designs and features ahead of us.\n\nOn this project we were using React-Testing-Library, a project by Kent C. Dodds that I had heard about, but hadn’t yet tried for myself. As I dove into the documentation, one thing in particular stood out to me: the philosophy of “The more your tests resemble the way your software is used, the more confidence they can give you.” React-Testing-Library allows you to write tests in a way that emulates how a user interacts with your app as it exists on the DOM level. This is in contrast to testing libraries like Enzyme, which focus more on testing components' implementation details.\n\nThis means no mocking, no mounting, just testing whether interactions with your components lead to the results in the DOM that you’d want and expect a user to get (note: you can do mocking with Jest or another framework if truly needed; see the react-testing-library docs for more details). Once I adjusted to this new mindset around testing, it felt so freeing and straightforward compared to traditional testing frameworks. Frequently, all I really care about is making sure what I expect the user to see, given some interaction, is what the user actually sees, so having a testing library built around that concept makes a ton of sense.\n\nThe syntax feels very intuitive as well—the way you’re testing client-side interactions is very similar to how a user would experience them, or how you, as a developer, wrote those interactions in the first place. The following set of code snippets shows how you’d test that a message with a count variable updates correctly after a user clicks a button that increases the count by one:\n\n// messageComponent.js\nimport React, { useState } from 'react'\n\nconst MessageComponent = () => {\n const [count, updateCount] = useState(1)\n\n return (\n
\n

{`The count is ${count}`}

\n \n
\n )\n}\n\nexport default MessageComponent\njavascriptCopy to clipboard\n// messageComponent.test.js\nimport React from 'react'\nimport { render, fireEvent } from 'react-testing-library'\nimport MessageComponent from './MessageComponent'\n\ndescribe('', () => {\n /* note - you could also use this in conjunction with a Jest snapshot\n and compare the rendered \"container\" to said snapshot */\n test('Component renders with a count of 1', () => {\n const { getByTestId } = render()\n // use getByTestId here for component with dynamic text\n const countMessage = getByTestId('countMessage').textContent\n \n expect(countMessage).toEqual('The count is 1')\n })\n \n test('Clicking the button adds 1 to the count', () => {\n const { getByText } = render()\n // methods like getByText are preferred when possible\n const button = getByText(/add/i)\n \n fireEvent.click(button)\n \n const countMessage = getByTestId('countMessage').textContent\n \n expect(countMessage).toEqual('The count is 2')\n })\n})\njavascriptCopy to clipboard\n\nThis felt much closer to writing in plain English than a lot of other testing syntax that I've used in the past, and I loved the simplicity of it.\n\nA lot of the things that change over time in a component, turns out, are implementation details—things like state shape, props (especially names!)—the stuff that often becomes tedious to continually update over time as the app and the components change. By contrast, I've found that intended outcomes of specific user interactions don’t often change in a way that drastically affects your test harness—an additional outcome might be expected, or perhaps an interaction gets removed altogether, but those changes would require additional tests regardless. I also believe that this makes tests more effective at, well, testing—if you don't have to update the tests every time something small changes anyway, it's clearer whether a change breaks the core intended outcome.\n\nI know that I’ll be reaching for React-Testing-Library the next time I’m choosing a library for client-side test coverage, and I recommend that you check it out if you haven’t already." ], "categories": { "primary": "test", "others": [ "frontend" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-lean-core-part-4": { "href": "https://nearform.com/digital-community/lean-core-part-4", "postType": "blog", "slug": "digital-community-lean-core-part-4", "date": "2019-04-16", "title": "The New React Native Architecture Explained: Part Four", "authors": [ "LORENZO SCIANDRA" ], "content": [ "First announced in 2018, the React Native re-architecture is a massive effort Facebook undertook to address some long-standing issues of this cross-platform mobile solution.\n\nIn this series we will give an overview of the main elements that comprise React Native’s new structure. We will avoid showing code, to keep this explanation as accessible as possible, and will share our excitement regarding this new implementation.\n\nIn this final post we tackle the last block of the old architecture graph presented in the first article:\n\nThis part is actually not directly iterated on code-wise—most changes come from how the previous elements have been reworked:\n\nThe New React & CodeGen\nThe JavaScript Interface (and JSC)\nFabric & TurboModules\n\nReact Native, on a more conceptual level, wants to be “agnostic” to its native platform. This is the key feature that enabled the creation of third-party implementations like react-native-web and react-native-windows, among others.\n\nMoreover, the Facebook team does not own either the iOS or the Android platform, so the approach on that last block can’t be “vertical” going deep into how those behave; but it can be “horizontal” in reducing the overall size of the react-native codebase involved.\n\nThis effort has been called “Lean Core” and it’s the aspect of the re-architecture where community help has been fundamental. At a high level, what this approach wants to accomplish is to take code current living in the main React Native codebase and extract it to its own repository.\n\nThis has two main benefits: to reduce the weight of a generated app and to allow proper maintenance on those elements not used directly by Facebook. The latter were receiving less care in the past, due to the complexities of modifying Facebook-owned code.\n\nSo, if we were to replace this fourth block and, in doing so, create the full graphic of the new React Native architecture, this is the result:\n\nAs you can see, the Facebook team’s complex effort affects many different aspects of how React Native works, without significantly affecting the developers using it. Not a small feat!\n\nThe new structure’s benefits will highly enhance apps developed via React Native, and the difference in quality and performance of them versus “pure native apps” will become smaller and smaller.\n\nWhen will these changes be ready and available? It’s likely this massive piece of work will reach its conclusion around Q4 2019 or Q1 2020, but there are no confirmed dates. Given the Facebook team is developing this re-architecture in the open, you can keep an eye on updates at any given point. At the time of writing, we can summarize it as follows:\n\nnew React = 16.8 is supported from version 0.59 (nitpick: Suspense is partially available since 16.6)\nCodeGen = development proceeding in the main repository (dedicated discussion)\nJSI = already on master and usable from version 0.59 (but no direct documentation on how to, at the moment) (dedicated discussion)\nTurboModules = development proceeding in the main repository (dedicated discussion)\nFabric = development proceeding in the main repository (dedicated discussion)\nLean Core = constantly ongoing, you can refer to this issue for more details (dedicated discussion)\n\nFor most of the points above I’ve included a link to a dedicated conversation on GitHub with the most updated information, so keep an eye on those for the latest!\n\nIn conclusion, we think this effort demonstrates several great enhancements to React Native. It’s an exciting time to be a React Native developer and we hope that this series of articles helped you gain a better grasp of these massive changes on the horizon.\n\nIf this was the case, remember to share this article with your fellow developers or reach out for follow up questions over on Twitter (DMs are open).\n\nAs you can imagine, we hope this blog series sparked excitement on how powerful these changes and how they will impact your codebases, without requiring any rewrites.\n\nAll aboard the hype train!\n\nOther installments:\n\nPart 1 | Part 2 | Part 3\n\nWe would like to thank Kadi and Carlos of the Formidable crew for reviewing this article series and making sure that they were on point, Mark for the graphics, and Amy for the editorial work. Special shoutout to Eli White and Rick Hanlon of the Facebook React Native team for proofreading the drafts and making sure that the content was correct." ], "categories": { "primary": "mobile", "others": [ "frontend" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-oss-maintenance": { "href": "https://nearform.com/digital-community/oss-maintenance", "postType": "blog", "slug": "digital-community-oss-maintenance", "date": "2019-04-17", "title": "OSS Maintenance Levels", "authors": [ "LAUREN EASTRIDGE" ], "content": [ "From the beginning, Formidable has valued and emphasized open source contribution. We know we could not exist without the enormous ecosystem of open source software that runs the modern web. We try to give back to this ecosystem by generalizing and sharing some of the patterns that we've found useful in our consulting practice, and by supporting creative open source contribution through internal programs. As Formidable has grown, we have continuously added projects to our portfolio, and today we have more than 70 open source projects that are downloaded and used a couple of million times each week. We try hard to make sure the software we build and maintain is reliable and useful. But how can we continue to maintain and improve every project in our ever-growing open source portfolio? Honestly, we can't.\n\nInstead of trying—and risking developer burnout in the process—we're opting for a more realistic approach. Rather than maintaining all, or even most of the projects in our portfolio, we will be selective and transparent about our priorities. To this end, we're introducing the concept of clearly delineated maintenance categories. We have spent the last few months prioritizing projects within our portfolio and sorting them into maintenance categories: experimental, active, stable, and archived. More detailed explanations of these categories are given below.\n\nExperimental\n\nBrand new! Anything goes!\n\nIdea generation, prototyping, and experimentation are crucial steps in developing new open source projects. The expectation of ongoing development and maintenance can impede the creativity and fun of building something new. For some, the idea of committing to maintain a project might keep them from ever even starting. In an attempt to minimize these effects, all of our new projects are automatically labeled as experimental. Development of new experimental projects may be quite active as we incubate new ideas, but ongoing maintenance is not guaranteed. As experimental projects mature, they are reevaluated and moved to one of the following categories.\n\nActive\n\nOngoing work! Upcoming features!\n\nProjects in this category solve problems for us and our clients. They provide tangible value so we work hard to maintain and improve them. When we move a project into this category, we are committing to ongoing maintenance and feature work for the foreseeable future. Moving projects out of this category is done thoughtfully and infrequently.\n\nStable\n\nNothing new on our roadmap.\n\nWe're not planning any new features for projects in the stable category. Stable projects still receive regular maintenance and bug fixes, but the pace of updates may be slower than for our active projects. Many projects in this category are small, simple, and feature complete. Larger projects in this category tend to be useful, reliable projects that we, at Formidable, are no longer trying to modernize or improve upon. The decision to de-prioritize new feature work on a large, active project is not one we take lightly. When this happens, we will try to be as transparent as possible about our motivations.\n\nArchived\n\nFork it if you like it!\n\nThe archived category is for projects that we are not currently maintaining, and are unlikely to develop or maintain in the future. Archiving projects lets us focus limited developer time on our active projects and devote more energy to generating new ideas. Experimental projects will be archived frequently. Active and stable projects will be archived only after a great deal of consideration and warning.\n\nIf you use one of our open source projects and you're curious about its maintenance status, please visit the project's Github repo. We've added maintenance status badges and descriptions to each project readme." ], "categories": { "primary": "oss", "others": [] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-sauce-program": { "href": "https://nearform.com/digital-community/sauce-program", "postType": "blog", "slug": "digital-community-sauce-program", "date": "2019-05-02", "title": "Paying Cold, Hard Cash for Open Source Contributions", "authors": [ "JANI EVÄKALLIO" ], "content": [ "At Formidable, open source is at the heart of everything we do. We help our clients build mission-critical systems using open source technologies like React, Node, GraphQL, and dozens of others. In return we contribute back to these projects, and give our engineers dedicated time to maintain more than 70 of our own open source projects that others can build upon.\n\nBut recently we’ve come to realize this is not enough.\n\nWhen push comes to shove, our clients take first priority, and there’s only so many hours in a work day (eight, to be exact). This means that some people are able to contribute more than others depending on their workload, or some may be able to do more in quieter periods and then have to juggle their maintainer responsibilities when things get busy.\n\nA side effect of building a company culture around OSS is that the kind of people who gravitate to work at Formidable are passionate about their open source work, and won’t stop contributing when they clock out at 5 pm. We need to acknowledge that most of the meaningful progress in open source communities happens outside of office hours, and if we truly value the open source ecosystem and believe that the work we do has a positive impact, we need to recognize and reward people for this work.\n\nIntroducing Sauce\n\nFor the last nine months we’ve experimented with paying our employees for any open source contributions to any project they do on their free time, no strings attached.\n\nWe call this program Sauce, and here’s how it works:\n\nWe pay our employees $20/hr for contributions to OSS and tech communities, whether it’s a third-party library we use in our work like React, Next.js, or styled-components; one of our own OSS projects like Spectacle or Urql; or even a personal hack project purely for fun and learning, as long as it’s released under an OSI license. Contributions can be code, documentation, design work, pull request reviews, issue triage, community management, or really anything that the individual thinks counts as a contribution\n\nMore recently, we’ve expanded the definition of contributing to include any social impact work within the field of technology, whether it’s teaching children to code at your kid’s school, speaking at your local meetup, or volunteering at a bootcamp for underrepresented minorities in the industry. This makes the Sauce program available to those who want to give back to the community, but don’t feel OSS is their preferred medium.\n\nDuring the trial period, 42% of all Formidables (and half of our engineering staff) have been paid for contributions to 55 different OSS projects and local mentorship communities. Our employees have fixed critical bugs in code we use every day, launched new OSS projects, had a lot of fun, and learned a ton!\n\nDolla dolla bill y'all\n\nIt’s well known that nominal compensation isn’t the most effective incentive to get people to do things, and compared to engineer salaries in our US and UK tech hubs, $20/hr isn’t exactly a windfall.\n\nThis is intentional. We don’t want people to log on after hours to earn money. Instead, we think of the Sauce bonus as a recognition of the work people want to do anyway, and the compensation is aimed to be meaningful enough to do something fun with, but not so high that it would skew their priorities to stare at their computer screens instead of spending time with their hobbies, families, and friends.\n\nWith the Sauce bonus, you can grab a free coffee and respond to a couple of issues, treat yourself to a cocktail while reviewing a PR, earn a nice meal by fixing a bug, buy yourself a Nintendo Switch to wind down after implementing a new feature to an existing project, or fund a weekend getaway with your partner by launching a new library that solves a previously unaddressed problem.\n\nBy keeping the dollar amount reasonable, we can also ensure that the program is sustainable. Even if every single Formidable employee spent all their evenings contributing to open source, we could afford it in perpetuity.\n\nPlease, steal this\n\nThe program is working well for us, and after an initial trial period, we’ve now made the Sauce bonus a permanent perk for all Formidable employees.\n\nWe foresee Sauce playing a part in the personal development and employment satisfaction of our team, but we are far more excited about the good work we can support them to do in OSS and broader tech communities. We also see Sauce motivating people to work on their passion projects, encouraging them to experiment with new technologies to support their career growth, and pass on learnings to the benefit of our clients.\n\nIf you think what we’re doing with Sauce is a good idea, feel free to start your own OSS sponsorship program at your company, or forward this article to your manager with a wink emoji! Or, you could always just become a Formidable 😉.\n\nIn fact, Sauce itself is heavily inspired (both in name and concept) by Spice Program, a similar social impact initiative pioneered by my former employer Futurice.\n\nSo, please fork this idea and make it your own. And as always, we’d love to hear your feedback over on Twitter." ], "categories": { "primary": "oss", "others": [ "work" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-speeding-up-react-ssr-announcing-esx": { "href": "https://nearform.com/insights/speeding-up-react-ssr-announcing-esx", "postType": "blog", "slug": "insights-speeding-up-react-ssr-announcing-esx", "date": "2019-05-08", "title": "Speeding up React SSR: Announcing ESX", "authors": [], "content": [ "Improve Server-Side Rendering throughput with ESX\n\nReact is a hugely popular frontend framework that revolutionised the frontend development world.\n\nAs a Principal Architect and Consultant at NearForm, it has become painfully clear that React's Server-Side Rendering (SSR) is a performance bottleneck for web backends around the world. ESX presents a simple solution that can be dropped into pre-existing React applications to significantly improve Server-Side rendering throughput.\n\nThis month I announced ESX at React Amsterdam. It’s primarily designed as a high-speed Server-Side Rendering engine for React that may be used with absolutely no manual modifications to your code base. Check out the repo at https://github.com/esxjs/esx.\n\nThere are many workarounds to React SSR overhead such as caching, streams, and snapshotting – all of which can be useful in different scenarios. However, ESX improves the rendering algorithm itself. This is extremely important when it comes to any dynamic SSR requirements such as feature flags, A/B testing, or content based on contextualized state. Not to mention SSR is also important for PWA perceived performance.\n\nA template engine essentially injects variables into strings, this is quite efficient. On the other hand, React SSR creates an object for every HTML element, builds a tree representation of the DOM in memory and then converts that tree into a string. It does this every time a request is made. While it’s still under active development, ESX proves that we can take a template engine approach to React SSR for higher performance, lower overhead Server-Side Rendering.\n\nIn the small app microbenchmark a 15x speed improvement can be observed. But by nature, microbenchmarks are not necessarily indicative of real-world performance gains. Due to the multitude of architectural options in React applications, every case is different and ESX can improve speed to varying degrees. It may not increase the speed of your Server Side Rendering at all. In these cases SSR won’t be the bottleneck – it may be the CSS solution you’re using, it may be to do with a lot of serializing, it could be the HTTP fetching library you’re using, it could even be your logger. One of the easiest ways to figure out what your bottleneck is to use a flamegraph tool, such as 0x, or clinic-flame, but that’s a whole other subject.\n\nThe https://github.com/esxjs/esx-demo repo strives to represent a conventional React architecture with certain pieces (such as CSS and HTTP requests) stripped out to remove noise. You can peruse the React application here and view its optimized form here.\n\nIf we clone the repository, run npm install and then run npm run bench the benchmarking script will start a server for the unoptimized application and load test it with autocannon. Then it will do the same for the optimized application. The result should show approximately 75% lower latency, 325% more request per second and 330% higher throughput.\n\nIn future posts, I’ll explain the techniques used to achieve this gain in detail. For now, the aim of this post is to highlight the key piece of this optimization: tagged template literals. Not only can template literals be faster, but they’re also native syntax. It is my firm belief that if React were created today, it would use tagged template literals instead of JSX.\n\nAlmost the exact same syntax can be achieved:\n\nTo be clear, ESX does not enforce a requirement to use template literals directly. The JSX to ESX transpiler is currently experimental and work is ongoing but you have the choice between a babel plugin (babel-plugin-esx-ssr) or the built-in ESX preloader to convert all JSX and React.createElement calls into ESX tagged template literals.\n\nYou can try the experimental preloader out today with the following command:\n\nnode -r esx/experimental-optimize app.js\ntextCopy to clipboard\n\nIn addition, you can also use ESX directly both on the server and in the browser. Depending on preference, this can be quite useful during development. While ESX works in the browser, it won’t be as efficient in the browser environment as calling React.createElement. This is why a production transpiler for the browser is provided: babel-plugin-esx-browser. This converts ESX to React. createElement. It’s the ESX equivalent of transpiling JSX. Of course, this won’t be needed if you stick with JSX and simply use the SSR babel plugin or preloader mentioned above.\n\nIf you’d like to get started with ESX there is an easy and straightforward way to minimize the risk: render with both React and ESX and diff the resulting HTML. This is both strongly advised and highly encouraged. Issues and PR’s are very welcome as we take ESX forward.\n\nConversely, if you are struggling with Server Side Rendering (React, or otherwise) and need some pointers get in touch or hit me up on Twitter.\n\nAbout the Author\n\nDavid Mark Clements is a Principal Architect who has been coding with JavaScript for over 20 years and Node.js since 2011. David is a part of a unique team at NearForm which is helping to drive the commercial opportunities of Open Source for leading organisations worldwide.\n\nWith NearForm, David has engaged in performance engineering, architectural consultancy, brown-field technical leadership and project bootstrapping for a vast array of our clients. We help connect enterprises and users with builders and maintainers to help them adapt to a modern technology stack to drive faster lead-times for digital innovation.\n\nLearn more about our React UI development services.\n\nYou might like some of our other recent React posts:\nIntroducing GraphQL Hooks\nSay Hello to React Browser Hooks\nForget everything you learned about React..Hooks rock!" ], "categories": { "primary": "frontend", "others": [ "devops" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-runpkg": { "href": "https://nearform.com/digital-community/runpkg", "postType": "blog", "slug": "digital-community-runpkg", "date": "2019-05-13", "title": "runpkg: The Online Package Explorer", "authors": [ "LUKE JACKSON" ], "content": [ "We are seeing advances in browser technologies that have the potential to change the way we write applications on the web. Now that ES6 modules are well on their way to being supported by all evergreen browsers, we may no longer need to build and bundle our JavaScript code using complex and proprietary tooling. Our source code is becoming our distributed code!\n\nTLDR; You can now import JavaScripts directly from your JavaScripts in the browser, at runtime. The benefits of this are amplified by CDN services such as unpkg.\n\nUnpkg was created and is maintained by Michael Jackson from React Training; its sponsors include CloudFlare and Google (via the Angular project). Despite being somewhat under the radar, unpkg is a big deal and serves up more scripts than you would believe!\n\nFrom April 3 to May 3, 2019 unpkg served 16,811,631,733 requests and a total of 213 TB of data to 1,500,325,458 unique visitors, 99.16% of which were served from the cache. Woah.\n\nWhile build step free single-page web apps are still on the bleeding edge, these numbers hint at great demand and demonstrate that there is tremendous infrastructure in place to support this approach.\n\nWe have been experimenting with this methodology and new tooling for a while now, but wanted to improve the overall developer experience making it easier to work with and generally more welcoming to newcomers.\n\nNew problems\n\nWhen importing a script from the internet (rather than installing it locally with npm or yarn) it is very easy to pull in more than you bargained for. For example one line of code such as:\n\nimport lodash from 'https://unpkg.com/lodash-es'\njsCopy to clipboard\n\nMay appear pretty harmless on the surface, but it set in motion a recursive dependency resolution process that runs client-side and that—in this particular case—results in more than 600 files (~600KB) being requested, downloaded, and evaluated by the browser. Yikes!\n\nTruly understanding the impact of your imports is hard. To begin to get an idea of what is going on under the hood you could visit the package url at https://unpkg.com/lodash-es and manually inspect the file.\n\nHowever, all you are presented with is a file that potentially depends on some other files. You have no idea what those files are doing and if they have dependencies of their own. Nobody reads through their entire node_modules directory, but as responsible developers, we should be aware of the implications of pulling in third-party dependencies, especially when doing it at runtime. Proper tooling can help us here.\n\nWe wanted to help in this regard by developing a tool that makes it easier to analyze and understand the code your application depends on.\n\nIntroducing runpkg\n\nWe took inspiration from tools like Bundlephobia, Octolinker, and Githistory, whilst we asked ourselves: What are the most useful and impactful functionalities we might need in a CDN-driven package/module era?\n\nMake the published code more readable.\nMake the packages more navigable.\nMake the impact of importing packages more transparent.\n\nThat's why we've built runpkg: the online package explorer.\n\nHow to runpkg\n\nSo, how do you use runpkg? Well, just prefix any unpkg url with r!\n\nRunpkg turns a static file into an interactive and information-rich browsing experience. In the navigational panel to the left we display package information and directory structure, which enables quick switching between files. Front and center we render a syntax-highlighted representation of the code itself to make it much more human readable. In the background we perform static analysis on the contents of the current file, generating a dependency graph and surfacing insights on the right-hand side panel.\n\nThese are the key features we set out to implement, but the fun doesn't stop there. We have a long list of potential improvements including prettier integration, permalinking, version diffing, and more advanced static analysis.\n\nVisit https://runpkg.com to try it out and give us feedback on Twitter!\n\nDisclaimer! Handling all the different module definitions and resolution algorithms employed in the wild (imports, exports, AMD, UMD, CommonJS, ejs, .mjs, require, relative, absolute, external, https urls, the list goes on...) turned out to be an interesting, but tough challenge to solve. If you find an edge case we didn't yet discover, please do let us know! The project is fully open source and contributions in the form of ideas, bug reports, and pull requests are welcome via the GitHub repository!\n\nRunpkg itself has been built using a buildstep-less ES6 module architecture, so check out the source code. You can read more about our experiments with ES modules at https://formidable.com/blog/2019/no-build-step." ], "categories": { "primary": "frontend", "others": [ "cloud", "oss" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-meet-the-team-at-fullstack-new-york": { "href": "https://nearform.com/insights/meet-the-team-at-fullstack-new-york", "postType": "blog", "slug": "insights-meet-the-team-at-fullstack-new-york", "date": "2019-05-13", "title": "Meet the team at FullStack New York!", "authors": [], "content": [ "The NearForm team will be at Fullstack NYC on 16th and 17th May to talk about high-performance Full-stack frameworks & tools including Node.js, Fastify, PWAs, Speeding up React SSR with ESX, React Hooks and Clinic.js and to offer a glimpse at our high-performing web applications designed for the future of banking. Matteo Collina , Technical Director, will be giving a talk on Fastify and how to use it to develop performant and maintainable Node.js applications.\n\nYou can also find out about ESX , recently announced by David Mark Clements . ESX is a simple solution that can be dropped into pre-existing React applications to significantly improve Server-Side rendering throughput, removing performance bottleneck for web backends around the world.\n\nOur team will be coming from far and wide to Fullstack NYC - from Italy, Ireland and across the US. Truly committed to shaping a better world in all that we do, and building on our Open Source origins, we love to promote the sharing of thoughts, knowledge and ideas! Hence the reason we're heading along to Fullstack NYC!\n\nOur global team is based on respect, inclusivity and diversity and as part of our involvement in Fullstack NYC, we will have a charity raffle (don’t worry, everyone coming to the conference gets a free ticket to enter!) and $5 per person will be donated to New York-based the Code Cooperative !\n\nIf you like the sound of us and would love to work with us, we're growing our team of US-based Senior Node/React developers.\n\nVisit www.nearform.com/careers/ to find out more or come talk to us at the event. See you there!" ], "categories": { "primary": "backend", "others": [ "frontend", "oss", "work" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-jetpack-blazingly-fast-serverless-packaging-and-deploys": { "href": "https://nearform.com/digital-community/jetpack-blazingly-fast-serverless-packaging-and-deploys", "postType": "blog", "slug": "digital-community-jetpack-blazingly-fast-serverless-packaging-and-deploys", "date": "2019-05-14", "title": "Jetpack: blazingly fast Serverless packaging and deploys", "authors": [ "RYAN ROEMER" ], "content": [ "We love the Serverless Framework at Formidable. We get to focus on application development while it takes care of details like packaging and deployment—all with a rich plugin ecosystem and a great technical community!\n\nHowever, an oft-recurring pain point for Serverless projects is that packaging and deploying can be really, really slow.\n\nWe're thrilled to introduce the serverless-jetpack plugin, a drop-in replacement for built-in serverless CLI packaging. For many large, real-world Serverless JavaScript applications, faster packaging may be only a few lines of configuration away!\n\nWhat slows down Serverless packaging?\n\nA few months ago, a co-worker noticed that Serverless Framework deploys for a client project were taking more than 10 minutes in just the packaging stage. This made the developers miserable, and even worse, significantly hindered our production deployment speed.\n\nWe dug in to how the serverless CLI packages files and discovered that a typical / default packaging arrangement leads serverless to:\n\nRead nearly all of node_modules (and other sources) from disk into a preliminary file list.\nThen exclude files from the list detected as devDependencies. (And, perform additional disk I/O in node_modules to infer what are devDependencies to exclude.)\n\nThis approach hit us hard, as our client project had a git monorepo with many individually packaged Lambda functions, meaning lots of large node_modules directories driven primarily by devDependencies.\n\nA simple, faster idea\n\nSo boiling the problem down: the vast bulk of files in node_modules read during packaging end up being excluded later because they're devDependencies. Then we thought, what if we didn't have to read all of those devDependencies? What if we somehow had the serverless CLI read just the production ones?\n\nWell, we would need a tool to quickly get us production dependencies... But, as it turns out we have not one, but two! Modern npm and yarn, the ubiquitous package managers your project already uses, install production dependencies very quickly when used with a lockfile.\n\nWe postulated a theory: the cost of an additional, temporary yarn|npm production install would be far less than the current time the serverless CLI uses in excluding extraneous node_modules files post-read.\n\nHow it works\n\nWith this hunch in hand, we tried a simple packaging experiment:\n\nDo a fresh production yarn|npm install into a temporary directory.\nDo normal exclude/includes on project sources except node_modules, instead matching against the production one in our temporary directory.\n\nThe results were amazing. Across various packaging [scenarios][jp_repo_scenarios], we were able to see consistent, impressive packaging speedups. And the speedups increased as development dependencies increased.\n\nSome timings for relative comparison from our project benchmark:\n\nScenario\tMode\tType\tTime\tvs Base\nsimple\tyarn\tjetpack\t5687\t-42.16 %\nsimple\tyarn\tbaseline\t9832\t\nsimple\tnpm\tjetpack\t6163\t-31.37 %\nsimple\tnpm\tbaseline\t8980\t\nindividually\tyarn\tjetpack\t8259\t-50.44 %\nindividually\tyarn\tbaseline\t16665\t\nindividually\tnpm\tjetpack\t9787\t-50.10 %\nindividually\tnpm\tbaseline\t19613\t\nhuge\tyarn\tjetpack\t13473\t-71.85 %\nhuge\tyarn\tbaseline\t47864\t\nhuge\tnpm\tjetpack\t9451\t-71.45 %\nhuge\tnpm\tbaseline\t33105\t\n\n(The Mode column has clickable links to scenario projects on GitHub. For Type, baseline is built-in Serverless Framework packaging, jetpack is our new plugin. Time is in milliseconds.)\n\nTry it out!\n\n... and thus the serverless-jetpack plugin was born!\n\nInstallation should be a breeze for most projects. Jetpack works seamlessly with built-in Serverless packaging configuration, including service and individual function-level configurations with exclude, include, etc.\n\nyarn and npm users should add this to serverless.yml:\n\nplugins:\n - serverless-jetpack\nymlCopy to clipboard\n\nand npm users will also need:\n\ncustom:\n serverless-jetpack:\n mode: npm # (default `yarn`)\nymlCopy to clipboard\n\nAnd that's mostly it!\n\nWe take correctness seriously at Formidable. In addition to the usual tests and style checks, we validate that Jetpack's output in each scenario identically matches that of built-in Serverless packaging.\n\nAs a few parting thoughts, you should be using yarn with a yarn.lock file or npm@5.7.0+ with a package-lock.json to get a full speedup. And, there are a few esoteric complexities and additional configuration options that you may want to review before integration.\n\nAll in all, if Serverless Framework packaging/deployment speed is cramping your style, hook up a jetpack and see if your deploys take off! 🚀" ], "categories": { "primary": "devops", "others": [ "cloud", "backend" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-tipple": { "href": "https://nearform.com/digital-community/tipple", "postType": "blog", "slug": "digital-community-tipple", "date": "2019-05-16", "title": "Tipple: Stealing Ideas From GraphQL and Putting Them to REST", "authors": [ "ANDY RICHARDSON" ], "content": [ "You've been using Redux for a while now. It was exciting at first, but the amount of code you need to ship a new feature is starting to creep upwards.\n\nThe line between your application state and data cache is blurred and you wonder how your redux store managed to become so complex despite countless efforts to keep things simple.\n\nWith every new addition to the backend, you find yourself making sweeping changes across the project. Actions, reducers, containers — it feels like you're touching every file in the codebase and you ask yourself: Were things always this complicated?\n\nDoes this sound familiar?\n\nFirst things first — you're not alone. Redux is the industry standard for managing application state, and while some of the problems mentioned above can be attributed to Redux, much of the complexity originates from the way we currently manage front-end caching with REST backends.\n\nTo understand this problem, let's look at the typical approach for front-end caching with REST and compare it to GraphQL.\n\nActionable changes with REST\n\nIf you've ever used the classic Redux + REST combo, chances are you're familiar with this approach. It goes a little something like this:\n\nFetch data from REST API.\nParse data and add to a local store.\nAs a pushing action occurs (POST, PUT, DELETE, etc.) update the local state to reflect the changes in your app.\n\nAt first this seems like a reasonable way to do things. As a new item is pushed to the backend, we add that item to our local store. When a push to the backend occurs and an item is changed, we change it in our local store.\n\nUnfortunately, our REST backends are often more than just an API for working with normalised data. There will be numerous API calls where changes to a single item cascade across our whole data model, and suddenly our simple caching implementation becomes a complex layer of redundancy that needs to be actively maintained.\n\nIntrospection assisted caching with GraphQL\n\nMost GraphQL clients in React (such as URQL or Apollo Client) don't require any reducers to mirror changes to the backend. Instead, any push to the backend will immediately update the values in the local cache, but how does this work?\n\nIntrospection is one of the single most impressive parts of GraphQL. While a REST client would need bespoke logic to parse data into the local cache, a GraphQL client is able to get additional information about the type of data being returned—and therefore, that data can be stored in a normalised format.\n\n// Example mutation\naddComment($postId: Int!, $text: String!) {\n Id\n comments {\n Id\n text\n __typename\n }\n __typename\n}\n\n// Example response\n{\n Id: 1,\n comments [\n {\n id: 5,\n text: \"I'm normalised!\",\n __typename: \"comment\"\n }\n ],\n __typename: \"post\"\n}\njsCopy to clipboard\n\nIn the above example you can see a request and response for \"adding a comment to a post\" in GraphQL. Unlike REST, because we are able to make use of introspection, the single object in our response can be identified as being two different data types to parse into our cache—a post with an id value of 1, and a comment with id of 5.\n\nThe major difference here is that the caching logic is no longer tied to the data model, meaning that it can be abstracted and reused across multiple projects. We're now consistently getting the changes to our data directly from a single source (our GraphQL API) rather than from making manual local mutations based on API responses.\n\nThat was a lot to take in...\n\nYou're right, let's break this down.\n\nActionable caching with REST\n\n✅ Caching of backend data\n\n❌ Redundant layer of backend logic\n\n❌ Complex modeling of data relationships\n\n❌ Project specific caching logic\n\n❌ Multiple sources of truth\n\nIntrospective caching with GraphQL\n\n✅ Caching of backend data\n\n✅ Normalised storage of data\n\n✅ Decoupled & abstracted caching logic\n\n✅ Single source of truth\n\nFine, I'll move to GraphQL\n\nIf only it were that easy. I recently asked the people of Twitter what backend they're working with, and it's clear that many are still using REST.\n\nWhile GraphQL has some compelling advantages, it's clear that REST is still putting up a fight. We need a simpler solution on the client side.\n\nIntroducing Tipple\n\nIt was this exact problem I encountered a few weeks ago that spawned the idea for Tipple. A client-side library that handles caching for the REST backends of yesterday, but in a manner that is inspired by the GraphQL clients of today.\n\nWhile a schema-agnostic normalised caching implementation with REST doesn't look to be possible, there are things we can do to implement caching which address the following:\n\nreduces redundancy\nabstracts caching logic\nuses a single source of truth\nHow Tipple works\n\nAt the very core, Tipple uses routes to cache data. While not as runtime efficient as managing your own normalised implementation, it's a huge reduction of complexity and ensures that your data is only being sourced from a single source of truth—your REST endpoint.\n\nA request in Tipple looks a little something like this:\n\nconst [state, refetch] = useFetch('/todo', { domains: ['todos'] });\ntsxCopy to clipboard\n\nFor the most part, this looks like a typical fetch API call, however, because this API is implemented as a hook, the fetching state is managed for us. The second difference is the domains property in the second argument.\n\nDomains in Tipple are similar to the __typename property in GraphQL that was discussed earlier. In REST, we might consider a domain to be a resource type, but for all intents and purposes, it's a way of uniquely identifying a subset of our data model. By specifying the domain when we make a fetch, we're explicitly stating the data domain for which our fetch is dependent.\n\nHere is a hook for pushing changes. See if you can guess what happens to the previous useFetch example call when this is executed.\n\nconst [state, execute] = usePush('/todo', { domains: ['todos'], body: JSON.stringify(todo) });\ntsxCopy to clipboard\n\nYou can probably see where this is going. Now when we trigger a push to our backend (in this case, adding a new todo item) we specify the domains which will be invalidated. This in turn causes any mounted useFetch hooks to be refetched if they are dependent on the 'todos' domain (such as the prior example useFetch call).\n\nSo, this is the perfect solution?\n\nNot entirely—every approach has its pros and cons, and Tipple is no exception.\n\nThe upside is, you will have much less code in your project—if complexity is your jam and you like seeing that line count grow, you'll be disappointed by how this simplifies your project.\n\nThe downside is that Tipple will likely increase the frequency of refetching data from your endpoints. Changes to a domain cause all mounted useFetch calls dependent on that domain to be refetched, so while there's no need to implement an action, reducer, and container for your 'add todo' API call, you will be refetching that list of todos every time a push is executed.\n\nFortunately, hooks in Tipple are coupled to the React component lifecycle. This means that refetches will only be occurring if your component is mounted. You'll only refetch the data you need on the screen. Otherwise, that refetch can be made next time the dependent component is mounted.\n\nTipple is an Experimental project. We're looking at ways in which this approach can be optimised, so do star the repo to keep up to date. If you have any thoughts, suggestions, or feedback, get in touch and let's make REST more enjoyable to work with!" ], "categories": { "primary": "frontend", "others": [ "backend" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-build-free-world": { "href": "https://nearform.com/digital-community/build-free-world", "postType": "blog", "slug": "digital-community-build-free-world", "date": "2019-05-21", "title": "CI/CD In a Build-free World", "authors": [ "KARA STUBBS" ], "content": [ "Back in the day, \"building a website\" used to mean crafting a beautiful soup of markup, styles, and scripts, and once you were happy with the result, uploading the files to a web server.\n\nThese days, with the move away from document-based web pages to SPAs and other highly interactive websites, the word \"build\" has taken on a new meaning: before we can see our site work, we need to compile, bundle, and minify our sources with tools like Webpack and Babel.\n\nBecause of this build step and the increased complexity of our apps, Continuous Integration tools and processes have become an essential part of web development. But builds themselves are not why CI is valuable, they're just a side effect of the approach we as an industry have gravitated towards, and they have some drawbacks.\n\nSlow, fragile, (sometimes) unnecessary\n\nThe intended goal of CI is to ensure that the code we produce is of high quality and works as expected, and that the process is automated and doesn't consume precious developer time.\n\nUnfortunately, for many large web applications, the majority of the CI time is spent on building the code, instead of verifying its quality and correctness.\n\nOne of the first frameworks for agile development, Extreme Programming, puts the ideal CI/CD time to be around ten minutes for a project. This is achievable, but when multiplied by failing or fragile builds, ten minutes can turn into a game of waiting, fixing, and rebuilding, resulting in slow feedback, developer frustration, and wasted time.\n\nWe've recently experimented with (and written about) using modern browser features such as native ES Modules and their support for importing packages directly from a CDN like unpkg.com, removing the need to bundle our source code prior to delivery.\n\nWhat we've discovered is that removing the build step doesn't only speed up the local development process, but also helps us achieve CI/CD pipelines that take significantly less time and end up giving us more confidence in the code we're shipping.\n\nBuild once, run anywhere\n\nWe recently launched runpkg.com, a web application that helps developers browse, analyse, and understand the JavaScript modules they download from unpkg. We also wanted to create a non-trivial web application using a build-free architecture to learn more about the possibilities and limitations of this approach.\n\nFrom the CI point of view this means that our CI has gone from checking whether the build is successful and produces functional code, to simply checking the quality of the code being introduced by the developer, resulting in a quick feedback loop. On Sail CI, our entire CI pass takes only a minute, most of which is spent installing yarn devDependencies such as linters and test runners. As the project scales, we predict the total duration of the the CI pass will not grow significantly as the number of dependencies doesn't grow as we add code and tests.\n\nOne of the surprising side effects of the removal of the build step was the added confidence it gave us in shipping code. We found whilst working with runpkg that \"It works on my machine\" was almost a reality (browser differences aside, which could be solved by running browser automation tests as part of the CI pipeline). By pulling built ES6 modules from unpkg we knew that when we pushed our work to production, the code running there would directly mirror what was on our local machine, as it hadn't been touched by a bundler.\n\nDeployment\n\nFor deployment we settled on ZEIT's Now for its simplicity. The entire application is hosted as static assets on ZEIT's CDN for free!\n\nAfter the Sail CI step passes, Now's Github App integration handles deploys of every branch to a testing environment, and master branch pushes deploys to runpkg.com. Once configured these deploys were incredibly fast and allowed us as developers great confidence that we would not break the app.\n\nNow worked as a great compliment to our build-less system and I would highly recommend it for build-less projects.\n\nConclusions\n\nWhat we found was that CI/CD pipelines for build-less projects simplified what we wanted out of our processes. It allowed us to focus on what was really important in our CI pipeline, i.e. code quality and quick feedback. This resulted in increased confidence in the code we're writing and, that when the code gets into production there should be no issues.\n\nAs always when working with bleeding-edge methodologies such as ES modules, some problems crop up. For us, we found that our Cypress e2e tests were not able to run in headless mode without bundling our ES modules, and we opted for running our e2e tests locally as git pre-push hooks instead. As the build-free approach becomes more common, we expect the tooling ecosystem to support it natively.\n\nThere are also some inherent limitations to the build-free approach. When working with TypeScript or ReasonML, or huge projects that may need a bundling step, we'll need to fall back on running our builds on CI.\n\nBut for apps like runpkg, the build-free approach and lightning fast CI/CD are huge benefits, and something we'll continue to experiment with. Check out the runpkg project on GitHub to see how this approach works in practice.\n\nSo give it a go, the technology is there and the CI/CD tools (mostly) work!" ], "categories": { "primary": "devops", "others": [ "frontend" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-podcast-nearform-open-source-and-node-js-with-ceo-cian-omaidin": { "href": "https://nearform.com/insights/podcast-nearform-open-source-and-node-js-with-ceo-cian-omaidin", "postType": "blog", "slug": "insights-podcast-nearform-open-source-and-node-js-with-ceo-cian-omaidin", "date": "2019-05-22", "title": "Podcast - NearForm, Open Source and Node.js with CEO Cian Ó'Maidín", "authors": [], "content": [ "Cian O'Maidin shares the founding principles of NearForm, the critical factors to the future success of Open Source in the enterprise and how Node.js has evolved in its 10 years.\n\nDifferent Perspectives with NearForm · NearForm, Open Source and Node.js: from Zero to Hero\n\nNeed Node experts for your next project? Contact us today to see how we can help!" ], "categories": { "primary": "oss", "others": [ "backend" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-strong-typing": { "href": "https://nearform.com/digital-community/strong-typing", "postType": "blog", "slug": "digital-community-strong-typing", "date": "2019-05-23", "title": "Game of Types: A Song of GraphQL and TypeScript", "authors": [ "STEVEN MUSUMECHE" ], "content": [ "Over the last few years, the popularity of both GraphQL and TypeScript has exploded in the web ecosystem—and for good reason: They help developers solve real problems encountered when building modern web applications. One of the primary benefits of both technologies is their strongly typed nature.\n\nStrong typing is a communication tool that uses explicit statements of intent. Method signatures tell you exactly what kind of input they expect and what kind of output they return. The compiler doesn't allow you to break those rules. It's about failing fast at compile time instead of by users at runtime. TypeScript is a strongly typed language that brings this to the JavaScript ecosystem.\n\nGraphQL also brings this benefit to an area of web applications that is notoriously error-prone–interacting with backend APIs. By providing a schema both the server and client can depend on (because it is enforced by the specification), GraphQL provides a strongly typed “bridge” between both sides of the application.\n\nGoing forward, this post will assume the reader has a working knowledge of both GraphQL and TypeScript. If you don’t, that’s totally fine, and you should still be able to understand the concepts.\n\nAn app of the seven kingdoms\n\nLet’s build an app about one of my favorite shows, Game of Thrones, so we have an example to work from. We’ll build a GraphQL server for the backend and a React app for the frontend, both written in TypeScript.\n\nGraphQL server\n\nWe’ll start with the server. To keep this example focused on GraphQL, we aren’t going to use a real database to store our data. Instead, we’ll hard-code the data to serve as an in-memory “database”. I’ve taken the liberty of writing the data functionality ahead of time, but if you’re curious, you can inspect all of the code in this repository.\n\nFirst, we’ll get the boring boilerplate out of the way. We’ll spin up a server and provide the GraphQL context, which will be provided as an argument to all of our resolvers. It’s a good place to store user information, data models, etc. Pretty standard stuff. The details here aren’t pertinent to this post.\n\nimport { ApolloServer } from \"apollo-server\";\nimport * as bookModel from \"./models/book\";\nimport * as characterModel from \"./models/character\";\nimport * as houseModel from \"./models/house\";\nimport * as tvSeriesModel from \"./models/tv-series\";\nimport { resolvers } from \"./resolvers\";\nimport { schema } from \"./schema\";\n\nexport interface Context {\n models: {\n character: typeof characterModel;\n house: typeof houseModel;\n tvSeries: typeof tvSeriesModel;\n book: typeof bookModel;\n };\n}\n\nconst context: Context = {\n models: {\n character: characterModel,\n house: houseModel,\n tvSeries: tvSeriesModel,\n book: bookModel\n }\n};\n\nconst server = new ApolloServer({\n typeDefs: schema,\n resolvers,\n context\n});\n\nserver.listen().then(({ url }) => {\n console.log(`🚀 Server ready at ${url}`);\n});\njavascriptCopy to clipboard\nSchema\n\nWhen I’m working on a GraphQL server, I like to start by modeling the “domain” in the schema, and then later implement the resolvers and data fetching. Here’s what our Game of Thrones schema looks like:\n\nimport gql from \"graphql-tag\";\n\nexport const schema = gql`\n type Query {\n getCharacters(sortDirection: SortDirection): [Character!]!\n getCharacter(characterId: ID!): Character\n getHouses(sortDirection: SortDirection): [House!]!\n getHouse(houseId: ID!): House\n }\n\n type Character {\n id: ID!\n name: String!\n culture: String\n titles: [String!]\n aliases: [String!]\n born: String\n died: String\n father: Character\n mother: Character\n spouse: Character\n children: [Character!]\n allegiances: [House!]\n appearedIn: [TvSeason!]!\n isAlive: Boolean!\n playedBy: String\n books: [Book!]\n }\n\n type TvSeason {\n id: ID!\n startDate: String!\n endDate: String!\n name: String!\n characters: [Character!]!\n }\n\n type House {\n id: ID!\n name: String!\n titles: [String!]\n members: [Character!]!\n slogan: String\n overlord: Character\n currentLord: Character\n founder: Character\n ancestralWeapons: [String!]\n coatOfArms: String\n seats: [String!]\n }\n\n type Book {\n id: ID!\n name: String!\n releaseDate: String!\n }\n\n enum SortDirection {\n ASC\n DESC\n }\n`;\njavascriptCopy to clipboard\nResolvers\n\nNext, we’ll implement the resolvers:\n\nimport { Context } from \"./\";\nimport { Character } from \"./data/characters\";\nimport { TvSeries } from \"./data/tv-series\";\nimport { House } from \"./data/houses\";\n\ntype ResolverFn = (parent: any, args: any, ctx: Context) => any;\ninterface ResolverMap {\n [field: string]: ResolverFn;\n}\ninterface Resolvers {\n Query: ResolverMap;\n Character: ResolverMap;\n TvSeason: ResolverMap;\n House: ResolverMap;\n}\n\nexport const resolvers: Resolvers = {\n Query: {\n getCharacters: (root, args: { sortDirection: \"ASC\" | \"DESC\" }, ctx) => {\n return ctx.models.character.getAll(args.sortDirection);\n },\n getCharacter: (root, args: { characterId: string }, ctx) => {\n return ctx.models.character.getById(parseInt(args.characterId));\n },\n getHouses: (root, args: { sortDirection: \"ASC\" | \"DESC\" }, ctx) => {\n return ctx.models.house.getAll(args.sortDirection);\n },\n getHouse: (root, args: { houseId: string }, ctx) => {\n return ctx.models.house.getById(parseInt(args.houseId));\n }\n },\n Character: {\n allegiances: (character: Character, args, ctx) => {\n if (!character.allegiances) return null;\n return character.allegiances.map(allegianceId =>\n ctx.models.house.getById(allegianceId)\n );\n },\n appearedIn: (character: Character, args, ctx) => {\n if (!character.tvSeries) return [];\n return character.tvSeries.map(seriesId =>\n ctx.models.tvSeries.getById(seriesId)\n );\n },\n isAlive: (character: Character, args, ctx) => {\n return !character.died;\n },\n father: (character: Character, args, ctx) => {\n if (!character.fatherId) return null;\n return ctx.models.character.getById(character.fatherId);\n },\n mother: (character: Character, args, ctx) => {\n if (!character.motherId) return null;\n return ctx.models.character.getById(character.motherId);\n },\n spouse: (character: Character, args, ctx) => {\n if (!character.spouseId) return null;\n return ctx.models.character.getById(character.spouseId);\n },\n children: (character: Character, args, ctx) => {\n if (!character.childrenIds) return null;\n return character.childrenIds.map(childId =>\n ctx.models.character.getById(childId)\n );\n },\n playedBy: (character: Character, args, ctx) => {\n if (!character.playedBy || character.playedBy.length === 0) return null;\n return character.playedBy[0];\n },\n books: (character: Character, args, ctx) => {\n if (!character.bookIds) return null;\n return character.bookIds.map(bookId => ctx.models.book.getById(bookId));\n }\n },\n TvSeason: {\n name: (tvSeries: TvSeries, args, ctx) => {\n return tvSeries.id;\n }\n },\n House: {\n members: (house: House, args, ctx) => {\n return ctx.models.character.getByHouseId(house.id);\n },\n overlord: (house: House, args, ctx) => {\n if (!house.overlordId) return null;\n return ctx.models.character.getById(house.overlordId);\n },\n currentLord: (house: House, args, ctx) => {\n if (!house.currentLordId) return null;\n return ctx.models.character.getById(house.currentLordId);\n },\n founder: (house: House, args, ctx) => {\n if (!house.founderId) return null;\n return ctx.models.character.getById(house.founderId);\n }\n }\n};\njavascriptCopy to clipboard\n\nA few TypeScript-related things should jump out at you. First, we have to define the properties of our resolver object so TypeScript knows what to expect (Query, Character, etc.). For each of those properties (resolver functions), we have to manually define the type definitions for all of the parameters.\n\nThe first argument, usually referred to as the “root” or “parent” parameter, has a different type depending on which resolver you are working on. In this example, we see any, Character, TvSeries, and House, depending on which parent type we are working with. The second argument contains the GraphQL query arguments, which is different for each resolver. In this example, some are any, some take are sortDirection, and some accept an ID. The third argument, context, is thankfully the same for every resolver.\n\nIf we want type-safe resolvers, we have to do this for every resolver. Exhausting.\n\nAnd there’s a catch. If we decide to change our GraphQL schema by, for example, changing or adding a new argument, we have to remember to manually update the type definitions for the respective resolver. I don’t know about you, but the chances I’ll remember to do that are lower than 100%. Our code will compile, TypeScript will be happy, but we’ll get a runtime error.\n\nBummer.\n\n(spoiler alert: we will solve this problem later in the post.)\n\nNow that our server is done, let’s run the app and make sure it works.\n\nIt worked! Awesome.\n\nFront-end application\n\nNow that we have a server, let’s write a front-end application. We’ll use create-react-app to simplify the setup and Apollo Client for the GraphQL functionality. Our app will show a list of Game of Thrones characters with some basic information. If you click on a character, you will see more information about that character.\n\nWhen I’m working on a component, I like to start with the data. The following GraphQL query will give us the data we need to render the character list.\n\nimport gql from \"graphql-tag\";\n\nexport const CharacterListQuery = gql`\n {\n getCharacters(sortDirection: ASC) {\n id\n name\n playedBy\n culture\n allegiances {\n name\n }\n isAlive\n }\n }\n`;\njsCopy to clipboard\n\nLet’s use that query along with react-apollo’s Query component to fetch our data and display it in the UI.\n\nimport React, { SyntheticEvent } from \"react\";\nimport { Query } from \"react-apollo\";\nimport { CharacterListQuery } from \"./queries/CharacterListQuery\";\nimport CharacterListItem from \"./CharacterListItem\";\nimport \"./CharacterList.css\";\n\ninterface Props {\n setSelectedCharacter: (characterId: number) => void;\n}\n\nexport interface Character {\n id: string;\n name: string;\n playedBy: string;\n culture?: string;\n allegiances?: Array<{ name: string }>;\n isAlive: boolean;\n}\n\ninterface Data {\n getCharacters: Character[];\n}\n\nconst CharacterList: React.FC = ({ setSelectedCharacter }) => {\n return (\n
\n

All Characters

\n query={CharacterListQuery}>\n {({ loading, error, data }) => {\n if (loading) return \"Loading...\";\n if (error || !data) return `Error!`;\n\n return (\n
    \n {data.getCharacters.map(character => (\n {\n e.preventDefault();\n setSelectedCharacter(parseInt(character.id));\n window.scrollTo(0, 0);\n }}\n />\n ))}\n
\n );\n }}\n \n
\n );\n};\n\nexport default CharacterList;\njsCopy to clipboard\n\nAgain, there are a few TypeScript-related things that will jump out at you. The loading and error properties are already auto-typed, which is great. Unfortunately, the data property is not. In order to have type-safe data, we need to manually define a TypeScript interface (based on what’s requested in the query—see Data and Character). Just like before, if we change the query, we have to remember to update the TypeScript interface.\n\nHere’s the character detail query and component:\n\nimport gql from \"graphql-tag\";\n\nexport const CharacterDetailQuery = gql`\n query CharacterDetail($id: ID!) {\n getCharacter(characterId: $id) {\n name\n playedBy\n culture\n titles\n aliases\n born\n died\n allegiances {\n name\n }\n isAlive\n father {\n id\n name\n }\n mother {\n id\n name\n }\n spouse {\n id\n name\n }\n children {\n id\n name\n }\n appearedIn {\n name\n }\n\n books {\n id\n name\n }\n }\n }\n`;\njsCopy to clipboard\nimport React from \"react\";\nimport { Query } from \"react-apollo\";\nimport { CharacterDetailQuery } from \"./queries/CharacterDetailQuery\";\nimport \"./CharacterDetail.css\";\n\ninterface Props {\n selectedCharacter?: number;\n setSelectedCharacter: (characterId: number) => void;\n}\n\ninterface CharacterDetail {\n id: string;\n name: string;\n playedBy: string;\n culture?: string;\n born?: string;\n died?: string;\n titles?: string[];\n aliases?: string[];\n father: { id: string; name: string };\n mother: { id: string; name: string };\n spouse: { id: string; name: string };\n children: Array<{ id: string; name: string }>;\n allegiances?: Array<{ name: string }>;\n appearedIn: Array<{ name: string }>;\n isAlive: boolean;\n books: Array<{ id: string; name: string }>;\n}\n\ninterface Data {\n getCharacter: CharacterDetail;\n}\ninterface Variables {\n id: string;\n}\n\nconst CharacterDetail: React.FC = ({\n selectedCharacter,\n setSelectedCharacter\n}) => {\n return (\n
\n {selectedCharacter ? (\n \n query={CharacterDetailQuery}\n variables={{ id: String(selectedCharacter) }}\n >\n {({ loading, error, data }) => {\n if (loading) return \"Loading...\";\n if (error || !data) return `Error!`;\n\n return (\n {\n setSelectedCharacter(id);\n window.scrollTo(0, 0);\n }}\n />\n );\n }}\n \n ) : (\n <>\n

Character Detail

\n
Please select a character
\n \n )}\n
\n );\n};\n\nconst Detail: React.FC<{\n character: CharacterDetail;\n select: (characterId: number) => void;\n}> = ({ character, select }) => {\n return (\n <>\n

{character.name}

\n {character.allegiances && character.allegiances.length > 0 && (\n
\n Loyal to:{\" \"}\n {character.allegiances.map(allegiance => allegiance.name).join(\", \")}\n
\n )}\n {renderItem(\"Culture\", character.culture)}\n {renderItem(\"Played by\", character.playedBy)}\n {renderListItem(\"Titles\", character.titles)}\n {renderListItem(\"Aliases\", character.aliases)}\n {renderItem(\"Born\", character.born)}\n {renderItem(\"Died\", character.died)}\n {renderItem(\"Culture\", character.culture)}\n {renderCharacter(select, \"Father\", character.father)}\n {renderCharacter(select, \"Mother\", character.mother)}\n {renderCharacter(select, \"Spouse\", character.spouse)}\n {character.children && character.children.length > 0 && (\n
\n Children:{\" \"}\n {character.children.map(child => (\n <>\n select(parseInt(child.id))}>\n {child.name}\n {\" \"}\n \n ))}\n
\n )}\n {renderListItem(\n \"TV Seasons\",\n character.appearedIn ? character.appearedIn.map(x => x.name) : []\n )}\n {renderListItem(\n \"Books\",\n character.books ? character.books.map(x => x.name) : []\n )}\n \n );\n};\n\nexport default CharacterDetail;\n\nconst renderItem = (label: string, item?: string) => {\n return (\n item && (\n
\n {label}: {item}\n
\n )\n );\n};\n\nconst renderListItem = (label: string, items?: string[]) => {\n return (\n items &&\n items.length > 0 && (\n
\n {label}: {items.join(\", \")}\n
\n )\n );\n};\n\nconst renderCharacter = (\n select: any,\n label: string,\n item: { name: string; id: string }\n) => {\n return (\n item && (\n \n )\n );\n};\njsCopy to clipboard\n\nWe see the same issues here. A lot of manual work. But at least our app works!\n\nStepping back\n\nWhat we have is pretty cool—GraphQL data-fetching and type-safe client and server applications. But we also have a big problem. There is a ton of duplication between the GraphQL schema and the TypeScript interfaces, requiring manual synchronization when changing our schema.\n\nWhat we really want is for our GraphQL schema to be the single source of truth for our types.\n\nIs there any way to accomplish this? As you can probably guess from the title of this post, the answer is yes.\n\nGraphQL Code Generator\n\nGraphQL Code Generator is a tool built to solve this problem. By parsing and analyzing our GraphQL schema, it outputs a wide variety of TypeScript definitions we can use in our GraphQL resolvers and front-end components. It supports many output formats, but we will focus on the resolver definitions and the react-apollo component generation. That’s right, it can even generate fully typed React components for us.\n\nServer\n\nLet’s start with generating type definitions for the resolvers. After reading the documentation, which is quite thorough, this is what I came up with:\n\nschema: ./server/schema.ts\n\ngenerates:\n server/gen-types.ts:\n config: \n defaultMapper: any\n contextType: ./#Context\n plugins: \n - typescript\n - typescript-resolvers\njsCopy to clipboard\n\nThere are a few important pieces that I’ll explain. The schema field, as the name implies, tells GraphQL Code Generator where to find our schema. The generates field tells it where to place the generated type definitions, and the plugins array tells it which plugins to use when generating that file.\n\nAfter running the tool with the above configuration, we now have this file. It’s pretty complex and uses a ton of TypeScript generics, but I recommend you dig around to see what it’s doing.\n\nIt’s pretty magical.\n\nUsing only our GraphQL schema, the tool automatically generated type definitions for all of our resolvers.\n\nWe can now replace all of the manual type definitions we wrote earlier with the generated types. Our modified resolver file is here, and you can view a before and after comparison below. Notice how many of the manual type definitions we were able to delete?\n\nThe benefits are already enormous, but it gets better. This workflow really shines when we need to make a change to our GraphQL schema. All we have to do is make the change, generate new types, and we’ll get type errors in all of the places that need to change. In this example, we removed the sortDirection parameter from the getHouses query.\n\nCompile errors, not runtime errors!\n\nClient\n\nNow we’ll move on to the client. Here’s the modified configuration file to generate client-side stuff:\n\nschema: ./server/schema.ts\ngenerates:\n server/gen-types.ts:\n config: \n defaultMapper: any\n contextType: ./#Context\n plugins: \n - typescript\n - typescript-resolvers\n ./client/src/gen-types.tsx:\n documents: ./client/src/queries/*.tsx\n plugins:\n - add: /* eslint-disable */\n - typescript\n - typescript-operations\n - typescript-react-apollo\njsCopy to clipboard\n\nGraphQL Code Generator will use the previously -configured schema from our server, as well as the client-side queries it finds in the queries directory, to generate type definitions and React components. Check out the generated file. Again, it’s pretty complex, but try to understand what it’s doing.\n\nUsing only our GraphQL queries, the tool automatically generated fully-typed react-apollo components that we can use in our application.\n\nWe can now replace all of our previous usage of react-apollo’s Query component (which required manual typedefs) with the auto generated components, which come “batteries included.” Here’s a before and after comparison:\n\nAgain, this is huge. And as before, it’s worth its weight in gold when there is a schema or query change. They will be reflected in the generated types and you’ll immediately see what needs to be fixed.\n\nConclusion\n\nGraphQL and TypeScript’s popularity explosion in the web ecosystem is, in my opinion, a Good Thing. They help developers solve real problems encountered when building and maintaining modern web applications. One of the primary benefits of both technologies is their strongly typed nature.\n\nSince they are both independent type systems, however, there is a risk of duplication and divergence between the two. By treating GraphQL as the single source of truth for our types and generating TypeScript definitions from it, we diminish this risk. Luckily for us, amazing packages like GraphQL Code Generator exist!\n\nRecommended workflow\n\nWhile you can manually run the code generator after a schema or query change, you might forget. Instead, I recommend adding an npm script which monitors the appropriate files and runs the generator tool when it detects changes. You can run this command concurrently with your normal development workflow using the concurrently package.\n\nCode\n\nThe code for the completed application can be found in the following repositories.\n\nFirst example with manual typings\nSecond example with auto-generated typings" ], "categories": { "primary": "backend", "others": [ "frontend", "data" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-the-future-of-webapps-and-the-winners-at-finjs-fintech-world-forum-12-years-later": { "href": "https://nearform.com/insights/the-future-of-webapps-and-the-winners-at-finjs-fintech-world-forum-12-years-later", "postType": "blog", "slug": "insights-the-future-of-webapps-and-the-winners-at-finjs-fintech-world-forum-12-years-later", "date": "2019-05-24", "title": "The Future of WebApps and the winners at FinJS & FinTech World Forum 12 years later", "authors": [], "content": [ "This week I was lucky enough to attend both FinJS and the FinTech World Forum in London - two very different events but with lots of crossovers.\n\nA fun aspect for me about the latter was that it was held in the Kensington Conference Centre. The last time I was there was in 2007 for the Future of Web Apps conference with a big contingent of Irish startups. I thought it might be interesting to start this post with a comparison of what was being talked about back then and where we are now 12 years later. And how does this relate to FinTech?\n\nAfter doing a trawl of some blog posts (including my own) from back in 2007 and comparing them to the areas I saw discussed this week, I came up with this list of hot topics and challenges:\n\n2007\t2019\nWeb 2.0 in general for improved UX\tReplacing legacy .NET and J2EE apps for improved UX\nBuilding High-Performance Web-Sites\tBuilding High-Performance WebApps\nBuilding Mobile Web-Sites and the challenges of legacy mobile browsers.\tBuilding Progressive Web Apps and React Native Mobile Apps\nSemantic Web for more effective use of complex data\tData Science and ML for more effective use of complex data\nZimki Server-Side JavaScript PaaS (Anyone remember “Pre-Shaved Yaks”?)\tNode.js on AWS Lambda and Azure Functions. (Plus JS on Fastly and Cloudflare)\nNew services from Amazon called EC2 and S3 presented by Werner Vogels\tNew services every day from some company called Amazon :-)\nLast.fm personalised social music service\tPersonalised customer experiences in WebApps and mobile.\n“Soocial” contacts synchronisation service\tManaging and using high-volume heterogeneous enterprise data\nYahoo APIs and Yahoo Pipes\tThe power of open APIs and Open Standards like OpenFin, FinOS and Open Banking to provide new business opportunities\nWebApp Security challenges\tWebApp Security challenges\nAdobe Flash for rapid application development\tOpen Standards-based tools for rapid application development\nAdobe Apollo for both Web and Desktop App development\tOpenFin and HTML5 for both Web and Desktop App development\nMOO.com disrupting the biz card industry via a focus on the entire customer experience delivered with the latest tech stacks.\tChallenger banks disrupting the incumbents via a focus on the entire customer experience delivered with the latest tech stacks.\nCommunity building for startups\tCommunity building for startups, Enterprises and Open Source projects\nA range of long-dead mostly proprietary services: Picnik, APML, fav.or.it, Dapper, Dopplr, Plazes, Fire Eagle, Soocial, Zimki\tWhat will be the list of long-dead services in 12 years time?\n\nIt’s amazing how the tools and companies have changed over the 12 years but not the challenges. The biggest difference is that Open Source won and Open Standards won . We believe they will continue to win as we build the next generation of high-performance web runtimes and frameworks for the newly emerging cloud architectures.\n\nLooking back even a few years, NearForm’s approach of user-centric rapid agile delivery, using optimised Open Source stacks plus a focus on high-performance architectures, was actually not very appealing to a lot of traditional slow-moving financial organisations. There was much sucking of air through teeth about “toy” languages like Node.js or “non-Enterprise-level” infrastructure like EC2.\n\nBut that has all changed.\n\nTraditional banks are now being disrupted by faster nimbler newer companies with no legacy systems and no legacy customers (to borrow a phrase from Starling Bank yesterday). They have to embrace our approach or they will be roadkill.\n\nSimilarly, whilst Financial Trading systems have always been obsessed about performance, they have hit the limits of what the older stacks can provide, particularly around User Experience, flexibility, speed of delivery and ease of deployment. This is why “consumer web” stacks have begun to take over the Enterprise.\n\nLooking at the specific events themselves:\n\nFinJS - FinTech embraces the JavaScript-everywhere juggernaut\n\nWow London! I was shocked by the numbers of people queuing outside the amazing Leadenhall Building when Dave Clements and I arrived. There were several hundred attendees. For a mid-week evening event about JavaScript in the Financial industry. This is one scorching hot topic obviously!\n\nThe meetup is organised by OpenFin who have an extremely interesting Electron-based \"OS for Finance\". It runs on normal desktops but gives you highly-secure Desktop Web apps with application interoperability, notifications, intents, distribution, etc etc. Plus it’s Open Source and Open Standards driven.\n\nThe talks were universally good and ran the gamut from the horror of traditional notifications to ultra-high-performance data grids for financial web apps to entirely new ways of thinking about user interfaces.\n\nBut the same messages came through in almost every talk:\n\nUser Experience\nOpen Standards\nOpen Source\nPerformance\nSecurity\nData Visualisation\nSpeed of development and deployment\n\nLegacy systems remain a huge challenge for everyone in Finance. When AngularJS is seen as bleeding-edge and some orgs are still building things with WPF, there is so much work to be done by these companies to catch up.\n\nBasically all of the same things we in NearForm talk about to our customers are the absolute top priorities for those working in FinTech. But with the overarching point, as ever, that this is fundamentally about delivering value to your business and to your customers/users.\n\nFinTech World Forum - How to innovate in a world of legacy\n\nIf FinJS was a strongly tech-centric event, FinTech World Forum was more focused on business challenges for FinTech and where things like cryptocurrencies are going. The words “compliance”, “regulation” and “legacy” were used time and again.\n\nYou will be very familiar with some of the presenting companies including Mastercard, IBM, HSBC and Barclays. Others not so much.\n\nThe talk highlight for me was by Julian Sawyer, COO of Starling Bank. He really dug into the meat of payments as a service and banking as a service. Their focus on APIs, SaaS and white-labelling look like a winning approach to me. Their fully agile development methodology was refreshing. Their brave decisions to have no legacy systems and no legacy *customers* were extremely impressive. They only have native mobile apps on an AWS back-end.\n\nHe also made some good points about the stats from the big banks and how some of them are now calling themselves FinTechs. One of the biggest banks claims to have 5 million mobile users. But they have 25 million customers. So what are the other 20 million doing and why aren’t they switching to mobile? Are we back to looking at UX problems and low-performing legacy back-ends perhaps?\n\nOverall I found the event very useful but thought that there was an excessive focus on talks about various coins and blockchains. Several of those talks did an excellent job of framing many of the problems and challenges in the global financial sector but failed to properly explain why a cryptocurrency or blockchain was the best solution to them. There were a lot of “if all you have is a hammer” moments for me. However, I very much appreciated the notes of caution expressed by Lasse Meholm of DNB Bank in Norway, particularly around timescales for “success” in crypto.\n\nOne important point was made several times about the mix of people working in FinTech. It’s not a silo of Finance-only people. In some cases, Product Managers and Developers have no Finance experience at all but they are bringing in critical outside technology experience into FinTech.\n\nWe heard a related message from multiple attendees at the IT Directors Forum in Watford last week. That was the first time some of them had ever attended an event that was not specific to their vertical. So for example, those working in insurance felt they had been missing out on global tech advances by only attending insurance-tech events. It looks like the FinTech sector is avoiding this problem and embracing all that the broad technology landscape has to offer.\n\nSummary\n\nAs I said earlier, FinTech in 2019 feels a lot like Web 2.0 in 2007. Everything is moving fast and lots of things will fail, but the foundations for the next decade are being built. It’s an incredibly exciting time for us to be involved in the industry right now.\n\nAbout the author\n\nConor O’Neill is Head of Product in NearForm. He is responsible for all productization activities in NearForm and is working closely with NearForm’s Open Source and R&D teams to evolve the web platform for FinTech and the Enterprise. You can connect with Conor on LinkedIn. NearForm has been instrumental in bringing Node.js itself and high-performance JavaScript to its current dominant position in software development. In the past 3 years alone, there have been over 3 Billion downloads of NPM modules that NearForm has built, supported or maintained . Anyone in FinTech and beyond working on high-performance Fullstack JavaScript is almost definitely using code for which NearForm is responsible. Our delivery teams have been designing and building solutions with these stacks for Enterprises globally since 2011." ], "categories": { "primary": "frontend", "others": [ "cloud", "data", "devops", "product" ] }, "verticals": { "primary": "finance", "others": [] } }, "digital-community-jetpack-revisited-even-faster-serverless-packaging-and-deploys": { "href": "https://nearform.com/digital-community/jetpack-revisited-even-faster-serverless-packaging-and-deploys", "postType": "blog", "slug": "digital-community-jetpack-revisited-even-faster-serverless-packaging-and-deploys", "date": "2019-05-28", "title": "Jetpack revisited: Even faster Serverless packaging and deploys", "authors": [ "RYAN ROEMER" ], "content": [ "Two weeks ago we introduced the serverless-jetpack plugin, a drop-in replacement for Serverless Framework packaging. We thought that we had sped up serverless CLI packaging and deployments as much as possible.\n\nIt turns out we were wrong.\n\nWe discovered we could make it even faster...\n\nReexamining the problem\n\nAs we discussed previously, serverless CLI packaging slows to a crawl when reading large node_modules directories on disk, only to later exclude most files from application packaging as devDependencies.\n\nOur solution with serverless-jetpack was to avoid any introspection of node_modules by doing a yarn or npm production installation in a temporary directory. This takes a bit of time, but often far less than globbing on disk with built-in serverless packaging.\n\nIn the course of our initial release, we received great feedback from the community, including some undiscovered issues and new ideas as to how to tackle the speed problem.\n\nBack to the drawing board\n\nThe existing design of Jetpack offers an easy means of replacing built-in serverless packaging with a new heuristic of our choosing. Jetpack also has a full benchmark and integration test suite to ensure that the plugin is faster than serverless while still correctly producing identical packaging output.\n\n...so maybe we can take a different approach?\n\nAfter a seemingly promising false start, we reexamined the problem. We need to not read devDependencies. How else could we do it?\n\nTurns out that we have already tackled this problem in depth with our inspectpack project, which does detailed bundle and dependency analysis of Webpack-built JavaScript applications.\n\nUsing techniques pioneered in inspectpack, we created a small, focused library named inspectdep, which efficiently reads node_modules and discovers the on-disk locations of production modules. By hooking inspectdep into Jetpack we were able to:\n\nQuickly identify production dependencies before globbing.\nUse that information to skip disk I/O for devDependencies by reading only production dependencies in a project's node_modules when globbing.\n\nIn effect, Jetpack is able to do pretty much the same thing that serverless does, just much, much faster.\n\nA faster, more powerful Jetpack\n\nWith this refactor, the severless-jetpack plugin is much simpler.\n\nThere are no yarn or npm installs anymore. All of the dependency inference is performed in pure JavaScript code. This also makes the plugin more compatible with a wider range of Serverless Framework applications.\n\nThere are no more configuration options! The plugin \"just works\" with existing include|exclude Serverless packaging configurations. If it works with serverless, it should work with serverless-jetpack.\n\nSo, how much faster is it? Let's check out some new benchmarks!\n\nThis time around, we have Windows VM timings from our new AppVeyor CI. The speedup for Windows seems to be even more dramatic—for the huge scenario, serverless-jetpack is over 15 times faster than built-in serverless packaging in our CI setup.\n\nOS\tScenario\tType\tTime\tvs Base\nMac\tsimple\tjetpack\t4338\t-46.37 %\nMac\tsimple\tbaseline\t8089\t\nMac\tindividually\tjetpack\t2964\t-76.77 %\nMac\tindividually\tbaseline\t12760\t\nMac\thuge\tjetpack\t4524\t-84.03 %\nMac\thuge\tbaseline\t28321\t\nWindows\tsimple\tjetpack\t2890\t-73.88 %\nWindows\tsimple\tbaseline\t11063\t\nWindows\tindividually\tjetpack\t3110\t-83.90 %\nWindows\tindividually\tbaseline\t19312\t\nWindows\thuge\tjetpack\t3500\t-93.34 %\nWindows\thuge\tbaseline\t52548\t\nFire it up!\n\nWe've been very pleased with the reception of serverless-jetpack since its introduction. Our internal refactoring should now make it better and easier to integrate in Serverless Framework applications. We hope the newer, shinier Jetpack speeds up your serverless packaging even more! 🚀" ], "categories": { "primary": "backend", "others": [ "cloud", "devops" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-cypress": { "href": "https://nearform.com/digital-community/cypress", "postType": "blog", "slug": "digital-community-cypress", "date": "2019-05-29", "title": "End-to-End Testing React Applications with Cypress", "authors": [ "PARKER ZIEGLER" ], "content": [ "Cypress has been creating a lot of buzz in the JavaScript ecosystem recently, promising a simple yet powerful API for writing integration and end-to-end tests. With an open source core written in JavaScript, you can test anything that runs in a browser, regardless of language or framework (think Reason, WASM, or Svelte). Cypress is unique in that it operates in the same run-loop as your application—client code and test code are embedded in separate iframes right next to each other and communicate over websockets. Pretty clever!\n\nWhen it comes to end-to-end testing React applications, Cypress is rapidly emerging as the community standard. While nothing about Cypress is React-specific, the design of its APIs pairs uniquely well with the nuances of React's reconciliation process and virtual DOM. In this post we'll dig into how Cypress works with React, focusing specifically on how it addresses the challenges of DOM-based testing and manipulation in the era of asynchronous web applications.\n\nThe DOM is Unstable\n\nI've spent a lot of time perusing the Cypress docs recently while setting up end-to-end tests for clients, and I love the section on Conditional Testing. The central problem outlined concerns the instability of the DOM in modern client-side web applications. In React, changes to application state trigger a reconciliation of the DOM by way of the diffing algorithm. For human users, the reconciliation process is barely perceptible in even moderately performant React applications. Other visual cues like loading spinners let us know that elements aren't \"interact-able\" or that data is being fetched. For test runners like Cypress or Puppeteer, however, this instability can be a problem.\n\nTest runners attempting to access and operate on DOM nodes that haven't yet been mounted or are in the midst of an update may error out. Moreover, discrepancies across hardware and memory resources between developer machines and CI environments mean your application may run differently for different users. This leads to test \"flake\" and a handful of \"works on my machine\" scenarios that are hard to debug.\n\nCypress takes care of a lot of test flake for you via built-in \"retry-ability\", in which the test runner recursively tries commands until it reaches a timeout. For example, if you attempt to access a DOM node via cy.get that takes, let's say, a full second to mount, Cypress will keep querying the DOM automatically for you until it finds the node. This is awesome, because we as developers get to leave retry boilerplate to Cypress and instead focus on writing reproducible, resilient tests. However, even automatic retry may not save us in the most unstable stage of a React application—the initial render.\n\nDealing with Initial Render\n\nA lot of applications do some pretty heavy lifting on initial render. In addition to mounting the entire component tree, users are being authorized, data is being fetched from multiple remote resources, and React is, well, reacting to all these changes. Cypress isn't aware of this instability; once it receives the load event from your application, it'll start running your tests. How can we tell Cypress to wait until the DOM has reached a more settled state? One strategy is to use our network traffic as a proxy for DOM stability using cy.wait.\n\ncy.wait allows us to specify particular network requests for Cypress to \"wait\" on. For example, if our application makes a request to our API's /users endpoint, Cypress will wait to execute subsequent commands until it's received a successful response from /users. To get this working you'll need to setup cy.server to intercept all requests from and responses to your app, and cy.route to specify the route to listen for. Here's how this might look in a simple test suite:\n\ndescribe('App', () => {\n beforeEach(() => {\n // setup cy.server to intercept network requests\n cy.server();\n\n // alias the /users endpoint to @users\n cy.route('/users').as('users');\n\n // wait until /users has responded\n cy.wait('@users');\n });\n\n it('should not run until a response has been received from /users', () => {\n // Start accessing the DOM and running tests!\n cy.get('[data-test-id=\"node-under-test\"])\n .click();\n });\n});\njsCopy to clipboard\n\nSo why does this strategy work? For most React applications data fetching will be initiated after first mount, either in componentDidMount or inside of a useEffect call if you're using hooks. This means React has likely finished its initial render of the tree, your API requests have been triggered, and most DOM nodes have been mounted. By the time the /users endpoint has responded to your application's request, it's a pretty safe bet that React has finished most of its initial rendering work. The great thing about cy.wait is that it also accepts an array of aliased routes—in the event that your initial render relies on more than one network request, you can give React additional time to complete its reconciliation. Combined with Cypress's support for custom commands, you can abstract this nicely. Let's look at an example using TypeScript:\n\n// cypress/support/commands.ts\n\ndeclare global {\n namespace Cypress {\n interface Chainable {\n // add our custom command to Cypress's namespace\n visitAndWait: typeof visitAndWait;\n }\n }\n}\n\ninterface Endpoint {\n route: string | RegExp;\n alias: string;\n}\n\nfunction visitAndWait(appRoute: string, endpoints: Endpoint[]) {\n // setup cy.server to intercept network requests\n cy.server();\n\n // iterate over endpoints and alias them\n endpoints.forEach(({ route, alias }) => {\n cy.route(route).as(alias);\n });\n\n // visit a page in your application\n cy.visit(appRoute);\n\n // wait for all of the endpoints to respond before beginning tests\n cy.wait(endpoints.map(({ alias }) => `@${alias}`));\n}\n\n// register the custom command with Cypress\nCypress.Commands.add(\"visitAndWait\", visitAndWait);\ntypescriptCopy to clipboard\n// cypress/integration/app.spec.ts\n\ndescribe('App', () => {\n beforeEach(() => {\n cy.visitAndLoad(\n '/home',\n [\n { route: '/users', alias: 'users' },\n { route: /(\\/order)(\\?.*)?/g}, alias: 'order' },\n { route: '/home/**', alias: 'home' }\n ]\n )\n });\n\n it('should not run until a response has been received from /users, /order, and /home', () => {\n // Start accessing the DOM and running tests!\n });\n});\ntypescriptCopy to clipboard\n\nAwesome! By using the network as a proxy for DOM stability we can normalize differences in memory and computing power across different environments and work cleanly with React's reconciler and virtual DOM. This makes our end-to-end tests more reliable, meaning that test failures become better indicators of something amok in our application.\n\nBeyond REST\n\nWhile the above strategy works well if your application is solely comprised of calls to a REST API, it breaks down a little bit for another popular transport protocol—WebSockets. The Cypress docs are a bit cryptic on WebSocket support.\n\nBy this, the Cypress team means that you can still run end-to-end tests against an application backed by WebSockets. However, you're not able to cy.wait on a WebSocket connection or mock its return values in any way. More precisely, this means you can't wait until the client and server have completed their handshake and the first frame has been received from the WebSocket server. If your React application depends on data returned by those frames to render specific UI that you want to test, cy.wait can't really help you. So what can we do here? We can implement retry-ability ourselves with simple recursion!\n\nLet's say, for example, we want to get an element with data-test-id=\"modal\". The node is mounted in our application with a default value of \"Loading...\" and populates with data once the WebSocket has begun sending frames. How could we get a handle on this element and only run assertions once we're certain it has data? We could check the inner text of the element recursively every 500ms or so until the value is no longer the default of \"Loading...\".\n\nconst MAX_RETRIES = 5;\nconst TIMEOUT = 500;\n\nfunction selectModal(retryCount = 0) {\n cy.get('[data-test-id=\"modal\"']).then((el) => {\n // wrap the element as a Cypress.Chainable so we can chain further commands\n cy.wrap(el)\n // grab the element's text content\n .invoke('text')\n .then((val) => {\n // if we hit the max retries, throw an error\n if (retryCount > MAX_RETRIES) {\n throw new Error(\n `Element could not be found after ${TIMEOUT * MAX_RETRIES} ms`\n );\n // if the element still says loading, wait 500ms and recurse\n } else if (((val as unknown) as string) === 'Loading...') {\n cy.wait(500);\n return selectModal(retryCount++);\n // if the element is found, return the element (base case)\n } else {\n return cy.wrap(el)\n }\n });\n });\n}\n\ndescribe('App', () => {\n it('should not run assertions until the value is populated', () => {\n selectModal()\n .then((modal) => {\n // begin running assertions on the modal\n }).catch((err) => {\n // catch the max retry error\n });\n });\n});\ntypescriptCopy to clipboard\n\nThis strategy isn't half bad and acts like a naive implementation of what Cypress does already under the hood. However, this should be treated as somewhat of a last resort. You may get more value out of integration testing components that rely on WebSockets rather than spinning up a full end-to-end test for them. I'd definitely recommend the awesome react-testing-library for such cases.\n\nGo Forth and Test (Reliably)\n\nIn this post, we've dug into the challenges of end-to-end testing with asynchronously rendered React applications. As we head into the era of Suspense and Concurrent Mode in React, we're only going to see our applications become more asynchronous. Cypress' APIs give us great tools to check our DOM for relative stability before running end to end tests, which gives us more confidence in our tests in the long run. We've had great success with Cypress both in client work and open source here at Formidable, and we think you will too!\n\nThanks to my wonderful colleagues Amy Dickson, Mariano Martinez III, and Brian Mathews for reviewing this piece." ], "categories": { "primary": "test", "others": [ "frontend" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-digital-innovation-success": { "href": "https://nearform.com/insights/digital-innovation-success", "postType": "blog", "slug": "insights-digital-innovation-success", "date": "2019-05-29", "title": "How to succeed with Digital Innovation", "authors": [], "content": [ "Digital Innovation Strategy with Damian Beresford\n\nDigital innovation is a vital component to any organisation's survival and growth. Creating a culture of organic innovation is a key part of successful digital innovation.\n\nBelow is a summary of an interview with NearForm Technical Director Damian Beresford.\n\nHow enterprises fail at digital innovation\n\nDigital innovation projects fail more often than not.\n\nThere are 3 different types of digital innovation that organisations attempt and the problem lies in the balance among them:\n\nOrganic innovation is when innovation is internal.\nMergers and Acquisitions (M&A) are when companies get their innovation as mature offerings from mergers and acquisitions.\nCo-creation is when companies work with vendors to bring new concepts to market.\n\nIncreasingly problematic is that most companies rely on M&A.\n\nThe problem with M&A\n\nThis digital innovation strategy can be successful but a lot of companies are paying a lot of money for a new product or service that someone else has de-risked. There is a better ROI in organic innovation which will allow you to develop the skill sets and innovation culture you'll need to survive.\n\nM&A innovation doesn't always work as it brings in complexities that can be insurmountable without the proper focus. Basically you can't buy the culture changes that are necessary for systemic innovation.\n\nSuccessful, modern digital innovation methodologies\n\nWe see a lot of success with the following types of innovation: Design Thinking, Lean and Agile. Much of that success depends on the culture within an organisation.\n\nAt NearForm we work with enterprises to see how they innovate so we get to experience what does and doesn't work.\n\nInnovation Funnel\n\nMany successful organisations create an internal startup mentality in an effort to move quickly. They have an internal Venture Capital like fund with a traditional \"funnel\" of innovation projects.\n\nIn this process an idea moves through stages:\n\ncome up with an idea\nidea is identified and receives support\nidea is validated\nidea is executed\nbenefits realised\n\nWe've observed Design Thinking, Lean and Agile methodologies to be very effective in funnels such as this. Another valuable aspect of such a funnel is that concepts that are not valuable can be weeded out. Many companies are not good at this.\n\nThese processes should be nimble. The balance between fast decision making and risk important for every enterprise.\n\n[caption id=\"attachment_300003586\" align=\"aligncenter\" width=\"597\"]\n\nDamian Beresford speaking at CIO Benelux[/caption]\n\nIdeas from the ground up\n\nA few common innovation failures are that people don't have enough ideas and often don't pick the right ideas. With the right culture ideas will be coming from the ground up.\n\nDesign Thinking has a key role here. It's important to focus on the customer needs. If Design Thinking is systemically and culturally ingrained in the organisation everyone is focused on what's best for the customer and is personally invested in thinking of new ways to achieve that mission.\n\nIdentifying and Supporting ideas\n\nEveryone in the company knows that they are free to - and expected to - share ideas for improving things. They also understand how to share those ideas.\n\nWhen everyone understands how to share ideas the next crucial step is to identify promising ideas and support their promoters through to execution.\n\nThis requires real commitment from the company since there is an opportunity cost here: taking people away from their jobs and giving them a window to validate the concept.\n\nThat support should come from something like an Innovation Team. In our experience when that support is absent, ideas tend to remain dormant. It becomes evident that although bright ideas are being asked for they aren't being nurtured.\n\nAn absolute commitment to supporting people with ideas is imperative, even for ideas that end up not being viable.\n\nRewarding employees that come forward\n\nEnployees need to be rewarded intrinsically and extrinsically.\n\nIntrinsically\n\nPeople need to feel that contributing to the company is personally rewarding and valuable.\n\nExtrinsically\n\nPeople also need to be rewarded with salary, benefits and promotion.\n\nRegardless of whether an idea pans out or not entrepreneurial employees should be extrinsically rewarded for sharing promising ideas.\n\nCulture\n\nSuccessful digital innovation is all about culture, culture, culture.\n\nA culture of innovation cannot be bought it must be developed internally through Design Thinking and grassroots innovation systemically.\n\nValidation - How NearForm makes a difference\n\nIn the validation stage we work closely with organisations to deploy a rapid process . We call this our discovery phase.\n\nThink of it as modern Lean methodology. It is rooted in discovery-driven planning. We work with enterprises to deliver an accelerated validation of a concept for digital projects. This usually lasts around 2-4 weeks.\n\nThe process can be leb by design, architecture or devops depending on the concept.\n\nExample of Validation process\n\nTake an enterprise that is looking to develop a new customer journey. Over two weeks we bring the customer, business and technology together. We start with an intense workshop and spend the remainder of the time on the outcomes of that workshop.\n\nOutcomes of validation process\n\nThere are usually three outputs:\n\nHigh-fidelity prototype: these come from design-led engagements and can be presented to stakeholders and customers to test assumptions that have fed into the project to this point\nArchitecture document: describes how the product will be built, the technology choices that will be used, and calls out major risks and the assumptions we're making\nWork plan: a refined project plan that defines go-to-market-ready product, defines milestones towards creation, specifies resources needed, and provides a rough budget\nCo-innovation\n\nWe've worked with a lot of companies who can come up with good digital innovation strategies, run successful pilots, and not be able to fully execute. We help our clients execute.\n\nA lack of appropriate skills or capability, or capacity problems can stand in the way of a project's success.\n\nCo-innovation is when enterprises bring in delivery specialists from outside the organisation to work in tandem with their internal team to bring projects to fruition. It's a satisfying and modern way to innovate bringing collaboration to a level that many enterprises have never experienced, but it works. Damian Beresford is Technical Director of NearForm, which partners with organisations across the globe to help them achieve sustainable innovation through the design & delivery of open software, methodologies and technologies. \n\nDamian has worked with organisations across many sectors.\n\nIf you’d like to understand how we can help you stay relevant & scale to demand, contact us for an exploratory review and feel free to connect with Damian on LinkedIn." ], "categories": { "primary": "product", "others": [ "design", "devops" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-oss-starter": { "href": "https://nearform.com/digital-community/oss-starter", "postType": "blog", "slug": "digital-community-oss-starter", "date": "2019-05-30", "title": "Head-First into Open Source", "authors": [ "DOMINIC COELHO" ], "content": [ "As more and more people enter the software industry each year, companies can benefit from learning how to bring out the best in their engineers. To that point, this is the story of how my team at Formidable and I quickly built something ambitious and valuable, without compromising my learning, support, and autonomy along the way.\n\nChoosing problems worth solving\n\nAs a software consultancy, most of our time is spent on client projects. However, we sometimes have opportunities to work on open source software (OSS). At any given time we are supporting up to 70 OSS projects, and we also keep track of problems we encounter that don't yet have an established solution.\n\nOne such problem was identified by Luke Jackson's research about build-free single page applications. Browser support for ES6 modules is rapidly improving, and while the unpkg CDN provides infrastructure for taking advantage of them, there was no user-friendly way to explore these scripts and their dependencies.\n\nI was part of a small Formidable team tasked with coming up with a solution. We affectionately gave this project the code name \"Dora The Unpkg Explorer,\" which eventually became runpkg. My teammates, Luke and Kara (read Luke's intro to the problem, and Kara's write-up about the CI/CD strategy we chose on this blog), have already written about the project's technical aspects. This post describes my first experience with a professional open source project.\n\nIdea to execution\n\nI was pleasantly surprised how much autonomy I was given on my first project. I jumped straight in and built a basic proof of concept. I cloned Luke's es-react boilerplate—the obvious choice for a project focusing on ES6 modules—and got to work. A few lines of RegEx, a couple of React Hooks, and a fetch request later, we had a working prototype that allowed us to click through the imports of the lodash-es package.\n\nAfter quickly validating this solution, Luke, Kara, and I spent a two-week sprint with the aim of producing something useful to share with the wider developer community for validation and feedback.\n\nEven in the short sprint, we found quick feedback cycles proved effective for directing our development. After a few days of work, we showed our work-in-progress version to our colleagues, whose questions and insights unearthed new feature ideas, identified UX issues that we were blind to, and helped us to prioritise our remaining tasks.\n\nDespite feeling like we were 80 percent complete after the first week, the end of the second week rapidly arrived, and we still had dozens of features and refinements in mind. However, we were all well aware of the trap of feature creep and the fact that nothing is ever completely finished. Instead of pushing back the release, we documented what still needed to be done and used our remaining time to tackle edge cases, update the documentation, and send Dora out to explore the world wide web.\n\nConcept to production in two weeks\n\nWe launched the project (runpkg.com) on Twitter, and quickly received positive responses from Michael Jackson (the creator of unpkg) and Dan Abramov from the React core team. After a half hour of basking in the warm, fuzzy feeling of a successful launch, we got to the most valuable part: addressing the feedback we'd received in the form of tweets and GitHub issues.\n\nThe community raised helpful, constructive issues that we've used to address the accessibility of runpkg, as well as improving syntax highlighting and the mind-bending recursive dependency fetch, which we rely on for discovering all of a script's dependencies and computing its \"true\" size.\n\nLearnings\n\nI had always wanted to contribute more to the open source ecosystem but, as many other developers are, I was quite nervous about getting my teeth into a significant OSS project. My experience building runpkg provided me the perfect opportunity to experience OSS project stewardship, and I'm excited to continue to improve the product we have, build out more features, and learn much more along the way.\n\nJumping right into a challenging project with interesting technical problems proved rewarding. It's been gratifying to receive enthusiastic feedback from users across the world on something I worked on.\n\nThe balance of autonomy and support I received meant that I felt trusted and empowered to voice my own ideas and put myself forward to solve difficult problems, but still very comfortable to ask \"stupid\" questions. My teammates Luke and Kara have been invaluable to bounce ideas off and pair program with, and it's through their collaborative attitudes that I've felt as comfortable as I have.\n\nMy advice for employers is to work hard on fostering a culture where developers are challenged, trusted, and made comfortable enough to ask questions.\n\nMy advice for newer developers is that open source isn't as scary as you think; you can contribute in a meaningful way, and create something cool sooner than you might think.\n\nThe best way to get started is to dive in head first." ], "categories": { "primary": "oss", "others": [] }, "verticals": { "primary": "none", "others": [] } }, "insights-fastify-fast-low-overhead-http-web-framework": { "href": "https://nearform.com/insights/fastify-fast-low-overhead-http-web-framework", "postType": "blog", "slug": "insights-fastify-fast-low-overhead-http-web-framework", "date": "2019-05-30", "title": "Take your HTTP server to Ludicrous Speed with Fastify: Tech Talk Video", "authors": [], "content": [ "How can fastify be so...fast?\n\nIn Matteo's journey through nodeland, he always wondered about the cost of his abstractions. Express, Hapi, Restify, or just plain Node.js core? require (‘http’) can reach 44k requests/sec, Express 28k, and Hapi 21k.\n\nMatteo began a journey to write a HTTP framework with extremely low overhead, and Fastify was born. With its ability to reach an astonishing 47k requests/sec, Fastify can halve your cloud server bill.\n\nHow can Fastify be so... fast? You will discover all the not-so-secret techniques that were used to optimize it. In Fastify you can reach a point where even allocating a callback is too slow: Ludicrous Speed.\n\nAs a Technical Director at NearForm, Matteo Collina consults for some of the top brands of the world. Matteo is a member of the Node.js Technical Steering Committee focusing on streams, diagnostics and http. He is also the author of Node.js MQTT Broker, Mosca, the fast logger Pino and of the Fastify web framework.\n\nNeed Node experts for your next project? Contact us to see how we can help!" ], "categories": { "primary": "backend", "others": [ "cloud", "perf", "devops" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-urql-2019": { "href": "https://nearform.com/digital-community/urql-2019", "postType": "blog", "slug": "digital-community-urql-2019", "date": "2019-05-31", "title": "Urql, Grown Up", "authors": [ "PHIL PLÜCKTHUN" ], "content": [ "Early 2018 we released the first version of our minimalist GraphQL client urql. For the last year, we’ve been rethinking, rearchitecting, and rebuilding the core of the library, and a few months ago we silently launched urql v1.0.\n\nToday, with the release of the new documentation site, we’re happy to call urql a stable, production-ready GraphQL client library for both small and large React applications.\n\nNew features in v1 include React Hooks for GraphQL queries, mutations and subscriptions, and a new powerful extensibility mechanism called Exchanges.\n\nIf you've used urql before, this might sound like we've rebuilt it from the ground up and are heading in a different direction. And indeed we are.\n\nOrigin story\n\nThe initial motivation for the project was to go back to basics. urql was created out of frustration with the maximalist approach of GraphQL client libraries like Apollo and Relay. These projects are incredibly powerful, but loaded with so many features that the sheer size of their APIs (not to mention their code bundles!) raise the barrier to entry to using GraphQL in your React application.\n\nAs the old saying goes, the simplest GraphQL client is just a fetch call. However, going down this path, you'll eventually have to reinvent functionality like caching and figure out how to integrate it to your UI library.\n\nThe initial version of urql attempted to hit the sweet spot between these two approaches. It made it easy to get started, and provided all the functionality we needed in simple GraphQL projects. But as we worked with various GraphQL applications, we began to understand how libraries like Apollo got where they did—every project has slightly different requirements, and supporting them all leads to inevitable complexity.\n\nInstead of going down the same path, we wanted to keep the core of urql small and easy to work with, and provide an extensibility mechanism that allows app authors (that's you!) to scale and customize their GraphQL library to suit their needs.\n\nIntroducing Exchanges\n\nApollo has the concept of Links, which allow you to reach into your GraphQL requests, change how and when they're sent, and how eventual responses are treated.\n\nWith urql we wanted to go further and move all logic to a similar construct, called Exchanges. Essentially, Exchanges are an operation pipeline that allows you to customize and augment every aspect of the GraphQL client from how data is cached to how components receive their data.\n\nSince we want urql to be a fully functional client when you first install and use it, it already ships with Exchanges that make up the small core of a basic GraphQL client. They are also excellent templates if you're writing new exchanges.\n\nSome of the more interesting ones are:\n\ndedupExchange for de-duplicating in-flight requests\ncacheExchange that can short-circuit the network request and return a cached result, or pass the operation onwards and cache the ensuing response\nfetchExchange to handle network requests\nsubscriptionExchange which can optionally be added to support GraphQL subscriptions\n\nThe great thing about urql Exchanges is that they are flexible, composable, and interchangeable. We've already had some great suggestions from our users, and we look forward to an ecosystem of Exchanges growing as the community begins to adopt the new version of urql. Exchanges are also fully tree-shakeable, so any built-in exchanges you don't use don't end up bloating your client bundle!\n\nOne of the trickiest things to do well in GraphQL clients is performant and consistent caching that supports every use case, and we're particularly excited about caching now being something we can customize!\n\nHooks & onwards\n\nWe also wanted to further simplify the usage of GraphQL in React applications, which is why we now provide useQuery, useMutation and useSubscription Hooks alongside the classic render prop pattern:\n\nimport { useQuery, useMutation } from 'urql';\nimport { getTodosQuery, addTodoMutation } from './queries';\n\nconst TodoForm = () => {\n const [getResponse] = useQuery({ query: getTodosQuery });\n const [addResponse, addTodo] = useMutation(addTodoMutation);\n\n if (getResponse.fetching) {\n return 'Loading...';\n } else if (getResponse.error || addResponse.error) {\n return 'Oh no!';\n }\n\n return (\n <>\n
    \n {getResponse.data.todos.map(({ id, text }) => (\n
  • {text}
  • \n ))}\n
\n \n \n );\n};\njsCopy to clipboard\n\nThis reduces the amount of code you need to write to wire up your GraphQL queries, and improves client rendering performance by avoiding additional component nesting.\n\nGoing forward, as the React community will move to data fetching with React Suspense, thanks to urql's lean core and flexibility, we are well-positioned to take advantage of Suspense and avoid handling loading and error states in every component!\n\nType Safety\n\nGraphQL has been one of the most impactful improvements to how we write front-end applications since the introduction of React. One close competitor is the proliferation of type systems. That's why urql is written in TypeScript with thoughtful type coverage of the entire API.\n\nLooking to the future, we're also very excited about ReasonML and BuckleScript as a more strongly typed alternative to TypeScript. That's why we've written first-class Reason bindings for urql.\n\nFun fact: the lightweight callbag-style Wonka streams that urql Exchanges use to communicate with each other are written in Reason and transpiled to JavaScript with TypeScript typings, providing a unified, type-safe async primitive for urql apps, whether they're written in JavaScript, TypeScript, or Reason!\n\nExperiment!\n\nOut of the box, urql is a lightweight, batteries-included GraphQL client. That's pretty cool, but we are even more excited about what you will be able to build with urql in the future.\n\nWe're already working on several exchanges to extend urql and provide more options for applications that will use it. This includes a normalized cache, which brings us another step closer to building a smarter GraphQL client.\n\nGraphQL is still a new, but rapidly growing, technology, and we don't believe we've yet landed on the optimal approaches for every problem.\n\nIn the past year we've seen a lot of experimentation in the GraphQL Server ecosystem, but less so on the client-side. We hope that urql's extensibility will enable the community (yep, you!) to experiment with new approaches to GraphQL client-side challenges without having to reinvent the entire client stack.\n\nCheck out urql documentation, star the project on GitHub, and let us know what you think on Twitter!" ], "categories": { "primary": "frontend", "others": [ "backend", "data" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-radium-maintenance": { "href": "https://nearform.com/digital-community/radium-maintenance", "postType": "blog", "slug": "digital-community-radium-maintenance", "date": "2019-06-04", "title": "Placing Radium Into Maintenance Mode", "authors": [ "KYLE CESMAT" ], "content": [ "It has been more than four years since @vjeux proposed a revolutionary new idea for styling React components using JavaScript APIs. This CSS-in-JS talk sparked a wave of innovation in the React open source community as we experimented with new ways to apply styles to our React components. Radium was one of the early tools to provide APIs for interop between JavaScript and DOM style tags, and allowed React developers to avoid specificity conflicts by scoping styles to DOM elements.\n\nOver time this experimental idea turned into a valuable tool used across the community and has received 6,900+ stars with ~80 contributors, along with a community response of additional plugins, grid-frameworks, and tooling. Since Radium's initial release there has been tremendous growth in the css-in-js open-source world, with new tools like styled-components, emotion, and styled-jsx just to name a few.\n\nToday we are announcing that active development will be formally discontinued on Radium, as we move the project into 'Maintenance Mode'.\n\nWhat does stable maintenance mean?\n\nStable maintenance means we're not planning on modernizing Radium or adding any new features. Radium will still receive regular bug fixes and security updates, but the pace of updates will slow. You can read more about stable maintenance and our other maintenance levels here: https://formidable.com/blog/2019/oss-maintenance/\n\nMotivations for discontinuing active development\n\nBelieve it or not, the initial React target of Radium was version 0.12.0, and very-little prior art had existed showcasing strategies for managing inline styles using JavaScript. The world has changed since then, and today the space offers many wonderful alternatives to managing styles in JS, some even being framework-agnostic.\n\nWe believe the best way we can serve the React community is to recommend more flexible alternatives, while supporting users who already depend on our project. In our daily client work we have found better solutions that offer more flexibility and are built to work with the current modern toolchain.\n\nRecommended Tools\nEmotion\nAphrodite\nGlamor\nJSS\nstyled-components\nLinaria" ], "categories": { "primary": "oss", "others": [ "frontend", "design" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-nearform-at-the-inaugural-un-human-rights-and-ibm-call-for-code-event-in-geneva": { "href": "https://nearform.com/insights/nearform-at-the-inaugural-un-human-rights-and-ibm-call-for-code-event-in-geneva", "postType": "blog", "slug": "insights-nearform-at-the-inaugural-un-human-rights-and-ibm-call-for-code-event-in-geneva", "date": "2019-06-10", "title": "NearForm at the inaugural UN Human Rights Office and IBM Call for Code event in Geneva", "authors": [], "content": [ "Call for Code 2019 Global Challenge\n\nIt’s fair to say that I never expected to be writing a blogpost like this! Just over a week ago I learned that NearForm had been invited by IBM to take part in the Call for Code Geneva hosted by the United Nations Human Rights Office. Before anyone else had a chance, I excitedly offered to represent the company and I am so glad that I did.\n\nTo quote IBM:\n\n“

The Call for Code 2019 Global Challenge is a worldwide developer competition that seeks technology solutions for natural disaster preparedness, response, and recovery.

It is supported by the IBM Code and Response initiative, a multi-year program dedicated to creating and deploying open source technologies to tackle the world's biggest challenges.

”\n\nIn a brilliant move, IBM worked with the UN Human Rights to hold the Geneva Call for Code session in Palais Wilson which was the first home of The League of Nations and I felt every bit of this amazing location's history as I entered for the first time.\n\nThe 2-day event brought together four teams working on four separate challenges. Unlike a standard hackathon, the teams were not in competition with each other; and instead of writing code, the focus was on building out the concepts and high-level architectures.\n\nI was on Team 4 with three brilliant people including IBM Fellow Chris Ferris. We all clicked immediately and had very complementary skills and backgrounds. Our team’s top-level challenge was around Accountability and Centrality of Protection for Affected Populations. We decided to focus on providing feedback mechanisms for people affected by humanitarian crises.\n\nThe most critical aspect of the entire exercise was the involvement of UN subject matter experts Elsa Le Pennec, Patrick Rooney and Adam Fysh, all of whom were incredibly gracious with their time and guidance. There is always the danger of full-on Dunning–Kruger when a group of technology people get together to work on something completely outside of their domain. Having the UN experts explain what they did, why they did it, what they didn’t need and what they did need, ensured we didn’t go off on wild goose chases creating whiz-bang technical solutions to the wrong problems, that would never be used in the real world by the UN.\n\nWe were extremely cognizant of the potential for people to put themselves in danger by reporting abuse in a way that could be traced back to them by the wrong people. Our breakthrough came when we took a step back and we came up with the idea of “stories”. Rather than focusing directly on human rights abuse, what if instead, we enabled people to tell their stories? People, like the Rohingya, who may never have had their stories heard by a wide audience. People who may not have a high degree of literacy. People who have been disenfranchised or displaced and don’t have a voice. People in countries where the UN isn't even allowed to operate.\n\nEventually, our high-level spec became:\n\nA mobile app that enables you to anonymously and safely tell your story with a UX suitable for the vast majority of the world’s population.\nPotentially target both smartphones and KaiOS phones to broaden reach.\nVoice input by default. Text secondary.\nMultilingual voice-to-text on-device to reduce bandwidth requirements.\nEncryption of text and location with UN Public key and immediate local scrubbing of unencrypted voice and text. No ability to decrypt locally, even by the user.\nTransmission of anonymized encrypted text to UN “back-end” with the assumption of patchy network coverage and the possible need for peer-to-peer transmission.\nPotential use of a customised Secure Scuttlebutt (SSB) style network to achieve that transmission. SSB was created by Node.js legend Dominic Tarr.\nDecryption of text and location by the UN back-end.\nDuplication of stream into private and public.\nFull scrubbing of all Personally Identifiable Information (PII) and location, followed by rebroadcast/public-archive of a filtered version of that stream - An anonymous repository of people’s stories collected regionally. Potentially in multiple languages.\nML analysis of the private stream for human rights abuse signals, patterns and clusters.\nFlagging of potential human rights abuses to UN Human Rights Office for processing in their usual way. Likely via dashboard rather than real-time alerts etc.\n\nThe devil, of course, is in the detail and we are very aware that aspects of this like “how can I trust that the man is not listening and can’t track me down?” and “what could bad actors do here?” need to be carefully considered.\n\nWe hope we have created a concept that will be of value both to people affected by humanitarian crises and to the UN Human Rights Office. 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\nYou can read more about our Solution Starter Kit for Accountability and Centrality of Protection for Affected Populations here. We’d really like you to consider taking part in the Call for Code Challenge and we believe that an initial PoC should be achievable in a hackathon timeframe.\n\nAbout the author and NearForm\n\nConor O’Neill is Head of Product in NearForm. He is responsible for all productization activities and works closely with NearForm’s Open Source and R&D teams to evolve the web platform.\n\nNearForm has been instrumental in bringing Node.js and high-performance JavaScript to its current dominant position in software development. In the past 3 years alone, there have been over 3 Billion downloads of Open Source NPM modules that NearForm has built, supported or maintained. Anyone working on high-performance Fullstack JavaScript is almost definitely using code for which NearForm is responsible. Our delivery teams have been designing and building solutions with these stacks for Enterprises globally since 2011." ], "categories": { "primary": "oss", "others": [ "cloud", "product" ] }, "verticals": { "primary": "government", "others": [ "sustainability" ] } }, "digital-community-jetpack-multiple-engines-for-your-serverless-packaging-and-more": { "href": "https://nearform.com/digital-community/jetpack-multiple-engines-for-your-serverless-packaging-and-more", "postType": "blog", "slug": "digital-community-jetpack-multiple-engines-for-your-serverless-packaging-and-more", "date": "2019-06-11", "title": "Jetpack: multiple engines for your Serverless packaging and more!", "authors": [ "RYAN ROEMER" ], "content": [ "What's better than a blazingly fast engine for Serverless Framework packaging and deploys?\n\nMore of them.\n\nMeet the new serverless-jetpack plugin, now with parallel packaging!\n\nNow, even fasterer\n\nSince our initial release one month ago, we've been in the shop furiously hacking new ways to help wrangle even the gnarliest and biggest Serverless Framework projects. With our recent v0.4.x release, we are pleased to announce support for:\n\nLerna monorepos and yarn workspaces\nParallelized workers for packaging tasks\nSingle-function packaging\n\nIf you're behind on the news, our introductory post and follow-on rewrite post are great places to see the motivation and potential usefulness of the serverless-jetpack plugin. Now, without further ado, all the new details!\n\nMonorepo support\n\nMonorepos, either via lerna or yarn workspaces, are a very popular way to organize source code with cross-cutting interdependencies. Many Serverless Framework applications structure monorepo repositories such that different functions are logically organized into directories like functions/* or package/*.\n\nThis can sometimes be a challenge to package correctly because a simple direct dependency like bar for a package like functions/foo could be placed in:\n\nfunctions/foo/node_modules/bar\nnode_modules/bar\n\n\n... or even somewhere else if via a cross-linked package.\n\nTo this end, serverless-jetpack now provides features including service and function level options to specify places where a relevant function package.json is found for dependency inference. Jetpack can now \"just take care of the rest\", finding hoisted dependencies flattened to higher levels as well as symbolic links across packages.\n\nOne of our client monorepo projects used bespoke bash scripting to approximate Jetpack's previous (and now abandoned) approach of \"yarn install --production in a temporary directory\". The serverless package command took a full 44 minutes to run (lots of independent functions, lots of dependencies). Using Jetpack's new monorepo features, we were able to bring the total packaging time down to just NINE minutes!\n\nParallel workers\n\nServerless plugins run out-of-the-box in the same process as the serverless CLI application, which means all disk I/O and CPU work is shared in the main event loop. This can encounter bottlenecks when running serverless package (via Jetpack or built-in) over multiple functions that contend for both disk I/O (reading dependencies and source files) and CPU (bundling everything into a zip file).\n\nFortunately, the situation is \"embarrassingly parallel\", such that we should just be able to split independent units of packaging across different CPUs and processes/threads.\n\nWe identified a great abstraction library for parallelizing Jetpack: jest-worker. jest-worker is interesting in that it uses Node.js worker threads if available, and otherwise falls back to child processes. Hooking this into serverless-jetpack we split off the reading and zipping task into a function that could be run in serial as part of the main event loop or off event loop in parallel when desired.\n\nWe provide a simple configuration option, concurrency, to tailor the degree of parallelization to your specific environment and machines. Enabling parallelization in that same client monorepo project as before further reduced our serverless packaging time by more than half on developer machines and even more in CI!\n\nSingle-function packaging\n\nOne useful deployment strategy for Serverless Framework applications is to package and deploy single functions independently. To this end, serverless-jetpack now supports the built-in command:\n\n$ serverless deploy -f {FUNCTION_NAME}\nshCopy to clipboard\n\nout of the box! Curiously, although there is a serverless package command to package the service and all independent functions into zip files, there is no corollary serverless package -f {FUNCTION_NAME}.\n\nSo we added our own.\n\nJetpack now provides a simple helper CLI to create all or some service and function packages to further facilitate bespoke packaging and deployment strategies.\n\n$ serverless jetpack package\n$ serverless jetpack package -f {FUNCTION_NAME}\nshCopy to clipboard\nUp, up, and away!\n\nWe've been very pleased with the packaging results as we integrate the plugin into more Serverless Framework projects and a variety of different application configurations and setups. With the latest collection of features and support, we feel there's a good chance any given Serverless Framework project will have faster packaging and deploys with serverless-jetpack.\n\nHook up the plugin today and see what the new multi-engined Jetpack can do for you! 🚀" ], "categories": { "primary": "cloud", "others": [ "backend", "devops" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-design-to-dev": { "href": "https://nearform.com/digital-community/design-to-dev", "postType": "blog", "slug": "digital-community-design-to-dev", "date": "2019-06-13", "title": "How To Create an Ideal Design to Dev Workflow", "authors": [ "JOE ALTERIO" ], "content": [ "Products that require both design and engineering find an inflection point in their lifecycle that can cause confusion, delay production, and add multiple headaches further down the road. Specifically stated, that point is when the thing that is designed must now be made.\n\nTransition from concept to realization is tough. It’s no wonder the hand-off meeting can be a dreaded occasion for both developers and designers. Airy concepts must come crashing down to reality. Bad news is often broken in these meetings, sometimes resulting in disagreements, complicating a working relationship and immediately putting the build on the wrong foot.\n\nHow can we, as both designers and developers, mitigate these risks and foster a more inclusive workflow that ensures the final designs are not only beautiful, but functional and developmentally sound?\n\nTip 1: Priorities\n\n“‘That’s hard to build’ versus ‘That’s not my design’ is immaterial when you’re focused on ‘Let’s ship this thing.’“\n\nOur respective work can seem like the most essential work in the world, but we shouldn’t let that cloud our judgement about who we are making these products for. For the agency, it is our clients, but in a grander sense, it is the end users. Each decision we make needs to lead with the end user in mind. Our work has the potential to impact millions of people and this responsibility informs the hierarchy of importance we assign to each decision. Any type of consideration should be fundamentally subservient to this. It is the nature of our business.\n\nTip 2: A Cohesive Team\n\n“As a developer, understanding what the problem is we’re trying to solve, helps answer some of the questions about why I’m building the thing I’m building, which is very motivating for me.”\n\nSegmenting teams based on deliverables is not ideal. Even if development is not involved in the early day-to-day project activities, keeping all teams informed during the product development cycle will head off rude awakenings of technical impracticalities. Conversely, even for projects in which a client has assured the team the internal designs are “code-ready,” it’s good to let your internal design team validate the assumptions. Not only is there value in having a second team’s eyes on designs, but often the design team will have a good idea of development’s capabilities and make design arguments that support development’s stance. We’re firm believers in the enmeshed design/development team hybrid model, and it’s been successful for us specifically for this reason.\n\nTip 3: Specs, Specs, Specs\n\n“There have been jobs I have been on where I’ve had to take rasterized bitmapped images to make vector assets.”\n\nIt is a great time to be making digital products. The support afforded by modern digital tools such as Zeplin and Avocode makes digital product velocity lightning fast and allows quicker and cleaner file hand off. However, that efficiency has come at a cost. As recently as five years ago, design handoffs included not only actual redlines, but spec sheets. They seem to have gone the way of design briefs, which is a shame. Cloud-based links are now the norm, but even tools that include room for detailed notes and design systems are rarely used.\n\nIn the interest of keeping everything unified and speedy, we’ve sacrificed some of the less obvious yet essential practices that ensure clearer communication. If you’re a designer who is preparing to handoff files, make sure you include not only basic redlines, but also the following:\n\nContent Matrix\n\nThis may not be the designers responsibility, but making sure content is in usable forms (copy-and-pasteable text, usable file formats sized correctly) and has the ability to be tracked and validated by multiple parties is an essential part of a build. You’re not ready for development yet if this step is not complete.\n\nTechnical Expectations\n\nSpec sheets should, at a minimum, contain a broad overview of the technical expectations for the product’s features. Ostensibly, the development team will have a good idea as to expected functions, but not necessarily the location of function triggers, cross-functional actions, and features that are story or case-dependent. Laying these out in clear language will be a boon to not only the developers, but the entire product team, and serve as a good reference document going forward.\n\nFull Responsive Versioning, Including Device Expectations\n\nI’ve been shocked to learn that some designers do not give their developers fully responsive comp sizes. At a bare minimum designers should provide complete desktop, tablet, and mobile comps, as well as error states, form states, and empty states. Bonus points for flex fulcrums, such as where the padding increases, and by how much. One Formidable developer’s request was even more on point: “Most useful is to tell the developer what you are basing these sizes on.” Knowing the make and model of each intended device the screen size being is pulled from can inform the developer about expected optimizing and scaling.\n\nUser Stories/User Flow Map\n\nIncluding a (hopefully) previously generated user-flow map will align the development team with the expected architecture of the product. Even more importantly, if the naming conventions are adhered to, this helps development understand the screens design provided. Context for error states, empty states, and the like will save many headaches. The aggregate time spent figuring out where a design fits into the grand scheme of things can be hefty.\n\nPalette and Color Story\n\nA complete color palette, for both colors and situation colors (like error states), must be provided; don’t expect the developer to infer from existing elements what colors mean, and where they should be applied. Part of a designer’s job is to give the developer tools to solve small problems on his/her own. Explaining what colors are used why and when is a perfect toolbox for this.\n\nComplete Typography\n\nThe typographic support provided should not only outline (and provide files for) typographic choices, it should also outline type hierarchy and use cases for any speciality formatting.\n\nExamples of Motion and Animations\n\nMost modern digital products have some sense of motion or animation endemic to them. Motion storyboards, gifs of the animation, or ideally, prototypes of the movement are essential for the developers’ success. Our team prefers to use AfterEffects with Lottie from Sketch files for our animations, but there are multiple excellent tools available these days.\n\nThe use of spec sheets should not be a last resort of validation and argument resolution, but a source of agreed-upon truth for the entire product team.\n\nTip 4: Get Yourself a Remarkable Hybrid\n\n“Part of your role as a developer is to make adjustments along the way.”\n\nOk, you don’t have to call it a Remarkable Hybrid or a “Unicorn,” but this person is a unique type of digital product expert who both knows code AND truly understands the fundamentals of design.\n\nEven in the most planned-for products there will be gaps—it’s the nature of making things from scratch. By understanding the designs, and being able to make educated guesses about designer intent, as well as understanding the technology enough to implement changes on the fly, hybrids can bring the two sides of the rope together and tie a neat knot. These individuals are a valuable component in any digital product team. If you don’t have one (or many), hire some now.\n\nTip 5: Use the Right Tools\n\n“The ideal tool would be a something that creates real usable assets, but we’re not there yet.”\n\nThe most prosaic advice offered is also the most obvious, but must still be said: Use the right tools for the job. The host of lightweight, development-ready design tools is legion, and while some are better than others in generating actual usable CSS objects, they are all angled for digital development. Make sure your assets are as lightweight as possible, and scalable. There’s no reason to be scaling bitmapped images 1x, 2x, and 3x anymore, except for the occasional graphic, and if you have to, current design trends, from gradient overlays to image patterns all work towards the goal of not making a digital product overly weighty.\n\nIn Conclusion\n\nThere is no magical solution to a flawless and error-free design-to-development handoff. Errors and miscommunications will still happen resulting in pushed deadlines and compromises. However, using the above protocols will minimize your risk and you can get back to doing what you are good at.\n\nAll insights and quotes provided by Paula Lavalle, Carlos Kelly, David Earl Duncan, and Ryan Ray, members of the Formidable Design and Development teams." ], "categories": { "primary": "design", "others": [ "frontend", "product" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-glicky": { "href": "https://nearform.com/digital-community/glicky", "postType": "blog", "slug": "digital-community-glicky", "date": "2019-06-18", "title": "Glicky: A Graphical User Interface for JavaScript Development Workflows", "authors": [ "ALEX SAUNDERS" ], "content": [ "Modern web development is hard. Long gone are the days of opening up your text editor, writing some HTML, CSS and JavaScript, saving it to an index.html file, and loading it in your browser.\n\nThese days, starting a project involves setting up a lot of tooling, from bundlers to test runners, and linters to type checkers. All of this tooling takes so much expertise to set up that we tend to forget that it can also be complicated to use.\n\nYou might ask, \"What do you mean? You just fire up your terminal and npm run build. Easy peasy.\"\n\nFor many of us, fiddling with package.json and interacting with the terminal seems easy, because we've done it for a long time. But do you remember how you felt the first time you were faced with a terminal?\n\nCLIs are actually hard\n\nThe requirement for developers to learn how to navigate the command line is especially problematic for new engineers who are starting off their web development journey, and for less technical team members like designers, product owners, and testers. The mental overhead of having to learn necessary CLI commands before being able to run your application can be overwhelming, leading to confusion and frustration.\n\nBeing a coach at Codebar, a non-profit that helps underrepresented people to learn programming, has allowed me to witness this exasperation first hand. I can confidently say that I do not envy the new developers who just want to learn how to design and develop web apps in 2019.\n\nCommands, commands, commands\n\nA number of tools exist to help alleviate the pain of getting started on a modern web stack—tools like Gatsby and create-react-app aim to be low-friction ways of bootstrapping new projects with useful defaults and automatic dependency installation.\n\nHowever, all of these tools are command line-based and come with bespoke commands to help interact with the bootstrapped project, requiring developers to learn and remember more commands for common tasks. For example, create-react-app comes bootstrapped with a whole host of extra command line scripts (start, build, eject etc.) that are required for development on the project.\n\nAlmost inevitably, they don't provide exactly what is required for your project. And guess what? Installing and removing dependencies the correct way requires learning even more terminal commands!\n\nAfter my experience coaching junior developers and remembering my own beginnings, I began to wonder, could the overhead of these processes be reduced by providing a visual means of interacting with the project?\n\nWhy, as an industry, are we obsessed with creating CLI tools when our day jobs are concerned with creating GUIs?\n\nIntroducing Glicky\n\nGlicky is an in-browser task runner for modern web development that can be installed simply by running npx glicky inside of your project root directory.\n\nGlicky is hosted on NPM and runs in your browser, allowing for easy installation and fast startup times on any platform.\n\nHere are a few of the problems I wanted to solve with Glicky:\n\nAdding, removing & executing npm scripts: When running npm scripts, it can be hard to visualise the state of any given script. Scripts that have resulted in an error or need restarting could be left unattended, leading developers to wonder what's happened. With Glicky, however, we can display different visual states given the output of an executing script. Further, we can show an alert when a process has output an error, and provide a restart button when a script has stopped due to a fatal error.\nParallelizing tasks: Running multiple scripts is also tricky within a command-line environment, each process usually requires a new tab in your terminal, leading to an unnecessary context switch when attempting to understand the output of concurrent scripts. However, with Glicky, we can group these scripts and their output together on the same page, allowing developers to quickly scan what is executing, how it is performing and anything that may have gone wrong.\nManaging dependencies: Dependency installation and package discovery is also something a GUI can provide. A type-ahead component could be a perfect fit for newer developers attempting to find and install dependencies, allowing users to browse packages without having to know the exact name of the dependency they need. Vague command line arguments can be made obvious, replaced by visual components that allow dependencies to be defined as for development or optional.\n\nOverall, Glicky aims to make everyday development workflows more intuitive and ergonomic.\n\nBecause we don't want to introduce even more commands and configuration files, Glicky is zero-config and doesn't pollute your project with configuration files. It is also framework-agnostic; as long as your project contains a package.json, you should be good to go, whether you're writing apps for the browser or Node.js!\n\nOh, and Glicky comes with a light and a dark theme, in case you're into that type of thing!\n\nCheck out Glicky on GitHub or give it a spin with a simple npx glicky in your project!\n\nWhat is this magic?\n\nI did some research into existing graphical developer workflow tools and found ones like Guppy by Josh Comeau and JSUI by Kitze. They serve slightly different use cases, but I thought I could learn from how they work.\n\nBoth of the these projects are open source and written in web technologies, built with Electron so that they may execute native tasks (file access, running CLI commands, etc.).\n\nThe problem with Electron apps, however, is that because they are bundled as desktop apps, they result in large downloads and require installation via native package managers (such as Homebrew), and require you to provide an update mechanism to keep the user on the latest version.\n\nInstead, I wanted Glicky to run in the user's default browser. This required me to figure out if a browser could execute and display the output of terminal commands. How could a browser-based tool access and modify the file system?\n\nThe trick behind Glicky lies in WebSockets. When you run npx glicky inside your project, we spin up a local Node.js server and launch the Glicky client in a new browser tab.\n\nWhen launched, the browsers opens a WebSocket connection with the server via socket.io, which it then uses to communicate with the server and request platform-specific resources (like executing a command line script, installing dependencies, etc.)\n\nWebSockets are a perfect medium for such constant client-server communication as they provide a keep-alive mechanism out of the box, providing a low latency environment for the client to talk to the server. After experimenting with this, I found that the latency was so low when running the server on your local network that it can feel like you are running server commands directly on the client!\n\nThe future\n\nCurrently, Glicky provides helpers for common tasks inside projects that have already have a package.json file.\n\nIn the future, Glicky hopes to include an onboarding process for projects that do not contain a package.json. This would provide a visual means of guiding the user through the npm/yarn init process and bootstrapping the project with desired dependencies, or initialising a given boilerplate (Gatsby, create-react-app, etc.).\n\nCertain boilerplates could also include custom UIs to help perform tasks specific to their environment (an eject mechanism for create-react-app applications, for instance).\n\nI'd love to hear your feedback over at Glicky's GitHub repo or on Twitter!\n\nHappy coding!" ], "categories": { "primary": "frontend", "others": [ "devops", "oss" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-jon-reynolds": { "href": "https://nearform.com/digital-community/jon-reynolds", "postType": "blog", "slug": "digital-community-jon-reynolds", "date": "2019-06-18", "title": "Meet Jon Reynolds", "authors": [ "JON REYNOLDS" ], "content": [ "We're launching a new blog series to showcase our talented team of Formidables across the globe. Please meet Jon Reynolds from the Formidable Denver office.\n\nWhat brought you to Formidable?\n\nI first heard of Formidable when I saw a Formidable employee deliver a talk at ChainReact 2017. The speaker's passion and expertise really stuck with me. A year later when I was looking for new opportunities, I couldn't shake the idea of working at Formidable. I dug into Formidable's widely varying client portfolio, compelling mission statement, and generous OSS contributions. I was sold.\n\nWhat are you most excited about now that you are here at Formidable?\n\nConsulting is a totally different ball game. I previously worked at a product company, so I get really energized by the constantly varying opportunities that Formidable provides me. There's a rule that a Formidable employee will never be required to work on the same project for more than a year. This is so reassuring to me, because it means I get to solve new problems all the time.\n\nWhat are you currently doing to \"level up\" your skills?\n\nMy primary focus at the moment is to prepare for a future Project Lead role. To level up for this position, I've spent a lot of time sharpening my project management, client communication, and architecture skills. Thankfully, there are so many brilliant people at Formidable to learn from.\n\nWhat's your favorite part about working at Formidable? Maybe something people on the outside wouldn't know?\n\nI can't wait to open Slack! There are never-ending shenanigans. In truth, our Slack represents the Formidable culture that can thrive and span four offices across two continents. Formidables are kind, funny, intelligent, and never take themselves too seriously.\n\nWho or what inspires you and why?\n\nThere are a number of Formidable employees who came to the tech industry from totally unrelated fields by way of coding boot camps. This is my first time to work with people who have gone through boot camps instead of through a university degree program and I'm blown away. I'm continually inspired by their technical prowess, their willingness to grow at incredible rates, and the unique perspectives they bring to Formidable.\n\nInterested in joining Formidable? Please see our open roles posted on our Careers page and apply today." ], "categories": { "primary": "work", "others": [ "oss" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-conversations-with-changemakers-jason-mulligan-of-adobe": { "href": "https://nearform.com/insights/conversations-with-changemakers-jason-mulligan-of-adobe", "postType": "blog", "slug": "insights-conversations-with-changemakers-jason-mulligan-of-adobe", "date": "2019-06-18", "title": "Conversations with Open Source Changemakers: Jason Mulligan of Adobe", "authors": [], "content": [ "Jason Mulligan talks about event IOT, the future of digital badges, opportunities for open source, and the Experience League\n\nFollowing this year’s Adobe Summit in Las Vegas, we got the chance to catch up with Jason Mulligan, Senior Principal Architect & Developer EXL, to talk event IOT, the future of digital badges, opportunities for open source and what the Experience League is all about.\n\nBefore we delve into your world of software, code and customer experience management, can you tell us a little bit about yourself and your background?\n\nI'm a blue-collar developer (I don't have a CompSci degree) who fell into this career path after spending some time considering following a career as a 3D artist and an architect. I love finding the intersection of art & science in all kinds of mediums and have developed some useful skills in my pursuit of knowledge & experience.\n\nYou’re based in Canada, right?\n\nYes, I am from the Great White North.\n\nDo we detect some Irishness in that surname?\n\nYes, my father's side of the family came over to Canada a couple of generations ago. The name just lends itself to so many jokes in our field with refactoring, bugs, re-aligning on business strategies, & my grandparents on my mother's side owned & ran a golf course for many years, so I've always appreciated a well-timed \"I'm taking a mulligan on that\".\n\nCan you tell us about what you work on in Adobe?\n\nI work with a fantastic small team in Adobe Experience Cloud, where I architect & develop the Experience League platform, and carry out R&D with emerging verticals & technology.\n\nWe know you were keen to work with the NodeConfEU-based digital badge and see how you could build on it for the Adobe Summit. What drove that interest?\n\nIt's simply the coolest badge I've seen. Who wouldn't want to work with it, or have one? I kept a few for myself after our Las Vegas summit, for future R&D of course.\n\nHow did you hear about the NodeConf EU badge?\n\nI'm not sure if I happened to read a tweet from James Snell , or if it was on Hacker News, but I saw an early blog post for the '18 badge and I immediately wanted one.\n\n[caption id=\"attachment_300003737\" align=\"aligncenter\" width=\"768\"]\n\nDigital Badges in action at NodeConf EU 2018[/caption]\n\nWhat particularly caught your attention about it?\n\nI think it was the elegant design that caught my attention. It simply looked better than any tech conference badge I'd seen before, and after reading the blog post it stood out as simply being very well done/conceived/executed.\n\nDid the fact that it runs on Open Source hardware and Software present opportunities?\n\nAbsolutely yes! The EXL tech stack is primarily OSS/ node.js based, so it stood out as a natural vehicle into physical space, allowing me to apply the EXL platform to a conference booth very little effort & a whole lot of affordance.\n\n[caption id=\"attachment_300003748\" align=\"aligncenter\" width=\"768\"]\n\nL-R: Roman Luba & Jason Mulligan[/caption]\n\nHow important was it that it runs JavaScript?\n\nIt was the deciding factor from my point of view. Impressive tech is always fun to use, but sometimes it's a pain to program. I think JavaScript removes a barrier to hardware programming; it becomes \"easy\" if you have the right hardware, and the NodeConf EU badge is definitely amazing hardware.\n\nSo what is Experience League exactly and how did you see the digital badge delivering value?\n\nExperience League is a new Customer Enablement platform launched by Adobe in early 2018 for Experience Cloud users. Adobe has a lot of impressive tech, but getting started with it can be daunting sometimes, and we've created something new that turns the problem domain upside down, and makes learning fun & easy... but it's not just a website or application, it bridges digital & physical experiences through applied tech like the NodeConf EU badge , and our amazing teams around the world that hold Experience Maker events.\n\n[caption id=\"attachment_300003734\" align=\"aligncenter\" width=\"640\"]\n\nExperience League Digital Badges[/caption]\n\nWhat was your original intent for the badge?\n\nI wanted to provide a hardware platform that would afford anything I'd be asked to deliver for our Las Vegas Summit. Delivering 'impossible' things is what I do for Adobe, and this gave me a massive head start on the work. I needed a tool that could be as flexible as the EXL platform .\n\nHas Adobe used digital badges before at events?\n\nYes, but for our Creative Cloud/technology focused events; those were impressive badges that were produced in North America, but I think the Espruino hardware created by Gordon Williams was on another level. The last tech summit badge I saw was pretty similar to the first NodeConf EU badge , so naturally, the revision of the NodeConf EU badges we used was an evolutionary step or two forward.\n\nWhen you went about customising the badge for the Adobe Summit, what changes did you make and why?\n\nMy massive contribution was the idea of a back plate to avoid it catching on clothing. We got a revision of the hardware from Gordon that had different buttons; beyond that, I didn't want to make any changes - it was pretty much ready to go out of the box. General affordance was my goal, and the NodeConfEU badge hardware delivers that.\n\n[caption id=\"attachment_300003749\" align=\"aligncenter\" width=\"1024\"]\n\nL-R: Amelia Waliany & Jacob Hammons[/caption]\n\nWhat can you tell us about the software you created specifically to support the badge?\n\nI'd love to! I created a conference booth platform which I've named Hellcat (dedicated to my cat Halo, that passed away in '16) designed to run on-premise, which was comprised of multiple iPads for people to 'sign in' with their conference badge; a core server driving authentication, authorization, welcome boards, leader boards using node.js & web tech (SPAs, & EventStreams); multiple Raspberry PIs acting as BTLE stations which could do multiple functions, such as tracking people through a space, or gamifying their time in that space; and the magical \"loader\" which retrieves a data payload from the core server to then deploy to a random badge in a pool of available badges.\n\nThat last component was fun. I really enjoyed asking people which badge they thought they'd get because it only took a few seconds to drop our badge app onto the hardware via BTLE loading. I parallelized this after our Las Vegas event using a Raspberry PI Clusterhat & NGINX doing random load balancing to the \"loader\" app which was now running on each Raspberry PI Zero W.\n\nSo you used Node.js to build your software?\n\nYes, very much so. Hellcat is a blend of noble & bleno (BTLE stations/loader), tenso (core API server/loader), & ionic (iPad). It's node.js all the way down.\n\nEvery event has its glitches, particularly ones of such scale as your Adobe Summit - what was your no.1 biggest challenge?\n\nEccentric Cisco DHCP features are likely going to cause a Raspberry PI many problems, followed closely by an 8:1 bottleneck in Las Vegas (iPads:loader), followed thirdly by my BTLE stations inside of 2\" thick MDF cabinets (this was easy to remedy).\n\nDid the badge relieve any of the challenges that your event organisers would have typically encountered?\n\nI think it acted more like a creativity bomb; once people realized the possibilities of what we were going to deliver, they ran with the affordance in ways I hadn't considered. We were also able to pivot the experience in real time when we encountered a deployment issue on day 1 for Las Vegas; in my opinion, this was the true value of the badge + platform. How many tech companies can claim they can change the entire experience in a minute?\n\nWhat did delegates mostly use it for?\n\nWe flipped the engagement model such that people were approached by experts in context to what they were interested in at that time; badges would light up with 1 of 4 potential colors, which removed a lot of friction points for delegates & the attendees.\n\nHow did attendees respond to it and what was its most popular feature?\n\nThere was a blend of amazement and curiosity; it seemed to wow everyone for different reasons. It’s most popular feature? I want to say it's the haptic motor because no one expected it.\n\nWill you be using the badges again at future Adobe events?\n\nYes! I took them to our EMEA Summit in May'19 , but infra issues blocked me from deploying them. We're looking at Las Vegas'20 as the next big event for them.\n\nIt sounds like you’ve gained a lot of experience with the badge which is fantastic and it’s great to share this with others. For anyone looking to further build on the badge for their own events, what one thing would you change and why?\n\nI'd swap the batteries to be triple-A if you don't mind the added thickness. Secondly, I'd change the buttons on the badges; that's the only tech part that confused the attendees, as they blended into the badge too well. I would caution that it's easy to underestimate the effort to support a productized device.\n\nThe Adobe Experience League sounds like a great initiative for marketers and creatives. Where should people go to find out more?\n\nThey can learn more about it at https://experienceleague.adobe.com , and watch for news from Adobe ; Experience League is a new core component for the Customer story of Experience Cloud. The NodeConfEU badge has evolved in features since its inception in 2017. We’re looking forward to making it even greater again this year at NodeConfEU 2019. There’s a wealth of untapped opportunities to be explored and tested in IOT, cloud services, Data Analytics & Visualisation, ML and AI, Health/Wearables services, Communications (Cellular, IOT, Mesh), Crypto services and more. We’d love to involve & collaborate with more people in its development. If you’d like to learn more about the badge and the possibilities it can present to your area of technology, contact Conor O’Neill, our Chief Product Officer at NearForm. You can hear a little more about the badge from Conor here at our NodeConfEU fireside chat. Note there are a small number of core badges available to purchase on the Espruino site for anyone who wants to play with the technology. Like to know more about NodeConf EU 2019? Find out more about this year's conference here." ], "categories": { "primary": "oss", "others": [ "cloud", "product", "data" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-our-5-step-design-journey": { "href": "https://nearform.com/insights/our-5-step-design-journey", "postType": "blog", "slug": "insights-our-5-step-design-journey", "date": "2019-06-18", "title": "Our 5-step Design Journey", "authors": [], "content": [ "Our 5-step approach in taking organisations on a design journey\n\nAt NearForm, we follow a 5-step approach in taking organisations on a design journey that allows them to de-risk delivery, achieve repeatable success and rapid go-to-market development of well-defined user-focused solutions.\n\nYou can also download our e-book , listen to our latest podcast on achieving optimum digital CX design or visit some of the related blog posts here" ], "categories": { "primary": "design", "others": [ "product" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-open-source-conversation-with-nearform-founder-cian-o-maidin": { "href": "https://nearform.com/insights/open-source-conversation-with-nearform-founder-cian-o-maidin", "postType": "blog", "slug": "insights-open-source-conversation-with-nearform-founder-cian-o-maidin", "date": "2019-06-20", "title": "A Conversation on Open Source with NearForm founder, Cian Ó Maidín", "authors": [], "content": [ "Open Source for Enterprise\n\n[caption id=\"attachment_300003870\" align=\"aligncenter\" width=\"1024\"]\n\nPic: Naoise Culhane Photography[/caption] GBI Events recently caught up with NearForm founder and CEO to talk disruption, Open Source, and how the global development community is directly supporting business transformation. Following is a synopsis of the interview.\n\nBiggest Challenges Enterprises are Facing in 2019\nLarge, established companies are being rapidly disrupted on all fronts.\nCloud computing is enabling new companies to accelerate scientific and technological development.\nNew companies have a different playbook which is forcing established companies to adapt in order to stay competitive and meet consumer demands.\nEstablished economic systems that were traditionally a strength for large companies are becoming a hindrance.\nBiggest Changes to the Business Playbook\nFinancial Institutions\nTraditional competitors, such as financial institutions competing against each other, are now having to compete with disruptive startups and large tech companies who are offering financial services\nThese new competitors operate in a completely different way than traditional financial institutions.\nTraditional banks are faced with the prospect of losing customers and staff.\nTo keep pace they need to attract the brightest stars of the tech world.\nThese institutions need to be agile, break down the silos and bring their business leaders into the technical design of new products and features in order to deliver the customer experience set by the market.\nPrint Media\nSubscriptions are declining but media companies are still earning most of their revenue from traditional advertising.\nMedia companies that we work with, such as the New York Times and Conde Nast, are currently trying to monetize their digital properties and move away from the traditional model.\nEnterprise Transformation Programmes and Open Source. A good fit?\nEnterprises should ask the question, \"Do we need to become more agile and ideate new ideas that we can bring to working concepts quickly?\"\nIf yes, then Node.js, the technology stack used by NearForm, is the best way to build scalable prototypes rapidly.\nThe right culture and mindset as well as an open approach are just as important for a successful digital transformation as having the right technology stack, which is something NearForm understands.\nOpen Source is an excellent choice for transformation programmes.\nOpen Source allows developers to solve problems as a community and that knowledge is shared globally.\nThe power of open source has made emerging tech more accessible, lowered entry barriers and accelerated the speed to market for software applications.\nOne example that stands out is artificial intelligence (AI) which has been heavily invested in by Google, Amazon, Microsoft, and IBM; but only after Open Sourcing their projects saw a wave of innovation and made commercial applications a reality.\nOpen Source allows enterprises to use a lot of existing art to create new things.\nRisk Factors for Enterprises using Open Source\nDe-risking Open Source Projects\nIt's important to look at the fundamentals of Open Source modules you are considering for a project:\nDo they have a healthy community?\nAre they frequently downloaded?\nAre they frequently updated?\nAdhering to best practices for building Open Source cloud-based applications and developing or following a standard reference architecture for building web applications, as we do at NearForm.\nFor this reason enterprises choose NearForm, to act as the conduit between their organization and the Open Source world.\nNearForm makes Open Source safe for enterpises.\nComitted to Open Source\nIn 2018 NearForm invested about €1.2 million in external developers contributing to Open Source.\nThere's an explosion of creative energy in the Open Source community.\nMultibillion-dollar enterprises are committing to Open Source and getting real value from their investments.\nThe biggest challenge is how to capture that value and return some of the windfall to the developers.\nWill Open Source continue to support business transformation?\nYes, disruption and competition are intensifying.\nOrganisations need to innovate rapidly which can only be done with collaboration, code reuse, and communities.\nWe can see major business transformation already showing results.\nThe New York Times is surviving the decline of print because they are getting digital so right.\nSuccess stories like that are giving established businesses the proof they need to get on board with transformation initiatives." ], "categories": { "primary": "oss", "others": [ "cloud", "work" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-meet-the-nearform-team-at-fullstack-london-2019": { "href": "https://nearform.com/insights/meet-the-nearform-team-at-fullstack-london-2019", "postType": "blog", "slug": "insights-meet-the-nearform-team-at-fullstack-london-2019", "date": "2019-06-21", "title": "Meet the NearForm team at FullStack London 2019!", "authors": [], "content": [ "FullStack 2019 returns to London in its sixth edition from July 10-12th. Now hosted at the Business Design Centre, FullStack London has been growing each year and still remains the best place to connect with the international JavaScript community!\n\nIf you're heading along be sure to check out the talks and workshops from the NearForm team. We have a super line-up this year and we're also proud sponsors of this year's event.\n\nSpeeding Up React SSR with ESX - David Mark Clements (Day 2)\n\nReact is a hugely popular frontend framework that revolutionized the frontend development world. React is built primarily for the browser, while Node has fundamentally different operational constraints to the browser. As a Principal Architect and Consultant, it has become painfully clear that React’s Server-Side Rendering is a performance bottleneck for web backends around the world. During this talk, David will share and demonstrate a very simple solution that can be dropped into pre-existing React applications to significantly improve Server-Side Rendering throughput.\n\nRead more about React ESX here or watch David’s talk from React Amsterdam here.\n\nStripping Down Components With React Browser Hooks- Cian Foley (Day 3)\n\nOften times, developers directly access specific browser functionality/events within react components. The specifics take time to research and implement, especially given cross-browser considerations and other nuances. It can also negatively impact the readability and fingerprint of a component, and sometimes developers might even forget to tidy up. Based on their research, the same functionality is being implemented over and over again, and significant time is being wasted re-inventing the wheel. Custom React Hooks make it possible to strip out and abstract full slices of related browser functionality into tidy, testable, reusable atomic libraries. This means that developers can import and use hooks that completely abstract this functionality, keeping their components clean while improving productivity and quality.\n\nDuring this talk Cian will:\n\nProvide evidence of the problem based on our experience/research\nShow a real example of how such a hook could tidy up a component significantly\nDemo the various functions that have been wrapped up neatly for re-use in their React Browser Hooks npm package\n\nhttps://github.com/nearform/react-browser-hooks\n\nWorkshop: GraphQL, Simplified - David Mark Clements (Day 3)\n\nUse React? Use GraphQL? Love Hooks? Graphql-hooks is a new GraphQL client for React with a hooks-first API. It’s super fast and weighs only 1.9kB gzipped.\n\nThe motivation behind graphql-hooks was a barebones GraphQL Client, focused on speed and lightweight. Both Apollo and Relay have pioneered how to use GraphQL on the client. However, over the years they’ve grown in size and complexity. This has increased the barrier to entry for new developers excited to try out GraphQL.\n\nIn this workshop, David will be demonstrating how quick and simple it is to get up and running with graphql-hooks. He’ll also do a direct comparison with Apollo using the Next.js example.\n\nA simple GraphQL server using fastify\nIntegrating graphql-hooks with a CRA app\nAdd Caching\nAdd SSR\nAdd Pagination\nLive refactor of Next.js with-apollo to use graphql-hooks\n\nYou can check out the full line up here and keep up to date by following #FullStackCon on Twitter.\n\nBe sure to call over to our booth while your there to find out more about what exciting stuff we are up to, our current openings and life at NearForm. See you in July!" ], "categories": { "primary": "frontend", "others": [ "devops", "cloud" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-on-demand-webinar-creating-an-environment-for-accelerated-innovation": { "href": "https://nearform.com/insights/on-demand-webinar-creating-an-environment-for-accelerated-innovation", "postType": "blog", "slug": "insights-on-demand-webinar-creating-an-environment-for-accelerated-innovation", "date": "2019-06-25", "title": "On-Demand Webinar: Creating an Environment for Accelerated Innovation", "authors": [], "content": [ "Getting innovation right continues to challenge large organizations across industry verticals. But there are key lessons to take from enterprises who have successfully pioneered new products and services, in new markets, using new tools: truly transformational innovation that doesn't just deliver a great customer experience, but that also builds and changes the core capabilities of the large organization itself.\n\nIn this wide-ranging webinar on the nature of innovation, hear from Gordon Suttie, Director of Digital Advisory at EY, NearForm's Chief Product Officer Conor O'Neill, and NearForm's Head of Strategic Partnerships Clare Dillon on the key success factors for accelerating innovation and creating a pervasive innovation culture, including the role of DevOps, design-led workshops, open source and collaboration.\n\nProvide your details below to gain access to the webinar." ], "categories": { "primary": "product", "others": [ "devops", "design", "oss", "work" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-devops-is-a-mindset-culture-not-a-magic-set-of-tools": { "href": "https://nearform.com/insights/devops-is-a-mindset-culture-not-a-magic-set-of-tools", "postType": "blog", "slug": "insights-devops-is-a-mindset-culture-not-a-magic-set-of-tools", "date": "2019-06-26", "title": "DevOps is a Mindset & Culture not a magic set of Tools", "authors": [], "content": [ "Embracing DevOps\n\nIn the DevOps world there’s been an explosion of tools being developed with the express goal of facilitating the Agile principles, methods, and practices. Demand for DevOps specialists has soared by 986 percent in the last five years, according to recruitment firm Reed. But plugging the gap with people and tools will not magically bring you DevOps, no matter how sophisticated they are.\n\nWhat is DevOps?\n\nDevOps is the combination of development and IT operations with the goal of curbing the systems development lifecycle and facilitating continuous delivery of high quality software. See: DevOps on wikipedia\n\nConversation with DevOps experts\n\nIn this episode, NearForm's Director of DevOps Alex Knol and DevOps Consultant David Gonzalez discuss how organisations need to recognise and embrace DevOps and DevSecOps as a culture, the challenges and the success factors and the benefits that go far beyond speed and reduced waste.\n\nDifferent Perspectives with NearForm · DevOps is a Mindset & Culture not a magic set of Tools" ], "categories": { "primary": "devops", "others": [] }, "verticals": { "primary": "none", "others": [] } }, "insights-lets-make-systemic-software-failures-a-thing-of-the-past": { "href": "https://nearform.com/insights/lets-make-systemic-software-failures-a-thing-of-the-past", "postType": "blog", "slug": "insights-lets-make-systemic-software-failures-a-thing-of-the-past", "date": "2019-06-26", "title": "Let's make systemic software failures a thing of the past!", "authors": [], "content": [ "Much has been written about the well-known car rental company that has sued a prominent global systems integrator for $32 million. This comes after a core website overhaul – a critical part of the company’s digital strategy – went sour. Sadly, this kind of systemic failure is one we see replicated many times in the software industry. But there is a way to prevent these failures and to ensure all parties are celebrating at the end of their engagement, rather than seeing each other in court.\n\nAs has been highlighted in the recent Hertz vs Accenture lawsuit, failed software projects cost millions of dollars, and while they often present an opportunity for companies like NearForm to enter stage right and clear up, they're not ideal – for anyone. These failures aren’t just a matter of missed deadlines or lost revenues: the recent Boeing crashes, for instance, were directly traced to software failures.\n\nSoftware can do better. Our industry as a whole must do better.\n\nThe official figures are horrific: the most recent Standish Group Report outlines a mere 29% success rate for software projects, and those are only the official statistics; the unofficial or unreported numbers are probably much worse. The inability to execute on time and within budget is a crisis of the modern software industry.\n\nWhat went wrong in this instance?\n\nWhile it’s easy to look at that lawsuit and pick apart the individual components, the root problem comes down to the client deciding to outsource a core competency – the redevelopment of the central piece of e-commerce software its business heavily relies on – instead of taking active ownership and responsibility for its development. Some things are just too important to entirely hand over to a service provider.\n\nThe company may need to bring in external help with such a digital transformation in order to carry out the project internally, but it’s not always wise to outsource to an external vendor in its entirety. Instead, bring in expert help where you need it; experts who don't want you to leave it all to them, experts that can not only help you build your own capability and help with capacity but also to strategically advise you on executing your Digital Strategy.\n\nStarting out on the right foot: Discover, Deliver, Transition\n\nIn a nutshell, what most enterprises need is not a stop-gap but a deeper engagement that helps to build up their own capability and lays the foundations for continuous innovation and growth within the organisation. When we do this ourselves, we work very closely with the client to design, build, and then transfer or transition the working system back to the client. This ‘Discover, Deliver, Transfer’ process allows the client to build up its own store of modern, software development DNA inside its four walls. Rather than giving money to a vendor to develop the entire thing behind closed doors, focus on a deeper engagement that builds up your own capability.\n\nMy instinct is that many organisations do have a strong internal software development capability, we see this first hand. However, lack of trust and internal politics are common key factors that trigger the decision to fully outsource – and external consultants, in a sad pattern that's often repeated, were more likely to be listened to and trusted than the company's own personnel.\n\nI also suspect that complicating factors were at work: once the systems integrator went under the hood with the client, it probably discovered a spaghetti junction of disparate systems that were difficult to work with and refused to interoperate.\n\nLegacy systems and legacy resources\n\nLet me be clear: legacy systems are a reality that we all have to manage, and they can be the downfall of many new digital initiatives. Successful transformation often means you need to work with what’s there; modernising where it makes sense, while also bringing in newer technology and writing new services to meet the requirements of the business.\n\nOn the resourcing side, early on in engagement, it’s important to assess what kind of team is needed, and the extent to which internal resources need to be supplemented with partner resources.\n\nIn some instances, we help clients hire in new permanent staff with the skills needed to develop and operate the finished system once we transfer it back. We've done this very successfully: recently we worked with a client who decided to spin up a new business unit to pursue an innovative concept they wanted to bring to market. On day one, the business unit had no staff; as they hired and grew in the first few weeks and months, we built the product in parallel, augmenting and replacing our team as they found their own key talent.", "A design-led process for transformation\n\nMost, if not all, of our projects, start with a Discovery Phase, following which we develop a high-fidelity prototype in a matter of weeks.\n\nWe put a huge emphasis on architecture (which is often and unfortunately overlooked in many Agile projects), and on understanding the systems we’ll be working with, including the client's legacy systems. The development plan is the second key outcome of the Discovery Phase; what it is we are building, why we are building it, and how we are going to build it.\n\nAfter that, we develop the final outcome of the Discovery Phase - the work plan; a refined view of what's to be done, the resources needed, and the timeline. These are the 3 valuable outputs of the Discovery Phase: the prototype , the architecture and the work plan.\n\nFollowing this, we move on to the Delivery Phase. This is always done quickly, usually in 3 to 6 months. It's a real \"Avengers assemble\" moment where we bring in a team of our very best people to create a Minimal Viable Product (MVP). This involves a close partnership with the Client, often augmenting the team with resources from the client; helping them to build and modernise their software development capability.\n\nA world built on software\n\nIn summary, I want to reiterate that clients cannot afford to completely outsource any core competency; and I'd argue that software development is absolutely a core competency - even if you are not a software company. Any large or global organisation has software resources, but it may not have a modern and up-to-date capability, or may even be struggling with capacity. That's what it needs to work on. Companies can't simply throw all that responsibility over the fence to a systems integrator, especially where the end result is one the company hopes will create new innovative business models, or will offer a differentiating customer experience.\n\nThe final part of the NearForm process is the Transition Phase. Here we transition responsibility back to the client for the software we have co-created, in a phased, controlled and timely fashion. We are accountable to the client right up until the very final transfer, and thereafter we are always available for further collaboration.\n\nWe want to see you, our client, thriving and using the systems we built together. We want you to be capable of adding your own new features as your business thinks of new opportunities and other business models it wants to pursue.\n\nAny piece of software and any organisation must be able to evolve. Embracing that idea, and transforming your own software development capability is the best way to ensure competitiveness into the future.\n\nLet's make those systemic software failures a footnote of history. And let's see software development partners and enterprises working together to make that happen. Damian Beresford is Technical Director of NearForm, and partners with organisations across the globe to help them achieve sustainable innovation through the design & delivery of open software, methodologies and technologies.\n\n If you’d like to understand how we can help you stay relevant & scale to demand, contact us for an exploratory review and feel free to connect with Damian on LinkedIn." ], "categories": { "primary": "backend", "others": [ "devops", "cloud", "product" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-how-can-you-create-an-environment-where-innovation-accelerates": { "href": "https://nearform.com/insights/how-can-you-create-an-environment-where-innovation-accelerates", "postType": "blog", "slug": "insights-how-can-you-create-an-environment-where-innovation-accelerates", "date": "2019-06-28", "title": "How can you create an environment where innovation accelerates?", "authors": [], "content": [ "Overcoming the Challenges that come with Accelerated Innovation\n\nWhen innovation disrupts existing delivery models or other aspects of a company's status quo, that can be uncomfortable. But getting innovation right is imperative for enterprises who want to survive the current seismic changes and emerge steady, strong, and more customer-focused than ever.\n\nDuring our recent webinar, Creating an Environment for Accelerated Innovation , I was lucky to get a chance to discuss this issue with Gordon Suttie of EY and our own Conor O’Neill. How can enterprises face the challenges of innovation in an intrepid way, and deliver value for themselves and their customers, when it might involve changes that cause discomfort in the short term?\n\nTackling innovation on all three fronts\n\nThe good news is that, although large organizations across industries find innovation challenging, there are lessons to be learned from those who have successfully pioneered new products and services, in new markets using new tools.\n\nAs we heard from Gordon, that sort of innovation is what is termed transformational innovation: moving beyond the optimisation of existing products for existing customers, and beyond the pursuit of new lines of business, to achieve actual breakthrough innovation, defined as creating totally new offerings for new markets and new customers. But there are three varieties of innovation - Core innovation, Adjacent innovation, and Transformational innovation - as Gordon explained, and it's possible for an organisation to manage itself through these three kinds of innovation in a way which will let it achieve truly novel products and services, without killing its core product.\n\nGordon cited Nagji and Tuff's writing from Harvard Business Review on this illuminating analysis of innovation types and what each type means for the organization.\n\nGordon's key point was that an organisation must work on all three of these \"horizons\" simultaneously, and with different teams and resources, so that it nibbles away at the innovation challenge at all three levels, rather than focusing exclusively on just one kind of innovation and placing all its bets there.\n\nIt's a strong example of transformational innovation, and he shares frank insights about pitfalls and lessons learned, including the need to resist the temptation to simply \"digitize\" what an organization is already doing today. It’s imperative to centre everything around customer need, to ensure that what's being developed meets that need instead of basing innovation on the HIPPO concept (the Highest-Paid Person’s Opinion; their view about what customers need can't supplant feedback from customers themselves).\n\nA performance mindset is everything in innovation\n\nConor talked about the need for enterprises to approach any innovation project with a performance mindset. Conor discusses the value of taking a design-workshop driven approach where – similar to Gordon's point – the focus is on the customer problem.\n\nSometimes it involves questioning things that already exist and really getting to the heart of the market-facing objective. With a focus on performance , this can deliver efficiency benefits not just for the users internally but for the customers themselves. Conor cites an example to illustrate what he means: if the company is using a suite of spreadsheets to (inefficiently, unscalably) power a business process, it should ask itself what customer need those spreadsheets were really designed to solve. This may often lead to developing a solution - such as a cloud-native, web-based app - that allows customers to self-serve and enjoy a better experience .\n\nConor also gave an in-depth look at why open source is so valuable to innovation initiatives, delivering targeted capabilities, sourced from the world's largest population of skilled and passionate developers, that fit precisely with what an enterprise is trying to achieve.\n\nThe focus, Conor argues, for any innovation initiative must be to achieve true transformation: an enterprise truly wins when it doesn't just aim to catch up with the market or be a fast follower, but when it adopts performance as a philosophy and everything that entails.\n\nFrom project to product\n\nDuring the panel discussion, the topic turned to what Gordon described as moving from a \"project mindset\" to a product mindset. With a product mindset, Gordon argues, the organisation thinks chiefly about the customer and their needs.\n\nThis isn't just about customer-centred design, but about drawing on all parts of an organisation and their skill sets in order to focus 100% on finding the best solution to a customer problem. That means pulling in expertise from the organisation’s engineering team, the business side, actual customers, and designers, where everyone discusses and analyses true customer requirements and the best way to meet those.\n\nA project mindset, on the other hand, can often kill innovation initiatives: this is a mindset that sets metrics for success in advance and commits rigidly to those before the real work begins. On the contrary, a product mindset doesn't decide in a fixed way what success will look like but defines success based on what the team learns during the innovation process. With a product mindset, the entire team sees and agrees what must be developed next, based on lessons and insights they’ve all learned.\n\nThis led to the topic of DevOps and how it is vastly misunderstood in many organisations yet its role in accelerating innovation is crucial. The problem comes down to organisations who think that if they hire people with the title DevOps engineer or invest in some DevOps tooling that this is going to solve any bottlenecks and improve their IT delivery model. But that is not so. Whilst DevOps practices are expected to become as disruptive to IT as lean was to manufacturing during the 1980s, it will take business leaders to understand and IT leaders to adopt DevOps methodologies rather than just sets of tools and buzzwords.\n\nTo sum up the key message from the discussion: the best innovation projects, which achieve true transformation, don’t just deliver a great customer experience, but also build and change the core capabilities of the organization itself.\n\nHead over here to listen to the webinar in full and see what your key takeaways are.\n\nI’d like to thank Gordon Suttie for joining Conor and me on the webinar and we also thank Global Business Intelligence for hosting the event." ], "categories": { "primary": "product", "others": [ "work", "devops" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-speed-up-react-ssr-performance": { "href": "https://nearform.com/insights/speed-up-react-ssr-performance", "postType": "blog", "slug": "insights-speed-up-react-ssr-performance", "date": "2019-07-04", "title": "Speeding Up React SSR with ESX: Tech Talk Video", "authors": [], "content": [ "Overcoming React Performance Bottlenecks\n\nReact is a hugely popular frontend framework that revolutionized the frontend development world. React is built primarily for the browser, while Node has fundamentally different operational constraints to the browser.\n\nAs a Principal Architect and Consultant it has become painfully clear that React's Server-Side Rendering is a performance bottleneck for web backends around the world.\n\nDuring this Lightning talk David will share and demonstrate a very simple solution that can be dropped into pre-existing React applications to significantly improve Server-Side Rendering throughput.\n\nDavid Mark Clements is a Principal Architect, fullstack/React and Node.js performance specialist and the author of Node Cookbook. He is currently serving as Principal Architect with NearForm.\n\nLearn more about our React development and design services Need help with React and Node for your next project? Contact us today to see how we can help!" ], "categories": { "primary": "frontend", "others": [ "perf" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-streamless-future-with-javascript-async-iterators-and-generators": { "href": "https://nearform.com/insights/streamless-future-with-javascript-async-iterators-and-generators", "postType": "blog", "slug": "insights-streamless-future-with-javascript-async-iterators-and-generators", "date": "2019-07-04", "title": "Streamless Future with JavaScript Async Iterators and Generators: Tech Talk Video", "authors": [], "content": [ "There was a time when Node.js streams were all the rage but over time the Node.js Core Streams codebase became extremely complex and hard to understand. Worse still, WHATWG introduced an API for browser Streams. The two Streams API’s are incompatible with each other and both are complex and leaky.\n\nIn this talk, a Node.js Core Streams maintainer presents a stream-less future by demonstrating how to use pure JavaScript: Async Iterators and Generators can give us everything Streams can while being completely cross-platform and highly performant.\n\nAs a Technical Director at NearForm, Matteo Collina consults for some of the top brands of the world. Matteo is a member of the Node.js Technical Steering Committee focusing on streams, diagnostics and http. He is also the author of Node.js MQTT Broker, Mosca, the fast logger Pino and of the Fastify web framework.\n\nThis talk was given at WorkerConf , the Javascript community event in Dornbirn Austria, in June 2019.\n\nVideo credit: WorkerConf YouTube" ], "categories": { "primary": "backend", "others": [ "frontend" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-high-performance-data-architecture": { "href": "https://nearform.com/insights/high-performance-data-architecture", "postType": "blog", "slug": "insights-high-performance-data-architecture", "date": "2019-07-09", "title": "The importance of high-performance data architecture.", "authors": [], "content": [ "A conversation with Conor O'Neill about high-performance data architecture\n\nConor O’Neill, Chief Product Officer at NearForm, recently spoke to the IT Directors Forum in the UK on how a high-performing data architecture can drive overall business performance and value - and what characteristics that architecture most needs. Below is a synopsis of the interview.\n\nData Performance in Organisational Digital Transofrmation\nThe philosophy of embracing performance can be applied to people, processes, and technology. It goes far beyond just code.\nThis philosophy is gaining importance because of the digitalisation across all industries that is transforming the way we manufacture, learn, communicate, work and do business as well as the role of data as a driver of growth.\nPerformance must be at the top of the list in any digital transformation, much like security.\nImportance of a high-performing data architecture\nBusinesses can't be high-performing unless their data architecture is.\nData needs to be fast and available to whoever needs it whenever they need it.\nYou should be able to access the data you need immediately and always.\nExamples of Data Performance\nImproving processes\nWe helped a company turn a commonly-executed business process from a 45 minute task into a 5 minute task.\nThis required everyone involved, both client-side and NearForm side, to agree that this performance metric was the focus.\nEventhough all the data the workflow used was computerised a combination of legacy issues and processes contributed to the time-intensity of the task.\nShopping Experience\nOffering a personalised experience at checkout on modern shopping websites requires pulling in data from various systems.\nIntegrating that data becomes complex if those systems have come into your organisation through companies you've acquired, separate business units, or outside partners.\nThe data coming in from all these different sources may be wildly different based on numerous factors.\nThe complexity of getting all the data you need can be a nightmare to implement and cause serious strain on your systems even if the end product appears slick and personalised.\nTools like GraphQL help to take out that complexity by wrapping up all of the different APIs and systems and delivering only the data required at a given moment.\nThis makes it much easier for the whole team, including front-end developers, to deliver an excellent and consistent customer experience\nFast data delivers a faster experience.\nMoving from Big Data to Fast Data\nIn data architecture the move to fast data is happening because it's all about performance.\nFor example Conde Nast International had both a big data and fast data problem within their data architecture.\nFocusing on speed and performance helped us realise the best solution.\nWe migrated decades of content from multiple territories into a single CMS in a timely way.\nThis allowed for rapid and accurate transition of the content\nThe solution we developed together allowed them to achieve this much faster and with 99.9% accuracy.\nThis sped up the entire modernisation.\nTheir goal was to deliver their content across devices in a more consistent and reliable manner.\nThe better, high-performance data-architecture translated to more agility.\nHigh-performance Data Architecture and Business Goals\nA high-performance data architecture unleashes new business opportunities.\nFirst, you need the data with context in order to give it value.\nA high-performance data architecture can help you visualise new concepts for your business as well as new products for customers.\nIn Banking, PSD2 requirements are causing many organisations to modernise access to their customer data.\nThis is creating new ways to acquire customers as well as new services they can offer.\nCustomers want personalisation and speed.\nThe speed part of the equation relies on data that is available in context and real time.\nA high-performance data architecture is capable of delivering that speed and differentiates the best applications from the rest of the pack\nBetter-performing data architecture: how to get there\nMake sure data is understandable to those who are using it.\nUse visualisations.\nKnow your audience.\nUnderstand that simple user experiences are hard to deliver.\nImportance of Data Visualisations\nData Visualisations that are transformative can be viral.\nThe ability to show actionable insights and value will spread throughout your organisation.\n\nConor O'Neill is Chief Product Officer at NearForm and is responsible for all productization activities and works closely with NearForm’s Open Source and R&D teams to evolve the web platform. Some of the projects he has responsibility for in NearForm are Clinic.js and the NodeConf EU Digital badge.\n\nFeel free to connect with him on LinkedIn." ], "categories": { "primary": "data", "others": [ "perf", "cloud" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-how-to-use-graphql-in-react-using-hooks": { "href": "https://nearform.com/insights/how-to-use-graphql-in-react-using-hooks", "postType": "blog", "slug": "insights-how-to-use-graphql-in-react-using-hooks", "date": "2019-07-18", "title": "How to use GraphQL in React using hooks", "authors": [], "content": [ "What are Hooks?\n\nReact Hooks , introduced in version 16.8.0, are reusable stateful logic functions. They aim to simplify the development of complex components by splitting them into small functional blocks that are easier to manage, test and reuse.\n\nUsing hooks removes the need for many abstractions like Higher Order Components (HOC) and render props. They allow you to add functionality to the application without having to change the component hierarchy and without having to encapsulate components.\n\nAlso, it often makes the code more readable and maintainable.\n\nAs an example, here is a simple React clock component written using classes:\n\nimport React from 'react'\n\nclass Clock extends React.Component {\n constructor(props) {\n super(props)\n this.state = {date: new Date(), interval: 0}\n }\n\n render() {\n return (\n
\n

Hello, world!

\n

It is {this.state.date.toLocaleTimeString()}.

\n
\n )\n }\n\n componentDidMount() {\n const interval = setInterval(() => {\n this.setState({date: new Date()})\n }, 1000)\n\n this.setState({interval})\n }\n\n componentWillUnmount() {\n clearInterval(this.state.interval);\n }\n}\n\n\nAnd here the same component is written using hooks:\n\nimport React from 'react'\n\nfunction Clock() {\n const [date, setDate] = React.useState(new Date())\n\n React.useEffect(() => {\n const interval = setInterval(() => {\n setDate(new Date())\n }, 1000)\n\n return () => clearInterval(interval)\n }, [])\n\n return (\n
\n

Hello, world!

\n

It is {date.toLocaleTimeString()}.

\n
\n )\n}\n\n\nIn our example, both useState and useEffect are React hooks.\n\nWhat is GraphQL?\n\nGraphQL is a data query language designed for API. The language is meant to be declarative, strongly typed and exhaustive.\n\nThe design has two main types of operations: queries and mutations. The former is used when retrieving data, the latter for updating data.\n\nAnother important improvement of GraphQL is that multiple operations can be sent and retrieved using a single endpoint (usually /graphql) and a single network request. This reduces the number of roundtrips and overall data transfer, which is very important on mobile devices and bad network situations.\n\nHere's an example of a GraphQL mutation which adds a new user (and chooses which field to get a result):\n\nmutation CreateUser($name: String!){\n createUser(name: $name) {\n name\n }\n}\n\n\nAnd here's an example of a GraphQL query which gets the list of users:\n\n{\n users {\n name\n }\n}\n\nIntroducing graphql-hooks\n\nIn order to use GraphQL in a React application using hooks, we are going to use graphql-hooks , a small library with hooks support and optional Server-Side Rendering and caching support.\n\nHere's an example of how a real-world component might look like:\n\nimport { useQuery } from 'graphql-hooks'\n \nconst HOMEPAGE_QUERY = `query HomePage($limit: Int) {\n users(limit: $limit) {\n id\n name\n }\n}`\n \nfunction MyComponent() {\n const { loading, error, data } = useQuery(HOMEPAGE_QUERY, { variables: { limit: 10 } })\n \n if (loading) return 'Loading...'\n if (error) return 'Something Bad Happened'\n \n return (\n
    \n {data.users.map(({ id, name }) => (\n
  • {name}
  • \n ))}\n
\n )\n}\n\nGetting started on the server\n\nTo get started, let's create an application server which serves a React application.\n\nconst appShellHandler = require('./handlers/app-shell')\n\nfunction main() {\n const app = fastify({\n logger: true\n })\n\n app.register(require('fastify-static'), {\n root: path.join(process.cwd(), 'build/public')\n })\n\n app.register(graphqlPlugin)\n\n app.get('/', appShellHandler)\n app.get('/listUsers', appShellHandler)\n\n app.listen(3000)\n}\n\nmain()\n\n\nThe app-shell.js file is responsible for Server Side Rendering, the initial version injects the Javascript file created by webpack inside a bare metal HTML page:\n\nconst { getBundlePath } = require('../helpers/manifest')\n\nfunction renderHead() {\n return `\n \n \n \n `\n}\n\nasync function renderScripts() {\n const appShellBundlePath = await getBundlePath('app-shell.js')\n return `\n <script src=\"${appShellBundlePath}\"></script>\n `\n}\n\nasync function appShellHandler(req, reply) {\n const head = renderHead()\n const scripts = await renderScripts()\n\n const html = `\n ${head}\n
\n ${scripts}\n `\n reply.type('text/html')\n return html\n}\n\nmodule.exports = appShellHandler\n\n\nThe graphql.js file is where our tutorial will focus on. Here's the starting version:\n\nconst fastifyGQL = require('fastify-gql')\n\nconst userList = [\n {\n name: 'Brian'\n },\n {\n name: 'Jack'\n },\n {\n name: 'Joe'\n },\n {\n name: 'Kristin'\n }\n]\n\nconst schema = `\n type User {\n name: String\n }\n\n type Query {\n users: [User]\n }\n`\n\nconst resolvers = {\n Query: {\n users() {\n return userList\n }\n }\n}\n\nfunction registerGraphQL(fastify, opts, next) {\n fastify.register(fastifyGQL, {\n schema,\n resolvers,\n graphiql: true\n })\n\n next()\n}\n\nmodule.exports = registerGraphQL\njsCopy to clipboard\n\nThe GraphQL adapter we chose on the server is Mercurius . We evaluated other solutions but it had higher performances, as you can see in the comparison below.\n\nBefore moving on, let’s analyze the options passed to the adapter.\n\nThe very first thing to define when creating a GraphQL API is the schema. The schema must define all the queries, mutation and types supported by the API. In particular, Query and Mutation are considered “entry-point” types and of them should be present in every schema.\n\nIn our case, we define only Query (for now) and we define a single query, users, which will return a list (which is denoted using square brackets) of User. The User is the only other type in the schema, which contains a single string field called name. As you might wonder, GraphQL is language-agnostic, so the definition of language syntax tries to be similar to most used languages.\n\nOnce we have the schema ready, we need to pass the resolvers. As the name might suggest, resolvers is a Javascript mapping object which allows the adapter to map GraphQL queries or mutation to real application call. In our case, when performing the users GraphQL query (which we can rewrite using the dotted notation as schema.Query.users) it will execute the resolvers.Query.users (note that the path is the same) and the return value will be the result of the query.\n\nIn our example, we also passed the graphiql option set to true. This will add graphiql (note the i ), an in-browser IDE for GraphQL to the server, at the /graphiql route.\n\nGetting started on the client\n\nThe initial version of the client application is very simple: only two routes, one of them is a simple \"hello world\" one. Let's see what they look like.\n\nHere's the application main file:\n\nimport React from 'react'\nimport { Link, Router } from '@reach/router'\n\n// components\nimport ListUsers from './pages/ListUsers'\n\nfunction HelloWorld() {\n return (\n
\n

Hello World

\n
\n )\n}\n\nclass AppShell extends React.Component {\n render() {\n return (\n
\n \n Hello World |{\" \"}\n List Users )\n }\n}\n\nAppShell.propTypes = {}\n\nrender(AppShell, document.getElementById('app-root'))\n\n\nAnd here’s the initial version of the ListUsers route:\n\nimport React, { useState } from 'react'\n\nconst users = [\n { name: 'John' },\n { name: 'Sally' }\n]\n\nexport default function ListUsers() {\n const [name, setName] = useState('')\n\n function createNewUser() {\n users.push({name})\n setName('')\n }\n\n return (\n
\n

Users List

\n
    \n {users.map((user, i) =>\n
  • {user.name}
  • \n )}\n
\n \n \n
\n )\n}\n\n\nAs you can see, the first version already uses hooks, but it's not connected to GraphQL. Yet. Let's fix this!\n\nAdd a mutation to persist the data\n\nIn order to let the client update persisted data, we first have to modify the server.\n\nLet's start by adding a mutation to our schema and resolvers in graphql.js:\n\nconst schema = `\n type User {\n name: String\n }\n\n type Query {\n users: [User]\n }\n\n type Mutation {\n createUser(name: String!): User\n }\n`\n\nconst resolvers = {\n Query: {\n users() {\n return userList\n }\n },\n Mutation: {\n createUser(_, user) {\n userList.push(user)\n return user\n }\n }\n}\njsCopy to clipboard\n\nThe server is now able to handle a GraphQL mutation, which is the only way to modify the data.\n\nThis can be tested in graphiql by running this operation:\n\nmutation CreateUser($name: String!){\n createUser(name: $name) {\n name\n }\n}\n\n\nMake sure you don't forget to pass the operation variables:\n\n{\n \"name\": \"John\"\n}\njsCopy to clipboard\n\nAnd then you can verify that the data has been persisted by running the following query:\n\n{\n users {\n name\n }\n}\njsCopy to clipboard\nClose the loop: connect the client\n\nAs said earlier, the first implementation of the ListUsers route was only storing data in browser memory without using the server at all.\n\nSince the server is now capable of persisting data, let's connect it to the client.\n\nFirst, let's modify the main application file to instantiate a graphql-hooks client and add the context provider to the application:\n\nimport React from 'react'\nimport { Link, Router } from '@reach/router'\nimport { ClientContext, GraphQLClient } from 'graphql-hooks'\n\n// ...\n// Components definitions unchanged\n// ...\n\nconst client = new GraphQLClient({ url: '/graphql' })\n\nconst App = (\n \n \n \n)\n\nrender(App, document.getElementById('app-root'))\n\n\nThen, modify the route to use the useQuery and useMutation hook. Here's how the new ListUsers route will look like:\n\nimport React, { useState } from 'react'\nimport { useQuery, useMutation } from 'graphql-hooks'\n\nconst LIST_USERS_QUERY = `\n query ListUsersQuery {\n users {\n name\n }\n }\n`\nconst CREATE_USER_MUTATION = `\n mutation CreateUser($name: String!) {\n createUser(name: $name) {\n name\n }\n }\n`\n\nexport default function ListUsers () {\n const [name, setName] = useState('')\n\n const {\n data = { users: [] },\n refetch: refetchUsers\n } = useQuery(LIST_USERS_QUERY)\n\n const [createUser] = useMutation(CREATE_USER_MUTATION)\n\n async function createNewUser() {\n await createUser({ variables: { name } })\n setName('')\n refetchUsers()\n }\n\n return (\n
\n

Users List

\n
    \n {data.users.map((user, i) =>
  • \n {user.name}\n
  • )}\n
\n \n \n
\n )\n}\n\n\nThere are many values returned by the useHook query, but for now, let's focus on the main ones. data contains the results of the query returned by the server, while refetch is a callback that enables the client to ask for a data refresh on-demand.\n\nThe useMutation hook instead simply returns an async function which will trigger a mutation on the server.\n\nNotice that the component uses both React Hooks (useState) and graphql-hooks hooks. This is an example of where the hooks approach makes it really simple to add new functionality to components (even via external libraries) without having to reorganize the component hierarchy.\n\nAnd there it is: a fully working client-server application using GraphQL and React hooks.\n\nPagination\n\nSo far, the users GraphQL has returned all the users stored in the system. As you might imagine, this is not useful in the real world where you usually have thousands or millions of them. So, let's implement pagination.\n\nTo achieve this, we are going to use a mechanism you have already seen: query variables. If you look at the createNewUser method above, you will notice that it passes variables to the mutation. This is also possible for queries.\n\nLet's start by modifying the schema and the resolvers in the graphql.js file of the server:\n\nconst schema = `\n type User {\n name: String\n }\n\n type Query {\n users(skip: Int, limit: Int): [User]\n }\n\n type Mutation {\n createUser(name: String!): User\n }\n`\n\nconst resolvers = {\n Query: {\n users (_, { skip = 0, limit }) {\n return limit ? userList.slice(skip, skip + limit) : userList.slice(skip)\n }\n },\n Mutation: {\n createUser(_, user) {\n userList.push(user)\n return user\n }\n }\n}\njsCopy to clipboard\n\nAs you can see, the user's query is now parameterized. That's all we need to modify on the server, so let's switch back on the client.\n\nLet's create a new PaginationPage, which will be rendered under the /users path.\n\nimport React, { useState } from 'react'\nimport { useQuery } from 'graphql-hooks'\n\nconst USERS_QUERY = `\n query UsersQuery($skip: Int, $limit: Int) {\n users(skip: $skip, limit: $limit) {\n name\n }\n }\n`\n\nexport default function PaginationPage() {\n const [page, setPage] = useState(1)\n const { data } = useQuery(USERS_QUERY, { variables: { limit: 1, skip: page - 1}})\n\n return (\n
\n

Pagination

\n
    \n {data &&\n data.users &&\n data.users.map((user, i) =>\n
  • {user.name}
  • \n )}\n
\n \n \n
\n )\n}\n\n\nOnce again, we mix up React and GraphQL hooks in order to implement our component.\n\nThe biggest change is on useQuery call, where we now pass query variables.\n\nFinally, we can add the page to the client application index:\n\n// ...\nimport PaginationPage from './pages/PaginationPage'\n// ...\n\nclass AppShell extends React.Component {\n render() {\n return (\n
\n \n Hello World |{\" \"}\n List Users\n PaginationPage\n )\n }\n}\n\n\nLet's also add it to the server index for SSR:\n\n// ...\n\nmodule.exports = () => {\n const app = fastify({\n logger: true\n })\n\n app.register(require('fastify-static'), {\n root: path.join(process.cwd(), 'build/public')\n })\n\n app.register(graphqlPlugin)\n\n app.get('/', appShellHandler)\n app.get('/listUsers', appShellHandler)\n app.get('/users', appShellHandler)\n\n app.listen(3000)\n}\njsCopy to clipboard\n\nCaching\n\nTo ensure the best user experience, we don't want to make server queries that we already performed, we should use caching.\n\ngraphql-hooks has support for custom caching plugins which solve this problem for us.\n\nIn this example, we are going to use the graphql-hooks-memcache plugin.\n\nDespite what the name suggests, this plugin is not a server plugin backed by MemCache storage, but it is a client plugin which caches every operation by creating a hash of it. The cache is held in memory using a Least Recently Used (LRU) policy.\n\nTo use it, simply pass it the client application main file when instantiating the graphql-hooks client:\n\n// ...\n\nimport memCache from 'graphql-hooks-memcache'\nconst client = new GraphQLClient({ url: '/graphql', cache: memCache() })\n\n// ...\njsCopy to clipboard\n\nThat's it, it’s that simple!\n\nSSR\n\nThe last step of this tutorial to have a fully working real-case example is to hook up graphql-hooks in a server-side rendered (SSR) application.\n\nDoing this will allow the same client code to be reused on the server to return fully rendered pages. This improves browser boot and time to be interactive time and also improves search engine optimisation.\n\nAlso, by using state passing and rehydration, we can make sure no cache miss happens on the client after initial loading.\n\nTo get started, we are going to modify the client initialization to use isomorphic-unfetch . This enables fetch support on server (Node.js) and polyfills on the client if needed.\n\nThe newly modified server app shell will look like this:\n\nimport React, { useState } from 'react'\nimport { useQuery, useMutation } from 'graphql-hooks'\n\nconst LIST_USERS_QUERY = `\n query ListUsersQuery {\n users {\n name\n }\n }\n`\nconst CREATE_USER_MUTATION = `\n mutation CreateUser($name: String!) {\n createUser(name: $name) {\n name\n }\n }\n`\n\nexport default function ListUsers () {\n const [name, setName] = useState('')\n\n const {\n data = { users: [] },\n refetch: refetchUsers\n } = useQuery(LIST_USERS_QUERY)\n\n const [createUser] = useMutation(CREATE_USER_MUTATION)\n\n async function createNewUser() {\n await createUser({ variables: { name } })\n setName('')\n refetchUsers()\n }\n\n return (\n
\n

Users List

\n
    \n {data.users.map((user, i) =>
  • \n {user.name}\n
  • )}\n
\n \n \n
\n )\n}\n\n\nThe main modification is the introduction of the same GraphQL client on the server, with slightly different options: first, we have to specify the full client URL, then we have to specify the fetch method to use.\n\nThen we use getInitialState from graphql-hooks-ssr in order to get the state to send to the client, rendered as serialized JSON inside the renderScripts function.\n\nOnce the server is ready, let's modify the client. We have to modify the application main file in order to account for the initialState of the cache and the rehydration of the server-side rendered page.\n\n// ...\n\nconst initialState = window.__INITIAL_STATE__\nconst client = new GraphQLClient({\n url: '/graphql',\n cache: memCache({ initialState })\n})\n\nconst App = ( \n \n \n \n)\n\nhydrate(App, document.getElementById('app-root'))\n\n\nThe main modification are passing the initialState to the cache plugin and to replace the react-dom render with hydrate.\n\nConclusions\n\nAs shown in this post, graphql-hooks is a powerful package to easily add GraphQL to your React application using a very easy to use approach. Also, its plugin-based approach makes it very trivial to add complex features like caching and SSR without any cumbersome abstractions and without revolutionizing your components or application structure.\n\nIf you want to see the full application, you can check it out on GitHub , we use it as part of a workshop exercise for graphql-hooks .\n\nAt NearForm, we have vast experience in building solutions across a broad tech stack to deliver reduced complexities and overcome common hurdles. If you are creating modern applications and leveraging web technologies, contact us to learn more about how we can help. You might also like some of our previous blog posts on React:\n\nManaging React state with Render Props\n\nExploring React Portals\n\nSharing React components with Lerna" ], "categories": { "primary": "frontend", "others": [ "backend", "ai" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-a-new-way-to-profile-node-js-matteo-collina": { "href": "https://nearform.com/insights/a-new-way-to-profile-node-js-matteo-collina", "postType": "blog", "slug": "insights-a-new-way-to-profile-node-js-matteo-collina", "date": "2019-08-03", "title": "A New Way to Profile Node.js: Tech Talk Video", "authors": [], "content": [ "Identifying bottlenecks in Node.js and beyond\n\nIt’s been weeks and the organization you work for seems to be slowly turning against you. At least that’s what it feels like. User experience is poor because of slow API’s, sales are being missed, performance-linked SEO heuristics are causing a drop in page ranking. Mobile users have all but given up. Operations have reported that a critical Node.js service owned by your team is spinning at 70-100% CPU, and all parts of the application dependent on the service are experiencing intermittent slowdowns or in some cases, complete unavailability. What are you going to do now?\n\nIn this talk Matteo Collina will share with you a new and straightforward way to identify bottlenecks in Node.js and beyond.\n\nAs a Technical Director at NearForm, Matteo Collina consults for some of the top brands of the world. Matteo is a member of the Node.js Technical Steering Committee focusing on streams, diagnostics and http. He is also the author of Node.js MQTT Broker, Mosca, the fast logger Pino and of the Fastify web framework.\n\nThis talk was given at QCon London 2019 , brought to you by InfoQ.\n\nNeed Node experts for your next project? Contact us today to see how we can help!" ], "categories": { "primary": "perf", "others": [ "backend", "devops" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-input-smoothing": { "href": "https://nearform.com/digital-community/input-smoothing", "postType": "blog", "slug": "digital-community-input-smoothing", "date": "2019-08-16", "title": "Input Smoothing: An Intro To Reactive Animations", "authors": [ "MAX YINGER" ], "content": [ "Demo Link | Code Link\n\nToday we’re going to explore the concept of input smoothing as an introduction to reactive animations. So what exactly do I mean by reactive animations? For this article, we’ll use the term to describe animations that have no set endpoint, but instead react to a steady stream of incoming values.\n\nI find these animations particularly useful for components that require an animation layer on top of an interaction like dragging, scrolling, mousemove, and swiping. Specifically, in this article, we’ll focus on mousemove and those little circles you’ve seen following the cursor in certain eye-catching interactive sites like the ones seen below:\n\nhttps://www.giacomomottin.com/\n\nhttp://renvoye.com/\n\nPrerequisites\n\nSo I’m certainly not a die-hard when it comes to functional programming, but I do think some concepts from it can be quite useful in certain places. In this tutorial we’ll make heavy use of factory functions to create an rx-like pattern. We may even dabble in some currying here and there as well.\n\nIf you’re not familiar with these concepts, MPJ of Fun Fun Function has a wonderful series on functional programming in JavaScript here, specifically talking about factory functions and currying.\n\nThe End Result\n\nBy the end of this article we’ll have a nice little circle smoothly following your cursor used like the example seen below:\n\nconst App = () => {\n const smoothedMouse = useMemo(() => {\n return smooth({x: 0, y: 0}).start(({ x, y }) => {\n document.body.style.setProperty(‘--mouse-x’, x);\n document.body.style.setProperty(‘--mouse-y’, y);\n });\n }, []);\n\n const updateCursorPosition = e => {\n smoothedMouse.update({\n x: e.clientX,\n y: e.clientY,\n });\n }\n\n useEffect(() => () => smoothedMouse.stop(), []);\n\n return (\n
\n
\n
\n );\njsCopy to clipboard\n\nCodepen Example: https://codepen.io/littlemilk/pen/ZgvJym\n\nIf you’re familiar with popmotion, you’ll notice the api for our smooth() is quite similar. Matt Perry, the creator of popmotion, has some excellent blog posts and musings on animations as well at https://inventingwithmonster.io/\n\nOverview\n\nTo create this smooth object we’re going to need three parts:\n\nThe Request Animation Frame Loop — This loop will call some logic on every frame.\nThe Scan — This object will scan over a series of values and save some information between iterations. We’ll also expose a next() method here that we can use to schedule the next iteration.\nThe Lerp — This will be the function we’ll pass into our scanner to compute the next step on every iteration.\nThe Request Animation Frame Loop\n\nrequestAnimationFrame(), commonly abbreviated to rAF, is the native method our browser provides to us to execute some logic when the next frame is rendered. We’re going to create an object that recursively calls this and executes some listener on every frame.\n\nTo start I always like to think about what methods we’ll need, then the necessary state we’ll need to store between those methods. First off, our rAF() implementation will need a start() method that allows us to add a listener and start listening on every iteration of the loop:\n\nconst rAF = () => {\n const start = listener => {\n // @TODO initiate loop\n }\n\n return {\n start\n }\n}\njsCopy to clipboard\n\nNext let’s create the loop() method for internal use. This will be our point of recursion. To keep this method’s definition clean, let’s store our listener. I like to store necessary data, inside the closure, in a state object to make it clear where everything lives, so let’s do that!\n\nconst rAF = () => {\n const state = {\n listener: () => {}\n };\n\n const loop = timeStamp => {\n state.listener(timeStamp);\n requestAnimationFrame(timeStamp => {\n loop(timeStamp)\n });\n };\n\n const start = listener => {\n state.listener = listener;\n loop(performance.now());\n }\n\n return {\n start\n }\n}\njsCopy to clipboard\n\nAs you can see, our loop function calls our listener, then requests itself to be called again on the next animation frame. For now we’re passing our listener a timeStamp value. This isn’t relevant to this tutorial as we’re just going to be using rAF() as a scheduler, but will be useful when we get into other methods like physics or tweens in other blog posts.\n\nThe only issue with our current implementation is that we have no method to stop this loop once it has started. If we subscribe to rAF() with a component on mount, when the component unmounts, this loop will still be running. Let’s fix that by having start() return a stop() method:\n\nconst rAF = () => {\n const state = {\n listener: () => {},\n animationFrameId: null\n };\n​\n const stop = () => {\n cancelAnimationFrame(state.animationFrameId);\n };\n​\n const loop = timeStamp => {\n state.listener(timeStamp);\n state.animationFrameId = requestAnimationFrame(timeStamp => {\n loop(timeStamp)\n });\n };\n​\n const start = listener => {\n state.listener = listener;\n loop(performance.now());\n​\n return { stop };\n }\n​\n return { start };\n}\njsCopy to clipboard\n\nAs you can see, requestAnimationFrame() leaves us with a frame id we can keep track of between calls. To escape the loop, we simply cancel the call to the next animation frame.\n\nNow that we have a nice way to listen to the frames, let’s create our logic needed to execute on each frame.\n\nThe Scan\n\nIf you’re familiar with rxjs, you’ll most likely be familiar with the scan operator, but for those of us new to it, it simply allows us to scan over a series of incoming values and track some data between each new value.\n\nOur implementation of scan() will also expose a next() method which will tell our scan when to take the next incoming value. Let’s take a look at what our final result will look like here:\n\nconst scanner = scan((accumulator, v) => {\n return accumulator += v;\n}, 0).start(v => {\n console.log(v);\n});\n\nscanner.next(1) // console logs 1\nscanner.next(1) // console logs 2\nscanner.next(4) // console logs 6\njsCopy to clipboard\n\nNow that you’ve gotten a second to digest what our scan() method does, let’s implement it! First we know that we need to provide a reducer and an initial value to scan(), so let’s set that up:\n\nconst scan = (reducer, init) => {\n const state = {\n accumulator: init,\n reducer: reducer\n };\n}\njsCopy to clipboard\n\nNext, we need to provide a start method that allows us to add a listener to when the accumulator calculates its next iteration:\n\nconst scan = (reducer, init) => {\n const state = {\n accumulator: init,\n reducer: reducer,\n listener: () => {}\n };\n\n const start = listener => {\n state.listener = listener;\n };\n\n return { start };\n}\njsCopy to clipboard\n\nNow that we have a way to listen to each iteration, we need a way to signal the next iteration; let’s add that with a next() method returned by start():\n\nconst scan = (reducer, init) => {\n const state = {\n accumulator: init,\n reducer: reducer,\n listener: () => {}\n };\n\n const next = v => {\n state.accumulator = state.reducer(state.accumulator, v);\n state.listener(state.accumulator);\n };\n\n const start = listener => {\n state.listener = listener;\n return { next };\n };\n\n return { start };\n}\njsCopy to clipboard\n\nNow that we have a fully functioning scan() & rAF(), we can certainly animate, can’t we? Well yes, we can! What we have so far is the basic building blocks of animation!\n\nHowever, we want these animations to be beautiful. To evoke the feeling of cutting butter with a hot knife, just like Neil Young’s voice after drinking a glass of wine; using a simple reducer here my friends, is certainly not that 😬:\n\nCodepen Example: https://codepen.io/littlemilk/pen/KOZyjX\n\nBut not to fear, we’ve done the heavy lifting. Let’s create the last piece of the puzzle and wire this smooth cursor up.\n\nThe Lerp\n\nSo the last dependency of our smooth() object is the lerp. This stands for Linear Interpolation, which does nothing more than given a start, end, and percent, calculates what point we’re at. Here’s a simple example for reference:\n\n// progress is a value between [0-1] \n// lerp(start, end, progress) \n\nlerp(0, 2, 0.5) // result: 1\nlerp(1, 3, 0.5) // result: 2\nlerp(0, 4, 0.75) // result: 3\njsCopy to clipboard\n\nTraditionally we can use this to calculate the progress between two values where the start and end are fixed, and the progress changes from 0-1. However, for this tutorial we’re going to use this function similar to how it’s used in the context of noise smoothing.\n\nIn this application, start and end will be changing & progress will be constant. The Coding Train has an awesome breakdown of using p5.js‘s lerp() to smooth out a series of input values that contain noise here.\n\nAlthough the implementation of lerp in this context is the same as the traditional context, it helps to think about our inputs to the lerp() function differently. In this context, we’ll use it a little more like this:\n\n// roundness is a value between [0-1] \n// lerp(accumulator, target, roundness)\n\nlet accumulator = 0;\nlet target = 10;\nconst roundness = 0.5;\n\naccumulator = lerp(accumulator, target, roundness) // 5\naccumulator = lerp(accumulator, target, roundness) // 7.5\naccumulator = lerp(accumulator, target, roundness) // 8.75\n...\njsCopy to clipboard\n\nIn this implementation, roundness describes how closely the accumulator follows its input source. As the roundness approaches 1, the accumulator will have no smoothing and follow the input source exactly. As roundness gets closer to 0, the accumulator will take more and more lerp iterations to reach the target. The curve will become more and more exaggerated, hence naming this input roundness.\n\nNow that we have a high-level overview, let’s implement our lerp():\n\nconst lerp = (accum, target, roundness) => {\n return (1 - roundness) * accum + roundness * target;\n}\njsCopy to clipboard\n\nThe implementation above is just a fancier version of this easier-to-understand version:\n\nconst lerp = (accum, target, roundness) => {\n const delta = target - accum;\n return accum += delta * roundness;\n}\njsCopy to clipboard\n\nThe advantage of the fancier implementation is that it prevents a floating point error.\n\nNow that we have our base lerp() implementation, let's extend it to work with our point object we’ll be dealing with { x, y }:\n\nconst lerp = (accum, target, roundness) => {\n return (1 - roundness) * accum + roundness * target;\n}\n\nconst pointLerp = (accum, target, roundness) => {\n return {\n x: lerp(accum.x, target.x, roundness),\n y: lerp(accum.y, target.y, roundness)\n }\n};\njsCopy to clipboard\n\nLastly, lets curry some of the inputs so it fits into the reducer() signature for our scanner:\n\nconst lerp = (accum, target, roundness) => {\n return (1 - roundness) * accum + roundness * target;\n}\n\nconst pointLerp = (roundness) => (accum, target) => {\n return {\n x: lerp(accum.x, target.x, roundness),\n y: lerp(accum.y, target.y, roundness)\n }\n};\njsCopy to clipboard\n\nWooh! We’ve gotten through all of our dependencies. Now let’s wire up our smooth object.\n\nSmooth\n\nThis is the object we referenced in the beginning. It will be used like so:\n\nconst smoothCursor = smooth({x: 0, y: 0}).start(({ x, y }) => {\n document.body.style.setProperty(‘--mouse-x’, x);\n document.body.style.setProperty(‘--mouse-y’, y);\n});\n\n// Smoothly animates --mouse-x & --mouse-y css vars to { newX, newY } \nsmoothCursor.update({ newX, newY });\njsCopy to clipboard\n\nTo start, we will need a start() method that lets us listen in on each animation frame. Let’s set that up:\n\nconst smooth = (init, { roundness = 0.1 } = {}) => {\n const state = {\n scan: null,\n loop: null,\n target: init\n };\n\n const start = listener => {\n state.scan = scan(pointLerp(roundness), init).start(listener);\n state.loop = rAF().start(() => {\n state.scan.next(state.target);\n });\n }\n\n return { start };\n}\njsCopy to clipboard\n\nNow that we have something that is smoothly updating to target on every frame, let's add a method that allows us to change the target.\n\nconst smooth = (init, { roundness = 0.1 } = {}) => {\n const state = {\n scan: null,\n loop: null,\n target: init\n };\n\n const update = v => {\n state.target = v;\n };\n\n const start = listener => {\n state.scan = scan(pointLerp(roundness), init).start(listener);\n state.loop = rAF().start(() => {\n state.scan.next(state.target);\n });\n\n return { update };\n }\n\n return { start };\n}\njsCopy to clipboard\n\nWoof, that was simple. The last thing we have to do is expose a method that stops the infinite animation loop. This should be a pretty easy add-in as well:\n\nconst smooth = (init, { roundness = 0.1 } = {}) => {\n const state = {\n scan: null,\n loop: null,\n target: init\n };\n\n const update = v => {\n state.target = v;\n };\n\n const stop => {\n state.loop.stop();\n };\n\n const start = listener => {\n state.scan = scan(pointLerp(roundness), init).start(listener);\n state.loop = rAF().start(() => {\n state.scan.next(state.target);\n });\n\n return { update, stop };\n }\n\n return { start };\n}\njsCopy to clipboard\n\nNice! Now we have a fully functioning input smoother, we can consume it in a cursor component like so:\n\nconst App = () => {\n const smoothedMouse = useMemo(() => {\n return smooth({x: 0, y: 0}).start(({ x, y }) => {\n document.body.style.setProperty(‘--mouse-x’, x);\n document.body.style.setProperty(‘--mouse-y’, y);\n });\n }, []);\n\n const updateCursorPosition = e => {\n smoothedMouse.update({\n x: e.clientX,\n y: e.clientY\n });\n }\n\n useEffect(() => () => smoothedMouse.stop(), []);\n\n return (\n
\n
\n
\n );\n};\njsCopy to clipboard\n\nCodepen Example: https://codepen.io/littlemilk/pen/ZgvJym\n\nNext Steps\n\nIf you’ve made it this far, awesome work following the tutorial all the way through. I hope you picked up some new tricks and learned some fundamentals along the way.\n\nIf you’re looking for further exploration, dive into the demo code and consider implementing a value() object to keep track of things like velocity or direction between updates. This can add some extra flare to your custom cursor.\n\nMake sure to keep exploring and playing with it. Feel free to make it your own and break whatever rules you want. Always remember, if it looks good, it is good. 🤘\n\nReferences\nAn Animated Intro to RxJS - David Khourshid: https://css-tricks.com/animated-intro-rxjs/\nLinear interpolation - Wikipedia: https://en.wikipedia.org/wiki/Linear_interpolation#Programming_language_support\nPopmotion API - https://popmotion.io/api/\nr - 🌿 A light JavaScript library. - Aristide Benoist: https://github.com/aristidebenoist" ], "categories": { "primary": "frontend", "others": [ "design" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-virtual-coffee-with-nearform-director-of-devops-alex-knol": { "href": "https://nearform.com/insights/virtual-coffee-with-nearform-director-of-devops-alex-knol", "postType": "blog", "slug": "insights-virtual-coffee-with-nearform-director-of-devops-alex-knol", "date": "2019-08-21", "title": "Virtual Coffee With NearForm Director of DevOps, Alex Knol", "authors": [], "content": [ "Alex has lived an interesting life. Born in Holland, he lived a little while in North Carolina. Upon moving back to Europe, he desired a warmer climate, so he and his wife moved to a property a few kilometers outside of a small Spanish town, overlooking the Mediterranean. Now, Alex lives completely off the grid, with all of the energy needs for his family of five coming from solar power. They use solar power even to pump their water from a well and they generate enough to have all the mod cons and appliances any household would need. Alex studied electrical engineering, and he built their entire off-the-grid system, including continually running performance apps. A master of understatement, he told me, “So I kind of just knew how to do all that stuff.”\n\nAs Director of DevOps at NearForm, can you tell me how your DevOps team works?\n\nWe work closely in multidisciplinary teams, working as one with the Experience Architects and Technical Directors at NearForm, to create solutions for clients. I typically take care of some of the infrastructural platform parts of it.\n\nAs cross-functional teams, we share, with the client’s permission, lessons across different projects. We have ten people in DevOps at NearForm - in NY, Sweden, Prague and Dublin - and we try to get together as much as possible, even for a 15-minute sync, to talk about the things we do. It generates new insights because technology is evolving all the time and so quickly. It’s so important to share the burden of acquiring all this knowledge and these capabilities. It’s impossible to know it all as one single individual. This way, we can absorb knowledge from one another.\n\nCan you explain what DevOps is, to a beginner?\n\nTraditionally there are lots of silos in companies. In technical solution delivery, you could have a development team with designers that is separate from teams in operations, information security, testing and so on. DevOps is about integrating all those parts. It’s the responsibility of the DevOps person to be part of that end-to-end architecture conversation, taking into account that the solution in development has to be ultimately deployed somewhere and making sure things get done right the first time. I actually think “Platform Engineer” would be a better title for a DevOps Engineer.\n\nIt’s kind of like shifting left - shifting all the tasks that used to be done after the build was finished into the development process and as early as possible in the life cycle. But modern software development is no longer a linear process, it’s a continuous looped process. So really DevOps is about continuous integration, continuous development, continuous testing.\n\nMany people think DevOps is just about automation, but it’s more about culture. It’s a way of working - working in a more seamless and integrated way.\n\nWhat are some things you shift into the development process?\n\nReadiness, liveness. Letting the surrounding of a service know that you are ready to take requests. You connect to your database or cache - whatever you need to do to be operational - and show the outside world that you are ready for requests.\n\nAnd logging. Logging should be ubiquitous to developers, they shouldn’t have to know where they are going. Let the platform take care of that for you.\n\nIs this the case with all types of builds?\n\nGoogle Cloud, Azure, AWS – they all work differently. But the same principles apply: remove all the friction from later in the process and address it early on. Typically things become cheaper that way.\n\nIf a software project was a physical building in construction, is DevOps the scaffolding to support it during development?\n\nNo DevOps is the foundation of the building and the wireframe would be kind of like the blueprint.\n\nYou’d lay a completely different foundation if you were building a three-story building, than a 35-storey skyscraper. The foundation is your production run-time, that’s what it actually has to stand on for the next 50 years. Software always lives a lot longer than what is envisaged at design time – look at most of the banking systems for instance. In physical architecture the foundation is an integral part of the building, and so should your production deployment be when you’re designing software.\n\nThe way that we have built NearForm on open source, and we always give back to that open source community – I think that’s rare and it makes us unique.\n\nDoes your DevOps team come in right from the beginning of the build?\n\nSometimes we’re called in to do the automation after the software solution is built, and the client is looking to deploy it in a modern, cloud-native way. Sometimes they’re asking us to help them design an architecture from the start, in a cloud-native way. This is where we like to add real value.\n\nWhy is being cloud-native important?\n\nGoing cloud-native - whereby the application’s entire lifecycle exists on a cloud platform - allows an IT organisation to use automation, and by extension DevOps, to reduce time to market. It also lowers costs as you don’t need to keep the entire infrastructure park online all the time. You can use automation tools to scale apps and services more fluidly. And for this, there is a lot of technical stuff like Kubernetes – an Open Source container management platform designed by Google - that can greatly reduce the operational and security risk of massive failures by packaging of applications into smaller, more manageable chunks. This also improves agility and response times.\n\nWhat sectors do most of your clients operate in?\n\nFinance, business consulting, travel and technology. One of the most interesting projects I recently worked on was an automated benchmarking pipeline for a client in the technology sector. They wanted to know the impact of code changes on the performance of their networking transport system.\n\nSo we built a benchmarking infrastructure to provide their development team with graphical data on how their commits would affect the performance of libraries in various areas in their stack. We’re running Clinic.js , our node.js performance tool, automatically on all these libraries and the results are presented in a dashboard in visual format. The tool really gives a picture of the performance of your stack and what the slowest parts are so that teams can take corrective action.\n\nAnd that performance tool, Clinic.js, highlights any bottlenecks?\n\nThe aim is two-fold, one to increase performance, but the other is to give them feedback quickly if their commits or changes that they’ve committed have adverse performance effects. Someone could be working on an unrelated area and do a commit that has enormous performance implications.\n\nSo all-in-all NearForm makes organisations faster, more performant?\n\nThat’s true but it is also around the speed at which we deliver new end-to-end solutions that can be scaled and are flexible. Our sweet spot is around building a first version of an app or service and then delivering an MVP – one that can be used and has actual value but also be scaled up to be ready for primetime. It’s built in such a way that it can be extended and integrated easily. The same goes for the platform we put underneath it. It’s flexible and based on industry standards so that it’s relatively easy to put into a fully scaled, production-ready form.\n\nThe way that we have built NearForm on open source, and we always give back to that open source community – I think that’s rare and it makes us unique.\n\nYou’re right at the frontier-edge of technology... as trailblazers, you have to educate your clients as much about people change, and business change, as about technology?\n\nWe do some of that through leading by example, in how we collaborate and co-create with clients and their stakeholders as one team and in how we adopt a fail-fast approach to innovation, all the while transferring knowledge and skills inhouse. It’s also that we help organisations build a community around what they’re doing – doing new things with existing and new technology. We’re a big part of node.js and the community around that. NearForm can help a company mature in their journey to adopting new technology, and finding a community and people around it.\n\nCompanies want to be cloud-native. A big difference about NearForm is that we’re remote-native.\n\nCan you tell me a little about what it’s like to work for a remote-first company?\n\nA big difference about NearForm is that we are actually remote-native . Most companies that allow remote working, only doing it half measure. What happens there is that things go on when the camera is off and those that are remote miss out - even if it is just the water cooler moments.\n\nBeing a remote-native company, you instinctively know not to discuss anything important when the camera is off. NearForm does that really well, everybody is remote working and so all the important conversations happen when the camera is on.\n\nWorking for NearForm has enabled your lifestyle?\n\nYes, where I live with my family in Spain is very rural. We live on a hill and we overlook a huge rice delta, where we get to see all the colours of the rice fields changing through the seasons. It’s a slower pace of life. When I travel to NearForm, and go through Dublin, it all feels like a lot.... people, noise, cars and buses ...there's a lot going on!\n\nAlso, I’m into mountain biking. It’s so nice to go for my bike rides during lunch, especially because in the winter it’s too dark to do it before or after business hours. That kind of flexibility is accepted at NearForm. As long as you have a stable internet connection – and you’re good at what you do – you can work for NearForm. It’s a trust thing ingrained in the company culture and it works really well. That opens up the world as our resource pool.\n\nBefore we go, can you share some of the global DevOps communities that you use?\n\nI will have to say DevOps.com obviously - I am an author for the site. It’s practical, hands-on and AWS focused and it’s run by people considered the founders of DevOps, people like John Willis and Gene Kim. And there are lots of interesting blogs – Giant Swarm , Rancher , neuVector and Medium .\n\n*** Many thanks to Alex for his views on DevOps as the necessary foundation for a lasting structure and how tools like Clinic.js can help to identify and solve performance bottlenecks. It’s also great to hear how a remote-native working model can really help deliver positive lifestyle changes." ], "categories": { "primary": "devops", "others": [ "cloud", "oss" ] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-fellowship": { "href": "https://nearform.com/digital-community/fellowship", "postType": "blog", "slug": "digital-community-fellowship", "date": "2019-08-28", "title": "Progress Towards OSS Sustainability", "authors": [ "LAUREN EASTRIDGE" ], "content": [ "Open source sustainability has been an increasingly visible problem in recent years. The problem is too big for any one person, or any one company to solve, but at Formidable, we're hoping to make a very small, local dent by making open source work more sustainable for our business and for our engineers.\n\nFor Our Business\n\nIf you've heard of Formidable, it's probably because of one of our open-source projects. Our ongoing commitment to open source work has been one of the defining features of our company. It helps us attract talented, passionate engineers and maintain our status as cutting-edge experts in our field. While we believe in investing in open source work because it makes a positive impact in our community, we are able to sustain that investment because it aligns with our business interests. Many of our projects directly support the work we do for our clients, and maintaining a strong and ever-growing portfolio of open source work has been an effective supplement to out recruiting, sales and other marketing initiatives. In other words, it is in the interest of our business to keep our open source work exciting, useful and relevant with a regular stream of new projects.\n\nFor Our Engineers\n\nMost of the world's open source work is volunteer based; performed for free outside of work hours. We aim to do better for our engineers. For our open source program to be sustainable, it must conserve people's individual resources, both in terms of time and money. Our ability to generate exciting new projects should not rely heavily on free or discounted labor or come at the expense or anyone's work life balance. Ideally, our program should be built to encourage the participation of all of our engineers, regardless of their position within the company, or their circumstances outside of work. It should reward people for their curiosity and passion. It should be structured to reflect the high degree of trust we place in our engineers.\n\nOur Progress\n\nFormidable has been actively engaged in open source work from the beginning, but we have only recently begun developing a structured program. First we addressed maintenance. Our engineers were already spending their time between client projects helping out on open source work. We took stock of our open source portfolio, assigned maintenance levels to each project, and carved out additional work hours for our engineers to dedicate to the regular, ongoing maintenance of most active projects.\n\nNext, we introduced The Sauce Program to acknowledge (with cash) the work our engineers were already doing in their off-hours. In the last month, our engineers have taken advantage of The Sauce Program for work ranging from supporting the latest React Native release to generating rainbow party gifs to share in Slack.\n\nWith both initiatives going so well, we decided to double down on a program designed to enable the sort of ambitious new projects that excite our engineers and support our business goals. For our next experiment, Formidable will be sponsoring Fellowships for our engineers to work on OSS full time! We will start with a pilot program that will sponsor four Fellowships over the next year, with each Fellowship being up to six weeks long. All Formidable engineers will be eligible to apply by submitting a project proposal. A panel of our most senior engineers will work with applicants to help them refine their proposals, and one will be selected each quarter.\n\nThe Fellowship experiment is already underway! We recently accepted our first round of applications, and awarded our first Fellowship to Parker Ziegler. During his Fellowship, Parker plans to build a physics-based animation library. Building off projects like popmotion and react-spring, this library will draw inspiration from the natural world to experiment with new forms of animation — think gravity, air resistance, fluid dynamics, and particle systems. The underlying physics engine will be written in Reason, but the library will also expose a hook-based React API for controlling animations. We selected this project, in part, because it promises a compelling example of using Reason alongside React.\n\nParker's Fellowship will start at the beginning of December and we will be accepting our next round of Fellowship applications in October. Look forward to more posts as the experiment unfolds!" ], "categories": { "primary": "oss", "others": [] }, "verticals": { "primary": "none", "others": [] } }, "digital-community-kate-schaefer": { "href": "https://nearform.com/digital-community/kate-schaefer", "postType": "blog", "slug": "digital-community-kate-schaefer", "date": "2019-09-12", "title": "Say Hello to Kate Schaefer", "authors": [ "KATE SCHAEFER" ], "content": [ "Our Formidable Denver office is growing! Please meet Kate Schaefer, a software engineer from Colorado.\n\nWhat brought you to Formidable?\n\nI'm a recent boot camp grad and I was lucky enough to meet a Formidable employee at my capstone night, which sparked my interest in the company. I woke up the next morning and applied for a \"Future Senior Software Engineer\" position—how great is that job title? As I moved through the interview process and learned more about the company I knew this was the place where I wanted to launch my software development career.\n\nWhat are you most excited about now that you are here at Formidable?\n\nAt Formidable I get to be surrounded by amazingly talented engineers every day, and not only that, each and every one of them is willing to take the time to lend a hand when I'm stuck on a challenging code problem. Working at Formidable is like being at a boot camp x10 where you get to work with experts in their field and grow alongside them.\n\nWhat are you currently doing to \"level up\" your skills?\n\nRecently I've really been enjoying reading some technical books that I never had the time to tuck into while I was working my way through my boot camp. Currently I'm reading You Don't Know JS: ES6 & Beyond by Kyle Simpson, which has been a great refresher and introduced me to some more nuanced aspects of JS. I know that going beyond the basics of JS will allow me to be a stronger developer in the long run.\n\nWhat's your favorite part about working at Formidable? Maybe something people on the outside wouldn't know?\n\nOne of my favorite parts of working at Formidable is spending time with my coworkers. This is the first time in my career that I can honestly say I enjoy each and every person I work with. We get to grab lunch together once a week and we often follow them up with ridiculously themed photo shoots that keep us laughing for hours.\n\nWho or what inspires you and why?\n\nI have a coworker who is a young woman, also a boot camp grad, who has grown her skills as an engineer and her presence in the tech world at an astonishing pace since she started with Formidable a couple short years ago. When I'm having a tough day and I've struggled on a problem for what seems an eternity, I think about all she has achieved in such a short time and it inspires me to keep at it." ], "categories": { "primary": "work", "others": [ "frontend", "product" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-meet-the-nearform-team-at-jsday": { "href": "https://nearform.com/insights/meet-the-nearform-team-at-jsday", "postType": "blog", "slug": "insights-meet-the-nearform-team-at-jsday", "date": "2019-09-12", "title": "Meet the NearForm team at JSDay!", "authors": [], "content": [ "It’s not long until Ireland’s FIRST ever Javascript conference and we’re so excited to be a part of it! We have to give a huge congratulations to the organizers for a superb speaker line-up, in what promises to be a jam-packed schedule with some of the best JavaScript professionals and organisations around!\n\nOur speaker\n\nNearForm DevOps Consultant David Gonzalez will be giving a talk about building DevOps friendly applications, making them easier to operate and maintain using 12 Factor Javascript Applications on Kubernetes. He is going to walk through the process of building a DevOps friendly Javascript app following best practices. The talk will be full of war stories and tips to unlock the potential of your engineering team to deliver applications that are easy to build, maintain and operate, maximizing the ROI and business value.\n\nMeet the team\n\nYou’ll also get a chance to talk to some of the NearForm team on the day at our booth. Got any burning questions on React, GraphQL or any other javascript technology, we’d love to chat! \n\nWe’re also hiring so be sure to check out our current openings and learn more about our remote working model from Dean, Glen and Sean on the day.\n\nGiving back\n\nAt each event we sponsor, we really love to give something back to the local community. So instead of throw-away swag, we will be hosting a booth raffle where you'll have the chance to win a pair of Apple AirPods! Every raffle entry (tickets will be in swag bags!) will equal a donation to local organisation Citywise Education.\n\nCitywise Education, an educational charity based in Jobstown, Tallaght was established in 1994 as a response to educational under-achievement of young people living in underserved communities. 500 local young people, aged from 8 to 18 years, ranging from highly alienated youth to young people with third-level aspirations, attend Citywise Education’s character building, education and sporting programmes.\n\nWith a high focus on academics, Citywise provides supports for Junior and Leaving Certificate students through their award-winning programme, Fast Track Academy, as well as feeder programmes for younger students. It runs innovative STEM programmes, including 3D printing, robotics and computer coding, through STEMSquare@Citywise and there are also a variety of clubs for young people to participate in - Art, Chess, Guitar to name a few. Citywise Education emphasises the importance of character development, personal qualities and the need for each young person to serve society by giving back.\n\nBe sure to check out the JSDay website to see the full speaker line-up and grab your tickets! We’ll see you there!" ], "categories": { "primary": "devops", "others": [ "frontend", "cloud" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-journey-to-innersource-danese-cooper-james-mcleod": { "href": "https://nearform.com/insights/journey-to-innersource-danese-cooper-james-mcleod", "postType": "blog", "slug": "insights-journey-to-innersource-danese-cooper-james-mcleod", "date": "2019-09-13", "title": "Lessons from a Journey to InnerSource with James McLeod at FINOS", "authors": [], "content": [ "Danese Cooper talks to James McLeod, Director of Community at the FinTech Open Source Foundation - FINOS , about his journey to InnerSource at Lloyds Banking Group. James recently joined FINOS to pioneer and educate the Financial Services adoption of Open Source. In this podcast, you can learn how he overcame the challenges in establishing cross-functional collaboration within the regulated banking sector and how InnerSource is more than an engineering methodology. Find out how to dispel common misconceptions, discover your diamonds and learn to adapt by starting small.\n\nDifferent Perspectives with NearForm · The Journey to InnerSource at Lloyds\n\nIf you're new to InnerSource, NearForm can help. You can learn from our experts with hands-on experience of implementing InnerSource at enterprise scale. Get in touch about our InnerSource developer days, training and consultancy offers or to arrange an initial evaluation with Danese Cooper. Contact us today to find out more." ], "categories": { "primary": "oss", "others": [ "work" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-10-tips-successful-devops": { "href": "https://nearform.com/insights/10-tips-successful-devops", "postType": "blog", "slug": "insights-10-tips-successful-devops", "date": "2019-09-16", "title": "10 Tips for successful DevOps", "authors": [], "content": [ "A recent State of DevOps report shows that organisations that adopt a DevOps culture have 60 times fewer failures than those that do not.\n\nHere Alex Knol, NearForm’s Director of DevOps and David Gonzalez, DevOps Consultant at NearForm share 10 tips for successful DevOps.\n\n1) Change your culture\n\nInterest in DevOps is growing, but many organisations are failing in their implementation of DevOps .\n\nSuccessful DevOps means making sure your processes are usable by the right teams in your organisation.\n\nRecruiting the right people and developing the right set of tools can be futile without a change in culture.\n\n2) Create a complete picture\n\nSometimes organisations have a blank slate that allows them to implement DevOps without having to sort through legacy issues or ingrained team structures.\n\nMore often than not, however, an element of transformational change is necessary.\n\nTo create a complete picture you'll need to do the following:\n\ntake down silos\ndevelop a holistic view of the organization\nunderstand processes from start to finish\nreview software updates and how they are rolled out\n3) Empower your developers\n\nDevelopers often talk about 'shifting left', or testing early and often.\n\nThis helps us understand how software is delivered as well as the entire life cycle from start to launch.\n\nGaining this understanding allows us to incorporate these lessons early in the process.\n\n4) DevOps combines Development and Operations\n\nBottlenecks surface when developers don't have the right skills or required access level to maintain production.\n\nIf this is the case you will (hopefully) see complaints.\n\nThis is one of the tell-tale signs that a culture shift is needed.\n\nDevelopers need to be able to maintain, design, and build the software they are resposible for.\n\nThis means developers and management need to communicate.\n\nThere should be shared responsibility that allows all involved to take responsibility as a collaborative team in order to create solutions.\n\n5) DevOps is more than just hiring and/or labeling new talent\n\nThis scenario occurs often.\n\nManagement decides to create a DevOps group and hire with that job title.\n\nWithout a vision or culture the new hires end up sitting in another silo.\n\nThis can also happen when companies acquire new organisations or teams.\n\nDifferent visions of what DevOps means within those teams can make them difficult to integrate.\n\n6) Automate CI / CD\n\nEnable your teams with self-service capabilities.\n\nAutomation tools allow you to see how your software will be deployed across all platforms\n\nWhile automation exists to provide this self-service capability, without the correct culture these tools will be useless.\n\n7) Use DevSecOps correctly\n\nIn Equifax's huge data breach an attacker was able to execute criminal code because they were using an old version of a software platform.\n\nEquifax unfortunately decided the platform was either too risky to update or that it wasn't the right time which resulted in this devastating cyber attack.\n\nA key role of DevOps is to ensure that patching is up to date.\n\nAutomation can help in maintaining patching schedules which means vulnerable versions of libraries will be detected before they enter production.\n\n8) Make sure information flows freely between management and development\n\nSuccessful implementation of DevOps means that information between management and development flows freely.\n\nA culture of collaboration leads to a reduction in failures and increased productivity.\n\nPerhaps more importantly, it sets the path toward more secure software platforms .\n\n9) Be confident\n\nA long standing mantra of software development has been \"never deploy on Friday\".\n\nHowever, when you establish DevOps correctly you can be confident that what you are deploying will work.\n\nThis means you can deploy on Friday and know there will be no problems to fix.\n\nOne of the main benefits of DevOps is that it gives teams confidence in what they are building.\n\n10) Remove Friction\n\nRemove the friction between your development and operations, or any process for that matter, and you will see increased revenue and growth.\n\nIf you enjoyed this, we recommend that you listen to our podcast “DevOps – Is it a culture, or a magic set of tools?” with Alex Knol and David Gonzalez.\n\n[embed]https://soundcloud.com/nearform/devops-is-a-mindset-culture-not-a-magic-set-of-tools\\[/embed\\]\n\nSome other posts you may like:\nDevOps Tools 101: Key Technologies You Need to Know\nSecure DevOps: The What, the Why and the How\nBuilding a Career in DevOps" ], "categories": { "primary": "devops", "others": [ "security", "work" ] }, "verticals": { "primary": "none", "others": [] } }, "insights-7-lessons-on-a-journey-to-innersource": { "href": "https://nearform.com/insights/7-lessons-on-a-journey-to-innersource", "postType": "blog", "slug": "insights-7-lessons-on-a-journey-to-innersource", "date": "2019-09-18", "title": "7 Lessons on a Journey to InnerSource", "authors": [], "content": [ "7 recommendations on how to embark on a successful journey to InnerSource\n\nWith the increasing pressure to deliver new ideas, products and services faster and more efficiently, companies are asking themselves: Is our development model the best it could be?\n\nCompanies born in the digital world tend to have an inherent collaborative culture, using agile methodologies and open source ecosystems that drives a more efficient development model and delivers higher quality software. But for more traditional companies, InnerSource is becoming a popular strategy - the approach to using open source culture and best practices inside an organisation to create a more free-flowing collaboration style.\n\nRecently I spoke to James McLeod about his journey to InnerSource at Lloyds Banking Group. James recently joined the FinTech Open Source Foundation - FINOS as Director of Community to pioneer and educate the Financial Services adoption of Open Source. Here I share his top 7 recommendations on how to embark on a successful journey to InnerSource.\n\n1. Secure Your Aircover from early on\n\nFrom the get-go, there was a desire within Lloyds, from the top down, to have a more free-flowing collaborative style and reap the benefits of Open Source . They actively encouraged engineers to come together in order to evolve a real community spirit.\n\nJames is the first to acknowledge that having ‘enlightened management’ on his side was a critical first step in the journey to InnerSource and was instrumental in facilitating every step along the way.\n\n““If I‘m going to be honest, the mechanism of being able to do this wouldn't exist unless we had that executive air cover for people just to come together and start working together.””\n\nHaving a senior sponsor to support, advocate and even mandate is key.\n\n2. Recognise that it’s not just for the benefit of the Engineering Organisation\n\nAt Lloyds, the push to have a more collaborative model was applied across all disciplines. It was part of their group digital transformation that all disciplines should learn to communicate and share ideas with one another.\n\nThis presented an opportunity for James to take advantage of and paved the way for him to embark on his quest.\n\n“ “We wanted to not only do what was needed for the engineers who were using the system, but we also wanted to make sure that we brought everyone along on the journey as well. The real benefits are when you extend it to the wider organisation.””\n\n3. Alleviate People’s Fears\n\nOnce you’ve begun the journey, taken the first steps and created some platform for negotiation and collaboration, it’s important to make it known.\n\nPublicise your ambitions.\n\nThis can feel scary, but it’s a proven tactic promoted with the InnerSource Commons. Securing buy-in is easier when the benefits are understood. Seeing people get better together and seeing all the boats rise can be powerful and exciting.\n\nBuilding on his experience of meet-ups, James established ways to communicate, involve and motivate others. Along the journey, he brought out the engineering team to broadcast their intent, presenting to key stakeholders internally and externally.\n\n““To transform, it’s good to have people who want to transform. Talk about InnerSource projects, give them a name, make them your DNA. Alleviate people’s worst fears.Change is hard and change is scary for people. Once people get it - what it actually is - a lot of the things they were afraid of gets dispelled pretty quickly. Ultimately, it's a social dynamic.It’s how you bring great people together in order to collaborate and move forward together.””\n\n4. Recognise the problem and address it head-on\n\nMany companies who adopt InnerSource are encouraged to do so in order to address the silos that exist within their organisation. Discrete engineering teams are separated from each other.\n\nOften there’s a method to request features or enhancements across these silos, but the actual coding happens only within a closed group and bottlenecks are common. This was a key issue at Lloyds and was one of the first issues to be addressed.\n\nJames led an examination of all their systems of collaboration to explore where they could improve sharing of code across departments and across countries.\n\nThey looked externally to examine potential solutions that would remove bottlenecks and barriers to collaboration. That's where their journey into GitHub Enterprise started and allowed them to maximise the opportunities that InnerSource presented.\n\nThey had to take extra precaution not enforce too much control in the system whilst at the same time involve those from cybersecurity, risk, product owners & designers - those who actually owned the output. As an engineering team, they should not be seen as mavericks, particularly given the regulated industry in which they operate.\n\n5. Learn to Adapt\n\nWithin digital transformation, an organisation needs to learn how to adapt. It’s not enough placing the systems to improve much-needed collaboration and provide the missing metrics. You need to learn how to adapt and adjust your organisation to be able to meet the demand.\n\nAt Lloyds, the engineering demand drove the change within the wider organization in order to meet it. To build momentum and generate active interest and involvement, they rolled out brown bag sessions, streaming webinars, ‘horizontal’ working groups, and hackathons involving senior people and graduates and guest speakers.\n\nThey provided lakes of education and onboarded people into the systems that they needed to be able to use.\n\n6. Find Your Diamonds\n\nThe evolution into InnerSource is absolutely possible providing you have the right people on your team. But also by finding the diamonds outside of your organisation, those who think the same way and are trying to transform their companies within can lend tremendous weight to what you are doing.\n\nAlong his journey, James began to build trusted relationships with like-minded engineering teams from other large financial organisations and consultancies - like IBM, Wipro, TCS and Publicis Sapient - sharing ideas, collaborating technically and inviting one another to speak at events.\n\n“ “Collaborate with them, start broadcasting the message so both of your stakeholders can hear the great outcomes that you're doing together. That’s when organisations can truly start to transform.””\n\n7. Start Small\n\nOnce you’ve demonstrated how to solve big problems on a small scale, you can broaden it to the wider organisation. Embarking on a pilot and demonstrating results can really encourage the business to start thinking differently and educate them on the benefits.\n\n“ “I won't say they were the big bang explosion, you know, we didn't go from lights out to lights on overnight and, in fact, it's still continuing to happen. But even with those first seeds planted, we were able to yield some pretty interesting and big results which are just spectacular considering a lot of teams couldn't work together before.””\n\nBy applying the principles of open source within an organisation, InnerSource helps teams work better together by breaking down silos; reducing bottlenecks; and resulting in higher-quality development, cleaner code and more efficient use of resources.\n\nA more collaborative, effective and efficient delivery model helps to increase innovation and create a competitive advantage.\n\nIf InnerSource is new to you, you’re not sure what ‘great collaboration’ looks like and you need practical help in setting up ‘rules of engagement’ or embarking on a pilot, we can help you get there. Contact us to arrange an initial evaluation with me or to learn more about our InnerSource Developer Days, training and consultancy offers." ], "categories": { "primary": "oss", "others": [ "work" ] }, "verticals": { "primary": "finance", "others": [] } }, "digital-community-semantic-html": { "href": "https://nearform.com/digital-community/semantic-html", "postType": "blog", "slug": "digital-community-semantic-html", "date": "2019-10-02", "title": "Building a more accessible web with semantic HTML", "authors": [ "BRITTANY FEENSTRA" ], "content": [ "Broadly speaking, developers don’t look forward to accessibility audits. Nor do we purposefully build tools and sites that are harder to use for some people than others. Most of us would admit that we know we should learn more about accessibility when we have time. Today I want to make a case for semantic HTML as a way to unlock the door to building accessible apps from the ground up. Accessibility is something that we must get better at slowly, not overnight, and if we do, we will end up saving time and become stronger developers.\n\nSemantic HTML is the fancy way of saying you’re using HTML purposefully and that the elements you're using are named for their use cases, making it easy to read. You’re probably writing some already—when you use an unordered list (
    ) or a