tuist / SwiftyTailwind

💇 A Swift Package to pull and run Tailwind from a Swift process
https://swiftytailwind.tuist.io
MIT License
59 stars 7 forks source link

Add example code to run Vapor and Tailwind watch in parallel #27

Closed antingle closed 9 months ago

antingle commented 10 months ago

Because I am frequently testing different class values while using Tailwind, it is important to me that Tailwind is watching for changes and constantly regenerating the css. The .watch option is easy to pass and exactly what I need for this.

However, because I am running the Vapor server in parallel with the Tailwind watch process, it was not clear to me how to get them to run alongside each other. I spent a lot of time trying to figure out how to do this. Luckily I came across this syntax which finally helped me set it up:

let resourcesDirectory = try AbsolutePath(validating: app.directory.resourcesDirectory)
let publicDirectory = try AbsolutePath(validating: app.directory.publicDirectory)
let tailwind = SwiftyTailwind()

async let tailwindRun: () = tailwind.run(
    input: .init(validating: "Styles/app.css", relativeTo: resourecesDirectory),
    output: .init(validating: "styles/app.generated.css", relativeTo: publicDirectory),
    options: .watch, .content("\(app.directory.viewsDirectory)/**/*.leaf"))

async let runApp: () = try await app.execute()

_ = await [try tailwindRun, try await runApp]

I feel like this should be added to the README to help others save time and also set up the .watch function alongside Vapor. (Also I don't really understand why this works, so if someone could provide an explanation too that would be fantastic)

pepicrft commented 9 months ago

Hey @ingleanthony 👋🏼 I'm glad to read that you found a way to run the two processes side by side. First of all, I agree that we should add this to the README. However, I'd a modification so that we only do that when in #DEBUG

#if DEBUG
import SwiftyTailwind
// Do all the Tailwind stuff
#endif

When building the app for production, we don't want to link SwiftyTailwind at all. Instead, we want to have a script/executable that invokes Tailwind to output the CSS into the directory where the static assets live.

Also I don't really understand why this works, so if someone could provide an explanation too that would be fantastic

What's the piece that you don't understand? I'd happily give you an explanation.

antingle commented 9 months ago

@pepicrft thank you for the reply, and I agree with the DEBUG flag being added.

I was just curious about this line:

_ = await [try tailwindRun, try await runApp]

I've never seen this syntax with await followed by an array holding asynchronous functions. How does this allow them to run alongside each other when simply calling them on separate lines doesn't?

pepicrft commented 9 months ago

I've never seen this syntax with await followed by an array holding asynchronous functions. How does this allow them to run alongside each other when simply calling them on separate lines doesn't?

When you put them in an array, you have a collection of asynchronous processes that haven't been triggered. The triggering happens when you do await on the collection.

Both tailwind and vapor are long-running processes, meaning that once you await them, they run indefinitively until the process is terminated abruptly, for example by sending a SIGKILL signal (or in other words doing CTRL+C). Because of that, if you await one in one line, the execution will stay there forever and won't ever reach the second await.

Does it answer your question?

Would you like to go ahead and open a PR adding the example to the README?

antingle commented 9 months ago

Yes, thank you for the great explanation!