Skip to content
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: Add an SPA component to the built-in components #1216

Closed
1 of 3 tasks
RafidMuhymin opened this issue Aug 24, 2021 · 18 comments
Closed
1 of 3 tasks

💡 RFC: Add an SPA component to the built-in components #1216

RafidMuhymin opened this issue Aug 24, 2021 · 18 comments

Comments

@RafidMuhymin
Copy link
Member

RafidMuhymin commented Aug 24, 2021

Background & Motivation

The Six UI frameworks supported by Astro for templating are primarily used for building SPA. But the application generated by Astro isn't an SPA. And, it's also not possible because Astro turns the component into plain HTML and ships zero JS!

But to enjoy the advantages of an SPA, I have written a tiny script for my personal project that can turn an Astro website into an SPA. It's not only just an SPA component/library but it comes with many other features also.

The complete list of features:

  1. It prefetches the internal links using Intersection Observer for blazing-fast navigation
  2. It upgrades from prefetch to fetch on mouseover and touchstart if the resource hasn't been prefetched already
  3. It caches the prefetched resources using the Cache API
  4. It intercepts when you click on an internal link and then it tries to serve the request from cache, if a cache isn't found, it fetches the requested page and replace the current documentElement with the new documentElement
  5. Then it executes the scripts of the navigated page
  6. It shows a fade-in animation when the new page loads
  7. It dispatches a prefetch function and navigate function that can be used for prefetching and navigating programmatically
  8. It has two lifecycle functions, onNavigate & onMount that can be called to add effects and execute code
  9. It also works with popstate events (back/forward navigation)
  10. It clears the entire cache on page load/reloads to ensure there's no stale content
  11. If data saver is enabled (on mobile devices), it won't fetch or prefetch the pages

Installing the plugin (Until it gets accepted and added to the core)

Once you setup your Astro project simply run the following command:

# yarn
yarn add astro-spa

#npm
npm i astro-spa

You can then import the component like this:

---
import { Spa } from 'astro-spa'
// or import Spa from 'astro-spa/Spa.astro'
---
<Spa/>

And that's it, you're now ready to go!

Demos

