Serve css files dynamically in raw node.js - css

I can servre css files when the browser requests for it, which is like
var pathname = url.parse(req.url, true);
if(pathname=="style.css"){
//read the css file and write in the response
}
but using this approach i will have to write a router for each css and js file I use. Is there any way to do them dynamically. I have figured out a way which works but seems to be vaulnarable.
var reqArray = pathname.split("/");
if(req.Array[reqArray.length -1].indexOf(".css") !=-1 && fs.existsSync(pathname)){
fs.readFile("./"+pathname, function(err,data){
//server the file
}
}
is it okay, or there is any better suggestion. Please don't tell me to use express or any toher framework.

Related

Vite css response configuration

When i'm asking a css-file this way
let xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:8080/test/data/tst.css?', false);
xhr.setRequestHeader("Accept","text/css,*/*")
xhr.send();
console.log(xhr.response);
Everything is ok.
#ggg{font-size: 50px;}
But when this way
let xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:8080/test/data/tst.css?', false);
xhr.setRequestHeader("Accept","*/*")
xhr.send();
console.log(xhr.response);
The response looks like
import { createHotContext as __vite__createHotContext } from "/#vite/client";import.meta.hot = __vite__createHotContext("/test/data/tst.css");import { updateStyle as __vite__updateStyle, removeStyle as __vite__removeStyle } from "/#vite/client"
const __vite__id = "/home/user/dev/project/front/test/data/tst.css"
const __vite__css = "#ggg{font-size: 50px;}"
__vite__updateStyle(__vite__id, __vite__css)
import.meta.hot.accept()
export default __vite__css
import.meta.hot.prune(() => __vite__removeStyle(__vite__id))
Is there a way to configure vite to respond in the second example like in the first example?
Because vite has two strategies on css:
if a css request include text/css header, vite will inject css style code into directly, so you get the first result.
otherwise, vite will add a .js extension to css file, and treat it as a js, so you will see the second result.
if you want to know more details, please see source code

jsdom does not fetch scripts on local file system

This is how i construct it:
var fs = require("fs");
var jsdom = require("jsdom");
var htmlSource = fs.readFileSync("./test.html", "utf8");
var doc = jsdom.jsdom(htmlSource, {
features: {
FetchExternalResources : ['script'],
ProcessExternalResources : ['script'],
MutationEvents : '2.0'
},
parsingMode: "auto",
created: function (error, window) {
console.log(window.b); // always undefined
}
});
jsdom.jQueryify(doc.defaultView, 'https://code.jquery.com/jquery-2.1.3.min.js', function() {
console.log( doc.defaultView.b ); // undefined with local jquery in html
});
the html:
<!DOCTYPE HTML>
<html>
<head></head>
<body>
<script src="./js/lib/vendor/jquery.js"></script>
<!-- <script src="http://code.jquery.com/jquery.js"></script> -->
<script type="text/javascript">
var a = $("body"); // script crashes here
var b = "b";
</script>
</body>
</html>
As soon as i replace the jquery path in the html with a http source it works. The local path is perfectly relative to the working dir of the shell / actual node script. To be honest i don't even know why i need jQueryify, but without it the window never has jQuery and even with it, it still needs the http source inside the html document.
You're not telling jsdom where the base of your website lies. It has no idea how to resolve the (relative) path you give it (and tries to resolve from the default about:blank, which just doesn't work). This also the reason why it works with an absolute (http) URL, it doesn't need to know where to resolve from since it's absolute.
You'll need to provide the url option in your initialization to give it the base url (which should look like file:///path/to/your/file).
jQuerify just inserts a script tag with the path you give it - when you get the reference in the html working, you don't need it.
I found out. I'll mark Sebmasters answer as accepted because it solved one of two problems. The other cause was that I didn't properly wait for the load event, thus the code beyond the external scripts wasn't parsed yet.
What i needed to do was after the jsdom() call add a load listener to doc.defaultView.
The reason it worked when using jQuerify was simply because it created enough of a timeout for the embedded script to load.
I had the same issue when full relative path of the jquery library to the jQueryify function. and I solved this problem by providing the full path instead.
const jsdom = require('node-jsdom')
const jqueryPath = __dirname + '/node_modules/jquery/dist/jquery.js'
window = jsdom.jsdom().parentWindow
jsdom.jQueryify(window, jqueryPath, function() {
window.$('body').append('<div class="testing">Hello World, It works')
console.log(window.$('.testing').text())
})

Can I instruct Grunt to concat all JS files defined in index.html?

