Preact "ReferenceError: window is not defined" - server-side-rendering

I'm trying to use a web API in my Preact app and can't seem to find a workaround for this error
Build [=================== ] 93% (10.2s) after chunk asset optimization
ReferenceError: window is not defined
method: UqHU
Stack:
{
"fileName": "D:\\preact-app\\build\\ssr-build\\ssr-bundle.js",
"lineNumber": 1,
"functionName": "Object.UqHU",
"methodName": "UqHU",
"columnNumber": 93549,
"native": false
}
This is most likely caused by using DOM or Web APIs.
Pre-render runs in node and has no access to globals available in browsers.
Consider wrapping code producing error in: "if (typeof window !== "undefined") { ... }"
Alternatively use "preact build --no-prerender" to disable prerendering.
See https://github.com/preactjs/preact-cli#pre-rendering for further information.
I have tried "if (typeof window !== "undefined")" but still getting the same error. Commenting out the code or using --no-prerender solves it

The problem came from the import of axios, which depends on the "form-data" library and is not compatible with Preact prerendering as far as I understand. I chose to use fetch instead of axios to fix this but rschristian gives more solutions in this post: https://github.com/preactjs/preact-cli/discussions/1784

preact-cli prerenders your app in Node, where browser globals (such as window) do not exist.
If you've added a window check but are still getting the same error, that means you have other code also trying to access window. Each offending use will need to be wrapped in a window check if you want to prerender your app.
If you want to make a discussion on the preact-cli repo and provide your app, I can try to take a look.
Edit: The issue is in an upstream dependency of axios, form-data. This has an unsound browser vs Node check, meaning any use of axios at all will throw an error. The simplest solution would be to patch form-data/lib/browser.js with the following snippet:
module.exports = typeof self == 'object' ? self.FormData : typeof window !='undefined' ? window.FormData : undefined;
https://github.com/preactjs/preact-cli/discussions/1784

Related

how to contribute configurations from within a nuxt module

I'm writing a nuxt module following this guide.
Now I would like my module to add a proxy rule to the host application. Its a lot of guesswork and nothing has done the trick so far. I tried
nuxt.options.proxy.options.push(
{
target: 'https://target-url.com',
changeOrigin: true,
pathFilter: ['path/to/match']
}
)
}
but my IDE complains that proxy is not a known property of NuxtOptions. I did shorten the above code for the sake of this post. In my code I also made sure the respective objects exist before assigning something to them.
next best guess (based on the example for adding a css library) was to do the same thing, but on the runtimeConfig like so:
nuxt.options.runtimeConfig.proxy.options.push(...)
no complaints by the IDE anymore (duh, the runtimeConfig object is of type any) but no sign of the proxy actually working.

How are you supposed to get useful errors in Storybook?

When a component errors in storybook you only get the line number where it died in the main.iframe.bundle.js file. How can I get it to give me the line number in the original source file? Is there an option to have it generate & use some kind of sourcemap?
Are you using typescript ? Are you using React or something else ?
On my storybook, I use React with Typescript. If I put an error like that:
export function BookList (p: BookListProps) {
// ...
throw new Error('hey')
return (
//...
);
}
I have this error embed in the document (is that what you meant ?):
But I do have something useful in the console:
When clicking on the link, it open the sources panel in chrome dev tools.

How to access the moment object (from moment.js) from a QuickBase custom script

I've been writing a custom script for QuickBase, which requires some date manipulation. I decided to use moments.js and, since I'm using it within quickbase, I am loading moments.js dynamically, using $.getscript. I've done this process before with other plugin (jquery.md5.min.js), and this works correctly.
The problem is, even though moment.js is read correctly, when I try to use it (for instance, see the console.log() I added for debugging, I get an error message telling me that "moment is not defined".
I know moment.js is being read because I already had it dumped into the console after loading, and I'm trying to use its functions only after it is loaded via the asynchronous methods. I have also played with a few simple jsfiddles just to make sure I was calling it correctly. I also checked several times the url and it is correct. The rest of my code is also correct (if I comment out the lines with moment(), it works as expected).
$.getScript(domain + dbid_app + urlMoments)
.done(function(script, textStatus) {
rightNow = moment();
dfd.resolve(); // Resolve when the script is finished loading.
console.log("moments.js has finished loading.\n\n" + textStatus);
console.log(rightNow);
})
.fail(function( jqxhr, settings, exception ) {
console.log( "Triggered ajaxError handler." );
});
How do I call the moment() function? When running the fiddle, and after looking at many online examples, it is as simple as: var myTime = moment();, but this is not working inside of my script. Is there a chance that, even after loading moments.js with $.getscript(), it was not executed? From what I can see on the source code of moments.js, the factory function should be automatically called, shouldn't it?
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
global.moment = factory()
}
One last thing: the url points to the QuickBase code page I created with moments.js. This is also how I'm using jquery.md5.js without any problems.
It looks like your issue might be caused by Quickbase loading a different version of moment.js already. Specifically, Quickbase forms are using Moment 2.8.4 in some capacity and it is being loaded using RequireJS. Following Moment's example for using RequireJS I was able to get a moment object with the following code:
require(['moment'], function(){
moment();
});
rightNow = moment();
I hope that helps you solve your problem.

