luminus-framework / luminus-template

a template project for the Luminus framework
http://www.luminusweb.net/
MIT License
648 stars 146 forks source link

Boot support #223

Closed arichiardi closed 7 years ago

arichiardi commented 8 years ago

I love Luminus, and I am kind of keen on boot as well.

While I was developing Yet Another Template, I was wondering if I could just add boot support (and option) to Luminus instead.

Would you be interested in a PR?

yogthos commented 8 years ago

Yeah definitely, the tricky part here will be to keep build.boot and project.clj in sync. The dependencies will be easy enough to factor out. However, stuff like cljs and db support will need separate configuration for each. Let me know if you need help navigating the project for the pr.

tolitius commented 8 years ago

this would "open up" Luminus to a lot more people, @arichiardi thanks for taking the initiative! :)

yogthos commented 8 years ago

the key concern here is in keeping it sustainable :)

arichiardi commented 8 years ago

Yes I have already a boot configuration that is kind of ok, I am more concerned about the template and all its options...

yogthos commented 8 years ago

Yeah, that's my concern as well. I'd like to avoid duplicating the options as much as possible.

arichiardi commented 8 years ago

No well, boot does not have a template system per se, it re-uses leiningen's, which will make things easier. What I am worried about is more that I have never written a template :smile:

yogthos commented 8 years ago

the template part is actually pretty easy. I'm thinking more in terms of conditional things in the generated code. For example, if you look here, there are lots of conditional pieces for cljs. The build.boot file will have to have similar logic and add code for working with cljs when +cljs flag is used to build the project. I think +cljs and +war might be the only things that need to be handled in a special way.

The dependencies should probably get pulled out into code in luminus.clj, I could look at doing that. Then the same dependencies vector can be used for both boot and lein.

arichiardi commented 8 years ago

Understand, boot's build file is actually task driven so the conditional part will just elide a task and the part where it is called, I am not worried too much about that. About the dependencies, yes probably we'd better read them from luminus.clj's options.

yogthos commented 8 years ago

sounds like a plan 👍

arichiardi commented 8 years ago

Another thing that worries me is how to handle the build tasks for frontend and backend, I have a WIP/prototype and I will polish it up and post if here maybe, if it is of your (generalized you) liking I can then integrate it. Being not declarative boot is a bit more "free" about implementation. I got a mix of declarative and not declarative so who knows :) It is my solution to the problem ;) The nice thing is that, thanks actually not to my work only, I am able to launch two repls (backend and frontend) with the same command: boot dev

yogthos commented 8 years ago

@tolitius can probably comment on this part best, I'm pretty new to boot myself :)

tolitius commented 8 years ago

Another thing that worries me is how to handle the build tasks for frontend and backend

@arichiardi what worries you?

arichiardi commented 8 years ago

So here is the template I am working on: https://github.com/Lambda-X/lambone/blob/template/resources/leiningen/new/lambone/common/build.boot

As you can see it is my interpretation (I like multimethods to describe flavors), but some people can find it "dense" :)

tolitius commented 8 years ago

Without using it, it is hard to definitively say, but I really like the approach. multimethods fit right in for the options, and being able to simply do boot dev to jump into dev right away regardless of frontend/backend ":flavor" is very much aligned with Luminus goals to be simple and easy to start and work with.

What is your thinking on plugging it into Luminus? i.e. so it can take options such as +cljs +aleph, etc. and plug in appropriate configs in case any are needed?

arichiardi commented 8 years ago

Yes I was thinking about something like that, every option modifies the build boot slightly, with common functions in boot.clj. I was even thinking of moving the task dev* in that namespace so that build.boot is not cluttered...

arichiardi commented 8 years ago

I need to analyze what all the options do one by one and reproduce that in boot, but probably some "template logic" can be factored out (for instance the part that creates the files for the database)

tolitius commented 8 years ago

all power to you then :)

might be good to have a corresponding file/function to a Luminus plugin (i.e. +aleph option would have its own file that does the magic)

there could be some restrictions/overlaps thought which might need more thinking: i.e. lib a config overlaps with lib b config, but it is not unsolvable

arichiardi commented 8 years ago

About the +aleph file, it is a very good idea and it would also enable other people to help me ;)

arichiardi commented 8 years ago

A question, in my template the file structure is divided in src/backend and src/frontend (and probably I will add a src/common or the user will need to add common stuff in env/dev/src). I see that Luminus does not have this but puts everything in one unique src.

Same goes for the dependencies, I divided mine in frontend and backend so that in the two repls I only load what is necessary.

Is it something you guys would be interested to adopt? Maybe it is a big task to accomplish...I could actually port back my changes to Luminus and not have the division...

yogthos commented 8 years ago

Currently the template will generate:

src/clj - Clojure sources
src/cljc - cross-compiling sources
src/cljs - ClojureScript sources

I think that's the same idea as what you're proposing?

I think it's generally easier to keep dependencies together in most situation, so I'd be hesitant to make the change to split those up.

arichiardi commented 8 years ago

@yogthos it is not the same because what if I have ClojureScript macros ? Those would go in a .clj or .cljc file, but isn't this file also going to be included in the uberjar?

Maybe it is intentional, that is why I was asking :smile: :dancer: :dancers:

yogthos commented 8 years ago

If you put the clj file in the src/cljs sources then it's only going to be used by the ClojureScript compiler. The Clojure compiler doesn't look at that source path.

arichiardi commented 8 years ago

Gotcha, that's what I wanted to hear :smile:

arichiardi commented 8 years ago

So about the backend vs frontend stuff, I haven not investigated yet, but is everything marked :cljs for frontend only? Can I assume that? Basically I would need a way to differentiate what goes in src/cljs, but I guess you do the same in a way while compiling the :cljsbuild profiles right?

