Ah, that’s why I couldn’t figure it out. Thanks for the quick update.
Some generic feedback/rant
TBH I find the front-end side of templates hard to understand at times, there’s just so many things going on. The back-end is another story; it’s been relatively stable for years, just some changes around how ASP.NET loads files I believe, so “modular” is now more built-in than before, and some new things to learn due to ASP.NET’s “no class” Program.cs - but that’s MS’s changes, probably to appleal to an audence grown up with ExpressJS and the likes. I really like the x.Conf.cs files which plays nice with x mix.
On the front-end side, it’s harder to understand if the templates are meant as a showcase or starting point. There’s so much going on that it’s hard to grok. I’ve always enjoyed the new version announcements, with all the new stuff and code samples, but there’s a difference in usage between “read to enjoy” and a template. In my view a template becomes your own code, so it must be understood 100%. This is in contrast with say a library, where it’s OK to be a black-box as long as you know how to use it.
The front-end templates have so much different tech, such as Razor (is this now MS Razor, or SS variant?), SharpPages, pre-rendering (at least of Markdown), Vuex-style routing (nice for pages, but parameters, auto-componentization, auto-import, auto-icons, SWRV, Typescript (yes it does complicate a lot actually, lot’s of extra syntax). For a Vue app sometimes some of the pages, e.g. index.html are built built partially with Razor/SharpPages. Then there’s the new SS useXXX stuff. As an example I tried the useClient (in a plain Vue app, not from SS template) and it did not work. Nowhere could I find where the URL to the API was supposed to be given to a constructor or factory function. Digging into the source code, it seems the JsonServiceClient is injected by Vue, but then it must be registered somewhere. In the SS template it works of course, just an illustration that the individual pieces can be hard to understand. I ended up using the JsonServiceClient directly instead.
I could add MJS and the previous VueLite templates as further examples. I find the MJS very cool (a non node_modules future), but I guess at some point you want to add a library that doesn’t come packaged this way, and end up with npm/yarn anyway?
I know this is very critical, it’s just some feedback from me, having struggled for a long time with the templates. My strategy for now is to use most “vanilla” flavor of anything – then there’s lots of information and examples everywhere, and easier for the next guy to read my code. So vanilla SS being server-side, with the vue-components mostly for Locode customizations, and for a full front-end just vanilla Vue w. possibly a stable, full fledged, well documented (also training material) UI component framework. Only interaction will be JsonServiceClient (axios also works, but JSC saves some typing) and copying dist into SS’s wwwroot at build.
Is this complaining about there being so many different templates to choose from or that a single project template has so much different technology crammed into one, if so which template do you have issues with?
From the sounds of it your listing different technologies used across many different project templates? which is expected when there’s so many different UI technology stacks & approaches that modern websites are built with.
Did you register the JsonServiceClient instance your app should use into your Vue App?, e.g:
All providers are injected into the Vue App at construction (created with createApp()), this is where you would register all the providers your different app components want to have access with like client and store if your App uses one.
Now that all major browsers have native support for import maps the future is going to have less need for relying on an npm build system.
If you’re overwhelmed with the Vue Jamstack templates than I’d recommend choosing the simpler npm-free templates like vue-mjs or razor-tailwind (or razor-pages if you prefer Bootstrap)
I don’t mind constructive criticism when it’s actionable, but I’m finding it very hard to extract clear actionable concrete examples that can be improved from in this rant. It would be more helpful if you list each individual criticism clearly so I can better understand and respond to whatever you have issues with.
My apologies, sometimes it’s too difficult to give constructive criticism. I would if I could, but that’s the case when one gets overwhelmed.
Not asking you to change anything, just thought some generic feedback could be useful. Negative feedback like this quickly becomes complaining, I know, but at least it’s not behind your back or in some public blog where you couldn’t respond.
It’s not just me. I have two coworkers also using/quit SS. One couldn’t take it anymore after a week (overwhelmed), but the other one pushed through on a small project (read a lot of the doc, but told me it was a difficult read, and honestly I think he wouldn’t have stayed if it wasn’t for me showing him the ropes of SS and the quick responses in this forum).
To be concise I’ll say is that I find both the number of templates (confining myself to Vue, there are currently 13 templates, 9 for NET Core) and the amount of tech within some templates overwhelming.
As mentioned before, I don’t mind if a library, such as SS’s internals or Pinia’s source code, is complicated, because that’s not “my responsibility” to understand. However a template becomes my code the moment I write my program from it, and thus I need to understand all of it.
Take vue-vite as an example (want to have node_modules, because I like to have to choice of libraries, and I don’t want to be trapped at a later time by choosing vue-mjs now). Also most examples on-line use npm and access to material on-line is very important.
I believe that this template represents best practice, and that I should use as much of it as possible. Everything in it is probably there for a reason, and for that purpose I’d like to understand.
Idea: would it be possible to approach this by adding functionality incrementally? No idea how this could be done, but how this was solved with x mix server-side is very nice.
For this single template there is a large cognitive overhead. Extras compared to a bare-bones Vue/Vite:
I used some time to figure out what API_URL would be, looks like 3 possibilities.
deploy api (=production)
Where dev-api and ‘’ would be the same? Then there’s the option to use Vite’s proxy as well.
If both developing locally npm run dev plus sometimes testing a local build, a “dev server” build and a production build, it’s hard to know what is what sometimes. Not impossible of course. In a way, the use of .env.XXXX files is easier, better documented etc. Build for XXXX and you get whatever’s in that file – use it everywhere with import.meta.env.VARIABLE_NAME
The routing.ts is unlike a standard Vue router file you see most places, meaning that even if one knows Vue, there’s more to learn: Looking at the “route guard” for example.
Most examples add the authRequired or similar next to each route. Then in a beforeEach this is checked against a global variable or a store. Easy to understand. Or if most of your site is private, one could even hard-code in only the public paths right in the beforeEach.
In the template however, the route guards is listed in an array separate from the routes. Where are the routes? Oh yes, filename-based. So my guess is that it’s pretty easy to forget to add a route-guard.
The beforeEach is very different from usual. There’s a separation between loading or not, where the loading comes from a different file (the auth.ts). There’s a watchEffect with a stop function, which I believe will stop an ongoing auth request if the user clicks another route before auth is finished. Don’t know if I’m right about that, or why it’s needed when I don’t see anybody else doing it like this. It’s there for a reason, I just don’t now what it is, if I need it, and so on.
Took it from memory, so I guess I have mixed in from different templates yes. I believe there are templates using Vue on front-end plus Razor/SharpPages on back-end, but I don’t remember.
No I didn’t know about that (same as the DI in SS?), just wanted to try out some of the useX outside of a template. Thanks for clearing that up.
Yeah, sorry. Perhaps a mailbox that goes to /dev/null would be good for these types of posts ?
Never said the templates were anything but perfect, just that I’ve always found them too complicated and different from “standard”, so the cognitive overhead is large, and that’s why I’ve stuck with “web empty” or something using SS only on server-side, and using the templates as an inspiration on what to read up on, then creating totally separate UI projects with Vue/React (and even Axios instead of JsonServiceClient, because the latter requires the DTOs to work).
Is it just that they find Vue SPA projects complex? Are there other Vue + Vite + .NET integrated project templates they think is simpler to understand / use? If you didn’t have to integrate with backend auth the templates would be much simpler.
These are just a fraction of the different options available to build modern websites with, having fewer templates just means we support fewer of available popular options, and the demand is always for us to support even more templates, not less. If the options are overwhelming I can only recommend choosing a single template and sticking with it.
As I prefer to avoid complexity, my future Apps are likely going to be built with vue-mjs and razor-ssg since they enable full access to Vue + Vue Components, very fast dev reloads and none of the complexity of an npm build system.
Here’s a couple of new Apps we’ve created with razor-ssg:
The last is an example of rewriting https://blazordiffusion.com with Vue, I could’ve chose any Vue template but decided to use razor-ssg for best performance, seo, great dev UX with minimal complexity.
I’m definitely not fearful I’d miss out any library, any popular library is going to have ESM builds in order to able to be loaded directly in a browser which most popular libraries support.
All plugins registered in vite.config.ts in there are supposed to improve the development experience, e.g. the Auto Page Routes is so you don’t have to manually define routes for every page. The Auto Register Plugin is so you don’t have to manually register every component you create. The Markdown plugin is so markdown support is enabled OOB, the Icons plugin is so your App has access to the https://iconify.design vast SVG library.
There’s a lot more plugins that could be added, but IMO these were the essential ones most modern Vue Apps would use.
During development the Vite Server runs on a watched node build on http://localhost:3000 which needs to be configured to where your .NET APIs running on https://localhost:5001. You can either do this via CORS in which all API requests are made to https://localhost:5001/api/* or if you’re using a dev proxy all API requests are made to http://localhost:3000/api/* which are then proxied to https://localhost:5001/api/ using the vite dev proxy.
Otherwise in production it needs to be configured to use the production url instead captured in the DEPLOY_API variable that’s updated in CI production builds.
No you can’t layer plugin registrations, everything’s the configuration and structured layout are tightly coupled. If you want a simpler setup I’d seriously recommend taking another look at vue-mjs. It’s an MPA Razor Pages App where a lot of the extras you list aren’t used / are unnecessary.
It is using Vue’s standard router, and using Route Guards is how you’re supposed to enable authorized access to different routes. Using declarative route guards like:
Was the simplest way I could think of to be able to define which routes are restricted to which users. If there’s a simpler way to implement this feature I’d like to know about it?
I believe the watchEffect is to ensure the route guards are rerun after the user is authenticated, required for full page reloads when they could be executed before the checkAuth API returns. There’s probably an easier way to implement this now seeing that I just noticed they implement async route guards.
Again maintaining and enforcing SPA Routing is an SPA problem, these issues simply don’t exist with simpler MPA project templates like vue-mjs or razor-ssg.