I’m sorry, the following answer is long. In short, maybe now is indeed not a good time for adopting a new framework (or library), but we should do long-term strategic planning how the admin site should evolve to support dynamic page updates to keep up with the modern web.
The main question to answer first though would be: What would we gain and what would we lose?
The losses have been already explored somewhat, let me bring up some gains by quoting the excellent reasoning of the Wikimedia Foundation folks from their Adopt a modern JavaScript framework RFC as they are in a somewhat similar (albeit seemingly more chaotic) situation technology-wise, using jQuery and server-side rendering:
The need to evolve our platform is very evident when it comes to how we design, develop, and deliver experiences to users in the browser.
WMF projects still rely on the same approach to front-end development that they did a decade ago: most user interface elements are built in PHP (often without relying on templating languages), and enhanced in the browser using jQuery and our own in-house frameworks (OOJS and MobileFrontend) and UI component library (OOUI). There are many pain points associated with this way of working in 2019.
Thoughtfully adopting a modern JS framework will provide many immediate improvements to the front-end development process at the Foundation, and will help to pave the way for further architectural improvements in the future. Some advantages of using a modern JS framework include:
- The ability to build UIs in a declarative way (describing what to build), as opposed to the present imperative approach (describing how to build it), leading to more concise code that is easier to reason about
- Better support for breaking up UI code into small, manageable components with clear separation of concerns
- Components built with a modern framework would be reactive (automatically responding to user input) out of the box, with no need for manual DOM reconciliation. This can potentially eliminate an entire class of bugs
- State management systems (Redux/Vuex/etc) would be available to help make complex data flows consistent and predictable
- Unit-testing of UI elements would be greatly simplified, leading to better test coverage and fewer bugs in our UIs
- The ability to do server-side or isomorphic rendering of UI elements opens up many new architectural possibilities that could be explored in the future
- Aligning front-end development within the Foundation to current best-practices in the larger web will simplify onboarding of new developers (a process that is currently quite painful and time-consuming, since many things need to be re-learned here) and lower the barriers to contribution generally
- Relying on tools that have large, active communities outside the Foundation will let us benefit from the larger community’s work (fixing bugs, writing documentation, maintaining the framework); this will also make it easier for innovations developed within the Foundation to be adopted across the wider web.
I like Adam’s thought that Django has outlasted many JS frameworks and should therefore steer away from them. However, I would like to point out that we already use jQuery and bring in more and more complex external libraries like Select2 for autocomplete, driven by pressure to "deliver [better] experiences to users in the browser".
I use and have seen others use a common Django project architectural pattern where
- the core end-user application is a SPA using a modern JavaScript framework (Angular, React or Vue) and ready-made UI components (e.g. Vuetify with Material Design components) that uses either the Django REST Framework or Graphene to access data,
- the back office management application for staff is generated with Django admin and is usually customized both in the server- and browser-side,
- there is a reports module that is raw SQL-heavy that may exist as separate, fully custom views in admin (see example here).
This has been a very successful application development model and although the admin is not the core front-end of the application in this approach, its full power and customizability is crucial for effective back office application development. Usually the data structures are complex and data volume is considerable, so, for example, autocomplete has to be used in foreign key fields to avoid loading massive amounts of data during page rendering etc.
In practical terms, here are a couple of use cases that I would argue should be easy to achieve in the admin site, but are currently not:
- You build a book publishing site for a publisher. Books and authors are managed in Django admin. One book can have many authors and the staff would like to see and edit author information in the book change view. As there are tens of thousands of authors, you have to use the Django admin autocomplete multi-select field. How can you show the standard related object popup, like when clicking the ordinary
ForeignKey
field widget pencil icon 🖉?
- Authors live in different countries and you have to enter the municipality/city where they live. How can you filter the municipalities autocomplete by the country drop-down as the selected country changes?
- When you issue the invoice for a book, you select the customer from the customers autocomplete. How can you update a HTML element on the page to show if the selected customer requests an e-invoice?
These are just examples, I hope you get the general point - as data volumes and complexity grows, solutions like autocomplete, dynamically updating parts of the page as selections change and elaborate components become more and more relevant. This evolutionary pressure has caused the emergence of modern JavaScript frameworks, design systems and UI component libraries and it will affect the relevance of Django admin - should one not use Django admin and rebuild the admin site as a SPA instead when needing this?
It would be interesting to hear what architectures do you use in large production applications and how do you manage the complex and dynamic requirements for the admin site.
I do not buy the size argument. The JS file can be cached easily and time to first paint (or whatever) is not really relevant for the admin.
Agreed. I brought up the size argument to emphasize that it does not affect page rendering speed like full-blown SPA frameworks would and can harmlessly exist side-by-side with jQuery.
With size (mostly) out of the way it would then make sense to focus on something with minimal dependencies and not requiring a complex buildchain.
Neither petite-vue nor Alpine.js have dependencies nor require a build step. Just including them is sufficient. Angular and React are out on that regard, as they both require a build step (React can also be used without a build tool, but it falls back on its imperative CreateElement API which is not ideal for general use). Vue.js can, however, be used without a build step as well, that’s one of the reasons why Wikimedia Foundation chose it.
Last but not least, from a purely security point of view it has to fully work with a strict CSP (I guess most do, but just throwing it out).
Good point, thanks for bringing this up! Quoting petite-vue docs:
petite-vue
evaluates the expressions using new Function()
, which may be prohibited in strict CSP settings. There is no plan to provide a CSP build because it involves shipping an expression parser which defeats the purpose of being lightweight. If you have strict CSP requirements, you should probably use standard Vue and pre-compile the templates.
Likewise with Alpine.js:
In order for Alpine to be able to execute plain strings from HTML attributes as JavaScript expressions, for example x-on:click=“console.log()”, it needs to rely on utilities that violate the “unsafe-eval” content security policy.
In order to accommodate environments where this CSP is necessary, Alpine offers an alternate build that doesn’t violate “unsafe-eval”, but has a more restrictive syntax.