본문 바로가기

코딩

django, HTMX, Alpine, Tailwind

728x90
반응형

django + htmx + alpine


릴리즈 AI 글쓰기: Django-Vite 워크플로우에서 Tailwind 플러그인, HTMX, Alpine.js 활용하기

이번 포스팅에서는 Django-Vite 환경에서 Tailwind CSS 플러그인, HTMX, 그리고 Alpine.js를 어떻게 통합하여 사용하는지 자세히 알아본다. 이 접근 방식은 다른 JavaScript 패키지 통합에도 확장 적용할 수 있다.

 


1. Tailwind CSS 플러그인 통합: Daisy UI 및 Flowbite

가장 먼저 Tailwind CSSDaisy UIFlowbite 같은 유용한 플러그인을 추가하는 방법을 알아본다.

1.1. Daisy UI 설치 및 활용

Daisy UI를 Tailwind CSS 설정에 추가하는 과정은 매우 간단하다.

  1. Daisy UI 설치: 터미널에서 다음 npm 명령어를 사용하여 Daisy UI를 설치한다.
    npm install daisyui
  2. 플러그인 선언: main.css 파일에 다음 @import 지시문을 추가한다. Tailwind CSS v3에서는 tailwind.config.js 파일에 플러그인 배열을 명시해야 했지만, 이제는 CSS 파일에서 직접 선언하는 방식으로 간소화되었다.
    @import "daisyui";
    /* 다른 Tailwind CSS 관련 import는 그대로 유지한다 */
  3. 테스트:
    • npm run dev 명령어로 Vite 개발 서버를 실행한다. (이는 package.json에 정의되어 있으며, 개발 중 핫 모듈 리로딩을 가능하게 한다.)
    • 다른 터미널에서 Django 서버를 시작한다.
    • settings.py 파일에서 DJANGO_VITE_DEV_MODETrue로 설정하여 개발 모드를 활성화한다.
    • localhost:8000에 접속하여 Daisy UI 컴포넌트(예: 버튼, 타임라인)의 HTML 코드를 index.html 템플릿에 추가한다. Daisy UI 스타일이 성공적으로 적용되는 것을 확인할 수 있다.

1.2. Flowbite 설치 및 활용

Flowbite 역시 유사한 과정으로 통합한다. Flowbite는 번들된 JavaScript 파일을 함께 사용하는 경우가 많다.

  1. Flowbite 설치: 터미널에서 다음 npm 명령어를 사용하여 Flowbite를 설치한다.
    npm install flowbite
  2. JavaScript 파일 임포트: Daisy UI와 달리 Flowbite는 CSS 파일이 아닌 main.js 파일에 번들된 JavaScript 파일을 임포트하는 방식을 사용한다.
    import 'flowbite'; // main.js 파일 상단에 추가한다.
  3. 테스트:
    • Vite 개발 서버와 Django 서버가 실행 중인지 확인한다.
    • Flowbite 문서에서 토스트(Toast)와 같은 인터랙티브 컴포넌트의 HTML 코드를 복사하여 index.html에 추가한다.
    • 페이지를 새로고침하면 Flowbite 토스트가 나타나는 것을 확인할 수 있다. 개발 서버 사용 시 초기 로딩에 약간의 지연이 있을 수 있지만, 프로덕션 빌드에서는 이러한 현상이 발생하지 않는다.

2. HTMX 통합

HTMX는 경량의 라이브러리로, HTML 속성을 사용하여 AJAX 요청을 처리하고 DOM을 업데이트한다.

  1. HTMX 설치: 터미널에서 다음 npm 명령어를 사용하여 HTMX를 설치한다.
    npm install htmx.org
  2. main.js 설정: Vite는 ES 모듈을 사용하므로, HTMX를 window 객체에 전역으로 노출시키는 방식으로 설정한다.
    import htmx from 'htmx.org'; // ES 모듈 import 구문을 사용한다.
    
    window.htmx = htmx; // htmx를 전역 객체인 window에 할당한다.
  3. HTMX 요청 테스트:
    • index.html 파일의 버튼에 HTMX 속성을 추가하여 GET 요청을 보내도록 설정한다. 예를 들어, hx-get="{% url 'index' %}"와 같이 설정한다.
    • 버튼을 클릭하면 HTMX 요청이 백엔드로 전송되고, 응답이 현재 요소(버튼)에 삽입되는 것을 네트워크 탭에서 확인할 수 있다.
    • 기본적으로 요청을 트리거한 요소가 응답 콘텐츠의 대상이 되므로, 의도치 않은 UI가 나타날 수 있다. hx-selecthx-swap 속성을 사용하여 특정 요소만 선택하고 교체 방식을 지정할 수 있다. 예를 들어, hx-select="#click"hx-swap="outerHTML"을 사용하여 클릭된 버튼 자체만 교체하도록 한다.

