deep frontend integration

48 views
Skip to first unread message

Christian González

unread,
Jan 22, 2021, 2:43:53 AM1/22/21
to django-developers

Hello Django community,

caution: long post, TL;DR at the bottom.

in the past months, I tried much about tightly integrating a Js frontend framework into a bigger Django application. I already introduced GDAPS, a Django plugin system, where I want to have Dj apps bring their own frontend code with them.

I made a proof-of-concept with Vue.js, and now experimented a bit with Svelte, which I like more because it has no vDOM and it's maybe a bit easier to integrate. I think I tried every piece of code that is available in Git[hub|lab]* that sort of "integrates" Django with frontends. I wrote (or adapted another, djsnowpack) a middleware that injects output of e.g. snowpack into the Django dev http stream, so it combines Django with snowpack/svelte, which works too, as a concept


Most of them use or more of the following patterns, a liitle summary:

* Django parses it's templates, and produces HTML. In most of the cases the "templates" is just one index.html file that merely has static character and just is the "holder" of some <app></app> tag which will be replaced by some Js framework using injection or something similar. Django templates here are completely unused. No GenericViews, no DjangoForms, no SSR. Django mainly is the "backend" for an API. The Js frontend, whatever it is, neds to be either bundled using a Js or even node toolchain (webpack, rollup, snowpack, parcel etc.) which either compiles the complete frontend into a "static" website which then can be served from a web server.

Django could be replaced here using Express, or any API providing service, REST framework or similar.

* Others "combine" these technologies by adding "MPA" support, Django does the URL routing, has templates for every "page" then, and these pages are either spiked with Js pieces (like jQuery in ancient times ;-) ) - vue.js can be used like that, by just adding it "online" as script, and placing components into the templates. this is a little bit better, as it combines "the best of both worlds", as the tutorials say.

The downside here: you have to use a framework like Vue with a virtual DOM, which can be added to any static html page, and yoiu have to write all the Vue templates into Js code - the (really big) davantage of single file components (and therefore encapsulating functionality transparently) is gone completely, you have to write it (in Vue) like:

Vue.component('image-list', {
      data: function () {
        return {
          images: []
        }
      },
      template: `
        <div>
        <h1>Images</h1>
        <ul v-cloak v-if="images.length">
          <li v-for="image in images">
            <img :src="image.src" :alt="image.alt" />
          </li>
        </ul>
      </div>
      `,
    }
    // ...

This approach is more or less usable for independent apps that have their own "pages" in a bigger app, and for small components like the code example, just a few lines., You could even use Alpine.js in another page, within the same Django application.


But one thing lack all of them: when the good fairy told me I had a wish, I said: in my dream framework, I would like to have both advantages, without the correspoding disadvantage of it:

Django should process the Dj templates, using all the cool stuff it provides like extending templates of other apps, easy prefilling forms with data, reusable DjangoForms and Django Views, etc., AND, I want to have webcomponents like the ones you can build with Vue, React, Svelte etc. that are reusable too. Ideally like Svelte, without a virtual DOM. The Django dev server (or something else) should do that automatically. Single file components can be used, and provided even by other Django apps than the one that uses them (Django CoreApp provides webcomponent "foo", BazApp uses  <foo/> in it's template)


TL;DR

So, let's get closer to the point, and here is my question (and the cause I post this on django-developers):

Is there a possibility tweaking Django to integrate a frontend framework, keeping the Django template language, Views, Forms etc., AND using e.g. Svelte or Vue  (etc) - which need a compile step *afterwords*? HMR included

Django is known to be a bit "old-school" regarding frontend frameworks integration, and to be honest, this is true - there are plenty of cookiecutter templates, npx degit starter repositories, tutorials and the like, most of them a bit clumsy and outdated, no "batteries included" solution like Django itself - because there is no "API" for integrating frontend frameworks in Django, which all bundlers or frameworks could use.

So how would such a solution look like?

I could think of 2 things:

* creating/extending the DJango template backend which adds a compile step after parsing the templates.
    Downside: I've read that it may be not a good approach to let Django "spawn" the Js compiler.

* adding a Dj middleware that includes the framework "somehow" into the already parsed templates. Seems even more complicated to me.

* Use something like django-compressor with a plugin for that. Sorry, no HMR here during development



including e.g. Vue or Alpine dynamically comes close to my ideal, but I think a Js compile step is needed.

Do you have any thoughts here, hints about how to do that? Mission impossible?

Best regards,

Christian


-- 
Dr. Christian González
https://nerdocs.at

Christian González

unread,
Jan 22, 2021, 2:57:24 AM1/22/21
to django-developers

Ah, I forgot something:

* the Dj dev server serves static files "from their locations", e.g. the apps' static directories, which is great for developing with templates, but can not be used with a frontend framework, as this framework needs to be compiled *afterwords*.

* when going into prod, calling collectstatic finds all of them and puts it into STATIC_ROOT.
Then the compile step of a framework could happen.

So after each code change, I could call `./manage.py collectstatic` and keep the snowpack/webpack dev server running, wathing the "static" directory.

Which is kind of nonsense - BUT, like I asked, could it be a possibility to automate this process, to enable HMR for development?

Christian


Am 22.01.21 um 08:43 schrieb Christian González:
--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/45ae5c4e-ab1e-bbb5-9ed6-f71285306a08%40nerdocs.at.

Adam Johnson

unread,
Jan 22, 2021, 4:08:57 AM1/22/21
to django-d...@googlegroups.com
Hi Christian

I don't quite follow what you concretely want here. There are so many ways to build JavaScript dependencies these days, it's hard to keep track of, and Django thus mostly has a policy of "not touching that stuff".

The problems you describe in your second email are normally solved by doing things in the reverse order: doing your JS build, then Django's collectstatic. In development, you can proxy runserver with the webpack/etc dev server to get HMR (hot module reloading). In production, run 'npm run build', with webpack/etc dropping the results into a static folder, and collectstatic can then process them onwards (whitenoise and its manifest storage is popular).

Aymeric wrote a few good posts on build setups with React: https://fractalideas.com/blog/making-react-and-django-play-well-together/

If such a solution doesn't work for you, could you put together a more concrete proposal, perhaps with some examples of how you'd like commands to act, or even code?

Thanks,

Adam



--
Adam
Reply all
Reply to author
Forward
0 new messages