In typical JavaScript files we use require('some-module.js') to import functionality of this module where we need.
If we use TypeScript we also want to import this functionality using "import module from 'some-module.js'".
If we use nest.js we import using "import module from 'some-module'". The main thing that there is no ".js". How can i reach the same in for example express application. Maybe i should use webpack, babel or some special tsconfig.json configuration?
With Typescript's import and with Node's require, the extension is not necessary. Just the path to the file, or the name of the package you're importing. So in typescript you would do import * as module from 'some-module' and in js you would do const module = require('some-module'). You may want to check out this page on module resolution in Typescript.
Related
This question is not whether Node.js supports the ES Module system.
That question has been answered previously, eg:
How can I use an ES6 import in Node.js?
Node.js - SyntaxError: Unexpected token import
And these answers are supported by the official Node.js docs:
ECMAScript modules are the official standard format to package JavaScript code for reuse...Node.js fully supports ECMAScript modules as they are currently specified and provides interoperability between them and its original module format, CommonJS. Node.js has two module systems: CommonJS modules and ECMAScript modules. Authors can tell Node.js to use the ECMAScript modules loader via the .mjs file extension, the package.json "type" field, or the --input-type flag.
Source
So it is clear that Node.js supports the ES Module system.
This question is:
When using the ES Module system in Node.js, can all Node packages be imported using the same import syntax?
The reason I ask is that a lot of packages' documentation does not specify how to import them using ES Module style, eg:
https://expressjs.com/en/starter/hello-world.html
https://github.com/expressjs/session
I want to avoid the situation where I am trying to figure out the correct syntax to use each time I want to import a library.
This answer seems to suggest this syntax:
import * as [ whatever_was_previously_used_as_the_variable_name ] from [ whatever_was_previously_between_the_quotes_in_the_parenthesis ]
So, using the examples above, this:
const express = require('express');
const app = express();
const session = require('express-session');
could safely be converted to:
import * as express from 'express';
const app = express();
import * as session from 'express-session';
Is that the 'universal' syntax that should be used to import all Node packages?
(Update: that session import above doesn't work, at app.use(session(sessionConfig)); it caused the error TypeError: session is not a function - I needed to define the import like this: import session from 'express-session'. I also had to import axios like this: import axios from 'axios', or i got a similar error. However, to use msal-node i had to use import * as msal from '#azure/msal-node').
Just to confuse things, I have come across other syntax examples, such as these in the Node docs (which includes node:):
import * as fs from 'node:fs/promises';
// OR:
import * as fs from 'node:fs';
Source
I am hoping a definitive answer can be provided that covers the different scenarios that may exist, eg: Node packages that live in the node_modules directory as well as one's own custom JavaScript modules that live outside of node_modules.
In this way, if I ever come across a package that does not specify installation instructions using the ES Modules style, I will still know the correct way to import it.
The import statement is indeed universal and can be used to import a module of either system, whether inside node_modules or out, or built-in to Node. When importing a CommonJS module this way, the value it would normally expose to require becomes its default export, so import name from 'url';, or any other form of import statement that retrieves the default export, will get you what you need.
The import * as name from 'url'; form you mentioned is for retrieving all of a module's named exports. This creates a module namespace object, never a function, though the function or other value that a CommonJS module exposes to require is available on the default property. There's generally no need to use import * with a CommonJS module, since everything that Node detects as a named export will be properties on the default export anyways.
You can also create a require from inside an ES module; this will work exactly the same way as require in CommonJS, but that includes the limitation of importing only CommonJS and built-in modules, not ES modules.
I have a JS app which is importing a custom node_module with helper functions etc. I'd like to import these functions using ES6 imports like so:
import exampleHelper from 'mycustommodule/helpers/foo'
and have Webpack just import this file as though it was any other include in the app. ie Use the same babelrc, webpack config, package.json as the existing app.
At the moment none of the imports in the custom module are resolving.
I've looked into Webpack externals but I can't work out if they are what I'm looking for. Any advice would be appreciated.
I want to be able to import module from subfolder like this, without any lib folder, https://davidwells.io/blog/publishing-flat-npm-packages-for-easier-import-paths-smaller-consumer-bundle-sizes/
I want to publish both CommonJS and ES6 modules
I can specify the main file for commonjs with "main": "./index.js" and for es6 with "module": "./index.es.js" in package.json.
But how does it works when I import my-package/myfile ? Is myfile.js used or myfile.es.js
And why it isn't possible to specify a subfolder instead of a single main file ?
There's not a lot of magic going on in that blog post you mentioned, he's just asking for node_modules/his-module/P.js
The bundlers need a single entry because (in theory) that is where you have your
module.exports = {}
code which is what lets the bundlers access your functions.
If you are using an esmodule compatible bundler like webpack or rollup, they will read the module key
import someFunction from 'your-module';
Would import the es module unless you are using something like browserify which would take the commonjs version.
You can also ask explicitly for a different file
import someFunction from 'your-module/lib/index.min.js';
Whatever file you ask for here, it'll import that. If you add a / after your-module you are now breaking out of the main or module path conventions and asking for whatever file you want.
I prefer using the import x from 'y' syntax, but all I've seen online is const path = require('path').
Is there a way to import the path module using this syntax?
For people trying to import path in a TypeScript file, and ending up here:
Be sure to have node types installed:
npm install --save-dev #types/node
Import path symbol:
import * as path from 'path';
Note: #types/* are automatically included for compilation, providing you use typescript version 2.0 or above, and provided you don't override the types property in compiler options file (tsconfig.json).
If not using typescript
import * as path from 'path'
is the only thing that works for me.
You can either do
import module from 'path'
or if you just need to import path just do
import 'path'
import path from 'path';
As of now, this is the code that's working for me in typescript.
If the version of nodejs you're using supports the ES 6 features, then yes. Otherwise not. Most of the older versions (pre 6.x if memory serves but you should check for your version) required the --harmony flag in order to do this, the latest releases include it natively.
For this reason, and because it works in all versions, most online resources still use the require syntax.
So the ember-cli-builds.js file clearly states
// If the library that you are including contains AMD or ES6
// modules that you would like to import into your application
// please specify an object with the list of modules as keys
// along with the exports of each module as its value.
I'm importing regular javascript files this way
app.import('vendor/global.js');
but what is the proper way to "specify an object with the list of modules as keys along with the exports of each module as it's value"?
At the "AMD Javascript modules" heading of the guides, it is described like that:
Provide the asset path as the first argument, and the list of modules
and exports as the second.
app.import('bower_components/ic-ajax/dist/named-amd/main.js', {
exports: {
'ic-ajax': [
'default',
'defineFixture',
'lookupFixture',
'raw',
'request'
]
}
});
You can now import them in your app. (e.g. import { raw as icAjaxRaw } from 'ic-ajax';)
Reference From Guide
The selector answer is for older ember, pre ember-auto-import (webpack), and pre Ember Octane.
In modern ember, after npm installing a package, you'll be able to import directly from that package.
Example:
npm install qs
then anywhere in your app
import qs from 'qs';
related, it is recommended to avoid placing files in the vendor folder that you want to integrate with the module system. the vendor exists outside of the bundle, so if you have a standalone module, you can place it in your app folder, maybe under some descriptive folder:
app/external-modules/global.js, allowing you to import from it like:
import * as globalStuff from '<my-app>/external-modules/global';