To whom it may concern...
sintaxi opened this issue Β· comments
I recently spent time evaluating the current landscape of Front-End developer tools and SSGs/Frameworks and I have come to the following conclusions...
Utility-first CSS is a major workflow paradigm shift
I've been playing with TailwindCSS (& purchased the TailwindUI tool kit). It turned out to be nothing what I expected.
-
Tailwind is a low level tool that can be used to implement any web interface. Tailwind is effectively an alternative to SASS/Less rather than an alternative to Bootstrap.
-
The Tailwind documentation is exceptional. The CSS/DSL is very good & the tooling is decent (for the most part). Tailwind has a strong team so I suspect the issues I have with the tools will eventually get worked out. Regardless, Tailwind is production viable right now and is likely to only get better moving forward.
For those who don't like the Tailwind approach, I'm not here to convince you otherwise. You should use the tools that best compliment your skillset choose the technology that has the downsides you are most willing to accept based on your values as a technologist.
ESBUILD and SWC are amazing - and they fit the Harp architecture perfectly
Those who are familiar with Harp know its a JIT in the true sense - in that the no compilation happens until a request is made to the Harp server (html/css/js). This is why Harp starts up so quickly and feels so fast. Harp can process Jade/EJS/Markdown/SASS/etc very quickly.
Unfortunately Harp never got a proper implementation of JavaScript bundling because the overhead was too high to build it with a JIT architecture - UNTIL NOW!. ESBUILD and SWC are now just as snappy to process as any of the other supported pre-processers in Harp - which in my view means resurrecting Harp is seriously worth considering. Perhaps I'm not alone.
The current state of Harp
I've been using Harp lately to play around with Tailwind and even though Harp is quite outdated it absolutely slays at building things with Tailwind. Templating truly is a strength of Harp and it shines in this case. For example, with zero-modification I can CMD-C
a component from tailwindui.com and paste it directly into a file named _navbar.ejs
then in my harp project then call partial("_navbar")
from any other template. Later I can effortlessly add some variables to the EJS template <%= myvar %>
or when It time to hand-bomb a component I simply use .jade
to take advantage of the terse syntax. Then I use .md
to add some content and style it by adding a content.sass
file. Even without any updates to Harp its already a huge win - but I see so much potential in what this could become - and the question is would it be worth the work?
Harp's deficiencies.
To put it mildly, Harp is fairly outdated at this point which makes its flaws apparent compared to modern alternatives. However although the deficiencies are significant I think most would be nearly trivial to address. Harps architecture is solid and IMHO would not need to change at all. As I see it, these are the following deficiencies in Harp...
-
Proper JS Bundling - Harp need to handle JavaScript better and I think ESBUILD is the ticket to having a flawless implementation. Should certainly add
.cjs
,.jsx
support and if it comes without much additional effort it should also add.ts
, and.tsx
support. -
Shared Templates Client/Server - Harp could benefit with a template that can be called by both server Side by the SSG and Client Side using react .jsx seems like a natural fit for this use case and I think with this feature Harp would be a great tool for projects that are a SSG/SPA cross-over.
-
Embrace
package.json
- It appears as though package.json is now the home base of every project. Harp should be designed and documented to be used in this way - especially if it has first-class bundling baked in as dependency management will be a requirement. -
New CLI - Harps CLI needs a refresh. This should be straight forward and easy to do.
harp .
to start the server andharp . somebuilddir
to compile the assets. Easy enough. -
Logging - Logging in harp is pretty much completely absent which is sad. Harp should provide useful logs for both when serving and compiling your site. Again, this should be an easy win.
-
Cut the Fat task complete! π - Everyone loves lightweight tools so Harp should leave what its not good at too other tools. (I have actually already started on this work - and last night cut down terraform from 53MB down to 7.7MB by removing pre-processors that are not very popular or and removing libraries that have negligible benefit.
Thats it for now. If you have thoughts on the past, present, or future of Harp I would love to hear what you have to say. Tell me, Is Harp worth resurrecting?
Over the past years I have switched bundlers many times, but for simple web projects and prototypes Harp is still my go-to. It's integration of pre-processors and webserver is just so nice to work with. I've never stopped using it (and was actually updating it today, which is why I'm replying here).
I agree with most of the points you're making and could definitely see Harp become my primary "platform" to build more sophisticated web-applications on when JS-bundling is implemented, but it's simplicity is also the main reason why it stuck in my workflow for over 5 years.
Thanks so much for your work on it!
I use harp constantly, every day, and it's made my life SO easy. Over time I have come to depend on it so much that I resisted learning Hugo or some other static site generator and rely on Harp, especially as so few support EJS.
From my POV, it's absolutely worth it.
@ameesme @smnsc Thank you both for your input and encouragement. It helps a lot. Glad to know I'm not the only one still using harp :)
Here is my breakdown of the pre-processors and their status moving forward. Let me know if this doesn't look right to you...
Processor | Cost | Status |
---|---|---|
.ejs |
864k | keep |
.jade |
1.8MB | keep |
.md |
320k | keep |
.sass , scss |
4MB | keep |
.less |
5.8MB | remove |
.styl |
2.9MB | remove |
.coffee |
1.8MB | remove |
.jsx , .cjs |
8MB | add |
Wait. Is harp coming back?
If yes, a way to add lifecycle hooks so I could add things like image optimizations or other mark up manipulation at build or run time.
@jdcauley Its looking like a yes, harp is coming back.
I like the idea. Do you have an API design in mind? I think it would be nice if it was unobtrusive so people don't have to concern themselves with it if they don't want to. perhaps a harp.config.js
file?
@sintaxi I haven't given it a ton of thought yet, 11ty has plugin capabilities that might be a good place to review for API design.
I'm excited about a Harp rebirth after finding most of the tools that have come up in the last few years require a bananas amount of initial configuration for something simple.
But the ability to use external sources to build from apis is a big plus, I think there is a way to marry the quick to start from harp with the flexibility and compilation in the newer tools.
IMHO as long as it's compatible with more recent versions of Node, I'm happy.
One of harp's best aspects is the way it allows you to forget about it.
That's a rare feature in the current FE tooling environment.
@smnsc absolutely agreed.
Item 6 is now complete. The cut down version of terraform is a 87.17% reduction in size with very little change in functionality. This is a huge win in my view.
version | size |
---|---|
terraform@1.11.1 | 53M |
terraform@1.12.0 | 6.8M |
terraform with esbuild (in progress) | 15M (est) |
I think I'll cut a release of Harp using terraform@1.12.0
so that there is a super lightweight version. Then I'll start adding those new features.
This is awesome, thank you, @sintaxi! π
@jvandemo thank you my man! Got any requests/suggestions?
What a time to be alive. I've never been able to find a tool to replace harp, I'm excited to see its resurrection. I always loved how metadata etc. just declaratively and magically exists.
I've been working with Svelte a lot recently and I absolutely love it. I tried creating static websites using Kit (formerly Sapper) but it's not the same. To be fair the project is in beta but I don't like some of the design decisions.
Have you ever looked into Svelte? It definitely fits into your lightweight concept. What I'd love to see as a first step would be *.svelte
as an additional way to create pages (SSR without hydration, just static HTML). I think passing data to the components would feel very natural, e.g.
_nav.svelte
<script>
export let current;
</script>
<ul>
<li class:active={current.source === 'index'}>
<a href="/">Home</a>
</li>
<li class:active={current.source === 'about'}>
<a href="/about">About</a>
</li>
</ul>
Maybe you'll fall in love with Svelte as much as I did π
@Prinzhorn I love this idea and I have heard a lot about Svelte - though it hasn't clicked for me yet. Looks like we are on the same page in terms of where this is headed. Your example is a good one.
The other day I spent a considerable time attempting to find an approach to get JSX to work both client side and server-side with limited success. The template I was trying to get working looked like this...
export default function(props) {
const { email } = props;
return (
<h1>{ email }</h1>
);
}
Using ESbuild I was able to get harp to automatically load React
into the template using a shim on the client-side but when attempting to load the template server-side it would break because of the mixing of CommonJS and ES Modules. Perhaps you have ideas?
In any case having a template solution in harp that works both client and server-side would be a huge win - and is one of my big ticket items I hope to have for v1 of harp.
Sorry for the wall of text π
though it hasn't clicked for me yet.
Svelte means pedal to the medal and you always work with the actual DOM and have 100% control. Svelte also means reactivity, consistency and declarative programming (I've recently looked at a React code base and it caused me physical pain with the amount of imperative code and boilerplate). It clicked for me once I understood how powerful stores are (in addition to all the other amazing features such as actions). What makes stores incredible is that for the consumer they have a tiny declarative API. It essentially looks like a variable you can use like any other. But it's reactive so that assigning something will make it update across your app and reading the variable will update the expression when it changes. But it doesn't stop there. The API for implementing your own store is incredibly simple. I've abstracted away localStorage
, fetch
, WebSocket
and Promise
using stores. That means I can declaratively just "use" them as variables and everything is pure magic. One great example is how I've abstracted feeds over WebSockets (I have a data grid with new rows arriving dynamically). For the consumer you literally just do this:
{#each $feed.data as item (item.id)}
<div>{item.title}</div>
{/each}
and it magically renders the items when new ones arrive (it will of course only render the new ones, because Svelte smart). Here's a somewhat realistic example:
<script>
import { createFeedStore } from '~/feeds.js'
import { writable } from 'svelte/store'
// filters is a store that is bound to the UI, e.g. the <input> below.
// When the user changes the "age" input it will cause the "age" property
// of the filters object to be changed.
let filters = writable({
age: 27
});
// When the filter store changes this will cause a new "feed" store
// to be created because of the reactive statement below.
// And this will magically cause the "{#each}" block to render my new items
// (and I've set the feed store up to add new items and merge changes via WebSocket).
$: feed = createFeedStore($filters);
// The way stores work means this line will also automatically cause all listeners
// to unsubscribe from the previous "feed".
// And this will automagically close the WebSocket because that's how I've set up my store.
</script>
<input type="number" bind:value={$filters.age} />
<!-- In addition to using the actual items via $feed.data I also have a feed.loading boolean to show a spinner. -->
{#if feed.loading}Loading...{/if}
{#each $feed.data as item (item.id)}
<div>{item.title}</div>
{/each}
Perhaps you have ideas?
I haven't worked with React since 2018, so not really. Also not an expert on all the bundling stuff, I just want it to work π
In any case having a template solution in harp that works both client and server-side would be a huge win - and is one of my big ticket items I hope to have for v1 of harp.
Before trying to make this compile, have you thought about how the API would look like? I'm having a hard time imagining how harp would wire this together given that it isn't limited to just React. Maybe we can start there, how would this actually look like? So the first part is easy I guess, just turning the component into HTML and serving it. Because the resulting page would still be a static page that can work without JavaScript(?). But then you have multiple components across your page that you want to hydrate, right? So it's not the entire page that is one big app, or is it?
What I personally need isn't SPA. I want pure static websites that work without JavaScript and that get progressively enhanced. But not into a SPA, but just the current page. I want websites, not apps (SPA and routers will surfaces some fun bugs). Currently all I need is a static website that has one dynamic form, everything else is just HTML. I don't want to push harp into Svelte, but it is very well suited because it doesn't come with kilobytes of runtime. It is compiled to just what is needed. So I think it would even be possible to hydrate multiple parts of a given page independently to make different sections dynamic. And without a router and runtime this would essentially be a better version of what we did ten years ago (serving pages and making them dynamic using jQuery) but it would actually be good π.
So to summarize: I don't need SPA, serverless and all that fuzz. There are still a lot of websites that don't need that and all the problems that come with it. But I don't know if that's what you want harp to be. Also if harp could then be transparently used as an Express middleware I'd lose my mind. Because then I can have a route that my form can be POSTed to (even without JavaScript) but when it is progressively enhanced I can use the same endpoint via fetch
with my dynamic form. But all this without the full blown frameworks that compile server side code that you don't understand. These are somewhat unfiltered thoughts, there are a lot of open questions.
Edit: Uh oh, I forgot about CSS. So with Svelte you just use <style>
and boom, it is scoped to the current component. The compiler can then turn all of this into one big CSS file (if you want) that harp could serve in production. But with HTTP/2 we might just as well serve only the CSS needed for the current page for ludicrous performance.
@Prinzhorn thanks for the detailed writeup. Lots to cover.
Full blown SPA is not where I see Harp going, for that there are projects like Vite which focus on that approach...with that said, there should be no reason one couldn't create a 200.ejs
& app.cjs
file and be on their way building a SPA using harp.
What's changing moving forward is Harp will develop rigid opinions about what a .cjs
file is and take care of the bundling involved in making that file extension useful. A developer should be able to drop a .cjs file into the project and start require()
-ing libraries they have installed via npm - and they are on their way. No need for Babel or Webpack or any of those highly configurable tools. In the same way .sass
file just works, Harp will do that same thing with .cjs
, .jsx
, .ts
, .tsx
etc...
Imagine if Harp just knew what to do with a .svelte
file without any configuration? That is where this is headed - and those are the doors that have opened now that ESBuild is in Harp. I cannot stress enough, ESBuild changes the game and it fits the existing Harp paradigm perfectly.
Imagine if Harp just knew what to do with a
.svelte
file without any configuration?
There's one aspect I'm not sure we're on the same page. A *.svelte
(or *.jsx
) file could be used in two (almost) completely unrelated ways. One would be as an alternative to a jade template and literally just turn it into HTML and stop there. The second way would be to have a <script src="app.js">
say inside an ejs template and that JavaScript file imports a svelte file/component to render on the client. The first one is what I'm looking forward to, the second one is what Parcel etc. are already capable of. If doing both is what you are aiming for then that's amazing, because then we can use SSR to generate HTML (basically "abuse" jsx or svelte as a powerful templating language) and then I could manually hydrate the parts I'm interested in by also importing that same component on the client. But harp doesn't magically do that for me, it's just something that becomes possible. Is this correct?
Yes, Both
Shared Templates Client/Server - Harp could benefit with a template that can be called by both server Side by the SSG and Client Side using react .jsx seems like a natural fit for this use case and I think with this feature Harp would be a great tool for projects that are a SSG/SPA cross-over.
I still haven't found anything that beats the Harp + Surge combo. It's the fastest and most efficient way to spin up new sites. That, in combination (and regarding tailwind), with a utility-first CSS framework with templating β it's been hella fast and efficient. The convention over configuration model is unbeatable!
Thanks @mosster! I'm glad you agree. btw - surge has been getting big updates lately and some really nice features are being beta tested right now. Let me know if you have any thoughts on the direction you think it should go.
So happy to see Harp is getting updates! I think there is also a use case for it that may not be obvious at first for more dev-minded people.
My background is more HTML/CSS... familiar with JS but not an expert by any means.
Harp is super easy for a designer to learn, the templates/includes are awesome, then compile it all and run it locally until you are ready to deploy is a highlight too.
I'm actually in the process of building a new personal site, so going to grab the latest Harp and get back into it.
My point being, Harp is a really great entry point for people wanting to get into Static Site generation. I'd recommend keeping the easy-to-use aspects in the tool as you continue to build it out. Thanks!
+1
Woohoo, great news. Gotta get back to this.
I've been on harp.js probably like ages ago, while transitioning to Jamstack.
Happy to see this coming back alive!
I'm a math and computer science professor at a small liberal arts college in Kentucky. Every two years I teach a class in Web Programming, and I always include a unit on static-site generators. I started out using Harp because of its conceptual simplicity and its base in JavaScript, and I have always been a big fan. For the Fall 2020 iteration of the course, fearing code-rot in Harp, I switched to Hugo. I would switch back for the Fall 2022 offering if Harp is still being maintained.
@homerhanumat Harp has undergone a lot of maintenance this past year and is in very good shape right now.
Biggest change since you last used it is ESBuild is now built in and preprocesses .jsx automatically to .js the which makes it a fantastic option for react development.
Reach out if you have any questions.