Web development has always been a fast-moving field — making it hard to keep up with all the browser changes, library releases, and new programming trends that can inundate your mind over the course of the year.
The industry is growing bigger every year, making it harder for the average developer to keep up. So let’s take a step back and review what changed in the web development community in 2018.
We have witnessed an explosive evolution of JavaScript over the last few years. As the internet became even more important to the global economy, powerful commercial stakeholders like Google and Microsoft realized they needed better tools to create the next generation of web applications.
This led to the largest wave of changes to JavaScript since its inception, starting with ECMAScript 2015 (aka ES6). There are now yearly releases which have brought us exciting new features like classes, generators, iterators, promises, a completely new module system, and much more.
This launched a golden age of web development. Many of the most popular tools, libraries, and frameworks today first became popular right after ES2015 was released. Even before major browser vendors supported even half of the new standard, the Babel compiler project allowed thousands of developers to get a head start and experiment with the new features themselves.
Frontend developers for the first time were not beholden to the oldest browser their company supports but were free to innovate at their own pace. Three years and three ECMAScript editions later, this new age of web development shows no signs of slowing down.
Compared to previous editions, ECMAScript 2018 was rather light feature-wise, only adding object rest / spread properties, asynchronous iteration, and Promise.finally, all of which have been supported by Babel and core-js for a while now. Most browsers and Node.js support all of ES2018 except Edge, which only supports Promise.finally. For many developers, this means that all the language features they need are supported in all browsers they support — some wonder whether Babel is really necessary anymore.
JavaScript has always been lacking some of the more advanced regular expression features that other languages like Python have — that is, until now. ES2018 adds four new features:
Although many of these features have had workarounds and alternative libraries for years, none could hope to match the speed that native implementations provide.
There has been an incredible amount of new JavaScript browser APIs released this year. Almost everything has seen improvement — web security, high-performance computing, and animations, to name a few. Let’s break them down by domain to get a better sense of their impact.
Although WebAssembly v1 support was added to major browsers last year, it has not yet been widely adopted by the developer community. The WebAssembly Group has an ambitious feature roadmap for features like garbage collection, ECMAScript module integration, and threads. Perhaps with these features, we will start to see widespread adoption in web applications.
Part of the problem is that WebAssembly requires a lot of setup to get started and many developers used to JavaScript are not familiar with working with traditional compiled languages. Firefox launched an online IDE called WebAssembly Studio that makes it as easy as possible to get started with WebAssembly. If you’re looking to integrate it into an existing app, there are now plenty of tools to choose from. Webpack v4 added experimental built-in support for WebAssembly modules tightly integrated into the build and module systems and with source map support.
Rust has emerged as a favorite language to compile to WebAssembly. It offers a robust package ecosystem with cargo, reliable performance, and an easy to learn syntax. There’s already an emerging ecosystem of tools that integrate Rust with JavaScript. You can publish Rust WebAssembly packages to NPM using wasm-pack. If you use webpack, you can now seamlessly integrate Rust code in your app using the rust-native-wasm-loader.
If you’d rather not abandon JavaScript to use WebAssembly, you’re in luck — there are now several options to choose from. If you’re familiar with TypeScript, there’s the AssemblyScript project which uses the official Binaryen compiler together with TypeScript.
Therefore, it works well with existing TypeScript and WebAssembly tools. Walt is another compiler that sticks to the JavaScript syntax (with TypeScript-like type hints) and compiles directly to the WebAssembly text format. It has zero dependencies, very fast compilation times, and integration with webpack. Both projects are in active development, and depending on your standards they might not be considered “production-ready.” Regardless, they are worth checking out.
Modern JavaScript applications often do heavy computation in Web Workers to avoid blocking the main thread and interrupting the browsing experience. While workers have been available for several years now, their limitations prevented them from being more widely adopted. Workers can transfer data between other threads using the postMessage method, which either clones the data being sent (slower) or uses transferable objects (faster). Thus, communication between threads is either slow or one-way. For simple applications this is fine, but it has prevented more complex architectures from being built using workers.
SharedArrayBuffer and Atomics are new features that allow JavaScript applications to share a fixed memory buffer between contexts and perform atomic operations on them. However, browser support was temporarily removed after it was discovered that shared memory makes browsers vulnerable to a previously unknown timing attack known as Spectre. Chrome re-enabled SharedArrayBuffers in July when they released a new security feature which mitigated the vulnerability. In Firefox its disabled by default but can be re-enabled. Edge has removed support completely and Microsoft hasn’t indicated when it’s going to be re-enabled. Hopefully, by next year all browsers will have mitigation strategies in place so that this critical missing feature can be used.
Graphics APIs such as Canvas and WebGL have been supported for several years now, but they have always been limited to rendering only in the main thread. Rendering can, therefore, be blocking. And that leads to poor user experiences. The OffscreenCanvas API solves that problem by allowing you to transfer control of a canvas context (2D or WebGL) to a web worker. The worker can then use the Canvas APIs like normal while render seamlessly in the main thread without blocking.
Given the significant performance savings, you can expect chart and drawing libraries to look into supporting it soon. Browser support right now is limited to Chrome, Firefox supports it behind a flag, and the Edge team hasn’t made any public indication of support. You can expect it to pair well with SharedArrayBuffers and WebAssembly, allowing a Worker to render based on data existing in any thread, from code written in any language, all without a janky user experience. This might make the dream of high-end gaming on the web a reality, and allow even more complex graphics in web applications.
There is a major effort underway to bring new drawing and layout APIs to CSS. The goal is to expose parts of the CSS engine to web developers to demystify some of the “magic” of CSS. The CSS Houdini Task Force at W3C, made up of engineers from major browser vendors has been hard at work over the last two years publishing several draft specifications which are now in the final stages of design.
The CSS Paint API is among the first to reach browsers, landing in Chrome 65 back in January. It allows developers to paint an image using a context-like API that can be used wherever an image is called for in CSS. It uses the new Worklet interface, which are basically lightweight, high-performance Worker-like constructs intended for specialized tasks. Like Workers, they run in their own execution context, but unlike Workers, they are thread-agnostic (the browser chooses what thread they run on) and they have access to the rendering engine.
With a Paint Worklet, you could create a background image that automatically redraws when the element it’s contained in changes. Using CSS properties you can add parameters that trigger re-drawing when changed and can be controlled via JavaScript. All browsers except Edge have pledged support, but for now, there’s a polyfill. With this API we will begin to see componentized images used in a similar way we now see components.
Most modern web applications use animations as an essential part of the user experience. Frameworks like Google’s Material Design have made them essential parts of their design language, arguing that they are essential to making expressive and easy-to-understand user experiences. Given their elevated importance, there has been a push recently to bring a more powerful animations API to JavaScript, and this has resulted in the Web Animations API (WAAPI).
As CSS-Tricks notes, WAAPI offers a significantly better developer experience over just CSS animations, and you can easily log and manipulate the state of an animation defined in JS or CSS. Browser support at the moment is mostly limited to Chrome and Firefox, but there is an official polyfill that does everything you need.
Performance has always been an issue with web animations, and this has been addressed by introducing the Animation Worklet. This new API allows complex animations to run in parallel — meaning higher frame rate animations that aren’t impacted by main thread jank. Animation Worklets follow the same interface as the Web Animations API, but inside the Worklet execution context.
It’s due to be released in Chrome 71 (the next version as of the time of writing), and other browsers likely sometime next year. There’s an official polyfill and example repo available on GitHub if you’d like to try it out today.
The Spectre timing attack wasn’t the only web security scare of the year. The inherent vulnerability of NPM has been written about a lot in the past, and last month we got an alarming reminder. This was not a security breach of NPM itself, but a single package called event-stream that is used by many popular packages. NPM allows package authors to transfer ownership to any other member, and the hacker convinced the owner to transfer it to them. The hacker then published a new version with a new dependency on a package they created called flatmap-stream, which had code designed to steal bitcoin wallets if the malicious package was installed alongside the copay-dash package.
These kinds of attacks will only become more common given how NPM works and the communities’ cavalier propensity to install random NPM packages that appear useful. The community places a great deal of trust on package owners, trust that has been questioned greatly. NPM users should aware of each package they are installing (dependencies of dependencies included), use a lock file to lock down versions and sign up for security alerts like those provided by Github.
NPM is aware of the security concerns of the community and they have taken steps to improve it over the last year. You can now secure your NPM account with two-factor authentication, and NPM v6 now includes a security audit command.
The Reporting API is a new standard that aims to make it easier for developers to discover problems with their applications by alerting when issues happen. If you’ve used the Chrome DevTools console within the last few years you might have seen the [intervention] warning messages for using obsolete APIs or doing potentially unsafe things. These messages have been limited to the client, but now you can report them to analytics tools using the new ReportingObserver.
There are two kinds of reports:
While tools like LogRocket give developers insight into errors in their applications. Until now, there hasn’t been any reliable way for third-party tools to record these warnings. This means issues either go unnoticed or manifest themselves as difficult-to-debug error messages. Chrome currently supports the ReportingObserver API, and other browsers will support it soon.
Although JavaScript gets all the attention, there have been several interesting new CSS features landing in browsers this year.
For those unaware, there is no unified CSS3 specification analogous to ECMAScript. The last official unified standard was CSS2.1, and CSS3 has come to refer to anything published after that. Instead, each section is standardized separately as a “CSS Module”. MDN has an excellent overview of each module standard and their status.
As of 2018, some newer features are now fully supported in all major browsers (this is 2018, IE is not a major browser). This includes flexbox, custom properties (variables), and grid layout.
While there has been talk in the past of adding support for nested rules to CSS (like LESS and SASS), those proposals didn’t go anywhere. In July the CSS working group at W3C decided to take another look at the proposal, but it’s unclear if it’s a priority at all.
Node continues to make excellent progress keeping up with ECMAScript standards and as of December, they support all of ES2018. On the other hand, they have been slow to adopt the ECMAScript module system and thus are missing a critical feature that is preventing feature parity with browsers, which have supported ES modules for over a year now. Node actually added experimental support in v11.4.0 behind a flag, but this requires that files use the new .mjs extension, leading to concerns about slow adoption and what impact this would have on Node’s rich package ecosystem.
If you’re looking to get a jump start and you’d rather not use the experimental build-in support, there’s an interesting project from the creator of Lodash called esm which gives Node ES module support with better interoperability and performance than the official solution.
React had two notable releases this year. React 16.3 shipped with support for a new set of lifecycle methods and a new official Context API. React 16.6 added a new feature called “Suspense” that gives React the ability to suspend rendering while components wait for a task to be completed like data fetching or code splitting.
The most talked about React topic this year was the introduction of React Hooks. The proposal was designed to make it easier to write smaller components without sacrificing useful features that were until now limited to class components. React will ship with two built-in hooks, the State Hook, which lets functional components use state, and the Effect Hook, which lets you perform side effects in function components. While there is no plan to remove classes from React, the React team clearly intends Hooks to be central to the future of React. After they were announced, there was a positive reaction from the community (some might say overhyped). If you’re interested in learning more, check out Dan Abramov’s blog post comprehensive overview.
Next year React plans on releasing a new feature called Concurrent mode (formerly known as “async mode” or “async rendering”). This would allow React to render large component trees without blocking the main thread. For large apps with deep component trees, the performance savings could be significant. It’s unclear exactly what the API looks like at the moment, but the React team is aiming to finalize it soon and release sometime next year. If you’re interested in adopting this feature, make sure your codebase is compatible by adopting the new lifecycle methods released in React 16.3.
React continues to grow in popularity, and according to the State of JavaScript 2018 survey, 64 percent of those polled use it and would use it again (+7.1 percent since last year), compared to 28 percent for Vue (+9.2 percent) and 23 percent for Angular (+5.1 percent).
Webpack 4 was released in February, bringing huge performance improvements, build-in production and development modes, easy to use optimizations like code splitting and minification, experimental WebAssembly support, and ECMAScript module support. Webpack is now much easier to use than previous versions and previously complicated features like code splitting and optimization are now quite simple to set up. Combined with TypeScript or Babel, webpack remains the bedrock tool for web developers and it seems unlikely a competitor will come along and replace it in the near future.
Babel 7 was released this August, the first major release in almost three years. Major changes include faster build times, a new package namespace, and deprecation of the various “stage” and yearly ECMASCript preset packages in favor of preset-env, which vastly simplifies configuring Babel by automatically including the plugins you need for the browsers you support. This release also adds automatic polyfilling, which removes the need to either import the entire Babel polyfill (which is rather large) or explicitly importing the polyfills you need (which can be time-consuming and error-prone).
Babel also now supports the TypeScript syntax, making it easier for developers to use Babel and TypeScript together. Babel 7.1 also added support for the new decorators proposal, which is incompatible with the obsolete proposal widely adopted by the community but matches what browsers will be supporting. Thankfully, the Babel team has published a compatibility package that will make upgrading easier.
Electron continues to be the most popular way to package JavaScript applications for the desktop, although whether or not that’s a good thing is somewhat of a controversy. Some of the most popular desktop applications now use Electron to reduce development costs by making it easy to develop cross-platform applications.
A common complaint is that applications that use Electron tend to use too much memory since each app packages an entire instance of Chrome (which is very memory-intensive). Carlo is an Electron alternative from Google that uses the locally installed version of Chrome (which it requires), resulting in a less memory hungry application. Electron itself hasn’t made much progress with improving performance, and recent updates have focused on updating the Chrome dependency and small API changes.
TypeScript has greatly increased in popularity over the last year, emerging as a genuine challenger to ES6 as the dominant flavor of JavaScript. Since Microsoft releases new versions monthly, development has progressed pretty rapidly over the last year. The TypeScript team has put a strong focus on developer experience, for both the language itself and the editor tools that surround it.
Recent releases have added more developer-friendly error formatting and powerful refactoring features like automatic import updating and import organizing, among others. At the same time, work continues on improving the type system with recent features like conditional types and unknown type.
The State of JavaScript Survey 2018 notes that nearly half of respondents use TypeScript, with a strong upward trend over the last two years. In contrast, it’s chief competitor Flow has stagnated in popularity, with most developers saying they dislike its lack of tooling and popular momentum. TypeScript is admired for making it easy for developers to write robust and elegant code backed up by powerful editor support. It’s sponsor, Microsoft, seems to be more willing to support it than Facebook is with Flow, and developers have clearly noticed.
LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.
In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page and mobile apps.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowEfficient initializing is crucial to smooth-running websites. One way to optimize that process is through lazy initialization in Rust 1.80.
Design React Native UIs that look great on any device by using adaptive layouts, responsive scaling, and platform-specific tools.
Angular’s two-way data binding has evolved with signals, offering improved performance, simpler syntax, and better type inference.
Fix sticky positioning issues in CSS, from missing offsets to overflow conflicts in flex, grid, and container height constraints.