3. Alpine.js 통합

Alpine.js는 JavaScript 동작을 HTML에 직접 선언적으로 추가할 수 있는 경량 프레임워크이다.

  1. Alpine.js 설치: 터미널에서 다음 npm 명령어를 사용하여 Alpine.js를 설치한다.
    npm install alpinejs
  2. main.js 설정: HTMX와 유사하게 Alpine.js도 window 객체에 노출시키고 Alpine.start() 메서드를 호출하여 초기화한다.
    import Alpine from 'alpinejs';
    
    window.Alpine = Alpine; // Alpine을 전역 객체인 window에 할당한다.
    
    Alpine.start(); // Alpine.js를 시작한다.
  3. Alpine.js 컴포넌트 테스트:
    • index.html 파일에 x-data 속성을 가진 div 요소를 추가하여 Alpine.js 컴포넌트를 정의한다. x-data는 컴포넌트의 상태를 정의하는 JavaScript 객체를 포함한다.
    • 예를 들어, 토스트의 가시성을 제어하는 showToast 불리언 속성을 x-data="{ showToast: false }"로 설정한다.
    • 버튼에 x-on:click="showToast = !showToast"와 같은 클릭 리스너를 추가하여 showToast 값의 상태를 토글한다.
    • 토스트를 감싸는 divx-show="showToast" 속성을 추가하여 showToast 값에 따라 토스트의 표시 여부를 제어한다.
    • 이제 버튼을 클릭하면 토스트가 나타나거나 사라지는 것을 확인할 수 있다. 이는 Alpine.js가 성공적으로 통합되어 클라이언트 측 인터랙티비티를 제공한다는 것을 의미한다.

4. 프로덕션 빌드

개발 환경에서 잘 작동하는지 확인했다면, 이제 프로덕션 환경을 위한 빌드 과정을 살펴본다.

  1. 개발 서버 중지: npm run dev 명령어를 실행 중인 터미널을 중지한다.
  2. 프로덕션 빌드 실행: 다음 npm 명령어를 사용하여 프로젝트를 빌드한다.
    npm run build
  3. 빌드 결과 확인:
    • 빌드 결과물은 vite.config.js 파일의 build.outDir 설정에 따라 지정된 디렉터리(기본적으로 assets)에 생성된다.
    • 해당 디렉터리에 단일 CSS 파일과 단일 JS 파일이 생성된 것을 확인할 수 있다. 이 JS 파일은 Tailwind 플러그인, HTMX, Alpine.js를 포함하여 모든 필요한 JavaScript 코드가 하나의 파일로 번들링 및 압축(minify)된 상태이다.
    • Django 템플릿의 head 태그에서 {% vite_asset 'main.js' %}와 같은 vite_asset 템플릿 태그를 사용하여 이 번들된 파일을 참조한다. Django-Vite는 manifest.json 파일을 통해 이 참조를 실제 빌드된 파일 경로로 매핑한다.

결론

Django-Vite 워크플로우를 활용하면 Tailwind CSS 플러그인(Daisy UI, Flowbite), HTMX, 그리고 Alpine.js와 같은 다양한 프론트엔드 라이브러리를 효율적으로 통합할 수 있다. Vite는 Rollup을 사용하여 모든 JavaScript 및 CSS 종속성을 단일 파일로 번들링하여 프로덕션 환경에서 최적화된 성능을 제공한다.

이를 통해 깔끔하고 모던한 Django 웹 애플리케이션을 구축할 수 있으며, Tailwind로 스타일링하고, HTMX로 백엔드와 상호작용하며, Alpine.js로 클라이언트 측 인터랙티비티를 손쉽게 추가한다.


[참고] 더 복잡한 패키지(예: Three.js, React, Vue.js)의 번들링 또는 추가적인 고급 주제에 대한 내용은 댓글로 요청하기 바란다. 이 내용이 유용했다면 채널 후원을 고려해 주고, 구독과 좋아요도 잊지 말아 주기 바란다.

 

 


 
django-vite - HTMX, Alpine.js and TailwindCSS Plugin Installation

 

 

