Hacker News new | past | comments | ask | show | jobs | submit login

Lately I've been developing with a JS workflow that's finally made me think "hey this is fun!" again:

Chrome target, native ESM modules, VS Code with JSDoc annotations for types. All libraries (chosen preferentially from microjs.com) are copied into vendor/, and the front end is written in preact.js using htm [0] for native JS tagged html strings, leading to code like:

  import ImageView from "./image-view.js";
  render({ trail_item, selector }, state) {
    /** @type {LinkItem} */
    let link_item = trail_item;

    let title = this.render_title(trail_item);

    let favicon = this.render_favicon(trail_item);

    let img = html`<ImageView src=${favicon} />`;

    return html`${img}${title}`;
  }
There's a VS Code extension which formats html`` strings as actual HTML, and the Typescript checker built in to VS Code gives me advanced types and autocomplete, all with a workflow that's as simple as "refresh page".

Granted, not every project can afford to target just evergreen browsers, but for my use case it works perfectly and I finally feel like I have the perfect blend of old-style web dev (in terms of refresh cycle) with modern language features and typing. The overhead, both in page-weight and cognitive load, is as small as I can make it.

EDIT: Modified my code sample to show how you can use Preact components in a JSX-like way.

[0] https://preactjs.com/guide/v10/getting-started/#alternatives...




Yeah, the microjs approach is much nicer than the Node approach.

I think the mistake of modern JS (and many other languages) is conflating source files with libraries. A better model is combining many source files into one library file, which provides one toplevel name when imported. A good example is how Three.js, which has a complex internal structure, gets distributed as one file and provides one toplevel name THREE. And of course there are many examples in C-land, where a large library can live behind a single header file. A project should only depend on a handful of those, and there should be few dependencies between them, so package management becomes easy enough to do by hand - just drop a file in your project's vendor/ directory.

As a bonus, this fixes the problem of having many fine-grained imports. If done right, your project's source files might not need any import statements at all. Anything inside the project could be available without ceremony, as if it was all one big file, and external libraries live in a handful of big namespaces which are also available without ceremony.


I don't know enough about Three.js to say if that works well for them or not, it probably does, but I don't think a future where all libraries would do this would be very bright. If the library is big, you'd end up shipping a whole lot of unused code to the client, making the end user bored and angry while waiting the page to load (especially if they are the sort of person who hangs around in Hacker News). In fact, the direction has been the exact opposite in recent years! Look at how lodash has moved to exporting one function per one file so you can include just as much of the library as you need.


I was mostly talking about how things should look to the programmer. The compiler could still tree-shake the final version.


Sure, it's just that the person you were answering to--and this whole thread really--seem to be advocating for just importing module files without any sort of build step. Without a build step I also assumed tree shaking wouldn't be an option. Tools that handle tree shaking, like Webpack and Rollup, aren't really the simplest of JS tools anyway so if we are talking about simplicity of dev experience, I'd argue that multiple direct file imports--how inconvenient it may be--is still _simpler_ to get right than "single namespace import" + tree shaking.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: