Use "import" with Node library, rather than "require"? - javascript

Newbie Node question here.
I'm trying to use the Google Cloud Node client with an existing application (not written by me) that bundles its code with rollup.
I've tried importing the library with require, as per its documentation, as follows:
import REGL from "regl/dist/regl";
import Camera from "./lib/camera";
...
var gcloud = require('google-cloud');
But my application complains (CLARIFICATION: it only starts producing this error when I add the require statement, otherwise the imports work fine):
'import' and 'export' may only appear at the top level
So maybe I need to use import gcloud instead of require, but how? I tried looking at the code in node_modules and doing this instead:
import gcloud from "google-cloud/src/index";
But now I get a bunch of other errors
🚨 Unexpected token
node_modules/google-cloud/node_modules/ent/reversed.json (2:7)
1: {
2: "9": "Tab;",
^
How can I use import instead of require, or alternatively, how can I make require play nicely with import?

import is ES6 syntax. You either must use an experimental flag with nodejs or use babel to compile your js to be ES6 compatible.
EDIT:
Since the problem is with require and not import, i'm updating my answer.
I'm not sure what you're setup is but it's because, i'm guessing, google-cloud isn't written in es6. So you'll have to see if there's an es6 version in the src. If there is you could try (I doubt this will work)
Try:
import * as gcloud from 'google-cloud'
if that doesn't work - try a shimming module like riveted. You'll need webpack to compile this. Since you're using rollup.js, which i'm unfamiliar with you'll need a es5 to es6 compiler for this.

Related

What's the difference between node:process and process?

When I import node:process it works fine. However, when I try to require the same, it gives an error.
This works fine:
import process from 'node:process';
But when I try to require the same, it throws an error:
const process = require('node:process');
Error: Cannot find module 'node:process'
I am curious as to what is the difference between process, which works in both, commonjs and module, vs node:process.
Also, a follow-up, I am using webpack to bundle my js, and I discovered this error when I tried to run my bundled code and realised, that chalk imports node:process, node:os and node:tty. How do I solve that now?
import process from 'node:process'; and import process from 'process'; are equivalent.
The node: exists since version 12 for import.
node: URLs are supported as an alternative means to load Node.js builtin modules. This URL scheme allows for builtin modules to be referenced by valid absolute URL strings.
The idea behind node: is to make clear that it is actually a buildin module and not one installed and to avoid name conflicts, with 3rd party modules.
The node: protocol was first added only for import so a particular node version might support node: with import but not with require.
In v16.13.0 (not sure since which v16 version) you can also use it with require. And was also backported to v14 since v14.18: module: add support for node:‑prefixed require(…) calls
"node:" is an URL scheme for loading ECMAScript modules. As such it started for "import", not "require".
"node:process" is just an alternative name to load the built-in "process" module.
See also Node.js documentation - you can find the lowest supporting Node.js version inside the "History" tag (12.20.0, 14.13.1)
With newer Node.js it should be available for "require" as well (14.18.0, 16.0.0).
Some more details can be found here: node:process always prefers the built-in core module, while process could be loaded from a file.

Is it possible to use both CommonJS and ES6 module in a Node.JS command-line program?

I'm working on a CLI tool. I used "commander", which is a CommonJS module, to parse command-line arguments. I also want to use "p-map" to manage concurrency. However, "p-map" is a ES6 module.
Also I'm using Typescript.
Now both code editor and Typescript compiler won't complain. However I cannot execute my CLI tool. If I compile with "module":"commonjs", node would not load p-map and complains "Must use import to load ES Module... node_modules/p-map/index.js...require() of ES modules is not supported.". If I compile with "module":"es2015", use "require" to import the CommonJS modules, and add "type":"module" in my package.json, node would complain "ReferenceError: require is not defined".
I love the flexibility of Typescript/Javascript, however, it's time like this makes me miss Java. Java might be too prissy, but I don't spend hours trying to figure out import / export......
So, is it possible to use both CommonJS and ES6 module in a Node.JS command-line program?
To enhance compatibility, the (moderately new) node esm loader can import cjs-modules (e.g. import identifier from 'cjs-module-name';).
The other way around doesn't work, you can't require an esm-module, but dynamic import should work, if really necessary.
A related read may be the statement from p-map's owner regarding the topic.

ES6 module, what counts as the first import?

Here's my module:
console.log("module imported");
export function call(){};
In main.ts:
import * as mod from './module';
// other code that doesn't use mod.
I would have expected this to log "module imported" to the console. In fact, the example seems pretty much the same as this one. And they say:
A module code is evaluated only the first time when imported
But there are no console logs. However, after the following edits to main.ts the log message appears:
import * as mod from './module';
if(false){
mod.call();
}
It would make sense if only the first time the module is actually used counted as the first import. But here the log message seems to be based on static analysis alone. The code path that uses the module is never executed.
How does this work? What counts as the first import of an ES6 module?
Also, my gut feeling says that this might be about the bundler. Does it optimize away an unused import like this? I'm running these code snippets in a react app, created with:
npx create-react-app my-app --template typescript
cd my-app
# add the module and import it to index.tsx
npm i
npm run start
# browser opens, check the console
On the other hand, the typescript react app also has imports like './index.css' and they are only there for the bundler to package them. It seems common to import something only for its side-effects.
I have searched for related questions but so far haven't found something with this specific problem:
Run ES6 code only if module is executed directly
`if __name__ == '__main__'` equivalent in javascript es6 modules
In browser JS code that imports from ES6 module is not executed
The last of these looks like a duplicate, but it is about a specific syntax error in the module resolution.
Your guess is correct, it's happening because of bundler. Its a feature of bundler known as Dead code elimination. To know more about it, search for Tree Shaking or Dead code elimination.
If you are not going to use anything from imported module, source code of module will not be included in your build.
I think create-react-app use Webpack for bundling. If you want to disable the feature, starting the app in development mode may solve it. BTW, its good to remove unused code while building.

How do I properly load the lit-html module in Electron

I'm trying to use lit-html to save my self some time, but I'm having trouble getting everything set up correctly.
Electron 4.1.1
Node 11.15
As of 5 minutes before posting this, I've run npm install and electron-rebuild, no luck.
I use require() as one would with any other NPM package
var render = require('lit-html').render
var html = require('lit-html').html
console.log(require("lit-html"))
Unfortunately, I'm greeted with this error
In reference to the three lines of code above.
I don't see any problems with my code.
I've tried reinstalling lit-html through NPM to no avail. I would really love to use this library, but first I have to get over this hurdle. If I'm being honest, I don't know if this error is reproducible, but nothing I do seems to fix it. The problem seems to lie with node and the way that imports are handled.
Am I missing something here? Is this a common issue? If so, what can I do to fix it?
You need to transpile lit-html before you can require it
I tested require('lit-html') and I was greeted with this error:
/home/chbphone55/Workspace/test/node_modules/lit-html/lit-html.js:31
import { defaultTemplateProcessor } from './lib/default-template-processor.js';
It clearly states that the error is coming from lit-html/lit-html.js:31 where the line uses ES Module import syntax.
You can transpile it using tools like Babel or similar ones. However, you may want to try using ES Module syntax so you can import lit-html without transpiling it.
Example:
<!-- HTML File -->
<script type="module" src="index.js"></script>
// index.js
import { html } from 'lit-html';
What if you can't use type="module"
If you are unable to use the type="module" method above, you can also use the ESM package.
ESM is a brilliantly simple, babel-less, bundle-less ECMAScript module loader.
Here are a few examples of how to use it:
Using the node require flag (-r) to load esm before everything else
node -r esm index.js
Loading esm in your main file then loading the rest of your code.
// Set options as a parameter, environment variable, or rc file.
require = require('esm')(module/*, options*/)
module.exports = require('./main.js')

How to setup babel-standalone in my none node js environment?

I want to use es6's import, require and export in my web app using codeigniter.
i found babel-standalone but it's not working.screenshot of embed js files
With the added detail that
import, require and export is undefined
Here's the problem: that's not what Babel does. Babel transpiles code: it turns one file of ES6 code into a file that contains ES5 code that does the same thing. It does not combine source code files that use require or import into bundles.
You're looking for browserify or Webpack to do that - they are bundlers, tools that let you use require, import, and export to organize code. You'll need to use one of them to accomplish your goal - Babel alone will not do what you're trying to do.

Categories

Resources