How do we use Tailwind plugins, HTMX, and Alpine.js in a Django-vite workflow? We're going to dive in and look at that in this video. Now, if you want to know the fundamentals of Django-vite, we did an introductory video on that, it should be appearing on the screen now, and that's going to dive into how to set up Django-vite and get it working in a Django application, but we're going to go a step further in this video and look at integrating other packages and Tailwind plugins into our application, and this approach is going to be extendable to any other JavaScript package that you want to bring into your application. Before we get started, if you want to support the channel, check out our coffee page, and thanks very much to everybody that supported the channel via coffee, and don't forget to like and subscribe as well. Now, what we're going to do to start with is, we're going to start by adding a Daisy UI plugin to the Tailwind setup that we got in the last video, so let's open VS Code.

 

This was our entry point, the main.js file, where we loaded in the main.CSS file, and if we look at that one, that's the one where we import the Tailwind CSS module. Again, for more information on this, check out that previous video. Now, we want to extend. Tailwind CSS with some cool plugins, for example, Daisy UI and Flowbite, so let's go to the documentation here for Daisy UI.

 

Now, of course, to start with, we need to install Daisy UI with npm, and then we're going to add this plugin directive here to the CSS file. So let's go back to VS Code, and what I'm going to do on the terminal here is run that npm install command, and we're going to install Daisy UI, and we can also go back to the documentation and copy this plugin directive here, and let's add that to our main CSS file, and it really is as simple as that if we want to add Daisy UI. If you remember, Tailwind version 3, you had to have a plugins array in the Tailwind config file, it's now as simple as declaring this plugin here with this directive in your CSS file. So let's test this out.

 

What I'm going to do on the terminal here is run the npm run dev command, and if you remember from the previous video, if we look at package.json, that is running the Vite development server. That's going to enable hot module reloading while we develop this application, and on the other terminal, what I'm going to do is start the Django server. Now, there is one change I need to make from the previous video. If we go back to settings.py, we have the Django Vite config here, and We set Dev mode to false at the end of that video, just to show how we would use this in production, but we're going to change that back to True here.

 

Now, once we've done that, we're going to go to Local Host 8000, and we have this page here, and what we're going to do now is try and add a Daisy UI component. So let's go to the Daisy UI documentation, and we're going to go to the button section here, and I'm just going to scroll down and copy some HTML. Let's grab this here, and let's go back to our application, and we have an index.html template. Now, to test that it's working, we're going to add this button here, and I'm also going to.

 

Add a color class here, so button primary, and we're going to save that. And if we go back here to our application, you can see we now have this Daisy UI button appearing, that's the Styles here, and that's the primary color, so that installation has worked. And with our Django-vite setup, if we go back to the config file here, we have this main.js entry point, and if we look at that file here, we're importing the content from main.css, and that includes now this plug-in directive where we import da UI, so we just need to install da UI and declare it here, it's that simple. And I want to add a slightly more complex component here.

 

From DA UI, let's try the timeline just to make sure everything is working. We're going to copy this code here, and let's again go back to our index.html file, and we're going to replace this button, and in fact, not replace, I'm going to paste this code underneath the button, and then we can go back to our application, and you can see we now have this timeline. So DAC UI is now installed. We're now going to move on to flow bite very quickly, and it's going to be a similar process, and I'll leave a link to this page below the video.

 

Here on the right hand side, we have a section for using the bundled JavaScript, so we're going to. Use that after we install Flowbite using npm, so let's copy the npm install command, go back to the terminal, and we're going to run that command. While that's running, we can go back here and check out this bundled JavaScript. So one of the most popular ways of using Flowbite is to include the bundled Javascript file, and we can directly import that into our main JavaScript.

 

That's what we're going to do now, so let's copy that, and there's a slight difference from Daisy UI here. Instead of the CSS file, we're going to use the JavaScript here, and at the top, we can just import Flowbite, and if we go back to the Terminal that's running V here, that should have reloaded and it should still be working fine, and we can then start the Django server at the bottom. And what I'm going to do is grab a toast from Flowy, so I'm going to search for that particular component, and we're going to go to this page here, and let's click this interactive toast that we have here, and we're going to copy the HTML for this. And if this has been installed successfully, we can go back to index.html, and I'm going to remove that timeline that we added and paste in the code for the toast.

 

And if we go back here to Local Host 8000, notice there was a bit of a Flash there, but eventually that has loaded, and we can see the toast here. Now, you will get this flash when you're using the Vite dev server, but when you build these assets for production, you won't get that flash. So, there's a slight bit of latency when the Vite dev server reloads and reserves these static assets, but we can now see that we have this Flowbite toast available, and if we click the cross here, that's going to remove that from the page. So, that's interactive, and it's using the JavaScript in the Flowbite package.

 