Exception from Tracker recompute function

I have a template helper that access a collection in my app., but I have turned off reactivity:
Template.homeBoxGroupsTpl.helpers({
boxes: function () {
return Boxes.find({},
{
sort: {
order: 1
},
reactive: (Session.get("homeCanvasTplReactive") || false)
}
);
}
});
After I insert a new element on my page, that in turn updates the collection, Meteor will throw an error in the browser console:
Error: Exception from Tracker recompute function: reporters.js?1429904535194:67
Error: Error: Bad index in range.getMember: 16
at DOMRange.getMember (http://tidee-vm/packages/blaze.js?a5c324925e5f6e800a4c618d71caf2848b53bf51:586:11)
at http://tidee-vm/packages/blaze.js?a5c324925e5f6e800a4c618d71caf2848b53bf51:2727:45
at Object.Tracker.nonreactive (http://tidee-vm/packages/tracker.js?6d0890939291d9780f7e2607ee3af3e7f98a3d9c:593:12)
at Object.Blaze.Each.eachView.onViewCreated.eachView.stopHandle.ObserveSequence.observe.changedAt (http://tidee-vm/packages/blaze.js?a5c324925e5f6e800a4c618d71caf2848b53bf51:2721:17)
at http://tidee-vm/packages/observe-sequence.js?0532a9dd76dd78f543eb4d79a1e429df186d8bde:313:21
at Function._.each._.forEach (http://tidee-vm/packages/underscore.js?0a80a8623e1b40b5df5a05582f288ddd586eaa18:164:22)
at diffArray (http://tidee-vm/packages/observe-sequence.js?0532a9dd76dd78f543eb4d79a1e429df186d8bde:299:5)
at http://tidee-vm/packages/observe-sequence.js?0532a9dd76dd78f543eb4d79a1e429df186d8bde:147:9
at Object.Tracker.nonreactive (http://tidee-vm/packages/tracker.js?6d0890939291d9780f7e2607ee3af3e7f98a3d9c:593:12)
at http://tidee-vm/packages/observe-sequence.js?0532a9dd76dd78f543eb4d79a1e429df186d8bde:121:15
Any ideas how to debug this, or is it a Meteor issue?
Meteor's error messages are horrible in all browsers but Chrome, because Meteor expects stack traces to include the error messages, but this is only done by Chrome. I hate to say this, but you'll probably have to use Chrome when debugging a Meteor app. :(
I do not have the solution, but I too encountered the same error, and was able to solve for my case, so posting it, hoping it helps you debug the issue (although this hardly seems to be of any help). The cause was use of .length. I had a large array (name of array: data), and to make it short (decrease length of arrray), I was assigning data.length = 5, which was somehow causing the error, and meteor helper did not work as expected. Removing that line worked for me, and I accomplished shortening of array by a for loop, and storing first five elements in a different variable.
I have faced similar problem too :(
I was able to resolve it by giving unique names to Tempaltes, its corresponding Helpersobject's methods in .js file and Mongo DataBase object(s) names.
Hope it might work for you too :)
For me, I was getting this error from it saying ReactionProduct.selectedVariant() is null on one of Meteor's cycles.
I just handled the null case with:
if (ReactionProduct.selectedVariant() === null) {
return;
}
and it's working out for me.

Handlebars is not defined error with package livestamp-hs

I am using the package livestamp-hs in my Meteor app. This works fine, except in the console I see the error message: Uncaught ReferenceError: Handlebars is not defined, which is caused by this package (helpers.js):
if(Meteor.isClient) {
Handlebars.registerHelper('livestamp', function(timestamp) {
return new Handlebars.SafeString('<span class="livestamp" data-livestamp="'+ timestamp +'"></span>');
});
}
I checked package.js of this package to see if handlebars is being used, and as far as I know this is OK:
Package.on_use(function(api) {
api.use(['jquery', 'handlebars'], 'client');
api.add_files(['moment.min.js', 'livestamp.min.js', 'helpers.js'], 'client');
});
Although this is not a big problem on localhost, it causes an infinite loop when deploying to either meteor.com or heroku.com. Any ideas to solve this?
In Meteor 0.8, the handlebars package was replaced by the ui package. You'll want to use that in your package.js file to ensure that you pull it in.
Handlebars.registerHelper still works, but UI.registerHelper is the new syntax.
On another note, livestamp is last decade's way of creating updated timestamps. I recommend the Meteor-based way to use time on the client, which is reactive and synced to server time: https://github.com/mizzao/meteor-timesync. (Disclaimer: I maintain that package.)

Resources