Why the import url must start with "node:" - node.js

I was checking the node official docs and I found that the import url of the node native modules in the examples of es modules starts with node:.
I did not use node very much, maybe there were some huge changes happened. So:
Can someone share some links that I can get some context about this change?
What if we don't add the node: before the import url? I tested a bit and it seems everythings works fine.
Thanks a lot.
import { open } from 'node:fs/promises';
let filehandle;
try {
filehandle = await open('thefile.txt', 'r');
} finally {
await filehandle?.close();
}
I wrote some node packages and use "type": "module" in pacakge.json and not use node: when I import native modules, I did not see any errors.

From the docs:
Core modules can be identified using the node: prefix, in which case it bypasses the require cache. For instance, require('node:http') will always return the built in HTTP module, even if there is require.cache entry by that name.

Related

Cannot use import statement outside a module with #pusher/push-notifications-web nodejs - beams

I am trying to follow this tutorial using nodejs and express: https://pusher.com/docs/beams/reference/web/#npm-yarn
First I did: npm install #pusher/push-notifications-web before adding the code.
But when I add this code in the index.js file:
import * as PusherPushNotifications from "#pusher/push-notifications-web";
const beamsClient = new PusherPushNotifications.Client({
instanceId: "<YOUR_INSTANCE_ID_HERE>",
});
beamsClient.start().then(() => {
// Build something beatiful 🌈
});
I get this error:
SyntaxError: Cannot use import statement outside a module
It's also not very clear to me from the tutorial if the code has to be in the frontend or the backend. I tried both but got the same result.
How can I fix this problem?
The error is caused by the fact that you're trying to use ES module specific features in a regular CommonJS file (the default behavior in Node.js). However, what you're looking at is the Web SDK for Pusher which won't help you achieve your goals.
You need the server SDK for Node.js - https://pusher.com/docs/beams/reference/server-sdk-node/.
Verify that you have the latest version of Node.js installed and you have 2 ways of fixing that
Set "type" field with a value of "module" in package.json. This will ensure that all .js and .mjs files are interpreted as ES modules.
// package.json
{
"type": "module"
}
Use .mjs as file extension instead of .js.

How can I import other file in service worker file using workbox-webpack-plugin injectMode?

I am using vue-cli and workbox-webpack-plugin injectMode
new InjectManifest({
swSrc: './src/sw.ts',
swDest: 'sw.js',
}),
in sw.ts, I try to import other file
import { precacheAndRoute } from 'workbox-precaching'
import { registerRoute } from 'workbox-routing'
import { WorkboxPlugin, setCacheNameDetails, RouteHandler } from 'workbox-core'
import { CacheableResponsePlugin } from 'workbox-cacheable-response'
import { ExpirationPlugin } from 'workbox-expiration'
import Strategies, { CacheFirst, StaleWhileRevalidate } from 'workbox-strategies'
// import other file
import { CustomMessage, MessageType, MESSAGE_META, SWRouting } from './utils/registerSW'
but when building APP, it will fail,
error: js/chunk-2d213953.a6b52dae.js from Terser
Unexpected token: punc (:) [js/chunk-2d213953.a6b52dae.js:3,12]
when I remove this import statment, building works well.
So, Could I import other files ? How ?
Generally speaking, what you're trying to do should work. The InjectManifest plugin will kick off a webpack child compilation for the your swSrc file, and will inherit whatever plugins and config you have set up for your main, parent compilation. It should be able to bundle ES modules into a final service worker.
It sounds like there's something specific in one of those ./utils/registerSW imports that is causing Terser to be unable to parse the bundled code, though. I would recommend starting by just importing a very small, no-op function from ./utils/registerSW, and confirm that that works. Then try importing each of those functions from ./utils/registerSW one at a time until you find the one that's causing issues, and check the original source code to see what might be triggering it.
It's possible that the child compilation kicked off by InjectManifest is misconfigured, and perhaps that's due to a bug that needs to be fixed, but I would start with those debugging steps first.

Is there a way to import from this node module with 'import' instead of 'require'?