yogthos commented 8 years ago

Right, everything in src/cljs is strictly ClojureScript, and the :cljs key is used specifically for generating stuff for ClojureScript support.

skovuri41 commented 8 years ago

fyi..found some relevant work to generate luminus templates with boot. https://github.com/seancorfield/boot-new/issues/18

arichiardi commented 8 years ago

Yes that generates it, but then you need to use lein. My original intent was to use boot for the generated project as well.

coyotespike commented 8 years ago

Just want to bump this issue. Using this post as a guide, I've tried to migrate from Leiningen to Boot, but it's a little tricky.

The Luminus template is a great fit for me, but I'd love to use Boot for the generated project.

DonyorM commented 7 years ago

Has there been any progress on this? Anyway I can help?

arichiardi commented 7 years ago

The port has not been started on my side, as I at the time I concentrated my effort on https://github.com/Lambda-X/lambone.

I still wish to have this but it is just too much work for me at the moment.

I can help with guidance though as lambone was actually easy to put together.

DonyorM commented 7 years ago

OK. I might try to work on this for a bit, since I need a project. I'll try and keep my progress public so others can offer feedback/help.

DonyorM commented 7 years ago

@coyotespike Did you ever succeed in migrating the project over? I'm having trouble on that step right now.

coyotespike commented 7 years ago

@DonyorM I believe I wound up more-or-less rolling my own, taking inspiration from Luminus as appropriate. I just really wanted Boot and System/Component, and had difficulties migrating to Boot.

Interested to see how it goes as you roll your own or migrate over!

DonyorM commented 7 years ago

@yogthos So I've gotten pretty far with getting a luminus project to run with boot. Now that that's done, I want to start making a template that would allowing running as boot. What's the best way for me to do that? Should I submit a PR to luminus-template?

yogthos commented 7 years ago

Yeah, I think adding a +boot profile would work. I think there might be some tricky pieces around lein plugins that some profiles use. For example, ClojureScript profiles rely on Figwheel that's not available via boot.

arichiardi commented 7 years ago

Well it is 😀 I am going to self plug https://github.com/boot-clj/boot-figreload 😀😀

yogthos commented 7 years ago

oh excellent 👍

DonyorM commented 7 years ago

I've got a first shot at boot support. It works fine for lein new luminus myapp +boot but I haven't looked into any profiles yet. I'd love for you all to give me some thoughts on what should be improved. And if you would like to help with supporting various profiles that would be great.

https://github.com/DonyorM/luminus-template/tree/boot

yogthos commented 7 years ago

Overall it looks reasonable. For features that modify project.clj, you probably want to have an equivalent boot version. The biggest one would be cljs profile.

I think in these cases it would make sense to create a separate namespace to track injections into build.boot. I'd create a common namespace that has dependencies so that can be shared, and then separate ones for boot and lein.

The common namespace could also check if +boot flag is present and call the function from the boot specific namespace as opposed to lein one.

DonyorM commented 7 years ago

Ok. I'll start working on those.

I have next to no experience with ClojureScript and its ecosystem, so any help there would be much appreciated.

yogthos commented 7 years ago

Looks like the figwheel task @arichiardi made would be the way to go. I'll try help with anything cljs specific. :)

DonyorM commented 7 years ago

Ok, I've got another rendition of edits available at https://github.com/DonyorM/luminus-template/tree/boot. Most things should work, except for uberjar related tasks. ClojureScript support is there, but there's a bug in boot-cljs that won't let me specify the :main tag, which makes it a little difficult to test. Once that's fixed I'll be able to do more.

I ended up making both a boot and lein profile, with the lein one as the default but having them mutually exclusive.

yogthos commented 7 years ago

it's looking pretty good so far. Hopefully boot-cljs gets the fix soon, and we can roll this out. Thanks again for spearheading this. :)

DonyorM commented 7 years ago

Hey all, it's working! If you run lein new luminus proj +boot you should have a boot-powered luminus project. All profiles (except cucumber and kibit, which don't have easy boot support yet) should work, but I've only tested cljs extensively.

I haven't yet updated the README of the template or the project itself yet, so ignore any inaccuracies there. Let me know if there's anything I need to fix (or create a PR if that's easier).

yogthos commented 7 years ago

🎉 Great news, might be good to add a conflicting profile check for kibit/cucumber and just write out an error saying that those aren't supported with boot if selected. I think cljs is the most fiddly part, the other features don't rely on much functionality in project.clj, so should be fairly agnostic when porting to boot. Happy to merge once you think it's good to go. :)

DonyorM commented 7 years ago

Cool, kibit and cucumber both throw errors if they are used along with boot, so it should at least fail somewhat gracefully. (I put that in the kibit.clj and cucumber.clj files respectively, if that's not the right place to throw the error, let me know)

EDIT: Just noticed that I had done something different for kibit, it will work, just needs to be called manually. So the template outputs a warning message if you use kibit and boot to let the user know the difference.

yogthos commented 7 years ago

Ah ok, that's reasonable. 👍

DonyorM commented 7 years ago

Great! I fixed up the READMEs and made a pull request. I made it a 1 commit PR, because I wasn't very neat when I was doing this and had several, unorganized commits, so I figured it was better to do it in one big commit (which you may have preferred anyway).

yogthos commented 7 years ago

Perfect, just merged in. I'll do a bit of testing locally, and then push it out. Thanks again for taking this one, looks like it's been quite an adventure. :)

DonyorM commented 7 years ago

You're welcome, I'm glad I could help. I'll try to get around to updating the luminus documentation as well.