inlivedev / inlive-website

inlive static site for blog and documentation
0 stars 0 forks source link

Make Tailwind CSS works on Hugo #2

Closed faiq-naufal closed 2 years ago

faiq-naufal commented 2 years ago

Updated because the previous issue is not relevant anymore I have mentioned in the comment below that the tailwind generated CSS file is not updated automatically by Tailwind whenever I write and put a new Tailwind class (which isn't generated previously). This is a quite problem because in this way whenever I try to write a new Tailwind class I need to stop the Hugo webserver and run hugo server again to generate the CSS file from Tailwind and see the result in the web.

We need to make the process automatically by leveraging the power of JIT mode in Tailwind 3, so whenever the developer write and put a new Tailwind class it will be generated automatically when the developer press "save" (change detected).

faiq-naufal commented 2 years ago

These are some discussions related with Tailwind CSS 3 with Hugo

faiq-naufal commented 2 years ago

Based on what I found, there are two ways of making Tailwind CSS 3 works with Hugo:

  1. Using NPM script just like on this comment and this example repo
    "scripts": {
    "start": "concurrently npm:watch:*",
    "watch:tw": "tailwindcss -i ./assets/css/main.css -o ./assets/css/style.css --watch",
    "watch:hugo": "hugo server",
    "build": "hugo --minify"
    }
  2. Using Hugo pipes without external NPM scripts based on this post. The example can be seen here.

I will try implementing with the Hugo pipes one, because there is no need to change and using the NPM script when we can actually use the Hugo one

tyohan commented 2 years ago

@faiq-naufal sorry i forget to add instructions in readme. We have package.json in repo. So we should run 'npm i' first when setup the repo. The repo already have working Tailwind postcss setup.

faiq-naufal commented 2 years ago

Mas @tyohan, thank you. I also forgot to install the node_modules, because I only followed the setup instructions in readme. I will update the readme later.

faiq-naufal commented 2 years ago

I have noticed the css file is not updated automatically whenever I write and save a new tailwind class that isn't generated from initial build hugo server so I need to stop the development and run hugo server again to generate the css file again. I will try to explore to make the process automatically

faiq-naufal commented 2 years ago

In order to automate the Tailwind generation file in Hugo, especially when the file changes (because user save the file) I tried experimenting with two approaches I wrote above :

  1. I tried to use only Hugo pipes approach by following this example. The explanation can be read here . Unfortunately, this will generate a lot of CSS files inside resources folder because in order to make the CSS watch happens the CSS need to be generated again and again with different file name (using Unix time here). I think this approach is not really ideal even though we can use hugo server --gc whenever we want to run the web server.

  2. I tried to combine the Hugo pipeline with NPM script just like in the first approach I mentioned above by following the example repo. Turns out this approach is easier to implement and because this is the similar approach with what I did in inlive repo for automating the Tailwind generation. Basically what I do is to make the Tailwind JIT CSS generation to run and work together with the hugo web server using concurrently. I create separate script in package.json for Hugo and Tailwind. And then I run the script together with concurrently. I also need wait-on library to make the Hugo script waits until the CSS file is generated by Tailwind, otherwise there will be an error. This is the scripts that I write

    "scripts": {
    "dev": "concurrently npm:watch:*",
    "watch:tw": "tailwindcss -i ./themes/inlive/assets/css/tailwind.css -o ./themes/inlive/assets/css/_generated.css --watch",
    "watch:hugo": "wait-on ./themes/inlive/assets/css/_generated.css && hugo server --gc",
    "build": "concurrently npm:build:*",
    "build:tw": "tailwindcss -i ./themes/inlive/assets/css/tailwind.css -o ./themes/inlive/assets/css/_generated.css --minify",
    "build:hugo": "wait-on ./themes/inlive/assets/css/_generated.css && hugo --gc --minify"
    },

And then, in head.html I use this code to get the generated file and put it into the link tag

{{ $styles := resources.Get "/css/_generated.css" | postCSS }}

{{ if .Site.IsServer }}
  <link rel="stylesheet" href="{{ $styles.RelPermalink }}"/>
{{ else }}
  {{ $styles := $styles | minify | fingerprint | resources.PostProcess }}
  <link rel="stylesheet" href="{{ $styles.RelPermalink }}" integrity="{{ $styles.Data.Integrity }}"/>
{{ end }}

I think I can make the CSS file generated automatically with the NPM script + Hugo pipeline approach. However, there is an adjustment when we want to run the local web server. Previously, we only need hugo server for running the local web server, but now we need to run npm run dev. This also applied to the build workflow. If previously we only run hugo for building the static assets, now we need to run npm run build. I will include these in documentations.

tyohan commented 2 years ago
  1. I tried to use only Hugo pipes approach by following this example. The explanation can be read here . Unfortunately, this will generate a lot of CSS files inside resources folder because in order to make the CSS watch happens the CSS need to be generated again and again with different file name (using Unix time here). I think this approach is not really ideal even though we can use hugo server --gc whenever we want to run the web server.

@faiq-naufal sorry if this is a bit late, just have time to take a look into this. If we use this approach, is everything working as expected? I think the idea of using a unique filename by appending UNIX timestamp in the filename is to make sure when we develop the website, we don't need to deal with a cache issue if we use a unique filename. This usually happens when you're not opening the browser debugging tool and you're not disabling the browser cache manually. Also this will not add more complexity to running the dev server. This is why most bundlers like webpack will generate a unique filename when they generate a bundle, to avoid the browser cache issue when we are in development.

My preference is always to avoid complexity if we can. How much effort do you need to switch this to the first approach?

faiq-naufal commented 2 years ago

Mas @tyohan, the first approach is working as expected. Indeed, by using the unique filename, we can prevent any cache issue during development. However, this will generate a lot of CSS files inside resources/_gen folder every time Hugo detects any change on development. This will make the project size becomes bigger quickly in the local. Please see the screenshot below.

Screen Shot 2022-02-25 at 10 04 27

Sure, we can clean the resources/_gen folder every time by using --gc flag when starting the local web server (ex: hugo server --gc). However, this clean up method only works on the first time when the local web server is starting. On file changes, the resources/_gen folder won't be cleaned up, and I still cannot find how we can clean the resources/_gen folder every time Hugo detects any change and generates the new assets.

The idea of having my local project becomes bigger because Hugo generates a lot of CSS files inside the resources/_gen folder is making me uneasy, although I can clean up manually by stopping and running the server again using hugo server --gc

tyohan commented 2 years ago

@faiq-naufal can we modify the head partial template mentioned here and remove the Unix timestamp from that template? So it will generate the same CSS filename. Or it won't update the file because it's using the same filename?

I don't mind having a lot of CSS files if the above approach of removing UNIX timestamp doesn't work, because they will be cleaned up every time I start the development server and also it won't affect the production deployment. This is better than adding complexity in our system.

faiq-naufal commented 2 years ago

Mas @tyohan, I already tried to remove the Unix timestamp, and it doesn't regenerate the CSS file again because when using the first approach we need to generate unique filename for resources.ExecuteAsTemplate each time the web server triggers a rebuild of the content as mentioned on this comment https://github.com/gohugoio/hugo/issues/8343#issuecomment-1013956389.

To convert my old approach to use this approach should not take too much effort. This approach is actually a hack approach. If there will be support from official Hugo on version 3 of Tailwind (currently still work in progress), we might need to adjust the approach again.

faiq-naufal commented 2 years ago

Also this will not add more complexity to running the dev server.

I want to know about the complexity that you mentioned above. Is it because the scripts in the package.json here increase the complexity? To start the local web server, we only need one command, npm run dev which is quite similar with the inlive repo

tyohan commented 2 years ago

Also this will not add more complexity to running the dev server.

I want to know about the complexity that you mentioned above.

Yes, adding NodeJS to the development part is one thing I like to avoid. I know it looks simple and similar to our inlive repo, but this is a Hugo repo which is a Golang repo, and adding NodeJS here (we already add Tailwind this way) is making us maintain Golang and NodeJS at the same time, something I like to avoid if possible. Looks simple for now, but it might keep us adding more NodeJS components to this repo later because we already have it.

I like to keep this repo just as static build website to keep it simple so we can just focus in the content.

Mas @tyohan, I already tried to remove the Unix timestamp, and it doesn't regenerate the CSS file again because when using the first approach we need to generate unique filename for resources.ExecuteAsTemplate each time the web server triggers a rebuild of the content as mentioned on this comment https://github.com/gohugoio/hugo/issues/8343#issuecomment-1013956389.

Let's keep the timestamp then, and just make sure to add the instruction in the repo to use -gc flag in the comment to make sure it will clean the previous build. This way, we can keep the development focus on Hugo, not involving NodeJS.

faiq-naufal commented 2 years ago

This is already done with this PR