What is the difference between javascript require("file") vs require("file.js")? - javascript

I have two files.
import.js
export.js
In import I do:
const export = require('export')
This will successful import the module from export.js. When I do require('export.js') (with file ending) it is also working.
So I was wondering what is the difference there? Is without slower?

Node.js automatically resolves some extensions. For example: .js, .json, etc. No, it works the same with or without the extension.

require in Node.js takes one argument which can be either module name or path. You can read for more info.

The difference between import/export and require is that require uses commonjs under the hood. While the import was introduced in ES6.
Even if you use ES6 import it's still transpiled into thecommonjs. But using ES6 is recommended because with the time, it will be widely supported.
Performance-wise the difference will be negligible because the module files are evaluated only once but you will have to benchmark it, if you are very keen on the performance.

Related

Use import inside a nodejs usually using require

I have a NodeJS app with a lot of routes, functions, etc. I have a lot of files with const xxx = require('yyy').
I now want to use this: https://www.npmjs.com/package/simple-ldap-search
I thought my journey would be as peaceful as it has been for now, but I can't use it, let me explain: instead of the usual require, I have to use import, as described in the documentation:
import SimpleLDAP from 'simple-ldap-search';
I searched on StackOverflow, and I saw I could put "type": "module" in the top package.json file, but then if I do I can't use require... It seems unsolvable.
Does it mean I have to choose between using ES6 or CommonJS? I read this question: Using Node.js require vs. ES6 import/export
I have the impression the import is more efficient, am I right?
Is it possible to use simple-ldap-search in my current node app without making big changes?
Is it possible to "convert" (I know it's not the precise term but I think you'll understand) the use of require to import and vice-versa?
Thanks for your answers.
As this project issue states, it isn't possible to use require in a project that switched to type: "module" in its package.json. For these use cases one would need to use a loader like Babel, etc.
It is worth considering switching over to ES modules, i.e to add type: "module" to your top-level package.json. It is still possible to import a CommonJS module with import but it does not work the other way around.
Alternatively, you can switch back to a 2.x version of that package, from what I see they made the switch to ES modules from 3.0.0 onwards.
While you can't use import in a commonjs file, you can use import()
This will make it more annoying when having to deal with the async loading, but is probably easier than converting your entire project to ESModules.
const simpleLDAPLoader = import('simple-ldap-search');
// later
async function () {
const {default: SimpleLDAP} = await simpleLDAPLoader;
const simpleLDAP = new SimpleLDAP();
}
Adn this will use the cached version every time you await the exisiting promise
Source: https://nodejs.org/api/esm.html#esm_interoperability_with_commonjs
Using require to load an ES module is not supported because ES modules have asynchronous execution. Instead, use import() to load an ES module from a CommonJS module.
I am not sure if it is going to help you in your case but I have found this solution for myself and I can use ES6 import and "require" at the same time.
In package.json:
"type": "module"
And in your file:
import { createRequire } from "module";
const require = createRequire(import.meta.url);
Works for my projects!

Importing from outside webpack (runtime importing)

