Why would components in this Blazor app fail to render? - asp.net-core

I'm writing a Blazor app and obviously I want to get some components rendered in there. I've just tried adding a basic navigation element to my main layout but it's not rendering. I can see the element on the DOM, but that element is empty.
I went with some fairly simple content to start with in my NavMenu component that I'm trying to include on MainLayout.cshtml:
<h1>WHYYYY????</h1>
I've also taken a pretty simple layout on my MainLayout.cshtml page:
#inherits BlazorLayoutComponent
<NavMenu />
<div class="body-content">
#Body
</div>
The file structure in my project seems uncomplicated:
So I'm at a loss here as to what I've overlooked. It looks like Blazor knows there's something it should be rendering to the page - that's why I can see the NavMenu element in the DOM. But there's never any content rendered inside that element. What's missing?
I'm running the latest (at time of writing) version of Blazor: 0.5.1.

You are probably running into a bug with the .csproj file. It should look like this:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RunCommand>dotnet</RunCommand>
<RunArguments>blazor serve</RunArguments>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Blazor.Browser" Version="0.5.1" />
<PackageReference Include="Microsoft.AspNetCore.Blazor.Build" Version="0.5.1" />
<DotNetCliToolReference Include="Microsoft.AspNetCore.Blazor.Cli" Version="0.5.1" />
</ItemGroup>
Yours has most likely extra stuff in it, that prevents the component from compiling. This typically happens when adding files or copying them. See: https://github.com/aspnet/Blazor/issues/1206

It turns out the root cause was related to namespaces and casing.
When I originally set up the project, I created it using the command line in VS Code. Out of habit, I wrote everything in lowercase (i.e. dotnet new blazor -o myapp).
As a personal preference, I like my namespaces to be title cased, so some time later I decided to "tidy up" and change myapp to Myapp. I went through the code to refactor to the new titlecase name and everything compiled, so I carried on working... until a few weeks later when I went back to do some work on a component and noticed it wasn't behaving.
It turns out that razor pages are automatically namespaced based on folders and a subset of those are included in the _ViewImports.cshtml page. That file still referenced the lower case namespace and pages looking for a lowercase project root were no longer able to find the right shared components.
So unsurprisingly, it's an entirely self-inflicted issue and yes I feel very silly for not thinking it through properly from the start.

Related

Page specific tailwind classes with SSG

Currently I'm developing a website using the following stack:
vue.js
#vue/server-renderer
vite
tailwind CSS
SSG was chosen as the rendering mode.
Tailwind, as described in the documentation, allows you to specify directories and file extensions (content property) , in which he will try to find the classes, in order to leave only those that are actually used in the project.
As a result, the 'main.css' file is formed, in which only those classes that are used remain.
Next, I just take this file and include it in every page that was rendered during the build phase of the project.
This results in:
index.html - main.css
about.html - main.css
blog.html - main.css
It turns out that main.css file may contain classes that are needed only for one of the pages and are not needed for others.
I would like to implement the following:
Take main.css which turned out
Render a page, for examle about.html
take only those styles that are needed for about.html page from the main.css file
create a new about.css file
link the resulting about.css styles to about.html
I’ve already tried to implement this using an awesome PurgeCSS tool as following:
render page content usind #vue/server-renderer's renderToString() method;
Pass an resulting css and html sources to PurgeCSS
here is an example
But there are too many corner cases around this solution, such as:
Dynamic classes which can be added to the html on the client side
Some components may be missing in rendered html and their content will be added later (for example, v-if directive was used on the component)
A few takeaways:
PurgeCSS is not needed anymore since Tailwind v2 (the latest being v3.x)
as far as I know, you cannot have code-splitting with Tailwind, not that it matters anyway since it will still perform okay with further optmizations
the classes that will be generated, will be only once for the whole app (hence no need to have a bg-red-500 for index or about page, both are referencing the same unique declaration)
if you want to have SSR/SSG, I recommend the usage of Nuxt (in it's v3 if you're using Vue3 or plan to have anything long-term)
dynamic classes are not possible with Tailwind, you can create things like bg-[#ccc] but it goes on the opposite side of what Tailwind is achieving and should be used exceptionally
for Tailwind's content, still the defaults on this page, section Configure your template paths, no need to do anything crazy or complicated
if you want to have some scoped/local style, style to using style scoped, you can still use Tailwind inside of those tags tho
if you want to write vanilla CSS into dedicated CSS files like index, about, blog etc, then Tailwind is probably not the best approach because this is not how it is supposed to work
stay simple, the performance will still be amazing. Only focus on not having too many screens, colors etc that you're not using
you could run some bundle size tests to see if the CSS is taking a huge chunk in terms of size. Will probably not, but if it still is: you can then start making complex configurations
JS will be far harder to reduce and be more impactful regarding the performance (because of how a browser works with it: parsing, executing is indeed blocking the main thread)

Add another main page to vue 2.6.6 project or inject a view without applying the styles imported in index.html

I've a problem with a Vue-js application (Vue 2.6.6).
I need to create a new page in this application that must not be affected by vuetify and other styles placed in the head of index.html file. I wanna now if it is possible to inject a view (navigating to it with routing) without applying styles or if it is possible to create another entry point for the app, making it as a multi-page application.
I've found a documentation for doing it, but the structure of files and folders they talk about is different from mine (I did not create the project) and I don't understand what I gotta do to set multiple pages.
https://cli.vuejs.org/config/#pages
I have a "main-priv.js" file inside src, not a "main.js", don't know if it is same.
I'm really bad with configurations and stuff like that, I've probabily taken the wrong life choice with this work, but nevermind, can you help me?

VueJS 3.0.0 Pug Rendering Failure After Upgrade

I've been banging my head against the wall all day on this.
Basically, I inherited a pretty large Vue 2 project with webpack-only implementation (no CLI) and with hundreds of SFC components. Almost every SFC component uses a template with the first element indented -- like this:
<template lang="pug">
span
b Some Stuff
</template>
This has been compiling just fine for months. It seems like Vue 3 and its associated versions of the vue-loader and compiler don't like this... it must be like this:
<template lang="pug">
span
b Some Stuff
</template>
As you can imagine, I am getting hundreds of "unexpected character 'indent'" errors during the build. I run into this whether I use the CLI or whether I use the webpack implementation with all associated upgrades having been done manually...
As much as I love the idea of manually paging through each of the hundreds of .vue files and tabbing back the content, there has got to be a better way around this... right? There appears to be an npm package called vue-indent-pug-loader but after replacing the pug-plain-loader in the webpack file, this doesn't seem to have any effect on the problem.
Is there some utility you know of that can roll through and "fix" my template blocks, or something I can place in front of the compiler to let it process the templates as-is, or am I stuck either manually fixing these or staying on Vue 2?
Thanks!

Using different vendors with the same codebase in Vue

I'm working on a Vue project that is generated with the Vue cli 3. I would like to use different vendors in the same code base.
I need something that can load different images/styling based on a variable. For example something like:
<!-- In HTML templates -->
<img :src="`#/assets/vendor_name_here/banner.jpg`" />
/* In SCSS */
#import "assets/vendor_name_here/style/bootstrap";
Where vendor_name_here is a variable that can be set in the environment. Please, note that the above doesn't work.
Coming from an Angular background, something similar could be achieved by simply adding an app or project to the config. However, there is no such thing documented in the Vue docs (of what I could find).
So is there something similar in Vue?
Update:
I just found out that the following works for HTML images:
<img :src="require(`#/assets/${VUE_APP_VENDOR}/banner-large.jpg`)" />
So the question is still open for the SCSS files.
Update 2:
So apparently the same method also works for SCSS files. I added the folowing in my script block:
require(`./assets/${process.env.VUE_APP_VENDOR}/style/bootstrap.scss`);
And now it works :).
So I found my own answer to this. The fixes are in the answer itself in the updates.

ASP.NET, Twitter.Bootstrap.MVC4, ASP.NET and Menus using Navigation Routes

I installed Twitter.Bootstrap.mvc4 in a VS2010 project. I also installed Glimpse.
I found that the Menus using Navigation Routes that the Twitter.Bootstrap.mvc4 offers is "broken" by Glimpse. In the NavigationExensions.cs file, the RouteCollection is wrapped in Castle proxies causing the variable navigationRoutes to always return 0.
public static IEnumerable<NamedRoute> GetRoutesForCurrentRequest(RouteCollection routes,IEnumerable<INavigationRouteFilter> routeFilters)
{
var navigationRoutes = routes.OfType<NamedRoute>().Where(r=>r.IsChild==false).ToList();
I can see the information in the watch window and even get the information to show in the Immediate window using "((Castle.Proxies.RouteProxy_1)routes[5]).__target". So I thought to loop through the routes and looked for a named route. However, I don't know what to do to get the references I need to access the proxies. The Castle code is buried in the Glimpse.Core library.
I uninstalled Glimpse to make sure that was causing the problem (it is).
There is currently an issue which reflects the same problem, albeit in a different context.
There is currently no real fix, since GetRoutesForCurrentRequest checks for NamedRoute instances and Glimpse uses proxies, but you can always disable a part of Glimpse so that the navigation issue is fixed in the meanwhile.
To make it work again, you
must disable the RouteInspector of Glimpse
(optionally) remove the Routes tab from the Glimpse dashboard, since it will now show only partial information due to the missing inspector. Although this option is not required and the Routes tab might still show you some information you might want to see.
This can be done in the configuration section of Glimpse
<glimpse defaultRuntimePolicy="On" endpointBaseUri="~/Glimpse.axd">
<inspectors>
<ignoredTypes>
<add type="Glimpse.AspNet.Inspector.RoutesInspector, Glimpse.AspNet"/>
</ignoredTypes>
</inspectors>
<tabs>
<ignoredTypes>
<add type="Glimpse.AspNet.Tab.Routes, Glimpse.AspNet"/>
</ignoredTypes>
</tabs>
</glimpse>