Vite css response configuration - css

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

Related

CSS file not loading even after adding middleware

CSS files are not loading and on inspecting element(F12) and going to Networks, my CSS file is not visible.
I have added the middleware
app.use(express.static(path.join(__dirname, '/public')));
and also required path above it.
I have added the middleware, required it and npm installed it too.
My Folder Structure
-app.js
-package.json
-package-lock.json
-node_modules
-public
-stylesheets
-main.css
-views
-index.ejs
-partials
-header.ejs
-footer.ejs
My Header.ejs file has this and my body containing some text.
<link href="/stylesheets/main.css">
My app.js file is
var express = require('express');
var request = require('request');
var ejs = require('ejs');
var path = require('path');
var app = express();
app.set('view engine', 'ejs');
app.use(express.static(path.join(__dirname, '/public')));
and my css file changes the color of backgorund, index.ejs file calls the header and footer respectively
<% include partials/header%>
My css code
body{
background-color: purple;
text-align: center;
}
My chrome console shows no error and still I am not able to upload my CSS.
Thanks in advance for your inputs.
You are using the link tag wrong.
You need to supply rel and type attributes for it to load the css and parse it properly. Check out the documentation of link tag to know more
The problem is with the link tag. You have to specify rel, type and href attributes in your link tag.
<link rel = "stylesheet" type = "text/css" href = "/stylesheets/main.css" />
The mater is that your are requesting stylesheet file given an url who will be completed by navigator with the current root path.
For instance, this is your link below.
<link rel="stylesheet" href = "/stylesheets/main.css" />
This is your NodeJS server code.
app.get("/your/root/path", (req, res)=>{
})
Your href link will correspond to /your/root/path/stylesheets/main.css
I think that it will be your problem.
If so, to correct it, set <base> url for static files or don't let your routes path who return views to be in the form /your/root/path but instead /your-root-path

Serve css files dynamically in raw node.js

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.

Static file not being served to my individual blog pages

I am having trouble with serving a css file to the individual blog posts in the blog portion of my website.
So the way it works:
Go to /blog- you get the blog page and that works fine.
But when I am trying to get to, for example, /blog/post1 I am getting an error
http://localhost:4000/blog/static/css/style.css
I'd appreciate the help because I'm pretty new to express and routing files around and around. Cheers.
My file structure looks like this
blog
/node_modules
/src
/mock
/public
/css
style.css
/templates
/partials
_head.jade
_nav.jade
blog.jade
index.jade
layout.jade
post.jade
app.js
So the way it works:
Go to /blog- you get the blog page and that works fine.
But when I am trying to get to, for example, /blog/post1 I am getting an error
http://localhost:4000/blog/static/css/style.css
Here is what my respective files look like, maybe I'm missing something:
app.js
"use strict";
var express = require("express"),
posts = require("./mock/posts.json");
var postsLists = Object.keys(posts).map(function(value){
return posts[value]
});
var app = express();
app.use("/static", express.static(__dirname + "/public"))
app.set("view engine", "jade");
app.set("views", __dirname + "/templates");
app.get("/", function(req, res){
res.render("index");
});
app.get("/blog/:title?", function(req, res){
var title = req.params.title;
if (title === undefined) {
res.status(503);
res.render("blog", {posts: postsLists});
} else {
var post = posts[title] || {};
res.render("post", {post: post} );
}
});
app.get("/about", function(req, res){
res.send("<h1>About Page</h1>");
})
app.get("/projects", function(req, res){
res.send("<h1>Projects Page</h1>")
})
app.listen(4000, function(){
console.log("Frontend server is running on port 4000.")
});
_head.jade
head
meta(charset="UTF-8")
link(rel="stylesheet", href="static/css/style.css")
layout.jade
doctype html
html(lang="en")
include ./partials/_head.jade
body
block content
blog.jade
extends ./layout
block content
section(id="postHolder")
for post in posts
div.post
h2 #{post.title}
p #{post.body}
a(href="/blog/" + post.title)
button Read More
post.jade
extends ./layout.jade
block content
section
div.post
h2 #{post.title}
p #{post.body}
p This is the actual post page itself.
I guess doing this will get you there -
head
meta(charset="UTF-8")
link(rel="stylesheet", href="/css/style.css")
Okay so I want to draw your attention to my _head.jade file:
head
meta(charset="UTF-8")
link(rel="stylesheet", href="/static/css/style.css")
I needed to make a reference to the absolute path and add the "/" in front of "static"
It used to be static/css/style.css and now it's
/static/css/style.css I'm pretty new to this and I don't know if I explained the reference to the absolute path correctly.

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())
})

Reading documents CSS in Chrome Extension

