SvelteKit - "ReferenceError: File is not defined" - javascript

A quick problem I faced while developing a web-app using SvelteKit (and by extension, Vite):
Inside the <script> tag of my +page.svelte file I tried defining an empty placeholder File object the following way:
let formObject: FormCreationData = {
fileToUpload: new File([], ''),
anotherField: "",
...
};
While it should work in normal JS/TS (and Svelte if you aren't using SvelteKit), it now throws the following error:
ReferenceError: File is not defined
at +page.svelte:13:14
Why is this the case?

Since SvelteKit implements Server-Side Rendering (SSR) - The code that is on the +page.svelte file has to run both on client browsers and the Vite server.
The File class is only available in browsers, so it won't be able to fulfill this requirement (You might know that Node.js offers the fs module in order to allow for file operations instead).
This means that there are two ways to possibly fix this problem:
Disable SSR using the variable ssr in the +page.ts/js file:
export const ssr = false;
Find a way to define the File object at a point where the code runs on the browser (This can be done by checking the browser variable under the $app/environment module, or inside of one of the supported Svelte hooks, such as onMount()).

Related

Local tensorflow.js won't work as a module in webworker

I'm using a local copy of tensorflow.js tfjs.js in an experimental setup. All is browser side, no node.js.
I want to move the tensorflow functionality to it's own thread in a webworker since it's heavy on the browser. However the way I got the tensorflow module to work in a worker does not make sense:
This was the initial idea:
//main.js
let predictor = new Worker ('prediction_ww.js', {type: 'module'})
//prediction_ww.js
import * as tf from "tfjs.js"
But this produces the following error when I start execution (note: 'loadGraphModel' is a method in tensorflow.js):
prediction_ww.js:44 Uncaught (in promise) TypeError: tf.loadGraphModel is not a function...
etc...
After testing without a real idea of what I'm doing I get this code, without the type: 'module' to work:
//main.js
let predictor = new Worker ('prediction_ww.js')
//prediction_ww.js
var tf = import ("./tfjs.js")
I would like to understand why this works but not the case using module which my reading suggests should be the correct way of using an external module in a webworker on the browserside.
Also I noticed it only works using the ./ before the filename which I also don't understand why.
I use Chrome 96 on macOS 10.14.
First, tfjs works just fine in a web worker unless you try to use specific functions that rely on DOM (e.g. can't use tf.browser.* methods) - and that's not the case here.
When you say local tfjs.js - which variation of tfjs is that? it ships as many variations and only ESM modules can be loaded using {type: "module"}
Default tf.js is NOT ESM, but tf.es2017.js is

Require ffi-napi on browser

I am trying to create a local browser-based application.
I need to have access to some dlls so I used a module called ffi-napi:
Example (what I need to use is not specifically the libm module, just simplifying the example):
var ffi = require('ffi-napi')
var libm = ffi.Library('libm', {
'ceil': ['double', ['double']]
})
libm.ceil(1.5)
This works fine when on I am running on Electron. But when I compile it for use with the browser, I am getting this error message (which is being thrown by Webpack/node-gyp-build:
Error in mounted hook: "ReferenceError: require is not defined"
I understand that require is not native on the browser mode, but the framework I am using, I believe, already has browserify integrated (I am using Quasar framework). I think so because the other local modules I can use require() on the browser just fine.
Is there any way I can use ffi-napi on the browser?
Help!

InternalError Metro has encountered an error: While trying to resolve module `child_process`

I am trying to call a function in a python file from a js file, I got this to work through my console, but I am now trying to implement it in a mobile app using expo.
The way I had set this up is, I have the JS file for a certain screen in my app, this then calls a function in a separate JS file, which then calls the function in the python file.
I am using the child_process module to talk to python from JS.
And as I said, this was working before I tried to export the JS function to my screen file.
index.js
export function foo(process, sentence){
const spawn = require("child_process").spawn;
const process = spawn("python3", ["./python.py", sentence]);
...
}
screen.js
*other imports
import { foo } from "./filepath..."
...
But when I run npm start I get the following error:
Failed building JavaScript bundle.
While trying to resolve module `child_process` from file `/Users/mee/Documents/GitHub/project/app/screens/screen.js`, the package `/Users/mee/Documents/GitHub/project/node_modules/child_process/package.json` was successfully found. However, this package itself specifies a `main` module field that could not be resolved (`/Users/me/Documents/GitHub/project/node_modules/child_process/app/screens/screen.js`. Indeed, none of these files exist:
How can I fix this?
It won't work for few reasons
child_process is part of the node standard library, it's not available in other environments like react-native or browser
even if above was not true, there is no python3 executable on your phone
python.py file from your local directory wouldn't be even uploaded to the phone because bundler is only uploading one big js file with entire js code combined + assets, python.py is neither of those.
Only solution that make sense it to rewrite that code to javascript.
Technically it's not impossible, there might be a way to do that, by compiling python interpreter for mobile platform, or using some tool that translates python code into js, but it's not something that you should consider.

Single API to load JSON file in Browser and NodeJS?

Is there an existing API or library that can be used to load a JSON file in both the browser and Node?
I'm working on a module that I intend to run both from the command-line in NodeJS, and through the browser. I'm using the latest language features common to both (and don't need to support older browsers), including class keywords and the ES6 import syntax. The class in question needs to load a series of JSON files (where the first file identifies others that need to be loaded), and my preference is to access them as-is (they are externally defined and shared with other tools).
The "import" command looks like it might work for the first JSON file, except that I don't see a way of using that to load a series of files (determined by the first file) into variables.
One option is to pass in a helper function to the class for loading files, which the root script would populate as appropriate for NodeJS or the browser.
Alternatively, my current leading idea, but still not ideal in my mind, is to define a separate module with a "async function loadFile(fn)" function that can be imported, and set the paths such that a different version of that file loads for browser vs NodeJS.
This seems like something that should have a native option, or that somebody else would have already written a module for, but I've yet to find either.
For node, install the node-fetch module from npm.
Note that browser fetch can't talk directly to your filesystem -- it requires an HTTP server on the other side of the request. Node can talk to your filesystem, as well as making HTTP calls to servers.
It sounds like as of now, there is no perfect solution here. The 'fetch' API is the most promising, but only if Node implements it some day.
In the meantime I've settled for a simple solution that works seamlessly with minimal dependencies, requiring only a little magic with my ExpressJS server paths to point the served web instance to a different version of utils.js.
Note: To use the ES-style import syntax for includes in NodeJS (v14+) you must set "type":"module" in your package.json. See https://nodejs.org/api/esm.html#esm_package_json_type_field for details. This is necessary for true shared code bases.
Module Using it (NodeJS + Browser running the same file):
import * as utils from "../utils.js";
...
var data = await utils.loadJSON(filename);
...
utils.js for browser:
async function loadJSON(fn) {
return $.getJSON(fn); // Only because I'm using another JQuery-dependent lib
/* Or natively something like
let response = await fetch(fn);
return response.json();
*/
}
export { loadJSON };
utils.js for nodeJS
import * as fs from 'fs';
async function loadJSON(fn) {
return JSON.parse(await fs.promises.readFile(fn));
}
export { loadJSON };

How to use nodejs file with html file?

I have a frontend in HTML and JAVASCRIPT. I need to get value from nodejs file and display it in HTML label. So I create new node js file node.js as:
const Web3 = require('web3');
const web3 = new Web3('https://kovan.infura.io');
web3.eth.getBalance('0x9E632F36D8193a23ee76e7C14698aCF4b92869A2').then(console.log);
I include this file in script tag as:
<script src="node.js"></script>
First I want to look output in the console but it is giving an error
Uncaught ReferenceError: require is not defined
So, I try this code directly in HTML file within the script tag without including node file but still gives the same error.
Can somebody help me with this? I am new to use all this together.
Somehow, I managed to find a solution. I used browserify, which makes easy for me to run the nodejs code from my web app.
Browsers don't have the require method defined, but Node.js does. With Browserify you can write code that uses require in the same way that you would use it in Node.
browserify will recursively analyze all the require() calls in your app in order to build a bundle you can serve up to the browser in a single tag.
I referred this link: http://browserify.org/

Categories