javascript added using useHead is being executed on the server

I have a javascript to be executed on the client to check the browser version and also if some functionalities are available and if not match the criteria we redirect the user to a dedicated page (informing the user that he needs to update the browser) But I see that the code added to the script tag is being executed on the server and being changed original:
if (typeof window !== 'undefined') {
...
}
if (typeof window !== 'undefined') {
...
}
then turns into:
if ("undefined" !== 'undefined') {
...
}
if ("undefined" !== 'undefined') {
...
}
How can I prevent/fix this? Thanks
16 Replies
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
Victor Neves
Victor NevesOP10mo ago
thanks @Igor Jacaúna I'll gonna take a look and see if it feets on my needs even so, I'm trying to understand why the js code inside the script tag that is injected into the markup is being executed on the server and also changed It's something that I wasn't expecting to happen as it should "just" inject it into the markup
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
Victor Neves
Victor NevesOP10mo ago
I am not sure if it has to do with the way I'm declaring the js function I'm creating it as a "string"
const browserCheck = `(function(){
function addBodyClass() {
document.body.className += ' legacy';
document.removeEventListener("DOMContentLoaded", addBodyClass);
}

if (typeof window !== 'undefined') {
var customProps = true, cssGrid = true, proms = true;
// rest of the code
}
})();
`;

useHead({
script: [browserCheck],
});
const browserCheck = `(function(){
function addBodyClass() {
document.body.className += ' legacy';
document.removeEventListener("DOMContentLoaded", addBodyClass);
}

if (typeof window !== 'undefined') {
var customProps = true, cssGrid = true, proms = true;
// rest of the code
}
})();
`;

useHead({
script: [browserCheck],
});
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
Victor Neves
Victor NevesOP10mo ago
the code is inside app.vue
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
Victor Neves
Victor NevesOP10mo ago
it's hard as it's the config is very complex The addBodyClass function is called inside the if (typeof window !== 'undefined') { base on other conditions
if (!(customProps && cssGrid && proms) || isOnBlacklist) {
var currentLocation = document.location;
var url;

if (typeof currentLocation === 'string') {
url = currentLocation;
} else if (typeof currentLocation === 'object') {
url = currentLocation.href;
}

if (!/update-browser/gi.test(url)) {
document.location = '/update-browser';
}

if (document.readyState === 'loading') {
document.addEventListener("DOMContentLoaded", addBodyClass);
} else {
addBodyClass();
}
}
if (!(customProps && cssGrid && proms) || isOnBlacklist) {
var currentLocation = document.location;
var url;

if (typeof currentLocation === 'string') {
url = currentLocation;
} else if (typeof currentLocation === 'object') {
url = currentLocation.href;
}

if (!/update-browser/gi.test(url)) {
document.location = '/update-browser';
}

if (document.readyState === 'loading') {
document.addEventListener("DOMContentLoaded", addBodyClass);
} else {
addBodyClass();
}
}
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
Victor Neves
Victor NevesOP10mo ago
StackBlitz
Nuxt - Starter (forked) - StackBlitz
Create a new Nuxt project, module, layer or start from a theme with our collection of starters.
Victor Neves
Victor NevesOP10mo ago
No problem now I'm confused In my example, I have the same way as I have on the project and also doesn't change the code :/
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
Victor Neves
Victor NevesOP10mo ago
nope. I forgot to set the SSR Now I'm also getting the js code changed
No description
Victor Neves
Victor NevesOP10mo ago
looks like someone already reported this behavior https://github.com/nuxt/nuxt/issues/22559
GitHub
Unexpected substitutions in embedded scripts in useHead · Issue #22...
Environment Operating System: Linux Node Version: v16.20.0 Nuxt Version: 3.6.5 Nitro Version: 2.5.2 Package Manager: [email protected] Builder: vite User Config: - Runtime Modules: - Reproduction https://s...
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
Victor Neves
Victor NevesOP10mo ago
maybe The thing is that it wasn't me who implemented We had it more or less as you described on our Vue 3 SSR project and now that we are migrating to Nuxt, who was working on this, initially, it has made it the same way as you, but then the dev that implemented the initial solution said that going with that approach, it could lead to some problems for slower connection and then it was refactored to this approach. My proposal was to forget the check for browser functionalities and only use the browser version and do it directly on the server middleware, cause that way, instead of returning the page that was initially requested it would immediately return the outdated page...but the architects said it was ok the way it was and didn't want to change :/ this was my proposal
export default defineEventHandler(async (event) => {
if (event.req.url === '/update-browser') {
return;
}

const ua = event.req.headers['user-agent'];
let isOnBlacklist = false;
const browsers = [
//Safari:
{
version: 14,
rgxua: /(?:\s|^)(AppleWebKit\/[\d.]+)\s+\((.+)\)\s+Version\/(\d{1,3})(?:\.|\s|$)/gi,
rgxversion: /Version\/\d+.*?/gi,
},
//Firefox:
{
version: 78,
rgxua: /firefox/gi,
rgxversion: /Firefox\/\d+.*?/gi,
},
//Chrome:
{
version: 87,
rgxua: /chrome/gi,
rgxversion: /Chrome\/\d+.*?/gi,
},
//Edge:
{
version: 88,
rgxua: /edg/gi,
rgxversion: /edg\/\d+.*?/gi,
},
];

for (const browser of browsers) {
const match = browser.rgxua.test(ua);

if (match) {
const version = browser.rgxversion.exec(ua);
const parsedVersion = parseInt(version[0].replace(/^\D+/g, ''));

if (parsedVersion < browser.version) {
isOnBlacklist = true;

break;
}
}
}

if (isOnBlacklist && !event.res.headersSent && !event.req.url.includes('/update-browser')) {
await sendRedirect(event, '/update-browser', 302);

return false; // Prevent further request processing
}
});
export default defineEventHandler(async (event) => {
if (event.req.url === '/update-browser') {
return;
}

const ua = event.req.headers['user-agent'];
let isOnBlacklist = false;
const browsers = [
//Safari:
{
version: 14,
rgxua: /(?:\s|^)(AppleWebKit\/[\d.]+)\s+\((.+)\)\s+Version\/(\d{1,3})(?:\.|\s|$)/gi,
rgxversion: /Version\/\d+.*?/gi,
},
//Firefox:
{
version: 78,
rgxua: /firefox/gi,
rgxversion: /Firefox\/\d+.*?/gi,
},
//Chrome:
{
version: 87,
rgxua: /chrome/gi,
rgxversion: /Chrome\/\d+.*?/gi,
},
//Edge:
{
version: 88,
rgxua: /edg/gi,
rgxversion: /edg\/\d+.*?/gi,
},
];

for (const browser of browsers) {
const match = browser.rgxua.test(ua);

if (match) {
const version = browser.rgxversion.exec(ua);
const parsedVersion = parseInt(version[0].replace(/^\D+/g, ''));

if (parsedVersion < browser.version) {
isOnBlacklist = true;

break;
}
}
}

if (isOnBlacklist && !event.res.headersSent && !event.req.url.includes('/update-browser')) {
await sendRedirect(event, '/update-browser', 302);

return false; // Prevent further request processing
}
});
even so, with this approach, it would still be possible to cover the browser functionalities, by running that logic directly on the onMounted hook
Want results from more Discord servers?
Add your server