If I have the following code in a webpack project with css-loader and style-loader plugins:
import 'index.css'
It generates an inline style in a <style> tag. Is there any way to leverage browser caching feature by having it generate a <link rel="stylesheet" href="index.css"> instead? I know I can put CSS files in the public folder, but then it won't be in the Webpack build pipeline. Is there some existing CSS loader plugin that does this? Or are there strong arguments for abandoning this approach altogether (ofc. not putting them render-blockingly in the document <head>)?
There are no arguments against this. I would even say this is more common than to leave the css in the chunks. But you need to use a plugin for this.
Until recently the go to here was extract-text-webpack-plugin, but now if you are using webpack 4 I would suggest mini-css-extract-plugin.
You might want to turn this off for local development. It gets in the way of HMR.
Related
for example I have a public folder that stores all the css files, and a view folder that stores the ejs files. So when I link the css file in the ejs file, I do
<link rel=”stylesheet” href=”styles.css”>
or
<link rel=”stylesheet” href=”/styles.css”>
I don't understand how it gets the css file without me redirecting it, whereas in react I need to do e.g.
import "../public/styles.css"
which makes sense to me as I am starting from the current directory.
link- is a common JS syntax, and is added to the head of the HTML, optional for older browsers that doesnt recognize import.
import- es6 syntax
there is no much of difference between them, only in mechanism
I am using VS 2015 + ASP.net vnext + Angular 2 + Typescript + gulp.js. I have automated my scripts/**/*.ts files moving to the wwwroot/app folder. Now I want to do the same for my libraries like Angular 2. I want that a gulp process injects
angular.js inside index.html inside the <environment names="Development"> node;
angular.min.js inside index.html inside the <environment names="Production"> node.
Of course I want that this to happen for all my libs automatically, without having knowledge about a library:
<any>.min.js (production)
<any>.js (development)
The minification of any.js can be done by me.
Actually I would just have to regard all dependencies in package.json... but then I am lost.
Can my idea be done or does there maybe already exist a tool? Or should the workflow broken into more manual steps like I have to copy/paste a certain library?
Or is it possible to take the dependencies name and concat it with .js then search this file under the node_modules folder... (kind of hacky and not safe...)
UPDATE
Rephrase/Refine my question:
How can I automatically add my npm dependencies (not devDependencies) to the environment "Development" node when triggering a certain event like build/clear/etc...
There is a little tag helper for this, called asp-src-include.
Imagine the case where you have a handful of *.js files you want to include:
<script src="/app/app.js"></script>
<script src="/app/controller/controllerA.js"></script>
<script src="/app/controller/controllerB.js"></script>
<script src="/app/service/userservice.js"></script>
etc. You can include all of these with a single `´ tag.
<script asp-src-include="~/app/**/*.js"></script>
So for Production/Development deployment your Razor markup may look like
<environment names="Development">
<script asp-src-include="~/app/**/*.js"></script>
</environment>
<environment names="Staging,Production">
<script asp-src-include="~/app/**/*.min.js"></script>
</environment>
For this you need the #addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers" (starting with RC1 or RC2 it's ' #addTagHelper *, Microsoft.AspNet.Mvc.TagHelpers' - without the double-quotes ) declaration in your *.cshtml files or inside your _Layout.cshtml.
edit
There is an module called gulp-npm-files that does something similar, it copies all *.js files into the target folders. You can see it's source on GitHub in case you want write your own module to extend the functionality.
But that may not be exactly what you want, as the folders often contain multiple files, for example angular2 (AngularJS 2.0) contains dozen of files (*.js and *.ts), but you're mostly only interested in the compiled/minified ones, found in angular2/bundles/* like angular2.js, angular2.min.js or angular.dev.js.
The package.json of the particular dependency provides no information on where to find this compiled files. So I guess, there's no way to automate this unless you want to copy all of the files to wwwroot which makes no sense in my eyes, especially if you want to use asp-src-include, as it makes no difference on what it includes, so you want to minimize the number of *.js files in your wwwroot folder.
I guess the best you can do is to manually copy the dependencies via gulp task and then use asp-src-include to automatically include them into your razor generated html files.
So your problem is that you want to inject the scripts automatically into your HTML, right? You can use the Wiredep module for that.
And for copying the assets to an other folder, there are many modules to copy or link files from one folder to another. Gulp-copy is the first one i could find.
I'm going to use .less in my css.
Based on my understanding there different kind of way to use .less.
you can pre-compile it then use the css generated by .less
another one is using this scripts below:
This
<link rel="stylesheet/less" type="text/css" href="style.less">
<script src="less.js" type="text/javascript"></script>
or
<link rel="stylesheet/less" type="text/css" href="styles.less">
<script src="//cdnjs.cloudflare.com/ajax/libs/less.js/1.7.3/less.min.js"></script>
as for my understanding it doesn't need the css file because it will generate one for itself once it runs.
I've already installed Web Essentials and it is easy to follow number 1 because it generates the file already when you save it or build it. However, I'm planning to use number 2.
I've read: "Web Essentials uses the node-less compiler and it always uses the latest version" so I don't think I need to install anything.
When I run it i got this error:
FileError: _http://localhost:xxxxxx/Content/style.less wasn't found (404)
Actually, the VS intellisense can't even find the .less file when I put it in href="" so I code it anyway.
I've already look into these no one setup in Visual Studio Web Essentials.
http://verekia.com/less-css/dont-read-less-css-tutorial-highly-addictive
http://www.sitepoint.com/a-comprehensive-introduction-to-less/
http://webdesign.tutsplus.com/articles/get-into-less-the-programmable-stylesheet-language--webdesign-5216
http://lesscss.org/#using-less
It's because IIS doesn't know what a .less file is and therefore won't serve it. You need to add the following to your web.config's <system.webServer> section:
<staticContent>
<remove fileExtension=".less" />
<mimeMap fileExtension=".less" mimeType="text/css" />
</staticContent>
Try to use this tutorial. You have to include your css file. Some tools like Koala generate your css file to output folder ( Web Essentials do it too).
You have to include generated css.
If you are using less.js you have to set options in server side (that you see in this webpage).
dotless
I'm planning to use number 2.
I would definitely advise against using the less.js file as a script on your page. This will slow your page down as you have to download the js file and then it has to process your less file. As you are using Visual Studio and Web Essentials this is totally unnecessary, it will compile the CSS file for you.
Web Essentials automatically compiles a CSS file for you either on save or build depending on your settings. All you then need to do is add the CSS file to your page and NOT the less file.
<link rel="stylesheet" type="text/css" href="styles.css">
More info on settings within Web Essentials for less can be found on the Web Essentials site.
Less features
I would like to use ServiceStack as a pure AppHost implementation without using MVC. I want to use it to drive a Single Page App.
Serving the SPA's single HTML shell page is straightforward enough and I've found plenty of examples on doing that. However, I also need to serve a number of JavaScript files and I'm assessing the best way of doing this. I can simply put script tags in the HTML shell page but then I don't get the benefits of bundling and minification, and I would have to maintain this every time I add a new JavaScript file.
All these problems are solved with bundling solutions such as Cassette or ASP.NET MVC4 Bundles. But how would I use these with ServiceStack AppHost?
The ServiceStack.Bundler project is great but it seems to have dependencies on ASP.NET MVC, e.g. as a base for the HTML Helpers which render the JavaScript tags in the HTML.
I'd like to be able to do this without any dependency on MVC, if possible.
If you haven't taken a look at GruntJS yet, it's worth a look (http://gruntjs.com/). By creating some simple tasks, it can combine & minify your HTML, JS, and CSS and has no dependency on .NET. There are a lot of other really useful tasks available to GruntJS as well (js lint checks, JS unit test running, and tons more). You can easily setup different tasks for your environments as well (ie, don't combine/minify when deploying to dev server).
What it allows you to do is create a purely static HTML, CSS, and JS SPA, and you can manage that in a completely different solution/project than your ServiceStack AppHost.
So in your example, you'd just reference the scripts in your index.html file like you normally would and when you're ready to deploy to staging/production you'd run your grunt task which would bundle/minify your code for you and output the static html, min.css, and min.js files for you to some deployment directory. It's really powerful and flexible.
I used to use Bundler and I recently made the switch to GruntJS and I haven't looked back.
So, I don' think there is anything to need to do within ServiceStack's AppHost to use a 'bundling-and-minification' solution. To simplify the 'Bundling' process...
1 - 'Bundle' files from a folder(s) creating a new file(s)
2 - Reference the 'Bundled' file(s) from a View/Html
How to 'Bundle' files from a folder(s) creating a new file(s)
Cassette
Cassette seems to handle this process with 'some magic' (see web.config modifications for insight) that calls the Configure method of the CassetteBundleConfiguration class. Installing the Nuget package takes care of 'setup' for you.
ServiceStack.Bundler
ServiceStack.Bundler has a few different ways to handle this process...1) Manually with bundler.cmd, 2) A VS extension 3) Post Build Script 4) Short-cut key to an External Tool
Reference the 'Bundled' file(s)
You can do this however you like as long as you know the path of the file(s)
<link href="/Content/some.css" rel="stylesheet" type="text/css" />
<script src='some.js'></script>
Cassette offers some convenient rendering features
#Bundles.Reference('yourbundle')
#Bundles.RenderStylesheets()
#Bundles.RenderScripts()
ServiceStack.Bundler offers some as well (I think this is the code the depends on System.Web.MVC)
#Html.RenderJsBundle()
#Html.RenderCssBundle()
Note: These are just writing out the <link> and <script> HTML tags.
It seems neither Cassette nor Microsoft.AspNet.Web.Optimization (the bundling solution included with MVC4 projects by default) have dependencies on ASP.NET MVC. Therefore either solution can be made to work with an AppHost implementation of ServiceStack.
For Cassette:
It all works just fine if, from NuGet, you install:
ServiceStack.Host.AspNet
ServiceStack.Razor
Cassette.Aspnet
... and then use Cassette from a Razor 'cshtml' file as usual.
One small gotcha which did cause me to scratch my head for a few minutes:
The order in which the HttpHandlers are listed in your web.config is important. The ServiceStack.Host.AspNet package adds an HttpHandler path which uses a wildcard meaning any further HttpHandlers, such as that for Cassette.axd, are never reached.
Simply changing the order in my web.config from:
<httpHandlers>
<add path="*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" />
<add path="cassette.axd" verb="*" type="Cassette.Aspnet.CassetteHttpHandler, Cassette.Aspnet" />
</httpHandlers>
to:
<httpHandlers>
<add path="cassette.axd" verb="*" type="Cassette.Aspnet.CassetteHttpHandler, Cassette.Aspnet" />
<add path="*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" />
</httpHandlers>
fixed the problem. I don't know if installing Cassette.Aspnet from Nuget first would have prevented this issue from occurring in the first place.
For Microsoft.AspNet.Web.Optimization:
From NuGet, you install:
ServiceStack.Host.AspNet
ServiceStack.Razor
Microsoft.AspNet.Web.Optimization
Having done this, you can use Microsoft.AspNet.Web.Optimization bundling and minification as normal.
I added a BundleConfig.cs file, followng the convention you'd find in a default MVC4 project. I then call BundleConfig.RegisterBundles(BundleTable.Bundles); from the ServiceStack AppHost file.
Thereafter, all #Scripts.Render() statements in Razor files work just fine.
I'm beginning to evaluate javascript module tools like RequireJS for javascript modularization. This seems useful, especially during development, so I don't need to recompile all of the js files into mylib-<version>.js whenever I change one of the dependent files.
My app is distributed with both html and javascript files, and in production, I would like to use the compiled version of the javascript file.
So in development, my html file might look something like
<html>
<head>
<script data-main="scripts/main" src="scripts/require.js"></script>
</head>
</html>
But in production, I would expect it to look more like
<html>
<head>
<script src="mylib-1.0.js"></script>
</head>
</html>
I wouldn't think it production that there should be any need to reference requirejs if I am distributing a compiled file.
Is there a way to do this without having to manually change my html files before I distribute the app?
RequireJs has an optimization tool, which can help you to minify and concatenate your modules. It has a lot of options, and can be difficult to use, but it gets easier with a build tool like GruntJs or (especially) Yeoman, which uses GruntJs to build.
In both you can use the rjs task (which optimizes modules), but again Yeoman is a bit easier since it has generators which will configure it already for you:
// usemin handler should point to the file containing
// the usemin blocks to be parsed
'usemin-handler': {
html: 'index.html'
},
// rjs configuration. You don't necessarily need to specify the typical
// `path` configuration, the rjs task will parse these values from your
// main module, using http://requirejs.org/docs/optimization.html#mainConfigFile
//
// name / out / mainConfig file should be used. You can let it blank if
// you're using usemin-handler to parse rjs config from markup (default
// setup)
rjs: {
// no minification, is done by the min task
optimize: 'none',
baseUrl: './scripts',
wrap: true,
name: 'main'
},
In the index.html you just use a comment line to specify which js files should be minified/concatenated to which output file:
<!-- build:js scripts/amd-app.js -->
<script data-main="scripts/main" src="scripts/vendor/require.js"></script>
<!-- endbuild -->
In the example above, the modules will be concatenated to ONE file, named amd-app.js.
Edit:
This will be done by executing grunt from the command line. This will start a lot of useful tasks, which will build the project in a dist folder, but again this is highly adaptable.
The resulting index.html file (in dist) has only (if you want) one javascript file:
<script src="scripts/15964141.amd-app.js"></script>
My advice: use Yeoman to make life easier (at least for handling minification/concatenation).
First you have to compile your depency tree into one file using the r compiler. After that you can a striped down AMD loader like almond. At least you have to find a way to change the url in your index html.
Take a look at gruntjs which can automatize the whole thing, there a bunch task to like usemin that helps you with the process.