Home  >  Article  >  Backend Development  >  Four eras of JavaScript frameworks

Four eras of JavaScript frameworks

WBOY
WBOYforward
2023-04-10 11:51:031417browse

Back in 2012, I started coding primarily in JavaScript. I once built a PHP application, a basic CMS and website from start to finish for a local business, and the company decided they wanted to rewrite it and add some functionality.

Four eras of JavaScript frameworks

The project manager wanted me to use .NET, partly because that's what he knew, but also because he wanted the app to feel like a native app Program - No long wait for page refresh or operation action. After some research and prototyping, I convinced my manager that I could do these things using a new JS framework that was just starting to emerge at the time.

The first framework I chose was actually Angular 1. Having built a fairly large app and using FuelPHP's backend before I ran into some issues with the router - it would flicker every time a child route/outlet was re-rendered and it really felt like it was being designed This scenario was not considered at the time.

Later, someone recommended Ruby on Rails Ember to me. After trying it, I thought it worked very well. I also like the idea of ​​both frameworks, I like these community ecologies, and overall it's been very productive compared to the alternatives at the time.

A lot has changed since then - frameworks have emerged one after another and have evolved a lot. The idea that you could build applications with JavaScript in the browser went from somewhat of a fringe to a standard practice. The infrastructure we've built has completely changed, enabling a new set of possibilities.

During this period, there was also considerable competition and conflict among various ideas. Which JavaScript framework to use, how to write CSS, functional vs. object-oriented programming, how to best manage state, which build system or tool is the most flexible and fast, etc. Looking back, it’s funny how we often argue about the wrong things and ignore some forward-looking considerations. Of course, this is also hindsight.

So I wanted to do a retrospective, looking back at the past few decades of JavaScript development to see how far we have come. We can roughly divide it into four main eras. :

  • Original era
  • The first framework
  • Component-centered view layer
  • Full stack framework

Each era has its own themes and core contradictions. At the same time, it also wants to learn key lessons and move forward steadily.

Today, the debate continues. Is the web getting too bloated? Does the average website really need to be written in React? Should we even use JavaScript? Of course, the present cannot represent the future, and the existing framework will most likely be replaced in the future. However, it is also based on some existing perspectives to help us move forward.

Original Year

JavaScript was first released in 1995. Like I mentioned above, I started writing JS in 2012, almost 20 years later, near the beginning of what I call the first framework era. You can assume that I might be glossing over a lot of history here, and that this era might be broken up into many sub-eras, each with its own patterns, libraries, build tools, etc.

In other words, I can’t write about things I haven’t experienced. When I started writing front-end applications, the new generation of frameworks was just beginning to mature. Angular.js, Ember.js, Backbone, and more.

Before this, the most advanced technologies were libraries such as jQuery and MooTools. These libraries were important in their day - they helped smooth out the differences in the way browsers implemented JavaScript that were important.

For example, the way IE implements events is completely different from Netscape - bubbling events and capturing events. That's why our standards today finally implement both, but until then we need to use libraries to write code that works on both browsers.

These libraries are mainly used for making small, independent user interface components. Most of the application's business logic is still done through forms and standard HTTP requests - HTML is rendered on the server and served to the client.

There are no build tools to speak of in this day and age, at least that I know of. JavaScript at the time didn't have modules (at least not standard modules), so there was no way to import code. Everything is global, and it's very difficult to organize it.

In this environment, it’s understandable that JS is often viewed as a toy language rather than something you use to write a complete application. The most common thing we did back then was throw in jQuery, write some scripts for some UI widgets, and then that was it.

As time went on and XHR was introduced and popularized, people began to put parts of their UI processes into a page, especially for complex processes that required multiple back-and-forth interactions between the client and server. But most of the application remains on the server.

This is in stark contrast to the situation when mobile apps began to emerge. From the beginning, mobile apps on iOS and Android have been complete applications written in no-nonsense languages™ like Objective C and Java. Additionally, they are completely API driven - all UI logic is on the device and communication with the server is purely in data format. This led to a better user experience and an explosion of mobile apps, leading directly to the debate we have today about whether mobile or the web is better.

Doing all this in JavaScript was initially considered ridiculous. But as time went on, the applications started to become more ambitious. Social networks added chat, DMs, and other real-time features, Gmail and Google Docs showed that equivalent desktop applications could be written in the browser, and more and more companies turned to writing web applications because the web worked everywhere and was more Easy long-term maintenance. This pushed the entire industry forward - it was now clear that JS could be used to write non-trivial applications.

Back then JavaScript didn’t have all the features it has today, everything was global and usually required manually downloading and adding each external library to a static folder. NPM didn't exist yet, modules didn't exist, and JS didn't have half the functionality it has today.