Can I instruct Grunt to concatenate all JS files defined in
index.html without specifically naming them?
Can Grunt also create new index.html file that will load the concatenated JS file instead
of the previous multiple files?
Can Grunt also uglify the JS file at a same time?
Can Grunt do this not only for JS files but also CSS files used in a given html file?
I spent significant time googling but the Grunt ecosystem seems to be so fragmented and so unfamiliar to me :(.
PS: I have decided to use Grunt because there is direct integration in WebStorm 8 but maybe other tool would be more suitable for this task?
There are many different solutions available which is why it seems fragmented. I'll describe a couple of the seemingly popular methods.
Use grunt-usemin
You specify blocks within your HTML that it reads and feeds to your other Grunt tasks (concat, uglify, etc). Their docs have extensive examples to handle a lot of different scenarios.
Use a module bundler such as grunt-webpack, grunt-browserify or grunt-contrib-requirejs
Instead of adding script tags to your HTML, use a require() syntax to include files when needed. Which, depending on the method, will add the scripts to your page or bundle into a single file. These methods only require including, usually, a single javascript file.
Explore and figure out which solution makes the most sense for your needs.
I solved this problem by adding this function at the top of my Gruntfile:
var isCssRegex = /^\s*<\s*link.*href=["']([^"']*)["'].*$/i;
var isJsRegex = /^\s*<\s*script.*src=["']([^"']*)["'].*$/i;
var extractJsRegex = /src\s*=\s*"(.+?)"/
var extractCssRegex = /href\s*=\s*"(.+?)"/
function extractFilenames(src, type) {
var filenames = [];
var data = require('fs').readFileSync(src, 'utf8');
var lines = data.replace(/\r\n/g, '\n').split(/\n/);
var webContent = require('path').dirname(src);
lines.forEach(function (line) {
if (line.match(type === 'css' ? isCssRegex : isJsRegex)) {
var src = line.match(type === 'css' ? extractCssRegex : extractJsRegex)[1];
filenames.push(webContent + '/' + src);
}
});
return filenames;
};
Then in my concat task, I can do this:
concat: {
js: {
src: extractFilenames('src/main/resources/public/index.html', 'js'),
dest: 'build/app.js'
},
css: {
src: extractFilenames('src/main/resources/public/index.html', 'css'),
dest: 'build/style.css'
}
},

CDN Failover for Boostrap Javascript using AspNet.Web.Optimization

The AspNet.Web.Optimization bundling and minification package supports the use of a CDN and local failover.
public static void RegisterBundles(BundleCollection bundles)
{
bundles.UseCdn = true;
BundleTable.EnableOptimizations = true; //force optimization while debugging
var jquery = new ScriptBundle("~/bundles/jquery", "//ajax.aspnetcdn.com/ajax/jquery/jquery-2.0.0.min.js").Include(
"~/Scripts/jquery-{version}.js");
jquery.CdnFallbackExpression = "window.jQuery";
bundles.Add(jquery);
//...
}
All the examples provided that I have found, have focused on using this for jQuery but I am trying to find the appropriate CdnFallbackExpression for failover on the javascript file for Bootstrap when hosted on a CDN.
Anyone found a solution for this?
bootstrap.CdnFallbackExpression = "$.fn.modal";
Checking for the modal function should work, and seems to be the most common method on the interwebs (e.g. how to fallback twitter-bootstrap cdn to local copy).
That should write out something like:
<script> $.fn.modal || document.write('<script src="Script/bootstrap.min.js"><script>')</script>
If you also wanted something for css, then you could do it manually. This snippet might help: https://github.com/MaxCDN/bootstrap-cdn/issues/110
Or, there's this github project: https://github.com/EmberConsultingGroup/StyleBundleFallback

Load local file through HTML page inside stage webview

I have to show local image file in html through stagewebview.
When I load url of html in flex application, text content displyaed correctly, but it doesn't show a images for that. Any way I can load local file through html in stage web view?
The solution involves copying all your necessary files (html, images, css) to a storage directory, and then call your html in there. The URLs to images and CSS will be relative to that directory.
This code shows how to copy the contents of an entire directory called html into that storage directory, and then load test.html into your StageWebView object.
var source:File = File.applicationDirectory.resolvePath("html/") ;
var destination:File = File.applicationStorageDirectory;
source.copyTo(destination, true);
var initialURL = new File(destination.resolvePath("test.html").nativePath).url;
webView.loadURL( initialURL );
Be aware that you will be responsible for cleaning up that directory though.
You can load a local HTML file using the File Class. So it would be something like this:
var _locaWebFile:File = File.documentsDirectory.resolvePath(pathToHTMLContent);
var _webview:StageWebView = new StageWebView();
_stage.scaleMode = StageScaleMode.NO_SCALE;
_webview.stage = _stage;
_webview.loadURL(_localWebFile.url);
_webview.addEventListener(flash.events.Event.COMPLETE, loadData);
function loadData(e:Event):void
{
_webview.viewPort = new Rectangle(0, 0, _stage.stageWidth, _stage.stageHeight);
}
Also, you might have to make sure your paths to your images are correct.

Resources