[https://astro-spafy-component-demo.netlify.app/]
[https://ohka-bots-site-astro-ksoqn4flk7-j2q7uvclm-tc-001.vercel.app/] (Thanks to @Tc-001)

Source Code

You can also view the source script file at this URL:
https://github.com/RafidMuhymin/travel-guru-astro-preact/blob/main/public/spafy.js

Help make it happen!

  • I am willing to submit a PR to implement this change.
  • I am willing to submit a PR to implement this change, but would need some guidance.
  • I am not willing to submit a PR to implement this change.
@okikio
Copy link
Member

okikio commented Aug 24, 2021

I'd suggest creating a separate SPA library just for Astro, or waiting till the appHistory api is complete. appHistory is a means of fixing all the bugs and issues involved with creating an SPA with the current window.history.pushState/replaceState.

@RafidMuhymin
Copy link
Member Author

RafidMuhymin commented Aug 25, 2021

@okikio The demo spa component already tries to fix the issues related with pushState. And it's also not only just a spa component, it also utilizes prefetching & fetching techniques combined with the Cache API to give a blazing-fast experience. It also allows you to add visual effects like transitions and animations. I think the appHistory API should be adopted when it'll be available. Because waiting years just for a good API isn't a good idea at all.

@okikio
Copy link
Member

okikio commented Aug 25, 2021

I think the appHistory API should be adopted when it'll be available. Because waiting years just for a good API isn't a good idea at all.

I understand your enthusiasm, I've also created PJAX library before (https://github.com/okikio/native), the problem is that there are too many pit falls and bugs involved.

My main complaint is that I don't think this should be built into Astro.

  1. Astro tries to ship 0 js by default. Let's stick to this for as long we can
  2. AppHistory will ensure a great SPA user experience so I thinks we should encourage that; its better to wait a couple years to ship a higher quality product than to rush to get the product out with more bugs.
  3. This proposal would be very similar to react-router or other SPA Frameworks, thus (at least in my mind) it should be a separate package not built into Astro

@RafidMuhymin
Copy link
Member Author

Well, there are a few differences between this and other spa frameworks. One of them is that it the motivation of Astro of less js or no js has worked behind it. So, I have written a spa framework which is under 1kb min+gzipped.

Secondly, if a user wants to use it, he'll use it, if not, then won't. He doesn't need to install another package! Like the client: directives, when needed they are added, if not, then not added.

And also I have tried to combine the best features and not use the unnecessary complexities of quicklink, turbolinks, instant.page and other frameworks.

However, I think it's a relative matter. Someone like me will use it, someone will won't. The same is about appHistory, you think not waiting for a couple years just for a great API is rushing, and I think it's reasonable.

I must check your solution. From a glance at the repo, it looks great!

@akaufmann
Copy link

akaufmann commented Aug 26, 2021

Great work @RafidMuhymin. Just a few points from my side, why I also think this could be a good 3rd party lib that could maybe be referenced by the Astro docs. I think the real strength of Astro is SSG/(ISG/SSR - maybe in the future) with a minimum of JS and it should focus on that and make it the best framework for that if possible. I understand it's convenient to have everything out of the box, but look at SvelteKit, there are still bugs/requests for a real SPA mode - sveltejs/kit#1650. Maybe it's easier in the Astro world, but once you get in there it's hard to remove this if it causes more problems. In addition to what @okikio said, I can think of a few more reasons why it's not best to go this route:

  1. You have to maintain it, and what starts small, smart and simple can become complex over time as different requirements are needed and required. Especially in OSS, everyone wants their needs met and the burden is (mostly) on the core developers. For example, what if I want a true SPA where header and footer are not replaced every time the route is changed but the slotted content is? What if I want child routes, auxiliary routes, all, none or only part of the linked content to be prefetched, etc.?
  2. Good tests are needed to check if the server and client logic behave correctly in different modes (SPA vs. MPA).

But who knows, maybe Astro will go the same way as Next.js and allow you to do client-side route transitions between pages and your lib is the starting point. :-)

@okikio
Copy link
Member

okikio commented Aug 27, 2021

@RafidMuhymin the App History api is already live in Chrome Canary as an experimental web platform feature https://web.dev/app-history-api/ so it's coming soon

@RafidMuhymin
Copy link
Member Author

@okikio great! Perhaps, I won't have to wait for a long time/rush!!!

@RafidMuhymin
Copy link
Member Author

Thank you @akaufmann. You have come up with some really good points. I though about one of them before, the one of containerization. I think these need some discussion.

@jasikpark
Copy link
Contributor

Why don't you publish this component on npm today, while this rfc is still being discussed so people can use it today! I have similar reservations of pulling this into core, but I'd love to see something like this with a great developer experience available in the community! https://docs.astro.build/guides/publish-to-npm -- there's a list of astro packages on this page that we probably need to update :D

@RafidMuhymin
Copy link
Member Author

Great suggestion @jasikpark! I'll work on publishing the component to npm this week.

@RafidMuhymin
Copy link
Member Author

RafidMuhymin commented Aug 28, 2021

Just published the component to npm! Run yarn add astro-spa or npm i astro-spa to install the package, and then import { Spa } from "astro-spa".

@matthewp
Copy link
Contributor

@RafidMuhymin This would be a great thing to show off at a future Demo day if you'd be interested some time.

@jasikpark
Copy link
Contributor

astro-seo is now featured on https://docs.astro.build/themes#featured-packages! I'm going to close this for now, but we can reopen if there's a new attempt to make this part of core, rather than a solid community contribution!

lmk if I should reopen!

@RafidMuhymin
Copy link
Member Author

@jasikpark Though astro-spa is now a featured package I still think this should be a core thing or an official package (this term wasn't available at the time I posted this RFC). Because the UI libraries that Astro currently supports for templating and adding reactivity, all are used primarily to build SPA.

@RafidMuhymin
Copy link
Member Author

@matthewp I'm interested in doing a demo video!

@okikio
Copy link
Member

okikio commented Oct 9, 2021

In my mind it shouldn't be a built in package, as it adds js to your page. In my honest opinion, it should be a separate package.

@RafidMuhymin
Copy link
Member Author

@okikio I agree with you. I was talking about official package not built-in in the previous comment

@okikio
Copy link
Member

okikio commented Oct 10, 2021

Wait I thought it was already official

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants