on an ASP.NET website we have BundleConfig.cs set to minify and concatenate scripts when in Release mode but not when in Debug mode.
In debug mode I have the following sestup
in web.config file.
Then in Proj/App_Start/BundleConfig.cs
the last line is
#if DEBUG
BundleTable.EnableOptimizations = false;
#else
BundleTable.EnableOptimizations = true;
#endif
In debug mode the scripts are unminified, so we can debug them, but only when
using #Scripts.Render in the .cshtml page.
However there are some particular parts of the web application where we load script dynamically for small segments of functionality.
using jQuery.getScript we call the name of the bundle.
For some reason this script is still minified and all debugger; breakpoints are striped out. Why is this?
The only way around this is to do the following.
#if DEBUG
// Iterate over each bundle () *not needed if compilation debug="true"
foreach (var bundle in bundles)
{
// And strip out any transformations (minify)
bundle.Transforms.Clear();
}
#endif
this seems unnecessary and I don't know why this doesn't work without this.
Related
TL;DR: is there a Target during build/publish (in asp.net core Blazor app) for JS files compression which I can use in csproj to run my script before this Target?
Background:
I have Blazor frontend application which is loaded to different web application (different domains). So: main application loads many other applications and one of these applications is Blazor app (hosted at different URL).
What I did: I load manually _framework/blazor.webassembly.js with autostart property set to false and start Blazor manually:
Blazor.start({
loadBootResource: (
type: string,
name: string,
defaultUri: string,
integrity: string
) => {
const newUrl = ...;// here I can make some URL replacements for defaultUri
// so my `newUrl` points to place where Blazor app is hosted
return newUrl;
},
})
similar as described here: https://learn.microsoft.com/en-us/aspnet/core/blazor/host-and-deploy/webassembly?view=aspnetcore-3.1#custom-boot-resource-loading
It works correctly but one file is NOT loaded through loadBootResource. It is blazor.boot.json. Code which loads this file is located in blazor.webassembly.js (fetch("_framework/blazor.boot.json"...): https://github.com/dotnet/aspnetcore/blob/master/src/Components/Web.JS/src/Platform/BootConfig.ts#L6
Problem is described also in this issue https://github.com/dotnet/aspnetcore/issues/22220
There is also possible solutions suggested by me: https://github.com/dotnet/aspnetcore/issues/22220#issuecomment-683783971
I decided to replace content of blazor.webassembly.js (replace fetch("_framework/blazor.boot.json" with fetch(${someGlobalVariableForSpecificDomainURL}/_framework/blazor.boot.json) but there are also compressed files (GZ and BR). How to run my script for replacement before compression is started but after JS file is generated? Is it possible? Is there any Target which I can use in csproj?
I do not want to disable dotnet files compression and I do not want to overwrite compressed files (compress by my own).
My current csproj contains something like this (script is started after compression so too late):
<Target Name="ReplacementDuringBuild" BeforeTargets="Build">
<Exec WorkingDirectory="$(MyDirWithScripts)" Command="node replace.js --output=$(MSBuildThisFileDirectory)$(OutDir)" />
</Target>
<Target Name="ReplacementDuringPublish" AfterTargets="AfterPublish">
<Exec WorkingDirectory="$(MyDirWithScripts)" Command="node replace.js --output=$(MSBuildThisFileDirectory)$(PublishDir)" />
</Target>
Thanks for a help or any suggestion! If there is also another workaround to solve main issue, then I will be glad to see it (base tag does not work; replacement of fetch also is not so good).
I didn't find any fitting Target for my purpose. Code from question worked correctly but only with my own compression. So I reverted this and finished with overriding window.fetch to resolve main issue. If URL contains blazor.boot.json then I modify URL and pass it to original fetch. After all files are loaded, I restore original fetch. Similar to code suggested here: https://github.com/dotnet/aspnetcore/discussions/25447
const originalFetch = window.fetch;
window.fetch = function(requestInfo, options) {
if (requestInfo === '_framework/blazor.boot.json') {
return originalFetch('https://example.com/myCustomUrl/blazor.boot.json', options);
} else {
// Use default logic
return originalFetch.apply(this, arguments);
}
};
I have set up the BundleTranslator in my MVC 5 project via NuGet (BundleTransformer.SassAndScss v1.9.96 with the Core and LibSassHost components). Next I have added the bundle reference to my View.cshtml
#Styles.Render("~/Content/sass")
and redefined the BundleConfig.cs:
var nullOrderer = new NullOrderer();
var commonStylesBundle = new CustomStyleBundle("~/Content/sass");
commonStylesBundle.Include("~/Content/Custom/the-style.scss");
commonStylesBundle.Orderer = nullOrderer;
bundles.Add(commonStylesBundle);
After build, the website has a .scss reference:
<link href="/Content/Custom/the-style.scss" rel="stylesheet">
and everything is working locally probably only because I have installed SassAndCoffee package with SassyStudio. The problem emerges when I deploy on external IIS server. The file exists in the Content/Custom directory, but the website is broken. The HTML code also has the file reference (it links to .scss file, not compiled .css) but if I try to navigate to it, I get error 500.
I have changed the Sass file Build Action to Content (from None) and left Copy to Output Directory as Do not copy. I have also added httpHandlers to Web.config (but I actually don't know whatfor) but still nothing helps.
<httpHandlers>
<add path="*.sass" verb="GET" type="BundleTransformer.SassAndScss.HttpHandlers.SassAndScssAssetHandler, BundleTransformer.SassAndScss" />
<add path="*.scss" verb="GET" type="BundleTransformer.SassAndScss.HttpHandlers.SassAndScssAssetHandler, BundleTransformer.SassAndScss" />
</httpHandlers>
I didn't check all of the settings in Web.config because of the NuGet installation which (as I see) provides this kind of data for the BundleTransformer.
How do I configure the BundleTransformer to work correctly on IIS? Do I have to override the BundleResolver as in example code?
BundleResolver.Current = new CustomBundleResolver();
There are a few things to try to diagnose the problem. Firstly it works locally! :)
1.
It is worth testing that your bundling works correctly. You can do this by temporarily setting the following (take this out once you have finished).
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
BundleTable.EnableOptimizations = true;
// Bundles and stuff...
}
}
Run the site and then in your browser dev tools you should get something like this:
/bundles/commonStyles?v=BzJZwKfP1XV8a6CotGRsHhbxraPDst9zDL2X4r36Y301
If this works then we can be happy bundling will work in production.
2.
Permissions. If your getting a 500 internal server error, check the permissions on the folder that contains the scss files. Also check they are there :)
3.
Mime type. There may be a slight chance that IIS needs a mime type added for .scss, but I'm not convinced it will.
Have a little problem with bundles on site.There are source code of creating and including bundles
bundles.Add(new StyleBundle("~/Content/Administration").Include("~/Content/Administration.css"));
And on View
#Styles.Render("~/Content/Administration")
so on test server all OK,but on main(production),my bundle hadnt been loaded.What i can do with this bug?
I use
BundleTable.EnableOptimizations = false;
to debug css on test server,and find error after minification/now all ok
I have something like this:
bundles.Add(new StyleBundle("~/Content/Styles/Default/Forums").Include("~/Content/Styles/Default/Forums/Main.css",
"~/Content/Styles/Default/Forums/Slider.css"));
Now, when i release my application and run it, it creates a link like this:
<link href="/Content/Styles/Default/Forums?v=8vn0bgRpB8BncmaT_onrpNlXa4t9ydK6_Fep81xhhm01" rel="stylesheet"/>
Which refers to my site directory, and access to that is disabled. But ASP doesn't let me specify files outside of the application, then how can I do it properly?
The virtual path in the StyleBundle constructor doesn't have to match an existing path in your application:
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/Styles/Default/Forums/Main.css",
"~/Content/Styles/Default/Forums/Slider.css"));
If you want to use external files, you can use the CDN path on the bundle (you need to set the UseCDN property to true):
bundles.UseCdn = true;
bundles.Add(new StyleBundle("~/Content/css", "<CDN Path>").Include(
"<CDN Path>/Main.css",
"<CDN Path>/Slider.css"));
How do I determine if my app was compiled as "release" instead of "debug"? I went to VS 2008 Project Properties > Build and set the configuration from Debug to Release but I noticed no change? This is an ASP.NET project.
HttpContext.IsDebuggingEnabled
If you want to know if the dll was built in Debug mode, with the debug attributes, then your best bet is reflection.
Taken from "How to tell if an existing assembly is debug or release":
Assembly assembly = Assembly.GetAssembly(GetType());
bool debug = false;
foreach (var attribute in assembly.GetCustomAttributes(false)){
if (attribute.GetType() == typeof(System.Diagnostics.DebuggableAttribute)){
if (((System.Diagnostics.DebuggableAttribute)attribute)
.IsJITTrackingEnabled){
debug = true;
break;
}
}
}
This will get the assembly that is calling that code (in effect itself), and then set the debug boolean to true if the assembly was compiled in debug mode, otherwise it's false.
This could easily be dropped into a console app (as in the linked example), and then you pass in the path of the dll/exe you want to check. You would load the assembly from a path like this:
Assembly assembly =
Assembly.LoadFile(System.IO.Path.GetFullPath(m_DllPath.Text));
For one in Web.config debug will be set to true, however you can actually set this in a release application too.
In debug however defines like DEBUG are set, so it's simple to do:
bool is_debug;
#ifdef DEBUG
is_debug = true;
#else
is_debug = false;
#endif
You need to look for more than IsJITTrackingEnabled - which is completely independent of whether or not the code is compiled for optimization and JIT Optimization.
Also, the DebuggableAttribute is present if you compile in Release mode and choose DebugOutput to anything other than "none".
Please refer to my posts:
How to Tell if an Assembly is Debug or Release and
How to identify if the DLL is Debug or Release build (in .NET)