So, we can see now how we can integrate plugins for Tailwind CSS into our applications. We've done it with Daisy UI and Flowbite, there are also a number of others. If you have any recommendations or things you want to see on the channel, let me know in the comments. Let's now move on, and we're going to look at HTMX.

 

Now, I'm on the HTMX documentation, and we're going to go to the installation section of this documentation. Now, typically on this channel, we are using the CDN just to get up and running very quickly. What we're going to do now is we're going to look at the npm and webpack sections, so let's start by copying the npm install command, and we're going to go back to VS code, and we're going to paste that in there and install. Into this nodejs environment, now once we've got that installed locally, of course, it's going to add HTMX to the node modules directory, and we can then use HDMX very easily inside our build process.

 

Now, we can look at the web pack docs here, the process is going to be similar for vit in many ways. Vit is kind of like a replacement for webpack, but the Core Concepts are going to be the same. Now, we are going to need to modify it slightly, and that's because V uses es modules instead of common JS, and that means that this statement here, where we set the HTMX property on the window object, that's not going to work because of This require statement, so we're going to modify this input at the top very slightly, but I'm going to copy it, and let's go back to our application and go to the main.js. Now, just to make this a bit more clear, I'm going to remove the console log statements and those other imports, and let's import HTMX.org, but we're actually going to import HTMX from that package, and once we've imported HTMX, we can then start using the attributes, but we can also set it on the window object, so we're going to make HTMX globally accessible by setting on that window object, so window.HTMX is going to be equal to HTMX that we've.

 

Imported here at the top on line three. Now let's save this main.js, and that should trigger a rebuild here of the Vite development server, and we can now test, can we send an HTMX request? So let's go back to index.html, and I'm going to go to the top here. Let's go to this button that we defined, and I'm going to add some HTMX attributes here, so we're going to add a get request, and I have a URL in this Django application, so I'm going to use the URL template tag here, and the name of that URL is index. If we look at urls.py, you can see that one here, so let's close this, and we're going to save this file and see what happens now.

 

Going to restart the Django server on the terminal, and we can go back to the browser. So we're now on this page here, and if I click this button, notice that something pretty weird is happening. So this is definitely not what you would want to happen in a real application, but we're getting some kind of response here, and that is being swapped into the page. So that implies the HTMX is working, and if we go to the terminal at the bottom here, this is the request that was sent, and let's just look at the network tab to verify this.

 

So I'm on the dev tools here, on the network tab, I'm going to refresh the page, and then if we click This button, notice that we are sending this Ajax request to the back end, and that is all being triggered by HTMX, so let's close this off. We know that HTMX is installed and it's working, it's part of this vite build process, and it's contributing now to this crazy user interface that we see in front of us. Now, the reason this user interface is so bad is because we're sending this request to the index URL, and that's in turn hitting up this view here in the Django project, and that's returning the entire index.html template, and that's trying to swap that into the button, and the reason for that is that the button is. The element that's triggering the request, so by default that's going to be the target for the response content to swap into the DOM.

 

Now, we're going to fix this just to make it work, so we could, for example, give the button an ID here, and I'm just going to give it the ID of "click." And then from the response content, we could use HX-Select and only select the click button to make sure it's actually only replacing the button itself, and to replace that entire button, we can set the swap to Outer HTML. If you want to know more about these attributes, check out the HTMX series that we did that's appearing on the screen now. Now, if we go back here, we should be able to refresh the page. When we click the button, what's actually happening here is that the server sends back the entire page as a response, but we're only selecting out the button itself here by using its ID that you can see here, and the swap mechanism of outer HTML takes the original button here, and it replaces it with this new button coming back from the server.

 

So it's a completely pointless HTMX transition, but the point here is that HTMX is now installed and it's working in our project. We're now going to move on and we're going to look at Alpine JS, so Alpine JS is going to. be the last part of this video, we're going to add that to the workflow that we have, to the build process that we're using Django-vite for. So, I'm on the installation page of the Alpine.js documentation.

 

I'll leave a link to that below the video. There are two ways to easily include Alpine into your project: we can either include it from a script tag, or we can import it as a module. Now, the script tag is the CDN approach here that you see, or you can download the source code and just reference that locally. We're going to look at the module approach, so let's go to this section here and we're going to copy the npm install.

 

command. So again, when we're doing this, what we need to do is install these packages locally using npm, and that's going to install them into that node modules directory, and it will also install any dependencies of these projects. So Alpine JS is now installed. What we can do is go back to the documentation, and to import Alpine into your bundle, all we need to do is import the package, and then again, just like HTMX, we can set that on the window object, and then we call the Alpine.start method.

 

