Part 1 | Part 2

Table of Contents

Back-end challenges
    Avoiding reinvention of the wheel
    Implementing pragmatic APIs
    Implementing complex user workflows
Front-end challenges
    Building a single-page application to dogfood APIs
    Integrating Vue.js with Laravel
Conclusion


One of the most formidable challenges of implementing any large-scale enterprise website is the choice of a framework that will ensure both high performance and long-term maintainability. Tag1 recently chose Laravel to serve the needs of a customer that is a national organization providing for millions of users and hundreds of affiliate chapters across the United States. Laravel was selected not only because of its favorable developer experience and ability to simplify business logic but also due to its deep integration with Vue.js and feature set when it comes to building APIs for other consumers and services. The site in question required multiple levels of access control across arbitrary sets of users as well as workflows to allow users to modify details about themselves and learn about the benefits they are entitled to as part of their due payments.

In March, Laslo Horvath (Senior Laravel Developer at Tag1) got together on a Tag1 Team Talks episode with Fabian Franz (Senior Technical Architect and Performance Lead at Tag1), Michael Meyers (Managing Director at Tag1), and me (Preston So, Editor in Chief at Tag1; Senior Director, Product Strategy at Oracle; and author of Decoupled Drupal in Practice) for a discussion about how Tag1 implemented Laravel and benefited from its developer experience over the course of the project. In this two-part blog series, we discuss why you may want to consider Laravel for your next large-scale enterprise project. In this second installment, we cover some of the back-end and front-end development challenges that the team encountered as they built the project.

Back-end challenges

Before we proceed, I recommend you read through the first installment of this blog series as it contains key background information not only about the project we are covering here but also the rationales behind adopting Laravel for an implementation that was formerly in Drupal. In this section, we pick up where we left off and discuss some of the back-end development challenges the team confronted as they worked to build this project for an organization that needed to provide rich functionality for a wide array of users numbering in the millions.

Avoiding reinvention of the wheel

Laravel has many solutions housed in packages that work out of the box and allow developers to avoid reinventing the wheel. As an example, the client had begun implementing a generic filtering component, but the Tag1 team realized that as there was an existing package available, no custom development was necessary to switch to the filtering mechanism. This mirrors the commonly heard phrase in the Drupal ecosystem, "there's a module for that," or in JavaScript, "there's a Node Package Manager (NPM) package for that," though the latter may require many dependencies.

For myself and other readers accustomed to Drupal, we know that modules often serve a single purpose and thanks to the hard work of maintainers are usually of exceptional quality. Laravel and its surrounding ecosystem have the benefit of many high-quality and easy-to-use packages. This allowed the team to accelerate development in unexpected ways. For instance, as Laslo noted during our Tag1 Team Talks episode, the team endeavored to build APIs that could be generic, eschew code duplication, and provide for extensibility and certain actions without significant custom code needing to be written. Before starting any project, Laslo always confirms that a package handling a particular need is available.

Implementing pragmatic APIs

In the case of this Tag1 client, the APIs slated for development needed to leverage generic filtering, sorting, and eager loading mechanisms. Thanks to the Query Builder package in Laravel, maintained by a core Laravel developer, the team was able to provision API endpoints with necessary documentation and front-end and back-end touchpoints with minimal overhead. Fabian added during our conversation that this made returning relationships between items particularly easy. In a scenario where a single request required both a member's information and that member's address, housed in a separate entity, consumers solely need to add an include identifying the relationship to the API, thus providing an exceptionally straightforward developer experience.

During our episode, Laslo added that there are always trade-offs when it comes to API calls and front-end performance. He noted having seen applications where a list of a hundred entries (in this case members) with relationships to other entries (such as address, e-mail address, bank account, etc.) would require a server to pull a large proportion of information housed in the database on a single API call. Laravel is pragmatic in that it allows the implementation of pure APIs returning just raw data with appropriate consideration for asynchronous Ajax calls that come later.

Implementing complex user workflows

One of the features intrinsic to the project that generated considerable complexity was the member management workflows that required individual user actions to change certain aspects of their experience. Fortunately, thanks to Laravel Actions, complex workflows can be abstracted into individual actions (e.g. "set expiry date"). These actions can then be arbitrarily combined to form new workflows and reused in still other workflows. Laravel Actions call invokable classes that focus solely on executing a single action. Because this organization has many complex workflows in which certain membership and address changes may modify an affiliation, there are multiple steps the organization's three million users need to traverse. Laravel Actions made this process far more maintainable and graceful.

During our recent conversation, Fabian added that abstraction through Laravel Actions highlights the pragmatic nature of Laravel in that "it makes design patterns that are complex easy-to-use but not overly abstract." Laslo also noted that certain actions in Laravel can be defined as asynchronous, especially those that need to run in the background. Asynchronous jobs like exporting 20,000 rows in the database to a regularly generated comma-separated value (CSV) file can be designated with just a single line of code. As Laslo eloquently states, "If you're used to jumping through hoops to achieve your goal, it can be astounding to know that I can only add one line of code to make something asynchronous. When you do a lot of software architecture you realize that the complexity has to be housed somewhere. In Laravel, the complexity is taken away from you."

Front-end challenges

Another choice the development team needed to make had to do with the choice between leveraging a single-page application for the front end and sticking with a traditional monolithic application. As Laslo rightly states, there are advantages and disadvantages in both approaches, and monolithic architectures do have inherent benefits. Nonetheless, the web has been moving in a decoupled direction for some time now, particularly when back-office applications exist where search engine optimization (SEO) is less of an immediate concern.

Building a single-page application to dogfood APIs

With a single-page application approach, data management can become a key focus for internal users of an architecture where SEO is afforded less importance. This enables a better user experience, as users no longer have to wait for round trips to the server, especially given that many actions will only require a matter of milliseconds to complete and return a response. With such a full-stack architecture, however, where to place certain business logic becomes less clear, and key decisions have to be made about whether to store that logic in the front end or the back end.

In addition, dogfooding the provisioned APIs is of paramount importance, as it is possible that they will become orphaned without use in an application. This latter concern added weight to the notion of building a single-page application for this purpose, particularly given that many dynamic applications increasingly have the feel of desktop applications.

Integrating Vue.js with Laravel

Because Vue.js plays so well with Laravel and integrates with the framework so gracefully, Vue.js was the natural choice. As there are basic components that can require reuse everywhere across the application, the team also leveraged the Vuetify component framework for Vue.js (another example is Quasar) that plays nicely with a variety of Cascading Style Sheets (CSS) frameworks to boot.

With Vuetify's vast repository of components that can be plugged in and used immediately, this was the front-end choice with the most outsized impact on the rest of the project. After evaluating Vuetify, the team concluded that with components' morphological similarity to React components, along with certain elements favorable to developer experience such as a card component containing fillable slots nested therein, they could proceed with Vuetify to power a modern front-end experience for this national organization's membership application.

Conclusion

In this blog post, we covered some of the key aspects that highlight Laravel's suitability for large-scale enterprise projects like the one Tag1 recently built for a national organization with millions of members and hundreds of local affiliates scattered across the United States. Thanks to the back-end and front-end developer experience advantages intrinsic to Laravel's ecosystem, whether it involves easy setup of APIs or graceful integration with Vuetify, the team was able to conceive a modern approach to house both antiquated legacy data as well as an API-driven architecture that will stay resilient and maintainable for years to come.

Links

Special thanks to Jeremy Andrews, Fabian Franz, Laslo Horvat, and Michael Meyers for their feedback during the writing process.

Part 1 | Part 2


Photo by timJ on Unsplash