I'm using this node module 'deep-equal' () and so far the only way I've been able to access the function in it is with var equal = require('deep-equal');, as suggested in the documentation. I usually use import instead of require, and am wondering if it's possible to use import with this module. The main function is exported from the file in this line:
var deepEqual = module.exports = function (actual, expected, opts) {...}
Is it possible to import this function with import, or is it only possible with require?
Thanks!
Yes you actually can.
If you're using nodejs LTS then you'll have to use .mjs extension for the file where you're using import and pass experimental-modules flag while running node process.
// foo.mjs
import equal from 'deep-equal';
node --experimental-modules foo.mjs
As of nodejs 12.3.0 you can simply pass the experimental-modules. From docs
Once enabled, Node.js will treat the following as ES modules when passed to node as the initial input, or when referenced by import statements within ES module code
Also you can specify type as module in your package.json:
// package.json
{
"type": "module"
}
From docs
Files ending with .js or .mjs, or lacking any extension, will be loaded as ES modules when the nearest parent package.json file contains a top-level field "type" with a value of "module"

How to resolve fs.existsSync is not a function

In NodeJS I have:
const fs = require('fs');
if (!fs.existsSync("some_path")) {
...
}
But I get the error:
TypeError: fs.existsSync is not a function
After doing some searching, I read that Webpack brings its own require which clobbers node.js's require, so when you require a node.js core module that webpack can't resolve to one of your files or dependencies, it throws.
(My stack trace includes __webpack_require__)
But how can I fix it?
I was facing the same Error like TypeError: fs.existsSync is not a function
So, I figured out that one extra line was added automatically which was creating this issue in import.
after removing this line from import
import { TRUE } from "node-sass";
the issue has been resolved.
I had the same error that you have. Your vscode might have added a new module to your js file. Remove that module and your app should work just fine.
You can allow webpack to use the Node's require and include fs etc. by targeting node in the config:
module.exports = {
entry: './src/main.js',
target: 'node',
output: {
path: path.join(__dirname, 'build'),
filename: 'backend.js'
}
}
As described here: https://webpack.js.org/concepts/targets/ and https://webpack.js.org/configuration/target/
I was working on an electron application, I wanted to send a message from node and get in on the react side, but I was having that same issue when requiring ipcRenderer from electron, I tried
import { ipcRenderer } from 'electron';
and
const { ipceRenderer } = require('electron') This leads to an error due to webpack transforming node's require to its own webpack_require. See more info here
What worked for me was to use
const {ipcRenderer} = window.require('electron'); on the react side/renderer side from electron
In my case, I forgot that I'd only imported the promises API, const fs = require("fs").promises, which doesn't have exist or existsSync functions in Node 17.4.0.
To use exist or existsSync, make sure you've imported fs using the sync API (const fs = require("fs")).
Note: I'm adding this answer as a possible solution for future visitors to a canonical thread for the error, not OP who appears to have required fs correctly.
It is nothing to worry about, check your code for something like import { types } from "node-sass";, it would have mistakenly and automatically imported without you know. Remove that line, and everything should work perfectly.
Even if it is not type, it is something from node-sass in your node_modules file, and you can't edit that file.
So look for and remove import { types } from "node-sass"
In my case VSCode added a arbitrary import from electron. After removing it my application worked.
import { Menu } from 'electron';
In my case, i needed to send a message from the node to react. I tried importing ipcRenderer from 'electron'; and const ipceRenderer = require('electron') This results in an error owing to webpack changing the node's require to its own webpack require. See more info here

Writing WebSocket client with TypeScript running both on browser and Node.JS

I am writing a typescript code that would run in a web-browser and would be tested with Node.JS.
My client code looks like below.
import * as WebSocket from 'ws';
export class SomeClient {
constructor(url) {
this.ws = new WebSocket(url);
}
send(data: any) {
this.ws.send(data);
}
}
I had no problem in writing a unit test code using mocha/chai.
However, trying to bundle this code, browserify includes all the 'ws' node module and the size of the output file is almost 100kb. If I remove the import 'ws' statement, the bundle file size shrinks less than 1kb. But, in this case, the Node.JS test complains with 'WebSocket is not defined' error.
I think, this is because WebSocket is natively supported in web browsers but not supported in Node.JS and the external 'ws' module is required to run properly.
How can I make a bundle with the minimum size for web browsers yet can use in Node.JS???
Try isomorphic-ws:
npm i isomorphic-ws -s
or universal-websocket-client:
npm install --save universal-websocket-client
I struggled with the same problem, best solution I could find was to use isomorphic-ws create a decs.d.ts in my typescript rootDir with the following content
declare module "isomorphic-ws";
and then use it inside typescript like that:
import { IsoWebSocket } from "isomorphic-ws";
var ws = new IsoWebSocket("wss://echo.websocket.org") as WebSocket;

Resources