-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Preact CLI #496
Comments
@developit I was talking to you about exactly this yesterday, all features mentioned 😄 |
@lukeed if you've got time, would love if we could summarize some of the notes shared about your WIP from slack earlier 😸 In terms of overall implementation and design for a Preact CLI, it would be great if we could focus on solving a few specific pain points:
|
@addyosmani Would be happy to but unfortunately will have to wait until tomorrow. Not enough sleep and too much time in front of my screen today means that I'm toying with a potential migraine right now. Full force tomorrow 👌 Will have time to work on my pwa-cli too! |
@addyosmani I'm building a PWA generator for different libraries. So far, I'm for sure implementing for Preact, Inferno, and React. At some point I plan to extend the templating to include Angular2, Polymer2, etc. Like most of the recent build tools, the CLI can run through a series of prompts (like Yeoman) or by passing in flags. pwa new preact --sass --no-offline
# or
pwa new preact # run thru prompts By default, all builds will be with webpack2 (but rollup is also an option for the smaller pwa), center around AppShell, and be capable of offline use. One may also be able to specify a preference for SASS, LESS, Stylus, or CSS-modules. There will probably be a Babel vs Buble choice too, with default on Babel. I'm not sure what other flags to include at this time, but we'll get there. Once an app is created, it will create a simple directory structure:
The important part here is that all configurations are easily accessible via For example, one may want to add or remove webpack chunks, be more aggressive with their code splitting, or add service worker behaviors beyond an offline precache. Now, let's assume a dev created a PWA with an older version of the CLI. After upgrading the tool, the project config is scanned & diff'd for upgradeable features (as long as the structure remains intact). pwa upgrade Then another CLI prompt list appears with the installable features (a la Yeoman generators upgrade), which are really just installable configs. This is because the CLI/local install will already ship with all capabilities, but only an file entry in Similarly, individual PWA & build features can be installable by name... or you may want to just add everything new: # caved & now need babel
pwa add babel
# add multiple
pwa add babel offline
# add all!
pwa upgrade --all
By "upgrading" to use Babel, a new files is placed at Regarding routes (comment at The problem here is that, so far, Preact & Inferno have each ported a different version of One way around this is to just create a new router for one of the libraries. But then I think that the CLI should not interfere with App code itself, that magic can be bad, and that there are too many options in this space & I shouldn't be forcing only one. So then the easy route (heh) would be just to stub a router template for each library. They're all fairly easy to work with & I personally find it reassuring to actually see the structure of my application. Plus, devs can pick 'n choose routers, or drop 'em entirely if they so please.
The application code doesn't affect the build operations, which is my only priority after leaving them with a customized (and further customizable) PWA in their preferred flavor of library. (Sorta came to this conclusion while writing 😄) I haven't published any of the code yet because it lives as a handful of scattered, working pieces. It definitely needs to be unified under one codebase before being looked at. And some of the behaviors described are still TBD, but within reach. This was probably a bit longer than I (or you) wanted... |
@lukeed would you be open to having an option to use an internal (or via Regarding router, I'd argue an async-aware router probably warrants a new (or extended) router entirely, similar to how Next.js ships with a next-aware Router. |
@developit Sure, I just don't want to lose the ability to persist & save a feature list across machines or installs. It should be a part of version control, if using non-defaults. A I'm down for hiding all default config, then exposing it when asked. Then anything inside Would a root file ( |
Last paragraph makes sense to me - basically a CLI accepts arguments, which are config, so those could be saved somewhere (perhaps in the |
Yup, I'll work towards that @developit. |
This sounds interesting! With at least libraries with a heavy Webpack stack, the tooling & plugins needed to wire up a PWA using a PRPL like pattern are pretty similar and I could see having a deterministic directory structure making this more feasible. Fascinated to see where this work goes.
To what extent were you thinking of defaulting to particular performance patterns for mobile web? For example, one could imagine service-worker precaching (for prod) being something you default to.
Ah! I see. We'd considered going down this route for Web Starter Kit at one point. I think the biggest design challenge we ran into was how much (if at all) a config/babel.js type thing would require configuration beyond what a developer is used to using. How well the config for one type of pipeline works with other pipelines (like offline) when the config is separate. Any thoughts on that? Other quick thoughts: I think the awesome CLI you're describing here Luke is an evolution of something like Speaking from our experience creating Yeoman, it's really hard keeping workflows (and tooling + boilerplate) for multiple frameworks up to date over time. We ultimately found you optimize some more than others & will get community buy-in for a smaller subset vs. what most framework authors ended up doing - creating their own specific CLI. Thoughts? I think it's great you're exploring the idea. Just thinking out loud if there's value in following the model other libraries & frameworks have taken lately on this one with a view to focus. |
Thanks so much @addyosmani for your feedback!
I'm starting off each install with the basic Lighthouse requirements, so that the user can see firsthand what a 100/100 score looks like (I still have to teach others how this can be done). This also includes a precaching service worker (for prod). And I'll start them off with an example of an App Shell, too. Not sure if you got a chance to look at my
So far it's actually been very painless! By now, Webpack has enough plugins & integrations with tools that it's extremely easy to separate a plugin from its options (babel config example). So long as there's organization to it (aka, not a mix & match of root files and config directory), the developer and the CLI system has a clear expectation & destination to find these. After discussing with @developit, I can even hide this pwa config babel
# => printed: config/babel.js
Definitely my only concern. My response to this is to only worry about the React family, for now. Polymer, Vue, and (I think) Angular are pretty solid at this point, so I don't need to try & "compete" with their workflows. Unless enough developers request for a copy in one of those, I consider them solved. And by keeping it to one family, it's actually been pretty easy so far to update all members. I don't need to illustrate every nuance of each library; just produce a working default & maintain a highly useful done-for-you-but-also-highly-configurable build system. 😆
This is actually one of my motivations for making this. There are so many boilerplates out there already, and in the case of React specifically, there are hundreds! Then if you filter down by star counts alone, there's probably half a dozen truly useful kits...but you have to "buy in" to the whole setup. I often found myself digging through config files to figure out what was going on, then reworking them, or gutting them entirely just so that I could get going. Essentially, I was just keeping the app code, which eventually was replaced anyway lol. And that was all after an hour of weeding through a bunch of setups to find one I could start from. So even though I'm adding one more boilerplate to the mix, at least for me, it's really important that a starter kit is illustrative in its application code & not overwhelm or force its users into an untouchable build system. |
Wow great work being done here! I cannot help myself but mention a few projects I have been / am working on that might be interisting if you want to create a full-blown app scaffolding for Preact.
my-server.js import express from 'express'
import uexpress from 'uexpress'
import myapp from './myapp' // myapp is a uexpress app
express() // the 'normal' express app
// .use(cookieParser) // .. express middleware
.use(myapp) // myapp is mounted in express
.listen(8080) // start the server my-client.js import uexpress from 'uexpress'
import myapp from './myapp' // myapp is a uexpress app
uexpress() // uexpress works in the browser
.use(myapp) // myapp is mounted in uexpress
.listen() // start the client Admittedly, Any thoughts? |
@Download All three look pretty slick, especially I've got a couple spare cycles in the next 2 weeks that I'll be spending iterating on some ideas I've taken from Addy's wishlist. I don't think it will look much like the things that have been shared here, which is intentional since I don't want to reinvent things that are already great. My goal is to produce a prototype CLI that accomplishes what Vue's CLI does, but for Preact. It'll be leaning heavily on things that already exist, I'm just packaging up a good set of defaults that can help people get started quickly. |
Ha ha yes. To be fair I just made a leaner version of I am infected a bit with this sick need to have the smallest possible web bundle and |
@developit Nice! 199b! |
Quick update: we've started work on the CLI and @developit is going to noodle on some prototypes. I'm sponsoring via OpenCollective as we ❤️ Preact and would love to see it lower the friction for folks building PWAs. The current plan is to try building Preact CLI on top of the work @ev1stensberg is doing for Webpack CLI. See how far we can get. |
Just one remark. I love most of the ideas here, but not the directory structure. The way it is organized currently in the example at the top of this thread, is by file type. That's not a modular approach imho. Adding a module / app / component / whatever it's called should not mean adding files to 5 different folders. Instead it should mean adding a folder with 5 different files in it. In other words, the directory structure should be ordered based on functionality, not file types.
I'd like to see:
Ideally, 'pages' as a concept would not be needed... The topmost component in the tree would be the 'page'. |
@Download this grouping is in Ember known as |
@MartinMalinda I don't have any experience with Ember, but in Django they do something similar. There they call them 'apps'. This was in fact one of the driving forces for my uexpress experiment; Express has the concept of mountable 'apps' that can have their own settings, routes, handlers, middleware etc. It works very well. |
I personally have a strong aversion to that structure, and I really haven't seen that practice since Angular 1.x days. There's nothing wrong with it, per se, but for my project(s), I went with the other structure because 1) it's more common now and 2) I prefer it. |
@lukeed I have trouble determining which of the two approaches (by file type vs by functionality) you dislike and which one you like. |
I like the one you proposed to replace 😜 |
@Download - I don't want to prescribe a folder structure, maybe we can have a config/cli option to specify a routable component filename pattern. |
👆 Agreed, 100% doable and allows people to be flexible about their scaffold. |
@developit agreed. having a |
Just important to get that format right. For now it'll be a CLI parameter ( |
💗 I was hoping you'd go the auto-split route. |
Preact currently offers great compatibility with the rest of the CLI tools offered by the React ecosystem. These include
nwb
, which exposes Preact scaffolding and flags for build-time switching to Preact and create-react-app which you can mostly drop Preact into.Increasingly, with folks seeing
preact-compat
as a stepping-stone into using Preact and more than just a drop-in for better loading perf than React in production, there are opportunities for Preact to define it's own CLI with Preact ecosystem best-practices. I see great opportunities for providing a "fast-by-default", zero-config experience out of the box ⚡️Something that encodes:
create-react-app
too), link rel="preload" and maybe even Service Worker support (e.g support viasw-precache-webpack-plugin
oroffline-plugin
) for Progressive Web Apps (as we documented here).preact-cli
to be a PWA by default 🥇 (the Service Worker caching would help with instant repeat visit perf on both desktop and mobile. Also opts you into V8's code-caching earlier).A common question we might get is "Why does Preact need it's own CLI? Why not just continue using create-react-app?". My view is that as much as possible, c-r-a are open to baking in ideas like performance best practices out of the box, but are going to need to balance that with DX and beginner-friendliness. I feel like Preact is targeting a more performance savy audience and this gives us opportunities to explore this space a little more ambitiously.
Like, what if Preact even baked in ideas like PRPL for you? or could intelligently help you figure out what needs to be prefetched. This might be out of scope, but just throwing ideas out there to see if there would be interest in something like this 😄
PRPL support becomes a lot easier to automate once you know the directory structure. We could potentially take inspiration from Next.js's
pages/
and introduce aroutes/
directory that gets paired withbundle-loader?async
in there.Thoughts welcome! I'm approaching thinking of this through a browser vendor's perspective (perf) but there are probably other takes and ideas folks will have on what this might look like.
The text was updated successfully, but these errors were encountered: