I'm currently learning ASP.NET 4.5 of the MVC flavour, and I've decided to remove bootstrap completely and go with PureCSS (http://www.purecss.io).
This is largely due to the fact that my web application requires almost no scripting other than on the code-behind, and some light JS for data validation and the like.
Currently I'm linking to the combined PureCSS style sheet from the Yahoo! CDN:
<link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.6.0/pure-min.css">
in my _Layout.cshtml file. This is obviously functional, however I have 2 concerns:
If the CVN (for whatever reason) fails/goes down/changes, all of the styling disappears and I'll have to solve that on the fly (or implement some time of failsafe switchover to another CDN)
I really like the concept of bundling and I'd like to have the local PureCSS library bundled, to prevent the aforementioned problem as well as for the sake of modularization/compartmentalization.
Is generating this bundle a simple matter of:
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/purecss_release_1_6/some.css",
"~/Content/purecss_release_1_6/other.css",
"~/Content/purecss_release_1_6/neat.css",
"~/Content/purecss_release_1_6/etc.css",
...
"~/Content/site.css"));
If so, that's fine and dandy, but there are DOZENS of css files in the release. Is there a cleaner way to bundle them?
Thank you!
You can use IncludeDirectory to reference the whole directory containing all your CSS files.
Example specific to your case:
bundles.Add(new StyleBundle("~/Content/css")
.IncludeDirectory("~/Content/purcss_release", "*.css"));
New in .NET 4.5 is an integrated system for falling back from a failed CDN to local material. Tutorial/information: http://www.hanselman.com/blog/CDNsFailButYourScriptsDontHaveToFallbackFromCDNToLocalJQuery.aspx
Usable information from the link above:
The basic idea for CDN fallback is to check for a type or variable
that should be present after a script load, and if it's not there, try
getting that script locally. Note the important escape characters
within the document.write. Here's jQuery:
<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-2.0.0.min.js"></script>
<script>
if (typeof jQuery == 'undefined') {
document.write(unescape("%3Cscript src='/js/jquery-2.0.0.min.js' type='text/javascript'%3E%3C/script%3E"));
}
</script>
Related
I am trying to move the front-end part of a website to Angular 2.
Currently I have really big ASP.NET 4.5 website.
I would like to create a separated Angular 2 project as it will be growing with time (and hopefully replace the asp.net)
For now I would like to create this project in Visual Studio (2015) and use some angular components or modules in the actual ASP.NET website.
Does the angular AppModule as to be in the ASP website?
I made some research but could not find answers or examples.
Am I gonna be able to do this relying on npm and system.js ? I saw that a lot of people are using gulp for copying file.
Is there a "right" way of doing this?
Any help would be highly appreciated
This question is not specific to Visual Studio, but yes, you can certainly accomplish this.
As you have suggested you can and should maintain the Angular application as a separate project.
The only additions that you need to make to your .aspx page are
including SystemJS and its configuration via script tags in that page or in its Master Page (You can also do this dynamically for CMS pages and using all sorts of other strategies). For example
<script src="loction-of-systemjs.js"></script>
<script src="loction-of-systemjs.config.js"></script>
Adding a markup tag with the selector corresponding to the app's root element, say 'my-embeddedable-widget', to your .aspx markup. For example
<my-embeddedable-widget>Loading...</my-embeddedable-widget>
Importing your application via SystemJS.import from a script tag embedded in the page containing the component selector above. For example
<script>
SystemJS.import('my-embeddedable-widget')
.catch (function(e) {
console.error(e);
}); // not using .bind or => here since aspx tends to imply older browser support
</script>
Note that this presupposes two things
that the 'my-embeddedable-widget' is set up in your SystemJS configuration. For example
SystemJS.config({
packages: {
'my-embeddedable-widget': {
main: 'main.ts' // just an example, could be main.js or anything really
}
}
});
If it is not you can add the config entry above as appropriate for your app (strongly recommended) or just import it directly from the path to the app's entry point such as e.g. my-embeddedable-widget/main.ts or my-embeddedable-widget/main.js.
That the entry point of your widget declares all of its platform level dependencies, such as zone.js and likely various polyfills. For example
my-embeddedable-widget/main.ts
import 'zone.js';
import 'core-js';
// ...
import {platformBrowserDynamic} from '#angular/platform-browser-dynamic';
// ....
This means that SystemJS will automatically load them when your widget is requested. While you could bring them in via separate script tags as we do with the loader itself, making them explicit dependencies of our widget by using ES Modules improves maintainability and allows us to defer loading them until they are required. Furthermore it helps further decouple the widget from the .aspx page. However, if other JavaScript on the page requires these polyfills, you may need to adjust this approach (especially with respect to zone.js because it monkey patches window.Promise)
I've added bootstrap CSS files via a StyleBundle to my asp.net mvc 5 project.
(It uses as Cdn: https://www.asp.net/ajax/cdn#Bootstrap_Releases_on_the_CDN_14 )
var bootstrapCssCdnPath = "http://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css";
var bootstrapCssBundle = new StyleBundle("~/bundles/css/bootstrap", bootstrapCssCdnPath).Include("~/Content/bootstrap.css");
//bootstrapCssBundle.CdnFallbackExpression // ?
bundles.Add(bootstrapCssBundle);
var bootstrapThemeCssCdnPath = "http://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap-theme.min.css";
var bootstrapThemeCssBundle = new StyleBundle("~/bundles/css/bootstraptheme", bootstrapThemeCssCdnPath).Include("~/Content/bootstrap-theme.css");
//bootstrapCssBundle.CdnFallbackExpression // ?
bundles.Add(bootstrapThemeCssBundle);
However there is a problem: when I add an incorrect url as CDN (e.g. adding 'ahttp' instead of 'http') my custom "fallback" css file is not used, instead it shows 'ahttp://' in my html source.
Same when I'm running my site on Debug or Release.
Why is my fallback not being used?
What is the CdnFallbackExpression for a StyleBundle? (and in particular for a bootstrap.css and bootstrap-theme.css)
Should the .Include be the .min.css file or does it automatically search for the .min. version first?
Is there a way to .Include multiple css files, using a Cdn with fallback, so that I don't have to create a new StyleBundle everytime per css file that uses a Cdn?
1) This is a bug in the Microsoft ASP.NET Optimization Framework, documented here.
2) The solution is to modify the CdnFallbackExpression to be a javascript function that both checks for the stylesheet and loads the fallback, thus ignoring the bad script from the Optimization Framework.
Here is solution which provides a StyleBundle extension method to solve the problem: Style Bundle Fallback.
3) There should be unminified version like bootstrap.css (not bootstrap.min.css). When you build your web application for release it uses .min version. More here: Bundler not including .min files.
4) No, you can't use multiple CSS files with CDN (each of them must have its own bundle). Here is an article that explains when to use a CDN (or not) and why: Know When To CDN.
I'm right now using asp.net mvc 4.5 in my projects . I like the way asp.net MVC is designed and works, but i am struggling with the script and styles sheet management.
Every page of my project use different style sheet and scripts files so i can not add all the scripts and style sheet file in the layout file as it is not the good technique & increase page loading time , i want to add those related files on each page where they are needed. suggest me a good solution
You could register a section in your layout:
#RenderSection("scripts", required: false)
and then in each view override this section and define any custom scripts related to it:
#section scripts {
<script type="text/javascript" src="#Url.Content("~/scripts/myscript.js")"></script>
}
Using this same technique you could define another section for the custom stylesheets.
This being said, if you take advantage of the built-in bundling and minification mechanism, it might be more effective to have a single minified and compressed file rather than multiple files because the browser will need to make separate HTTP request to retrieve them.
i would recommend using ClientDipendancy Framework.
https://github.com/Shazwazza/ClientDependency
I have this:
bundles.Add(new StyleBundle("~/Content/Styles/Default").Include("~/Content/Styles/Default/Site.css"));
On my sites i have this:
#section Styles
{
#Styles.Render("~/Content/Styles/Default"))
}
My _Layout.cshtml looks like this:
#RenderSection("Styles", true)
Everything looks good, eh? Well, not really. When i compiled my application in release mode, decided to publish it, this is what it renders:
<link href="/Content/Styles/Default?v=78dkNySP_xsiuzsgxCx_GGnnHzYS-B8nNdnXqcl47XI1" rel="stylesheet">
Instead of generating href to a file, it generates some kind of id? Guid? Why? O.o
This is how bundles work. It's main purpose is for you to combine multiple CSS (and JS files for that matter) files into one package. e.g. you no longer have to put all your css (and js) into one huge file. Just split it up into sections, then add it into your bundles, and it packages it up into one item. Less web requests, the faster your page load time.
e.g. Lets say you had 2 css files. One's the main, but you had one for your menu system.
bundles.Add(new StyleBundle("~/Content/Styles/Default").Include(
"~/Content/Styles/Default/Site.css",
"~/Content/Styles/Default/Menu.css"));
This would show up as a single call with the GUID type code (to prevent caching on file changes) on the URL. This URL will link to a minified and bundled css.
But my browser cannot read that! There is no physical path to a file!
It's a sort of virtual file. MVC's bundling uses the routing engine to point it to a combined and minified version of a particle bundle.
I have no problem implementing a solution in my pom.xml using the samaxes plugin to minify and generate my required example.min.css file, is there script, how can I keep the development environment utilizing the CSS files on the fly without greatly changing the CSS source files?
I have the following code in my xhtml doc:
.
.
<link type="text/css" rel="stylesheet"
href="/assets/css/forms.css"/>
<link type="text/css" rel="stylesheet"
href="/assets/css/content.css"/>
<link type="text/css" rel="stylesheet"
href="/assets/css/images.css"/>
.
.
My pom creates an example.min.css and saves it in the same location using samaxes beautifully. I want to use this in my page but only in production...I want to be able to keep up with development on the fly on these various files but when I do the maven compile, it generates the example.min.css file from this and I intend on using this instead in production. There's tons of great answers saying which plugins to use to optimize and minify my css and js, I just need to know if there's a best-practice out there to point to them without bringing in another plugin like wr04J or is there some js I can implement that can build a conditional stylesheet statement on the fly if I use a param or something?
Originally I was using the concept of applying a rendered attribute to a ui:fragment tag that would render one way or another depending on a bean property that checked for the existence of the Maven debug property but this generated way too much overhead and just seemed like a bad hack just to get it to work. I need a better, simpler idea.
With the current version of Minify Maven Plugin you have to do something like this:
if productionEnvironment
<script src="js/bundle.min.js"/>
else
<script src="js/bundle.js"/>
end
It remains easy enough to debug and you only have to define your source files once (in the pom).
This will, however, be fixed in a future version of the plugin. Source Maps might soon become a reality and I'm planning to add support for it very soon.