In most cases, each application is customized, each page has different plugin settings, and each plugin has a different system for managing state and rendering updates. In order to solve these problems, the earliest JavaScript framework began to appear.

The First Framework

Around the late 2000s and early 2010s, the first JS frameworks specifically designed for writing complete client-side applications began to appear. Several famous frameworks of this era:

  1. Backbone.js
  2. Angular 1
  3. Knockout.js
  4. SproutCore
  5. Ember.js
  6. Meteor.js

Of course, there are many others, and probably some that are bigger in some circles. These are the ones I remember, mainly because Xiao Ming used them to code and they are relatively popular.

This is a generation framework that is entering uncharted territory. On the one hand, what they were trying to do was very ambitious, and many thought it would never really succeed.

There are many naysayers who argue that Single Page JS Applications (SPAs) are fundamentally worse, and in many ways they're right - client-side rendering means robots can't easily crawl these pages, and Users have to wait a few seconds before the application can even start drawing. Many of these apps are accessibility nightmares and don't work at all if JavaScript is turned off.

On the other hand, we have no experience building complete applications in JS, so there are a lot of competing ideas about the best approach. Most frameworks try to imitate what's popular on other platforms, so almost all of them end up being some iteration of Model-View-*. Model-View-Controller, Model-View-Producer, Model-View-ViewModel and so on. But in the long run, these are not really successful - they are not particularly intuitive, and they become very complicated very quickly.

This was also an era when we really started experimenting with how to compile JavaScript applications. Node.js was released in 2009, and NPM followed in 2010, introducing packages for (server-side) JavaScript.

CommonJS and AMD fight over how to best define JS modules, while build tools like Grunt, Gulp, and Broccoli fight over how to combine these modules into a deliverable final product.

For the most part, these are very general task runner-style tools that can really build anything that just happens to be building JavaScript -- but also HTML, CSS/SASS/LESS, and many other things that go into web applications.

However, we have learned a lot from this era:

  • URL-based routing is the foundation. Applications without this routing break the web, so this needs to be accounted for in the framework from the start.
  • Extending HTML through a templated language is a powerful abstraction layer. Even though it can be a bit clunky at times, it makes it easier to keep the user interface in sync with state.
  • The performance of SPA is very poor, and the web has many additional limitations that native applications do not have. We need to publish all the code over the web, have it JIT, and then run it to launch our application while the local application has been downloaded and compiled, which is a daunting task.
  • As a language, JavaScript has a lot of problems, and it really needs to be improved to make things better - frameworks can't do that alone.
  • We absolutely need better building tools, modules, and packaging for writing applications at scale.

Overall, this era has been productive. Despite the drawbacks, as the complexity of the application increases, the benefits of decoupling the client from the API are huge, and in many cases the resulting user experience is amazing. Unless there are special circumstances, this era may continue, and we are still iterating on MV* style ideas.

But then an asteroid suddenly appeared, smashing the existing paradigm into pieces, causing a small-scale extinction event, and pushing us into the next era - this asteroid was called React.

Component-centered view layer

I don’t think React invented components, but to be honest, I’m not sure where they first came from. But it goes back at least to XAML in .NET, and that's when web components started to evolve as a specification. Ultimately it didn't matter - once the idea emerged, every major framework adopted it very quickly.