This is just something I thought today and I didn't see a lot of information so I'm going to share this weird cases and how I personally solved them (if there's a better way please comment, but meanwhile this might help others ^^)
In a webpack bundle, every import/require you do, is managed by webpack using their internal require function. That means you cannot use anymore the original NodeJS global require if you are inside a webpack bundle.
See also: Exporting from outside webpack bundle
There's a workaround provided by webpack actually:
A variable called __non_webpack_require__ which is the original require so, in your code, you can do this:
const internalModule = require('internal/module');
// or import internalModule from 'internal/module'; in the ES6 way
const externalModule = __non_webpack_require__('external/module');
If you are using TypeScript, you can add this line in your global.d.ts file to avoid syntax errors:
declare const __non_webpack_require__: NodeRequireFunction;
Fact 1: Actually after the build, you can see how your commonly used require (webpack's) has been renamed to __webpack_require__, and that __non_webpack_require__ has been preserved as the original require.
Fact 2: Webpack also use the original require to import modules from the system (not bundled with the code), such as net, events, fs, etc.

How to correctly configure experimental ECMAScript module so import/export can be used in Node.js

Time is flying and now the Node.js ver.10.0.0 have been out for the public. While I'm working with my MERN stack, frequently I have to switch between ES6 import/export syntax for the front-end (React.JS) and the CommonJS module.exports/require syntax in my Node/Express server-side. And I'm really wish the writing style could be unified in import/export shortly without using Babel and get it from the native support.
A good news is since the last year I read James' post on Medium addressing in the difficulty of implementing the ES6 module system in Node.js, the experimental ECMAScript Modules is now in stability 1 for a while, which means it could be enabled by --experimental-modules flag.
However, when I'm trying to use import/export syntax on Node, it is never working. For example, I have try this:
import fs from 'fs';
console.log(typeof fs.readFile);
The above code will throw me error:
(function (exports, require, module, __filename, __dirname) { import fs from 'fs';
^^
SyntaxError: Unexpected identifier
I'm really sure I have enabled the experimental flag calling as $node --experimental-modules, so what should I really do in order to kick the ES6 import/export experimental module working on my Node local server? What am I missed?
Added:
The reason why I want to try this experimental feature is to have consistent coding style in both front and back. And because it is now available natively, so I want to get ready to it. Once it have been reach in stage 2, I then can adapted to import/export quickly and have less pain.
But obviously, Google (ref) and AirBnb(ref) have different view points upon if we should use import/export syntax or not in their code-style guide. And based on Google, I'm still surprising that the semantics of ES6 import/export is not yet finalized while ECMA2019 is on its way. I'm just wonder when I can really use import/export in my project, or what is really need to be finalized?
Updated:
After pointed out by Jaromanda X, if I changed my file name to .mjs then it works. Originally I thought is the module to be loaded have to be named in .mjs extension, but it seems I was wrong. However, if that is the case, which means I will need to renamed all my project file in .mjs... and that is not appealing. Just wonder if there is a way to use this feature it in the traditional .js file? What should I configure?
Right at this point ECMAScript Module is not yet finalized in node.js v10, so it is not recommended to use it in the production environment. Since the use of import/export is standardized in the ECMAScript specification, so no matter how, it is important for node to provide such supports for the community.
The major differences between require() and ECMAScript Module is how node is going to handle its cache. Unlike require(), so far ECMAScript Module have no such API to manipulate the module cache. Also, it is unknown if it would be directly supported in the normal *.js files without a loader, so stay tuned.
The direction right now is try to introduce a new *.mjs file to explicitly showing it used the standard JS module (in accordance with ES6), but if one read the doc closely you actually could see it is also possible to specify your own extension match, including the use of the more traditional *.js. However, it required more configurations and the use of --loader flag to load the extra configuration.
There are 6 different formats are supported, including the one for modules written in C++ (it can also be loaded by require()), which is very powerful. In short, to use *.js file extension, the key setting in the loader is to have:
const JS_EXTENSIONS = new Set(['.js', '.mjs']);
And the loader function will need to check as if the file to be loaded is in JS_EXTENSIONS data set. Here, the key in the loader function is that it should return an object that have two properties: url and format, i.e.:
return {
url: (...), // e.g. './x?n=1234'
format: 'esm', // there are 5 + 1 dynamic formatting
};
It would be recommended to named the loader as custom-loader.mjs, and use it as $node --experimental-modules --loader ./custom-loader.mjs since it was demonstrated in the official doc. Once you have configured the loader correctly (based on what you need), then you should be able to use import/export as if you may used in a front-end react app in your node project.

What is different between Import and require in TypeScript?

I understand that import and require both can work if I want to use a class/module from another file. But I don't really know why
if I use require ('./config.json') will work,
but use import config from './config.json' would not work.
Does this because import only accept class/module, can't work with JSON?
I also know import is working when compile, but require is working on run time.
But really confused.
These are two totally different module systems and thus don't work the same way.
import is part of what referred to as "ES modules" i.e the native javascript implementation of modules brought by ES6.
require, on the other hand, is the import keyword of the commonjs module system. It is still used widely today, because Node.js uses it (there was no native module system in the JavaScript spec at the time of its creation).
Have a look at both the import/export docs on the MDN and the require docs on the node.js website.

Do I still need a module loader if I'm using ES6 modules?

Unfortunately my knowledge of JavaScript module loaders is still growing and I'm trying to understand their relationship to the new ES6 Modules. As far as I can tell using a module loader like CommonJS or RequireJS using ES5 compliant JavaScript really needed the use of an asynchronous module loader to increase performance and load only as needed using the respective module loader's syntax.
However looking at the ES6 module documentation and reading other information, it appears to me that module loading is natively supported via the import and export keywords. If this is the case am I correct that ES6 JS modules natively support asynchronous module loading and therefore I do not need to use an additional tool like CommonJS or RequireJS?
it appears to me that module loading is natively supported via the import and export keywords.
Not exactly. The import and export declarations only define the dependencies and the interface of each module. They allow to statically extract strings that name the required modules, nothing else.
If this is the case, do I not need to use an additional tool like CommonJS or RequireJS?
No. You still need to use a loader for ES6 modules, which resolves the names or paths or whatever from the imports to actual module files and loads them with an implementation-dependent method.
There are many tools or toolchains available, examples for the different solutions are
webpack: bundles everything into one large script
System.js: loads single modules dynamically and asynchronously (similar to what require.js does)
native: node.js and web browsers are still figuring out how to support module loading without additional libraries
babel transpilation: you can convert ES6 modules to AMD or CommonJS format and use the known tools like require.js for these
As far as my understanding goes, ES6 supports the syntax for defining and importing modules. The actual act of importing the modules that are required are a job of the infrastructure.
In modern browsers (as of 2016 that is) do not have built in functionality to support module loading and as such you will still need something like SystemJS to do the actual loading.
ES6 JavaScript Files are inherently treated as a module. if you define anything in a .js file, it will only be visible within that file (local scope ). what export does is, it exposes the classes / variables defined as export, visible to outside. then you can import it to a another module. There are other ways to define modules such as using Commonjs or AMD etc.. . Module loaders are required if you want to dynamically lazy load modules. ex. Systemjs is a such a Dynamic Module loader. it will fetch the physical module file from server dynamically when it is requested, and will prevent having multiple loads the same file. in SPA application in past had to load everything at the beginning to it to work. with dynamic module loaders now we can have only the files we need to do the intended job. hope this will help you.
https://github.com/systemjs/systemjs

Categories

Resources