Urban-Analytics-Technology-Platform / web-app-template

https://urban-analytics-technology-platform.github.io/web-app-template/
2 stars 0 forks source link

CLI generator script #27

Open penelopeysm opened 2 days ago

penelopeysm commented 2 days ago

Closes #17

Test this out!!

npm create @uatp/web@latest

Select Rust, Python, or none. Then cd to wherever you set it up, and:

cd template_app
pnpm i
pnpm rust    # if you used Rust
pnpm python  # if you used Python
pnpm dev

and view on http://localhost:5173.

Overall thoughts

Readme

I've updated quite a few parts of the readme, so maybe it's a good starting point of what the repo looks like now.

https://github.com/Urban-Analytics-Technology-Platform/web-app-template/blob/create-template/README.md

@uatp on npm

I made a @uatp organisation on npm. (I mean, why not? But also to get the command above to work, the package has to be on the npm registry.) I will post about this on Slack and add everyone who wants to be added.

How to review this PR?!

Obviously, the code changes associated with this PR are slightly ridiculous and virtually impossible to review. I would like to suggest that you not evaluate it based on the code, but rather the effect ('try this out' section above).

Roughly, the steps I've had to do are:

As part of this PR, I've also removed some of Dustin's backend-loading code; I've replaced it with something I understood a bit better. Sorry!! For example the loading screen I think no longer appears and the initialisation calls are rather more dumbed down. My hope is that it is not too hard to add these back in as part of a separate PR.

Everything below this...

... is just finer detail. You don't really have to read it unless it interests you, or if you want to review this PR in more depth than 'works as expected'.

What does the repository reorganisation imply?

This PR will change how we view this repository. The repository contains the template, but the repository is not the template itself; it is code which generates the template.

Thus, most files will have to be considered from both a developer and a user standpoint. Take the simple example of a license. If we add a MIT license to the top level directory, this indicates that the entire repo structure is MIT-licensed. It does not mean that when someone runs npm create @uatp/web they will get a MIT license in their project: that is determined by the license file we put inside the template. This logic extends to other things, like documentation, as well as package.json.

From a workflow perspective, what this means is that you would only git clone this repository if you were a developer of the template. If you were just using the template, you'd just run npm create @uatp/web and be done.

I've documented some of these in the top-level repo README. I'm sure it can be more detailed, though.

The create-web script modifies the code?

Yes, that was really fun. You can see the script in packages/create-web/bin.js and packages/create-web/index.js.

This was a seriously difficult challenge because we want to accomplish several things:

  1. Retain the functionality of the template itself, so that local development on the template isn't prohibitively difficult. If the template cannot be built as a package itself and run with pnpm dev, it's going to be very hard to iterate on it.
  2. Avoid excessive code duplication. For example, we could simply have three different template repos, one for Python, one for Rust, and one with neither. The script would then just copy the appropriate directory. While this would work, it's not good as changes to Svelte code (for example) have to be made three times.
  3. A middle ground between generality and complexity. We want to be able to work on the template and somehow use comments to indicate "this bit of code needs to go into the Rust part". We don't want to write a script that excises specific line numbers in specific files because that will break (not general enough). On the other hand, I'm also not keen on reimplementing a whole templating language like Jinja (too general; and besides, Jinja code isn't valid HTML, see (1)).

I've written up notes on how I did this, and added them as documentation accompanying this PR: https://github.com/Urban-Analytics-Technology-Platform/web-app-template/blob/create-template/packages/create-web/DEVELOPER_NOTES.md

Did you write tests?

Yes, in the ci.yml GitHub Action workflow I've added tests which generate new web apps with Rust/Python/no backend and test that they build correctly.

Why didn't you use TypeScript for create-web?

Because then npm create @uatp/web has to needlessly pull in more dependencies before running, and we'd also have to add more bloat like tsconfig, eslint, etc.. For a script which is quite small and honestly isn't too hard to follow, I thought this was overkill. (As you can see in the commit messages, I started with TS and then ditched it.)

Why publish @uatp/components now to npm?

In this monorepo structure, our template app depends on the local version of components. This is specified using workspace: * in its package.json. This is exactly what we want for testing because we always want to test our local version of the template against the local version of the components.

When somebody sets up a new app using this template, they aren't going to have a workspace complete with the source code of the components library. (I mean, they could, in the sense that we could make the create-web script set that up for them — but it would be terrible practice because it would mean that every UA web app would bundle its own copy of the library.)

Thus, when setting up a new app for them, the create-web script has to modify package.json and specify an actual version of components to depend on. In general, we should assume that each version of the template app has a specific, known, version of components which it can reliably be built against. It will then be the user's responsibility to upgrade the version dependency if they want newer updates. (Note that this is true of every dependency in the template; components is not special in this regard.)

So, when a new user runs npm create @uatp/web, they will get a package.json that points to some version of @uatp/components, and if we don't publish components to npm now, they'll get an error when they try to pnpm i.

Does @uatp/template need to be published as well?

I don't think so, no.

But @uatp/create-web is published?

Yes, it's published so that npm create @uatp/web works correctly.