In hindsight, this totally makes sense - extend HTML, reduce long-lived state, bind JS business logic directly to templates (whether it's JSX or Handlebars or Directives).

Component-based applications eliminate most of the abstractions needed to get the job done and significantly simplify the code lifecycle - everything is tied to the component's lifecycle rather than the application's lifecycle Together, this means you have far fewer things to think about as a developer.

However, there was a shift at that time: the framework began to tout itself as a "view layer" rather than a full-blown framework. Instead of solving all the problems required for front-end applications, they focus on solving rendering problems.

Other issues, such as routing, API communication and state management, are left to the user to decide. The famous frameworks of this era include:

  1. React.js
  2. Vue.js
  3. Svelte
  4. Polymer.js

There are many others. Looking back now, I think this was a popular framework among second generation frameworks because it really did two main things.

  • It narrows the scope dramatically. Rather than trying to solve all of these problems upfront, the core of the framework is focused on rendering, and many different ideas and directions can be explored for other features within the broader ecosystem. There are a lot of bad solutions, but there are also good solutions, paving the way for the next generation to pick the best ideas from the cream.
  • This makes it easier for us to accept them. Adopting a complete framework to take over your entire web page means rewriting most of your application, which is not possible with existing server-side monoliths. Using frameworks like React and Vue, you can drop small portions of them into existing applications one widget or component at a time, allowing developers to migrate their existing code incrementally.

These two factors have led to the rapid development of the second-generation framework, eclipsing the first-generation framework. From a distance, it all seems to make sense and is a reasonable evolution. But being in it at the time was quite a frustrating experience.

First of all, when we are debating which framework to use at work, or whether we should rewrite our application, we don't often encounter such a framework. Instead, many times it's "It's faster!" or "It's smaller!" or "It's everything you need!".

There is also the debate about functional programming and object-oriented programming, with many people looking to FP as the solution to all our problems. To be fair, these things are true. View-layer-only frames are smaller (at first), faster (at first), and are all you need (if you build or stitch a lot of stuff yourself).

Of course, functional programming patterns solve a lot of problems that plague JavaScript, and I think that, on average, JS is better because of them.

However, the reality is that there is no magic bullet. Applications are still large, bloated, and complex, state is still difficult to manage, and basic issues like routing and SSR still need to be solved.

For many of us, what people seem to want is to abandon a solution that tries to solve all of these problems and replace it with a solution that leaves readers to figure it out for themselves.

In my experience this is also a common practice among engineering groups who will happily embrace this change in order to deliver a new product or feature and then not fund the full development of all those additional features required time.

The result is home-made frameworks built around these view layers, which themselves are bloated, complex, and very difficult to operate.

I think a lot of the problems people have with SPA come from this fragmented ecosystem, which is happening just as SPA usage is exploding. I still often come across a new website that doesn't do routing correctly or handle other small details well, and it's absolutely frustrating.

But on the other hand, the existing first-generation full-service framework does not do a very good job in solving these problems. Part of this is due to a lot of technical debt baggage. The first generation frameworks were built before ES6, before modules, before Babel and Webpack, before we had a lot of things figured out.

Iterative evolution is very difficult, and completely rewriting them, like Angular did with Angular 2, kills their community's momentum.

So developers are in a dilemma when it comes to JavaScript frameworks - either choose an all-in-one solution that's starting to show its age, or jump into the free-for-all and DIY half the framework in hopes of getting the most out of it. good result.

This was very frustrating at the time, but ultimately led to a lot of innovation. The JavaScript ecosystem has evolved very quickly, and a number of other key changes have occurred as these frameworks figure out their best practices.

  • Transpilers like Babel become the norm and help modernize the language. Rather than waiting years for features to be standardized, they can be used today, and the language itself starts adding features at a faster, more iterative pace.
  • ES modules were standardized so that we finally started building modern build tools around them, such as Rollup, Webpack, and Parcel. Import-based bundling is slowly becoming the norm, even for non-JS resources like styles and images, which greatly simplifies the configuration of build tools, making them leaner, faster, and more comprehensive.
  • As more and more APIs are standardized, the gap between Node and web standards is slowly but steadily closing. SSR started to become a real possibility and then something every serious application was doing, but each time it was a custom setup.
  • Edge Computing is released, giving JavaScript-based server applications the distribution/response time benefits of SPA (Spas previously typically started loading faster due to being static files on the CDN, Even if they take longer to fully load and end).

At the end of this era, some questions remain. State management and responsiveness were (and still are) thorny issues, even though we have better models than before.

Performance is still a difficult issue, and although things are improving, there are still many, many bloated SPAs out there.

The accessibility situation has also improved, but for many engineering organizations it is still often an afterthought. But these changes paved the way for the next generation of frameworks, which I would say we are now entering.

Full stack framework

Personally, the last framework era has really quietly arrived. I think it's because I've spent the last 4 years or so digging into the internals of Ember's rendering layer, trying to resolve the aforementioned technical debt that affected it as a first-generation framework (still). But it's also because it's more subtle, because all of these third-generation frameworks are built around the view layer frameworks of the previous generation. These frameworks include:

  1. Next.js (React)
  2. Nuxt.js (Vue)
  3. Remix (React)
  4. SvelteKit (Svelte )
  5. Gatsby (React)
  6. Astro (Any)

These frameworks started as the view layer matured and consolidated. Now that we all agree that components are built on top of the core, it makes sense to start standardizing the other parts of the application - routers, build systems, folder structures, etc.

Slowly, these meta-frameworks began to build the same capabilities out of the box as the first-generation all-in-one solutions, cherry-picking the best patterns from their respective ecosystems, and as they matured And incorporate it.

Then they went one step further.

Prior to this, SPA has only focused on the client. SSR is something every framework wants to solve, but only as an optimization, a way to get rendered, and ultimately replaced when the megabytes of JS are finally loaded.

Only one first-generation framework dared to think further, Meteor.js, but its idea of ​​isomorphic JS never really materialized.

But as applications grew in size and complexity, the idea was revisited.

We noticed that it is actually very useful to pair the backend and frontend together, so that you can do things like hide API secrets for certain requests, modify header files when returning the page, Proxy API requests. As Node and Deno implement more and more web standards, and the gap between server-side JS and client-side JS shrinks every year, it's starting to look like it's not such a crazy idea after all. Combine that with edge-computing and amazing tooling, and there's some incredible potential.

The latest generation of frameworks take full advantage of this potential, blending client and server together seamlessly, and I can't stress how amazing this feels. Over the past 9 months of working with SvelteKit, I can’t tell you how many times I’ve sat down and said to myself, “This is what we should be doing all the time.”

Here are some of the tasks I’ve encountered recently, With this setup, these tasks become incredibly easy.

  • Adding server-side OAuth to our application so that the authentication token never leaves the server, as well as an API proxy that adds the token when making a request to our API.
  • Proxy certain routes directly to our CDN so we can host static HTML pages built in any other framework, allowing users to make their own custom pages (a service we provide for some clients).
  • Add a few different one-time API routes when we need to use an external service that requires a key (no need to add a whole new route to our API and coordinate with backend people).
  • Moving our use of LaunchDarkly to the server side allows us to load less JS, thus reducing overall costs.
  • Proxy our Sentry requests through backend routing so we can catch errors that go unreported due to ad blockers.

And this is just the tip of the iceberg. There are really a lot of cool things about this pattern, the biggest of which is how it reinvigorates the idea of ​​progressive enhancement, leveraging the combined features of the server and client to allow the client to fall back to basic if the user disables JavaScript HTML HTTP.

When I started working in spas, I myself had completely given up on the practice and thought they were the trend of the future, but it's possible that we're going to see a world where it makes a comeback, which is really cool.

These are new features. From experience, I classify these frameworks as new generation frameworks. Problems that were previously difficult or impossible to solve now become trivial, requiring only a slight change in response processing logic.

Reliable performance and user experience come out of the box and don’t require any additional configuration. Instead of building an entire new service, we can add some additional endpoints or middleware as needed. This has been life changing.

I think this generation also resolves some of the major points of conflict between the first and second generation frameworks and their users.

It started with a shift toward zero-configuration terminology, but I think it's ultimately driven by the maturity and stability of the ecosystem around second-generation frameworks, which is also a cultural shift.

Third generation frameworks are now trying to be an all-in-one solution again, trying to solve all the fundamental problems we as front-end developers need to solve - not just rendering.

Now more than ever it feels like the community is united in addressing all the many issues plaguing SPA and, importantly, solving them together.

Where are we going next?

Overall, I think the JavaScript community is moving in the right direction. We have finally developed mature solutions for building complete applications from scratch that are not "just a view layer".

We are finally starting to compete on the same starting line as native application SDKs, providing a complete toolkit that works out of the box.

We still have a lot of work to do in this area. Accessibility has long been an afterthought in the SPA world, and outside of GraphQL I still think data stories could use some work (like it or not, most of the web still runs on REST).

But the trend is right, and if we continue to move in the direction of shared solutions, I think we can solve these problems in a better way than before.

I'm also excited about the potential behind further elevating these patterns into the web platform itself. Web components are still being quietly iterated on, working on issues like SSR and getting rid of global registration, which will make them more compatible with these third-generation frameworks.

In the other direction, WebAssembly can iterate on this pattern in an incredible way. Imagine being able to write a full-stack framework in any language.

Isomorphic languages ​​like Rust, Python, Swift, Java, etc. can finally reduce the barrier between front and backend to almost zero -- just a little HTML template at the edge of your system (which ironically makes We've almost come full circle, albeit with a better user experience).

My biggest hope here is that we are moving past the era of fragmentation and the era of new JS frameworks every day. Freedom and flexibility breed innovation, but they also lead to confusing, disconnected, and often fundamentally broken experiences on the web.

When developers have to choose between 50+ options and piece them together with limited resources and tight deadlines, this is the experience we see, and it makes sense. Some apps are fast, consistent, reliable, and fun to use, while others are frustrating, confusing, slow, and broken.

If we could give developers tools that were easier to use and did the right things by default, maybe the average website would be better and the average experience would be smoother.

It won't fix every website -- no amount of code can fix poor UX design. But it will lay a common foundation, so every website starts out a little better and every developer has more time to focus on other things. ​

The above is the detailed content of Four eras of JavaScript frameworks. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:51cto.com. If there is any infringement, please contact admin@php.cn delete