So I'm just going to copy these three lines of code, and we can go back to our entry point, which was main.js, and in this file. What we can do is just paste those lines of code, so now we're importing Alpine. We set that on the window object, just like HTMX, to make it globally accessible, and then we call Alpine.doStart. Now let's test this out and see if it's working.

 

What I'm going to do is go back to index.html, and we have this button here, and we have a toast underneath it. Now I'm going to start the server so that we can see what this is like, and we can go back to Local Host here, and when we refresh the page, we can see this user interface. What I'm going to do now is surround this content with a div, and we're going to make that an Alpine component now. The way to do that is to create an element, such as a div, and we can add an X data property to that element, and what we want to do when we click this button is we want to toggle whether or not the toast is shown on the page, so let's create an object here inside X data.

 

This is a JavaScript object, essentially, and it's going to have a Boolean property called show toast, and by default, we're going to set that to false, and then we can close the div off, and I'm going to tab all of this content over here, and that's going to live inside that Alpine JS component, and then we can close off the div at the bottom. Now, once we've added the component, let's scroll back up here to the button. When we click this button, we want to change the value of "show toast," and we basically want to invert that. So, for example, it starts off as being false, when we click the button, we want to change it from false to true, and the next time we click the button, we want to go back to false.

 

So, with Alpine, what we can do here is add a click listener here, and the statement that we're going to add here is we're going to take the "show toast" property, and we're going to set that to the inverse of whatever it is at the current moment, so again, from false to true, and so on. Now, once we've added That we can go to the div that represents the toast, and we're going to add a very simple property from Alpine.js, and that's the x-show attribute, and we're going to set that to showToast. So, in other words, when that value is false, this div and all of its children are going to be hidden on the page. They're not going to be shown, because x-show evaluates to false based on the state that we have in the Alpine component, and then when we click this button above, it's going to change the state of showToast from false to true, and therefore x-show will evaluate to true, and it's going to toggle this on the page.

 

Now I'm going to save. This, and what we can do, is go back to our application, and we can see that the toast no longer appears on the page when we click the button. It does appear, and we can now toggle whether or not that's shown just by clicking this button here. So this proves that Alpine is installed, and it's now working in this application, and with this setup in our Django application being powered by Vite and the Django Vite package, we're now able to build nice modern Django web applications using Tailwind and any number of plugins for Tailwind, as well as HTMX and Alpine.js, and HTMX is used for sending new requests to the back end, and Performing updates and updating the DOM in response, and you can, you can also use Alpine.js for client interactivity.

 

If you want to know more about Alpine.js, check out the video appearing on the screen now. And what Vite does in this workflow is it takes this entry point, which is main.js, and if we look at that here, this file here is handling the import of the CSS, and that CSS contains the import of Tailwind CSS and the DAUI plugin. And in main.js, we also import Flowbite, HTMX, and Alpine.js, so all of that is in the entry point, and Vite is going to use Rollup to bundle all of that into a single output file. Now we can show that output.

 

file. So what I'm going to do is stop the server here, and instead of mpm run dev, we're going to run the npm run build command, and that's going to build for production. Now, if we look at what's generated here, it's in the assets directory, and that's because in the build section of the V config file, we're specifying the assets directory as the output directory here. So let's go there, and we're going to look at the jangle assets that have been generated, and we can see we have a single CSS and a single JS file.

 

Now what I want to do is just look at the JS file here, and it's optimized for production, so it's been minified. A little bit, as you can see, and if we search here, for example, for HTMX, we can find that that code is part of this final bundle, and the same applies if we search for Alpine, code from the Alpine package is now part of this bundle that we're going to serve to our different clients that are requesting this application. And if we look at the base HTML file and go to the Head tag here, we're using the vite asset template tag to reference that entry point, and we can have multiple entry points, by the way, we have a single one here, and basically this entry point is going to be mapped to the built JS file that you see here, and that's Going to happen using this manifest.json file, if you want to see more about that, check out the previous video, but essentially, it takes that reference here and it maps it to this one here. So all of the code from the packages that we import into our entry point, and also any packages that those files that we're importing, is going to be included in that bundle and allows us to serve this single GS file back to our clients, as well as the CSS for Tailwind and Daisy UI.

 

So that's all for this video, if you'd like to see more advanced topics, potentially bundling more complex packages like 3GS or even React and VJs, then Let me know in the comments, and if you found this content useful, check out our coffee page. And thank you to everyone who's supported the channel, and don't forget to subscribe if you haven't already done so. Thanks again, and we'll see you in the next video..

 

728x90
반응형