express.js handlebars, get static files directory keep changes according to url - express

I am new to express. Basically my question is very simple.
I want to serve files like /css javascript from one public directory..
layout.hbs
<html>
<head>
<link href="css/style.css" rel="stylesheet" />
<script src="js/app.js"></script>
</head>
<body>
{{{body}}}
</body>
</html>
router.js --> I have three route that point to one index.hbs
router.get("/", function(req,res){
res.render("index.hbs");
})
router.get("/articles", function(req,res){
res.render("index.hbs");
})
router.get("/articles/show/:id", function(req,res){
res.render("index.hbs");
})
Now the problem is when I run this address:
curl "http://localhost:3000/"
http://localhost:3000/js/app
http://localhost:3000/css/style.css
----------------------------------------------
curl "http://localhost:3000/articles"
http://localhost:3000/articles/js/app
http://localhost:3000/articles/css/style.css
----------------------------------------------
curl "http://localhost:3000/show/1"
http://localhost:3000/show/1/js/app
http://localhost:3000/show/1/css/style.css
notice that the /css and /js path keep changing in accordance to UrlRequest. How to prevent this from happening?
I am using express and handlebars, and have already set my static file
app.use(express.static(path.join(__dirname, 'public');

You should specify the URLs to your JS and CSS as absolute URLs in your template: instead of css/style.css, use /css/style.css.
The first means "use this path relative to this page to browsers (and curl), the second "use this path relative to the host - which is what you want.

Related

vue project not working when change the base url in index.html file to my website url

This is my index.html file
when I change the base url to my website domain "https://new.weservio.com/" this error appears
Uncaught TypeError: Failed to resolve module specifier "vue". Relative references must start with either "/", "./", or "../". when I try to import vue according to this solution https://microeducate.tech/importing-a-package-in-es6-failed-to-resolve-module-specifier-vue/ .other modules can't be resolved too.
<html lang='en'>
<head>
<meta charset='UTF-8' />
<link href='images/logo.png' rel='icon' />
<meta content='width=device-width, initial-scale=1.0' name='viewport' />
<link href='https://fonts.googleapis.com' rel='preconnect'>
<link crossorigin href='https://fonts.gstatic.com' rel='preconnect'>
<link href='https://fonts.googleapis.com/css2?family=Poppins:wght#300;400;500;700;900&family=Tajawal:wght#300;400;500;700;900&display=swap'
rel='stylesheet'>
<link href=' https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.0-beta.14/vue.esm-browser.js' >
<title></title>
<!--
EDIT THE FOLLOWING CODE INSIDE THE BASE TAG
'http://localhost:3000/' ==> 'REPLACE IT WITH YOUR BASE URL'
-->
<base href='https://new.weservio.com/'>
</head>
<body class='rtl:font-tajawal font-poppins overflow-x-hidden'>
<div id='app'></div>
notice: when I leave the url as "http://localhost:3000/" and run the project locally with npm run dev .The website is working fine.
notice: This site was working correctly before on same domain url ,but I was tring to use ftp-simple extention on vs code to load automaticllay after save to server from my working directory .then the website is not working anymore .I don't know if this related.

Peerjs is not retrieved in vue js

I am trying to use peerjs in vue app. So I added the cdn script in vue index.html file's header like this.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta data-n-head="true" name="viewport" content="width=device-width, initial-scale=1.0">
<title>peer</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/peerjs/0.3.9/peer.min.js"></script>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
Now in a components' mounted hook, I am doing this to just console the id
var peer1 = new Peer();
peer1.on('open', function(id) {
console.log('My peer1 ID is: ' + id);
});
Nothing happens.
I then created a simple html file and run that html file I was able to see the id.
Next I tired to see XHR tab, I see when running a plain html file, two ajax calls is sent and in the result an ID is returned. But in vue, there is nothing like this. All I get a socket that returns this values
{websocket: true, origins: ["*:*"], cookie_needed: false, entropy: 1058218289}
cookie_needed
:
false
entropy
:
1058218289
origins
:
[":"]
websocket
:
true
One more thing, peers js documentations says to use api key, but if I use api key nothing happens in vue or html. Without the key, in html file I get the id.
Anyone knows please help me. Thank you.

Server Rendering SyntaxError with React/Redux/Express

I'm trying to get my app rendering from the server and so was trying to implement the ServerRendering example from here: http://redux.js.org/docs/recipes/ServerRendering.html
I can successfully run server.js but I get an "Uncaught SyntaxError: Unexpected token <" error # bundle.js:2 once I load up localhost. I believe it has to do with the renderFullPage() function:
function renderFullPage(html, initialState) {
return `
<!doctype html>
<html>
<head>
<title>Redux Universal Example</title>
</head>
<body>
<div id="root">${html}</div>
<script>
window.__INITIAL_STATE__ = ${JSON.stringify(initialState)}
</script>
<script src="/dist/bundle.js"></script>
</body>
</html>
`
}
If I remove the line <script src="/dist/bundle.js"></script> the error goes away, but then the counter doesn't work.
Here is the bundle.js that the error references:
bundle.js
It should be referencing bundle.js in my dist folder but it's not for some reason? If I make an index.html file exactly the same as what renderFullPage is returning, except getting rid of ${html} and
<script>
window.__INITIAL_STATE__ = ${JSON.stringify(initialState)}
</script>
then the counter works fine. When I do the server side rendering it seems like the client can't find the bundle.js code so creates one that has the exact same code as what it received from the server, and so there is an error as it runs into html when it's expecting javascript.
It's because your bundle.js contains HTML rather than your client-side scripts. Are you using a catch-all route and not letting it load your static assets? Your express.static middleware use call should go before this bit of code (middleware order matters).

(Dojo 1.10) URL returned by dojoLoader seems wrong/inconsistent, how can I configure this correctly?

We recently updated our server with signed certificates and changed the base URL from https://servername/ to https://servername.domain.info/ . This has broken module loading in Dojo and I can't seem to correct it. The current config looks like this:
var dojoConfig = {
async: true,
packages: [
{
name: "js",
location: location.pathname.replace(/\/[^/]+$/, "") + 'Scripts'
},
{
name: "widgets",
location: location.pathname.replace(/\/[^/]+$/, "") + 'Scripts/widgets'
},
{
name: "dgrid",
location: location.pathname.replace(/\/[^/]+$/, "") + 'Scripts/3.14/dgrid'
},
{
name: "dijit",
location: location.pathname.replace(/\/[^/]+$/, "") + 'Scripts/3.14/dijit'
}
]
};
This used to work, and it still works on my dev machine when the root URL is just 'localhost'. Looking at the errors in the console it seems to be trying to find the modules at https://servername/ instead of https://servername.domain.info/ and I've tried everything I could find to point it in the right direction, including setting baseUrl: 'https://servername.domain.info' explicitly. Anything I've tried results in different URL strings, sometimes just the pathname and no base URL, sometimes pathname plus protocol with no domain info, etc. For reference, I also tried just adding the server URL to each location's URL string and I get the same error that seems to drop all but the first word from the server domain name.
I'm not sure what I'm doing wrong and I'm baffled by what dojoLoader decides to drop. I've read and reread the documentation but not much is said about how the base URL is calculated as far as I can find, just stuff on how to set baseUrl in the config to something.
edit: Per the comment below, I realize more info is needed. I am using Visual Studio 2015 and publishing to Windows Server 2012 R2 running IIS (v7 iirc). It does look like maybe Visual Studio is messing with the URL somehow, Dojo is not to blame. I was able to work around it by editing the file directly on the server and setting a location URL for every package (and their dependencies). I'd still like to know why it's happening and how I can set it up correctly.
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title - ProjectName</title>
<link rel="stylesheet" href="~/Content/font-awesome.min.css" />
<link rel="stylesheet" href="~/Content/jquery-ui-1.10.3.custom.css" />
<link rel="stylesheet" href="~/Scripts/3.14/esri/css/esri.css" />
<link rel="stylesheet" href="~/Content/bootstrap-datetimepicker.min.css" />
#Scripts.Render("~/bundles/modernizr")
<link rel="stylesheet" href="~/Content/map.css" />
#Styles.Render("~/Content/css")
</head>

Handlebars with Express: different html head for different pages

I am using Handlebars in an Express Node.js app. My layout.html file includes a <head> section. How can I make the <head> section different for different pages? (So that I can, for example, reference a JavaScript file in only one page, and vary the <title> for each page.)
layout.html looks like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src='/public/ajsfile.js'></script>
<link type='text/css' href="/public/style.css" rel="stylesheet">
</head>
<body>
{{{body}}}
</body>
</html>
(I am imagining varying the <head> content with something analogous to {{{body}}} in the above, but with {{{head}}}.)
This is a great question and, in my mind, a glaring weakness in Express's view model. Fortunately, there is a solution: use Handlebars block helpers. Here's the helper I use for this purpose:
helpers: {
section: function(name, options){
if(!this._sections) this._sections = {};
this._sections[name] = options.fn(this);
return null;
}
}
Then, in your layout, you can do the following:
<head>
{{{_sections.head}}}
</head>
<body>
{{{body}}}
</body>
And in your view:
{{#section 'head'}}
<!-- stuff that goes in head...example: -->
<meta name="robots" content="noindex">
{{/section}}
<h1>Body Blah Blah</h1>
<p>This goes in page body.</p>
You can make the follow:
layout.hbs
<head>
<title>{{title}}</title>
{{#each css}}
<link rel="stylesheet" href="/css/{{this}}" />
{{/each}}
</head>
app.js
router.get('/', function (req, res, next) {
res.render('index', { title: 'MyApp', css: ['style.css', 'custom.css'] });
});
Result:
<head>
<title>MyApp</title>
<link rel="stylesheet" href="/css/style.css" />
<link rel="stylesheet" href="/css/custom.css" />
</head>
Maybe, you could use this implementation of the section helper: https://github.com/cyberxander90/express-handlebars-sections
You just need to install it and enable it:
yarn add express-handlebars-sections # or npm
const expressHandlebarsSections = require('express-handlebars-sections');
app.engine('handlebars', expressHandlebars({
section: expressHandlebarsSections()
}));
Hope it helps.
Younes
I know this is an older question but I wanted to point out a clear alternative solution to what you are asking (I'm not entirely sure why nobody else spoke about it over the years). You actually had the answer you were looking for when you bring up placing things in {{{head}}} like you do for {{{body}}}, but I guess you needed help understanding how to make it work.
It seems possible that most of the answers on this page are geared towards Node "Sections" because you speak about the different sections of HTML you've included in your layout file that you want to change. The "Sections" everyone is speaking about in this thread seems to be a technique, although I may be mistaken, originating from Microsoft's Razor Template Engine. More info: https://mobile.codeguru.com/columns/dotnet/using-sections-and-partials-to-manage-razor-views.htm
Anyway Sections work for your question, and so could "Partials" theoretically (although it may not actually be the best option for this). More info on Partials:
https://www.npmjs.com/package/express-partial
However, you simply asked for a way to alter the HTML tag content of your template layout in Handlebars, and assuming we are talking about HTML head tags, all you need to do is replace the content you have in your template layout HTML head tags with one of these (I use 3 brackets because it seems HTML would be included and you don't want it escaped):
<head>
{{{headContent}}}
</head>
Then you just dynamically pass whatever data you want through the route you create in your app.js file to "get" the page like so (I am mostly taking the code #Fabricio already provided so I didn't have to rewrite this):
router.get('/', function (req, res) {
res.render( 'index', { headContent:'I DID IT!' });
});
Now when you load your page, "I DID IT!" will be where you expect it to show up.