2017 was quite a year in frontend web development.
Frameworks like React and Angular have continued to enjoy large-scale support among the community, but new contenders like Vue have also exploded in popularity. Webpack continues to be the build tool of choice and NPM the package system of choice. WebAssembly opened up the web to a multitude of new and exciting use cases with unprecedented speeds. Technologies like GraphQL have innovated the way that APIs are both written and used in web applications.
Meanwhile, the language itself continues to evolve. The 2017 edition of the ECMAScript standard added asynchronous functions which considerably improve the developer experience when writing asynchronous code. They are now supported in all major browsers. Another notable addition was shared memory and atomic operations.
It is expected that shared memory will become available sometime this year when browser vendors figure out a way to prevent the vulnerability.
Libraries and Frameworks
React had a very eventful 2017 with the release of React 16 in September. This is the largest release of React to date, adding fragments (you can now return an array instead of having to wrap everything in a useless <div> element), better error handling with error boundaries (errors now cause React to unmount at the root or special error boundary components), portals (you can now render React children into DOM nodes outside the React DOM hierarchy) and streaming (allowing server-side rendered apps to stream renders to the client instead of waiting for the entire render to complete).
Furthermore, React has also switched to a RFC process for contributing ideas to the React team. Anyone is allowed to submit RFC proposals as long as those proposals change the React API. The React team has already posted their proposed context changes as the first RFC, which are a very interesting read.
The community has also already submitted several proposals that cover many interesting new features including:
- Render function arguments — to reduce code clutter, this proposes that the render function take props, state, and context as arguments.
- setState returns a promise — would pair nicely when you need setState to be synchronous and you’re in an environment with async / await.
- async-safe static lifecycle hooks — a complete overhaul of the legacy class-based API that makes it easier to work with async data while avoiding unnecessary renders and provide a clear upgrade path to functional components.
Of course, not all of the proposals will make it in a future release, but it’s nice that the React team has opened planning to the community. The RFC process has become more prevalent in the community with projects like Yarn and Ember adopting it recently.
Boilerplate projects have always been popular in the React community due to the relative complexity of setting up all the different tools required for modern web development. Most advise the user clone the project to use and build from there. This can be confusing for beginners because they are overwhelmed by a complex “blank slate” with tons of dependencies and configuration code they don’t understand.
Facebook’s create-react-app is different — it’s a CLI tool that wraps Webpack, Babel, PostCSS, and Jest and allows for zero-configuration development. It has continued to grow in popularity in the last year, from 18k GitHub stars at the start of 2017 to 40k by the end. It also allows you to stop using create-react-app by providing an “eject” command which installs dependencies and copies configuration files so that you can manually change them. It can be argued that it is partially responsible for much of the growth in React’s popularity in recent years.
For server-rendered React applications, next.js is a popular framework choice. It provides all the tools you need for a “universal” web application without the complicated configuration and setup. This is important since it seems the interest in universal (or “isomorphic”) apps has decreased recently in favor of progressive web apps — probably because of the development complexity. If you’re starting a new project, I would seriously consider next.js as a framework choice.
I think the React community will eventually develop something akin to create-react-app but targeted towards more complex applications.
Next.js gets close to this goal, but it’s targeted towards server-rendered apps which are by no means the majority. There’s a sweet spot between configuration and ease-of-use that — in my opinion — hasn’t been achieved by any framework.
The appeal of a “batteries included” approach will become tantalizing for more and more developers disillusioned with the complexity of build system configuration and the developer time required to maintain it.
Although the latest version of Angular (version 5.1.3) was released on January 3, the AngularJS project (a.k.a. the old Angular 1.x version) is still being actively developed and even released version 1.6.8 on December 18, 2017. Many large companies are still using the legacy version of Angular and because of that important speed improvements and security fixes have been backported to AngularJS.
It is not exactly known when Google’s support of the legacy project will end, but in the past the official line has been that support will not end until the majority of web traffic goes to the angular.io domain (the next-gen version’s site) rather than angularjs.org. However, given that the legacy version uses the rather liberal MIT license, even if official support goes away in 2018 you can expect further development.
Recent Angular releases have been impressive, especially the latest v5 release. It continues to distinguish itself from its competitors with every release by offering innovative features like ahead-of-time compilation of templates and service worker integration in a neat and easy to set up package.
While these features are of course available to any application, where Angular shines is with it’s integrated tools. Angular CLI is easy to use and now offers support for quickly generating universal and progressive web applications with App Shell.
The React community embraces a less opinionated philosophy of frontend development. For the most part, developers have to manually set up many of these complex features unless they use one of the multitude of boilerplate projects. Many developers prefer to set things up themselves so they understand all parts of the system.
Sometimes it feels like the web community cycles between opinionated and centralized to unopinionated and decentralized. One can’t help but wonder if the React community will eventually move back in the other direction.
After having worked on several large custom-build React / Redux / Webpack projects, having everything basically set up for you and “just work” is a very appealing prospect.
Given the recent releases, it will be interesting to see if Angular will become more popular in the coming year. Although it’s hard to measure, Angular doesn’t seem to be growing much at all when you look at NPM downloads. React has continued to increase its lead especially over the last year. It now has almost three times as many NPM downloads per day.
The Vue core team is planning the 2.6 release before this February that will focus error handling, functional components, and server-side rendering. Following React’s lead, they also plan on only targeting evergreen browsers in a future release.
Vue has grown in popularity over the last year, but it’s hard to see it replacing React as the king of frontend view libraries.
A lot has been written about its appeal for developers coming from Angular, and I expect this appeal to continue. The general argument is that unlike React, Vue doesn’t require you to use JSX and unlike Angular it doesn’t push you to use TypeScript.
Its templating language is also quite similar to Angular’s. Additionally, Vue has a close family of packages that are well maintained and together offer a similar set of functionality that Angular does but in a more decentralized way.
Webpack 3 was released in June 2017 and brought scope hoisting as its flagship feature. Instead of wrapping each module in an individual closure, scope hoisting brings all modules together in a single closure without breaking them. This can significantly improve both bundle execution time and bundle size. This was a notable feature of Rollup, another module bundler that has been a source of inspiration for features in Webpack 2 and beyond.
The new release will also focus on build performance — an issue voted by the the Webpack community as a top priority item.
In my opinion, Webpack should also focus more on the documentation and configuration. Although Webpack excels at a flexible configuration, it sacrifices user experience.
A Webpack zero-config mode has been suggested, but it hasn’t been greatly prioritized despite the breakout popularity of other module bundlers like Parcel.
Parcel made a huge splash on GitHub in late 2017, gathering an impressive fourteen thousand stars in less than a month. It’s been capitalizing on the growing dissatisfaction with Webpack regarding its confusing configuration and slow build times by introducing a offering a “zero-config” setup. It already has several important module bundling features popularized by Webpack such as code splitting and hot module replacement.
Most of the remaining development seems to be focused on adding smaller features to bring it on par with Webpack — such as entry points and a comprehensive plugin system.
I will be closely watching Parcel development in 2018 and it will be interesting to see whether or not it becomes a major challenger to Webpack’s dominance.
Although the recent versions of Webpack have introduced valuable features and the new documentation site is a vast improvement, it feels like Webpack is now prime for disruption.
It’s simply too much of a task to configure Webpack for complex use cases.
Parcel can grow into something big if it successfully exploits developer frustration and offers an easier alternative with less configuration.
Gulp and Browserify are still being used by thousands of projects in one shape or form but they are no longer considered to be the cutting edge of frontend build tools. Their continued development is important for maintenance of existing systems and they might still be used today in new projects for very specific use cases; however, the popular opinion among developers for the last few years has been that they are overcomplicated and require too much manual set up. Both have continued a relatively steady decline in NPM downloads in the last year in the midsts of an increasingly wide lead by Webpack.
TypeScript has a release planned for January that includes new ECMAScript features such as numeric separators and several advanced type system improvements involving object literals and classes. Also planned is a change that will improve how TypeScript’s module system handles non-ECMAScript modules.
This brings it more in line with how Babel handles module interoperability. Hopefully this should make using TypeScript easier when using modules of different types, something that is often a confusing pain point for new users. This release also plans improvements to the already impressive refactoring features by adding support for automatic conversion to ECMAScript modules.
Microsoft’s TypeScript is clearly winning against Flow (the rival type checking tool from Facebook). There are several reasons for this, but in my opinion it’s simply a matter of how well the TypeScript project has been run by Microsoft.
It gets large monthly releases by Microsoft compared to sporadic, smaller releases by flow. The tooling is also simply better with TypeScript, with excellent linter support with tslint and fantastic editor support with Visual Studio Code (and many other editors) which provide automatic transforms that are simply not possible with Flow.
Whether or not one is a better type system is almost irrelevant — I’m willing to bet most developers care more about support and ease-of-use.
Furthermore, the community around TypeScript is much larger. There are many more type definitions for popular NPM packages available for TypeScript through the DefinitelyTyped project compared to those provided by flow-typed. If nothing else, this fact is a serious threat to the long-term viability of any project that uses Flow.
Universal web applications first became popular around the time that React was introduced. This innovation allowed frontend web applications to render first on the server at the expense of development complexity. While they are still popular, they are by no means the de facto way of doing things.
For mobile, developers today are starting to focus on developing so-called progressive web applications — an initiative sponsored by Google to make web applications more friendly for mobile users. For the developer, this means an increased focus on speed and mobile user experience. This is achieved by using new technologies like service workers for offline support and application manifest files for customizing how apps look in the operating system. This can be seen as the natural evolution of responsive web design.
Google has also sponsored the Accelerated Mobile Pages (AMP) project, which drastically reduces load times for web pages on mobile devices by standardizing a lightweight document format that uses Web Components with caching provided by Google. It has been quickly adopted by major content publishers on the web, however controversy persists regarding publisher ad revenue and concerns about giving up control by hosting content on Google’s servers.
If we want the web to remain a competitive and engaging platform we need to compete with mobile apps.
Although they can’t do everything a mobile app can do, progressive web applications are a great step towards maintaining the long-term health of the web. I expect them to become more popular and even mandatory in the future.
Putting it all together
Overall, frontend has trended toward a consolidation around existing projects and many disparate sections of web development. React, Webpack, TypeScript have continued to get more popular. Vue and Parcel seem like they could become more of a threat to the respective frontrunners in their fields; meanwhile, the old guard technologies like Angular and Browserify are still around but are slowly declining.
Some trends are continuing, like component-based design. There is not a single new library to become popular recently that has challenged this tennet. It’s by no means a new concept and it’s recently revival is not limited to web development. I don’t expect any fundamental shifts in application architecture anytime soon.
There has been a trend towards more developer-friendly, “opinionated” tools. You can see this in the push-back against the complexities of Webpack and the React ecosystem. Simple is better than complex, but it’s hard to cater to a wide variety of use cases without complexity.
What frontend development needs is more consensus. It is often derided as being overly complex, an opinion I share.
While there has been a recent focus on appealing to new developers, I think we should also pay attention to the complexities in the average enterprise web project — both the application itself and the build tools around it.
Plug: LogRocket, a DVR for web apps
LogRocket is a frontend logging tool 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.