I am trying to read the pages CSS using a chrome extension. This is what i have in my content script :
var allSheets = document.styleSheets;
for (var i = 0; i < allSheets.length; ++i) {
var sheet = allSheets[i];
var src = sheet.href;
var rules = sheet.cssRules || sheet.rules;
}
For some reason the rules are always empty. I do get all the CSS files used in the 'src' variable. But the rules always come as null.. Its working when I try it as a separate javascript on a HTML page. But fails when I put it up in the content script of my chrome extension. Can somebody lemme know why?
Well thats the Why, but for fun and interest (never done anything with style sheets before) I thought Id do a How....
manifest.json
{
"name": "Get all css rules in stylesheets",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js" : ["myscript.js"],
"run_at":"document_end"
}
],
"permissions": [
"tabs", "<all_urls>"
],
"version":"1.0"
}
myscript.js
// Create the div we use for communication
var comDiv = document.createElement('div');
comDiv.setAttribute("id", "myCustomEventDiv");
document.body.appendChild(comDiv);
// Utitlity function to insert some js into the page, execute it and then remove it
function exec(fn) {
var script = document.createElement('script');
script.setAttribute("type", "application/javascript");
script.textContent = '(' + fn + ')();';
document.body.appendChild(script); // run the script
document.body.removeChild(script); // clean up
}
// function that gets inserted into the page
// iterates through all style sheets and collects their rules
// then sticks them in the comDiv and dispatchs the event that the content script listens for
getCSS=function (){
var rules = '';
// Create the event that the content script listens for
var customEvent = document.createEvent('Event');
customEvent.initEvent('myCustomEvent', true, true);
var hiddenDiv = document.getElementById('myCustomEventDiv');
var rules ='';
var allSheets = document.styleSheets;
for (var i = 0; i < allSheets.length; ++i) {
var sheet = allSheets[i];
for (var z = 0; z <= sheet.cssRules.length-1; z++) {
rules = rules +'\n'+ sheet.cssRules[z].cssText;
}
}
hiddenDiv.innerText = rules;
hiddenDiv.dispatchEvent(customEvent);
}
// puts the rules back in the page in a style sheet that the content script can iterate through
// youd probably do most of this in the injected script normally and pass your results back through the comDiv....Im just having fun
document.getElementById('myCustomEventDiv').addEventListener('myCustomEvent', function() {
var eventData = document.getElementById('myCustomEventDiv').innerText;
document.getElementById('myCustomEventDiv').innerText='';
var style = document.createElement('style');
style.type = 'text/css';
style.innerText=eventData;
style = document.head.appendChild(style);
var sheet = document.styleSheets[document.styleSheets.length-1];
for (var z = 0; z <= sheet.cssRules.length-1; z++) {
console.log(sheet.cssRules[z].selectorText +' {\n');
for (var y = 0; y <= sheet.cssRules[z].style.length-1; y++) {
console.log(' '+sheet.cssRules[z].style[y] + ' : ' + sheet.cssRules[z].style.getPropertyValue(sheet.cssRules[z].style[y])+';\n');
};
console.log('}\n');
};
// Clean up
document.head.removeChild(style);
document.body.removeChild(document.getElementById('myCustomEventDiv'));
});
exec(getCSS);
In the case of this question Id prolly do most of the checks in the injected script and then pass the results back through the div and its event. But I wanted to see if I could use the dom methods in the content script to go through the css and this was the only way I could figure to do it. I dont like the idea of inserting the rules back into the page, but couldnt figure any other way of doing it.
Just a guess, but since chrome extensions are Javascript based, they may have cross domain issues. Chrome sets the rules and cssRules to null when programmatically trying to get a stylesheet from another domain.
For getting all external css and all internal css file, you can use devtools API. If you want to use it in chrome extension you need to hook devtool into you chrome extension. This code will work
chrome.devtools.panels.create(
'my chrome extension',
'icon.png',
'index.html',
function(panel) {
var initial_resources = {};
// collect our current resources
chrome.devtools.inspectedWindow.getResources(function(resources) {
for (var i = 0, c = resources.length; i < c; i++) {
if (resources[i].type == 'stylesheet') {
// use a self invoking function here to make sure the correct
// instance of `resource` is used in the callback
(function(resource) {
resource.getContent(function(content, encoding) {
initial_resources[resource.url] = content;
});
})(resources[i]);
}
}
});
}
);
Answer is late, but I think I can help. One method of accessing the cssRules of external sheets protected by CORs is to use Yahoo's YQL service. I've incorporated it into a developer tools extension for Chrome for capturing styles and markup for a page fragment. The extension is in the Chrome Web Store and is on Github.
Grab the source from Github and look at the content.js script to see how YQL is used. Basically, you'll make an AJAX call to YQL and it will fetch the CSS for you. You'll need to take the CSS content and either inject it into the page as an embedded style tag or parse the CSS using JavaScript (there are some libraries for that purpose). If you choose to inject them back into the document, make sure to set the new style blocks to disabled so that you don't screw up the rendering of the page.
The extension itself might be useful to you:

Resources