What gets me more excited than anything? Performance.
|
Performance level 100 |
Its always exciting to me to perform at
max efficiency, because why should you be performing any less? What's even better than efficiency than
setting it and forgetting it? Nothing. Fact of the matter is while you may not be
caring about efficiency, you should - because your business does. Lack of efficiency costs dollars and time.
You aren't off the hook even if you are doing programming as a hobby or are self-employed.
We are going to explore how to minify your .cshtml files in a .NET Core web application, and why you should care to do so.
Why you should care
Time is a limited resource, and we are tending to
be more impatient nowadays,
these people think so too. The bottom line is that if you want a chance for your web application to be successful, you can't skimp on quality and hope that you will be a success. Your applications need to deliver quality, and an "easy" way to convey that is to build fast applications.
I quote "easy" because it is simple in practice, but can be sometimes hard to integrate within existing development processes.
The how-to
We'll walk through how to add automatic .cshtml minification in a new .NET Core web application, although you can easily add the necessary steps in your existing application.
First, create an ASP.NET Core Web Application:
|
The new project dialog |
It is essential that your project is using MVC, as this is not using Razor pages! (Razor pages are used if you select the "Web Application" template).
|
MVC mode activated |
Activating gulp
We will be using
gulpjs (or gulp for short) to do the actual minification. The
npm package is written by me, and inspired by the
html minification library that Google [
once] recommended to use. I never remember how to install gulp in my applications, because I install it and forget about it, but it's quite easy in Visual Studio 2017.
If you have Visual Studio 2015, you should also be okay with these instructions. But in case you are running Visual Studio 2013, you should really upgrade - if you cannot, you'll have to download this for later in the tutorial.
Create a gulpfile.js in your project root directory. (You need to name it this, don't change the name).
|
That's what we need |
Stick this code in that file. This code uses new
gulp 4.x task execution and wraps a "del"
and "minify"
task in a parent task named
cshtml. What this cshtml task does in totality is it first deletes any existing minified .cshtml files, then looks at all of the .cshtml files in your Views directory using
glob syntax, and
pipes (
SO link) the files to the same directory they were contained in (after renaming and minifying them).
var gulp = require('gulp');
var rename = require('gulp-rename');
var minifyCshtml = require('gulp-cshtml-minify');
var del = require('del');
gulp.task('del', function (done) {
// delete pre-existing .min.cshtml files
del(["Views/**/*.min.cshtml"]);
done();
});
gulp.task('minify', function (done) {
// create new .min.cshtml files
gulp.src("Views/**/*.cshtml")
.pipe(rename({ suffix: ".min" }))
.pipe(minifyCshtml())
.pipe(gulp.dest("Views"));
done();
});
gulp.task('cshtml', gulp.series('del', 'minify'), function (done) {
done();
});
You are likely to run into an error "ENOENT: no such file or directory" error when running the cshtml task. I'm not quite sure how to fix this yet, as it appears to be an issue with the core npm package del, as opposed to gulp itself. Running the task an extra time is a workaround, unless you try the fix at the end of this github issue.
Now, none of this code will work unless you
also have npm (and nodejs) installed. While I am not a fan of installing all these separate applications (I'd rather have them all packaged, it's just easier to maintain mentally), go and install
nodejs (npm comes with installing nodejs - "node" for short).
Real-world note - you will need to integrate support in your build/deployment process for installing the proper npm packages in your staging/qa/production environments. This is out of the scope of this article - although we may explore that later.
npm requires us to have a
package.json file, so create one of these in the project root directory with the following template code.
|
Just add the package.json file, the -lock file gets generated on its own |
{
"author": "",
"description": "",
"dependencies": {
"del": "3.0.0",
"gulp": "4.0.0",
"gulp-cshtml-minify": "1.0.4",
"gulp-rename": "1.4.0"
},
"license": "ISC",
"main": "index.js",
"name": "mywebapplication",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"version": "1.0.0"
}
Next, open up your favorite shell (
I like Powershell) and navigate to your project directory. You'll want to navigate to the directory that contains the
package.json file. Once you are there, you'll want to run
npm install which will install all of the npm packages our gulpfile depends on.
|
Installing npm packages |
Open the Task Runner Explorer and double click on our
cshtml task to run the minification.
|
The Task Runner Explorer |
|
Minify that .cshtml |
You will see all of the minified files in your Solution Explorer that the task generated. Feel free to browse what they look like.
|
Viewing the minified files |
If you see improvements or bugs that you'd like to contribute to the library, don't be afraid to submit a pull request to the library.
Fixing the Solution Explorer
The Solution Explorer looks ugly now, I don't want the minified files to show up on their own, I want them to be nested underneath the unminified file. We are able to fix this by modifying our
file nesting settings. Your Solution Explorer will look a little differently since you have not yet made a new file settings option, but click on the little nesting icon and choose Add Custom Settings...
|
Adding custom settings |
Choose the default settings to use the Web template. You can name the settings file anything you want, I named mine MinifiedCshtml. Add the following line in your settings file:
|
Adding file nesting for .cshtml files |
Select your solution or project in the Solution Explorer and change your file nesting setting to your custom setting and then all of your minified files will be nested under the unminified files.
|
Choosing our custom setting |
|
The minified files are nested properly now |
Fixing the build
If we built our application now, it would fail, and that is because our minification library is doing some things like
removing optional tags, so we need to fix that. The easiest way to fix these errors is to remove the minified files from being compiled. To
remove any files from being compiled, we have to change the
.csproj file. In Visual Studio 2017, you can directly edit the .csproj file by right-clicking the project. In Visual Studio 2015 you must first
Unload Project and then you will be able to edit the .csproj file.
You can still unload the project in Visual Studio 2017 too, but it's just more convenient to edit it directly. Note - if you unload the project, you will have to reload the project from the Solution Explorer once you are done editing the .csproj file.
|
Editing the .csproj file |
Add the following code in the .csproj file:
<!-- Prevents minified files from being compiled -->
<ItemGroup>
<Content Remove="**/*.min.cshtml"></Content>
</ItemGroup>
Our build is now successful! However - we lost all of our minified files in the Solution Explorer. In order to see them again (without modifying the .csproj file all the time), click the Show All Files button in the Solution Explorer in case you need to view the contents of your minified file.
|
Our files are back! |
Loading minified views from our controllers
We are halfway there, we have our minified files but have not yet coded our application to use them. In order for our controllers to load the minified files, we are going to create a base controller and have all of our mvc controllers inherit from this base controller. Create an empty mvc controller in the Controllers folder and name this file BaseController. The contents of this controller are below.
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
namespace MyWebApplication.Controllers
{
public abstract class BaseController : Controller
{
public override ViewResult View(string viewName, object model)
{
if (!IsDevelopment())
{
string action = ControllerContext.RouteData.Values["action"].ToString();
if (string.IsNullOrEmpty(viewName))
{
viewName = $"{action}.min";
}
else if (viewName == action)
{
viewName += ".min";
}
}
return base.View(viewName, model);
}
private bool IsDevelopment()
{
return Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == EnvironmentName.Development;
}
}
}
This controller overrides the View method that is
eventually called whenever you return a View in a controller. The code simply appends a .min to the name of the view if we are in any non-development environment.
Read here if you have needs that require more control over your environments beyond the defaults; development, staging and production.
Test if minification is working
Change your HomeController to inherit from this base class now.
Note - you will want to inherit from BaseController in ALL new controllers your web project needs.
|
Inheriting from the BaseController |
In Index.min.cshtml, add the following
<p> tag at the beginning of the view. If we see this text on our webpage, we will know we are loading the minified tag.
|
How to test if our code works |
Next, right-click our project and go into Properties. Navigate to the Debug tab and change the ASPNETCORE_ENVIRONMENT to Staging.
|
Changing to test in the Staging environment |
Run the application and verify that we see "minified" on the page.
|
Validating our code |
If you change the ASPNETCORE_ENVIRONMENT variable back to Development, you will no longer see the text "minified". This would be the recommended way I would test the minification locally if necessary.
Loading minified views from tag helpers
Minifying the view our controller loads isn't all we need to do, as
we likely do and should make use of tag helpers (
or HTML helpers) to load partial HTML within other views. To ensure our tag helpers are loading the minified partial views, we have to
create our own tag helper.
Create a new folder in the project root named TagHelpers and create a new class
MPartialTagHelper (minified-partial tag helper). Below is the contents of MPartialTagHelper:
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System;
using System.Threading.Tasks;
namespace MyWebApplication.TagHelpers
{
public class MPartialTagHelper : PartialTagHelper
{
public MPartialTagHelper(ICompositeViewEngine viewEngine, IViewBufferScope viewBufferScope)
: base(viewEngine, viewBufferScope)
{
}
public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
// Tack on a .min exension to load the minified partial view
if (!IsDevelopment())
{
Name += ".min";
}
return base.ProcessAsync(context, output);
}
private bool IsDevelopment()
{
return Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == EnvironmentName.Development;
}
}
}
The tag helper simply adds a .min extension to the view name we pass into the tag helper. So, if we had the following line of code within a .cshtml file:
<m-partial name="_mypartialview" />
and our ASPNETCORE_ENVIRONMENT was not Development, the tag engine would essentially be executing the line of code above if it looked like this:
<m-partial name="_mypartialview.min" />
Testing the tag helper minification
In order to test this, create a new partial view in the Views/Shared directory. I named mine _TagHelperTest. (Why did I include an underscore?). I then run the cshtml task in the Task Runner Explorer again. In _TagHelperTest.min I add a simple <p> tag in it.
|
The _TagHelperTest.min file |
I include this partial view with a tag helper in my Index view.
|
Including the tag helper in the Index view |
But wait! Something is wrong. Since we added a new tag helper, in order to use the tag helper, we need to add it to the Views/Shared/_ViewImports.cshtml file. Add the following @addTagHelper line to your _ViewImports file, ensuring you use the name of your project in place of MyWebApplication:
@using MyWebApplication
@using MyWebApplication.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, MyWebApplication
Now, simply change the ASPNETCORE_ENVIRONMENT variable to/from Development/Staging and notice the view including/not including the tag you added in your view (similar to what we did when testing the minification logic for the controllers).
Github source
If you'd like to view the source,
please go here. Suggestions or comments, please submit them below. I hope this is useful to you.
ReplyDeleteThanks for sharing such a great information.It is really one of the finest article and more informative too. I want to share some informative data about dot net training and c# tutorial . Expecting more articles from you.
Absolutely wonderful information. I am delighted. Many thanks!
ReplyDeleteAre there any solutions out there that use Webpack or something more modern (and not abandoned) than Gulp.
ReplyDelete
ReplyDeleteThanks for publishing this amazing article. I really big fan of this post thanks a lot. Recently i have learned about Civil ID Renew which gives a lot of information to us.
Visit them and thanks again and also keep it up...
ReplyDeleteFirstly talking about the Blog it is providing the great information providing by you . Thanks for that .Hope More articles from you . Next i want to share some Information about Salesforce training in Hyderabad .
Mua vé máy bay tại Aivivu, tham khảo
ReplyDeletevé máy bay đi Mỹ bao nhiêu tiền
vé máy bay hà nội hồ chí minh bamboo
giá vé máy bay đi hà nội vietjet
vé máy bay sài gòn đà lạt pacific airlines
chuyến bay từ mỹ về việt nam covid
thuê xe ra sân bay nội bài
combo flc quy nhơn 3 ngày 2 đêm
I was diagnosed as HEPATITIS B carrier in 2013 with fibrosis of the
ReplyDeleteliver already present. I started on antiviral medications which
reduced the viral load initially. After a couple of years the virus
became resistant. I started on HEPATITIS B Herbal treatment from
ULTIMATE LIFE CLINIC (www.ultimatelifeclinic.com) in March, 2020. Their
treatment totally reversed the virus. I did another blood test after
the 6 months long treatment and tested negative to the virus. Amazing
treatment! This treatment is a breakthrough for all HBV carriers.
Hi. I am trying to use your tutorial on my ASP.Net Razor Page Project but I am stuck when I convert BaseController.
ReplyDeletePlease give me some advice about it.
Thanks in Advance.
I in looking for of reality appreciated perusing your weblog. It transformed into every one in all adroitly wrote and simple to undertand. rather than auxiliary sites I have legitimate to utilize that are in mean of reality now not tht top notch. I after that decided your posts really alluring. As a matter of fact in the wake of examining, I expected to move ham it occurring it to my buddy and he ejoyed it as quickly! Windows 7 Crack
ReplyDeleteKaspersky License Key also defend your browsers from sticked substance by remove them enduringly. Kaspersky Total Security 2019 Keygen
ReplyDeleteDeep Dark Quotes concerning Life may be practiced at varied times in one’s life, like when a breakup, a business loss, A natural catastrophe. Deep Dark Quotes About Life
ReplyDeleteCheck out what I've got online. The software for cracking PCs can be found here. Here's the link:
ReplyDeleteSoul House Vocals VST
Really grateful for the information here. Don’t miss this profile Spacebar Clicker. A spacebar clicker is an effective tool for mastering keyboard use.
ReplyDelete