The zero-config usage of Parcel creates an SPA.
For many applications an SPA doesn't work out. (Because of search engines, social sharing, and performance.)
The main problem of our current tools is that they support only one app type.
For example for React:
By choosing one of these tools you are essentially choosing an app type and locking yourself into that app type. This means that before choosing one of these tools you have to research about what "SPA", "SSR", and "static website" mean and what the differences between them are. And that before even having started writing one line of code.
Even worse is that, most often than not, it's not possible to predict which app type is the right one before having created and battle-tested a first prototype.
Strictly speaking, saying that Parcel and Webpack create an SPA is not true. But creating app types other than SPAs (e.g. an SSR app) is very difficult with Parcel/Webpack alone.
From a user pespective, it would be neat to be able to use Parcel to easily create all kinds of app types. (SSR, MPA, Static Rendering, etc.) Basically having Parcel support all app types with (almost)-zero-config.
I can see that this would bring many problems from the perspective of Parcel's code architectural design. And Parcel would be less do-one-thing-do-it-well.
But, now that Parcel v2's core is small, maybe all app type support could be implemented as a suit of plugins instead of creeping all app type support into Parcel's core.
The best UI for all app type support I've designed so far is centered around:
Page configs:
~~~js
// A page config
// Also works with any other isomorphic view library such as Vue
import React from 'react';
export default {
route: '/hello/:name',
view: ({name}) => (
// By default, an SPA is built:
renderToDom: true,
renderToHtml: false,
/* To add SSR:
renderToHtml: true,
*/
/* For Static Rendering:
renderToHtml: true,
renderHtmlAtBuildTime: true,
*/
/* To remove browser-side JavaScript:
renderToDom: false,
*/
};
~~~
Render functions:
~~~js
// DOM Render
// This DOM render is for React but any kind of render can be written
// for Vue, Preact, React Native Web, etc.
import React from 'react';
import ReactDOM from 'react-dom';
export default domRender;
async function domRender({page, initialProps, CONTAINER_ID}) {
ReactDOM.hydrate(
React.createElement(page.view, initialProps),
document.getElementById(CONTAINER_ID)
);
}
~js
~
// HTML Render
// This HTML render is for React but any kind of render can be written
// for Vue, Preact, React Native Web, etc.
const React = require('react');
const ReactDOMServer = require('react-dom/server');
module.exports = htmlRender;
async function htmlRender({page, initialProps}) {
const html = (
ReactDOMServer.renderToStaticMarkup(
React.createElement(page.view, initialProps)
)
);
return html;
}
~~~
Server middleware:
~~~js
const express = require('express');
const parcel = require('@parcel/server');
const app = express();
// The parcel middleware serves your pages.
app.use(parcel);
// When the backend is a Node.js server, a middleware is super convenient.
// There are many reasons for that and I can elaborate more if you want.
~~~
To add SSR to a page you'd simply set renderToHtml: true. A static website can be built by setting renderHtmlAtBuildTime: true to all page configs. Browser-side JavaScript can be removed by setting renderToDom: true (super important from a mobile performance perspective). And so on and so forth. All app types are supported that way. This also intoduces new app types that aren't widespread (yet).
Not only does this design support all app types, but it also allows to easily switch from one app type to another. It would be super neat to have a (almost-)zero-config way to switch between app types. So that the user doesn't have to research what "SPA" or "SSR" mean before writing his first prototype. He can start coding and take care of the right app type later.
As far as I can see, this design could be a sweat spot between ease of use and flexibility.
The design can be used with any isomorphic view library. (With isomorphic view library I mean a library that can render views to HTML as well as to the DOM.)
Is supporting all app types something Parcel would be interested in?
I'm asking because I suspect that supporting all app types will need changes in Parcel's design, such as support for different targets for different entries.
It seems that a server middleware as shown above could be implemented as a reporter plugin. Instead of re-writing the dev server from scratch, maybe code from the current dev server could be re-used.
I'm busy at the moment but I'll further dig into all that and into the Parcel plugin APIs later.
I've said it many times already, but again, thanks for zero-config. It's wonderful to be able to quickly build an app without unnecessarily loosing time on infrastructure.
As far as I can tell this is entirely possible with Parcel 2's architecture.
Parcel 2's design doesn't really need to change, it's built to be really modular and #3302 is already on Parcel 2's todo list, https://github.com/parcel-bundler/parcel/projects/5#card-24711928.
Concerning these tools locking you in, I'm not really familiar with React's SSR/static tools but Nuxt.js(Vue) does allow for both SSR/SPA at the same time https://nuxtjs.org/api/configuration-mode.
I also don't think it's possible to easily support all of the framework out there as easily as you say it.
Supporting SSR/SPA/Static isn't just getting the dynamics parts from the url and rendering the template(view function) as you make it look like.
They each have component lifecycles, data passing from parent/child, ect, every different framework will need a lot of custom code to be supported.
And having a tool use these framework in an environment where they aren't supposed to work, force you to add APIs that will need to work with each of these frameworks(e.g SSR could use header data, while CRS not).
It's not for nothing that tools like Nuxt/Next focus on one framework.
This means that before choosing one of these tools you have to research about what "SPA", "SSR", and "static website" mean and what the differences between them are. And that before even having started writing one line of code.
The thing is, the 'only' real way to make SPAs is to use these frameworks, and they aren't really designed to be used outside of the browser, so the natural path to go about things is to first learn what a SPA is/do and then from there, learn about SSR and Static afterwards.
And it's not a bad thing, each of these types of apps have pros and cons and need to be understood by the developer before having to start writing code.
Don't get me wrong, I'd love to see a tool/framework that allow you to make apps that work everywhere seamlessly, but that's just not the case with how these frameworks work right now.
As i am not sure what you mean by
Basically having Parcel support all app types with (almost)-zero-config.
I can see that this would bring many problems from the perspective of Parcel's code architectural design. And Parcel would be less do-one-thing-do-it-well.
But, now that Parcel v2's core is small, maybe all app type support could be implemented as a suit of plugins instead of creeping all app type support into Parcel's core.
Is supporting all app types something Parcel would be interested in?
If you meant that Parcel should try and support it by itself(e.g via @parcel/react-ssr), i don't really think it's Parcel's job to support them.
If you instead meant that as just asking for #3302's support for the community/you to be able to do what you described, i'm all for it and highly encourage people to try and make that dream come true π.
By no means do I intend to replace CRA, gatsby, etc.
If someone wants to write a documentation website and React & GraphQL is his thing then Gatsby makes sense. It's clear that a static website is the way to go.
But if you're a startup, it's annoying to have to research all app types beforehand. And what's much worse is the constant anxiety of having chosen the wrong app type. That's bad.
How am I suppose to predict how my startup app will look like in 6 months? For the startups I worked at before, pivoting was super important. Any added architectural flexibility is a boon here.
the natural path to go about things is to first learn what a SPA is/do and then from there, learn about SSR and Static afterwards.
Yes I'd recommend that path as well.
Still, it is no fun to switch from CRA to Next.js. And sometimes I just want to experiment. I don't want to have to refactor my app for a week until I can test SSR to then realize I don't need SSR. And what if I want to add SSR to only a couple of my pages?
I also don't think it's possible to easily support all of the framework out there
I've already implemented a tool on top of Webpack that supports all app types. A friend of mine used it to built ghuser.io and he switched app types several times. It was easy each time.
The trick is that the tool implements things in an app-type agnostic way.
For example routing. By default the tool does server-side routing because it works with any app type. (You can still do browser-side routing if you want though.) FYI, all other tools out there do browser-side routing which is the reason why none of them support backend-only (that is no browser-side JavaScript and React/Vue is used only as HTML template engine).
Or another example is data fetching. To keep my post short, I've omitted an important aspect of the tool which is addInitialProps (it's similar to Next.js' getInitialProps).
This function allows you to fetch data in an app-type agnostic way. If you do renderToDom: true and renderToHtml: false (that is your page is an SPA), then your data is fetched in the browser. If you do renderToDom: false and renderToHtml: true (that is your page is backend-only and has no browser-side JavaScript), then your data is fetched in Node.js.
So far it really does seem that the set of configs addInitialProps, renderToHtml, renderToDom, renderHtmlAtBuiltTime, htmlRender, and domRender is able to support all app types and allows to easily switch from one app type to another.
People are complaining about JavaScript fatigue. Webpack has contributed to JavaScript fatigue — thanks to Parcel this is going to end, that's wonderful.
This app-type fragmentation contributes to JavaScript fatigue — it would be so nice to bring this to an end as well.
i am not sure what you mean
I meant whether Parcel is interested in having a plugin architecture that support such endeavour.
I hope it is and that Parcel core wouldn't need to change.
As far as I can tell this is entirely possible with Parcel 2's architecture.
Parcel 2's design doesn't really need to change
Ok neat. I'll have a look. I'll close this ticket if I don't need anything other than #3302.
3302 is already on Parcel 2's todo list
Awesome to hear &mdahs; I didn't know that.
highly encourage people to try and make that dream come true +1.
:+1: It is my dream as well :-)
But if you're a startup, it's annoying to have to research all app types beforehand. And what's much worse is the constant anxiety of having chosen the wrong app type. That's bad.
I don't know how much this happens but it seems like it shouldn't happen very often, have a performance critical application use SSR and/or Static, Frameworks like Next can do both automatically...
If your application isn't performance critical use whatever, it shouldn't matter in the end...
Never knew anyone who made a SPA and switched to SSR eventually, unless their application is performance critical and they didn't know anything about the technology to start with. But that seems like a lack of technical knowledge, which can be resolved by hiring an expert or research everything ahead of time...
I'm pretty sure your framework can't compete in stability and featureset compared to Next or Gatsby. These are both backed by a company, proper funding and a large community of companies and people using them.
The only role Parcel can really play in this is replacing webpack in Gatsby and Next. But that wouldn't change anything critical to the current ecosystem except for your application not taking ages to build and not requiring additional config... (which is a pretty significant impact, I've worked on many projects that take ages to deploy and even some that take multiple minutes just for HMR, which is insane)
It seems like this issue is mostly resolved based on the conversation. Parcel 2 wonβt be a full fledged app framework itself but one could be easily built on top of it.
@DeMoorJasper
I understand that feasbibility is a concern from your perspective. But note that:
It's not like effort for my tool = effort for Gatsby + effort CRA + effort Next.js. Not at all — my tool is only a page builder.
To give an order of magnitue of how small the tool is:
The core contains the logic for all-app-types support. The plugins are about integrations with various third-party libraries (path-to-regex for server-side routing, middlewares for express/koa/hapi, etc.)
What's most interesting here is that out of 7k helpers, 5.5k is about managing the Webpack compilations. The Webpack API is far from great and it's been a huge pain to build the tool on top of Webpack.
This means that more than half of the codebase is because of Webpack's shortcomings. And all complex code are all related to this code. The rest of the codebase, including core, is actually fairly straightforward.
My hope here is that using Parcel instead of Webpack would cut my codebase size by up to two. It will then be easy to maintain my tool once/if it's widely adpoted. E.g. the #3302 ticket will considerably help me.
Also I don't want to compete here. I would actually very much welcome frameworks such as Next.js to use my tool. If they switch to parcel, they might as well use my parcel plugin(s) that I will implement. (If I implement my tool as Parcel plugin(s)).
Btw. I've seen your POC blazingly — I'd be up to collaborate.
@DeMoorJasper @Banou26 @devongovett
To me, this ticket is not about whether my tool will succeed. Where I may fail someone else may succeed.
This ticket is about this: as a Parcel community, do we want all-app-types support?
I will be writing more about the various benefits of all-app-types support in the coming weeks.
It's not only about SSR and SPA. It's also about new app types. For example what I call "Backend First App": an app that is rendered to good old plain HTML (using React/Vue as HTML template engine). Almost everything is rendered to HTML and only a couple of interactive views are rendered to the DOM. This is wonderful for websites that are mostly about content, for example an online newspaper. Great mobile performance (since much less browser-side JavaScript), great SEO (since all content is rendered to HTML), interactive views, and fast dev speed (using React/Vue as HTML template engine is vastly simpler).
As far as I can see, all-app-types support will be obvious in the future. Just like it has become obvious that zero-config is the way to go for web app bundlers.
@brillout awesome, I always thought Next.js was heading that way with their framework. But anyway that's off topic for Parcel.
About my experiment with blazingly-ssr I'll probably be rewriting it again once Parcel 2 is a bit more stable, not sure if I'd turn it into a production ready tool though (probably more an experiment to showcase the posibilities of Parcel 2). Anyway I'd also be up for any collaboration on that, hit me up on twitter for that as this issue is probably off-topic for the Parcel repo.