ES6 import "module" don't give acces to function of "module" - javascript

I am trying to use ES6 imorts with babel and Node.js
import "./utils.js";
log("something"); //throw an error : log is not defined
My utils.js look like this :
function log(... params){
console.log(... params);
}
log("module utils executed");
//Is executed and display "module utils executed" in the console.
I have also tryed to use export function log(... params) and export default log(... params) but it doesn't works.
So I don't understand how this is suppose to works...
EDIT:
I know that an other way to import is to do import utils from "./utils.js"
But it's not what I want. I want to be able to use log() without prefixing it with the module variable name. Like in this blog post

there Different ES6 import and Node.js require Question Describe The Difference
In case you will use Node.js require:
your utils.js File will be
function log(params) {
console.log(params);
}
module.exports = {
log
};
The other File will import your Utils Module will be
var utils = require('./utils');
utils.log("test");
In case you will use ES6 Modules:
your utils.js File will be
var log = function (params) {
console.log(params);
}
var utils = {
log: log
}
export default utils;
The other File will import your Utils Module will be
import utils from 'utils';
utils.log("test");
UPDATE
According to your Comment, Yes you can do this But using ES6 Module
your utils.js File will be
function log(params) {
console.log(params);
}
function anotherLog(params) {
console.log(params);
}
export { log, anotherLog }
The other File will import your Utils Module will be
import { log } from 'utils';
log("test");

No, there is no way to import all exported members of a module into the current namespace. Importing a module for side effects (i.e. import 'utils') does nothing with the members of utils.
The closest you can get is something like this:
utils.js
export function log(...params) { ... }
export function foo(a) { ... }
main.js
import * as u from './utils';
u.log(1, 2, 3);
u.foo(4);
or
import { log, foo } from './utils';
log(1, 2, 3);
foo(4);
One of the design goals of the ES6 module spec is a static module structure, which allows resolution of imports at compile time (before executing anything). Allowing blanket imports would make static analysis more difficult.
EDIT (do not do this!)
As #Bergi pointed out in the comments, you can add functions to the global namespace as follows:
utils.js
function log(...params) { ... }
global.log = log;
main.js
import './utils'; // import for side effects, add properties to the global object
log(1, 2, 3); // the global object is in the scope chain, so this is resolved
However this is a bad idea. Global variables are slow to resolve and in general break the modularity you try to achieve by using modules in the first place.

Related

Import, rename, and export a function in JavaScript?

With JavaScript what's the shortest way to import a named export, rename it, and export it again?
This code works but it feels more verbose than it should be
import { mock as myFunctionMock } from 'context/myFunction';
export const myFunction = myFunctionMock;
You can combine the import and export like so:
export { mock as myFunctionMock } from 'context/myFunction';
See MDN Docs
Note that you won't actually be able to use myFunctionMock within your code file since you haven't imported it. Neither mock nor myFunctionMock will be defined within this module.
This is a useful shorthand when you're building a library that will be used by other modules or by your end-user.
For example, if you had a utils library that you wanted to export, but you wanted to organize your util functions across several smaller files, such as stringUtils, objectUtils, dataUtils, etc, you can export the contents of those modules within your utils module to create a single, monolithic access point:
stringUtils.js
export function toLower(){}
export function toUpper(){}
objectUtils.js
export function propertyMap(){}
utils.js
export {
toLower as stringToLower,
toUpper as stringToUpper,
} from "stringUtils.js";
export {
propertyMap as objectPropertyMap
} from "objectUtils.js";
I wouldn't generally recommend this approach for internal code as it can make your dependency trees a bit wonky in some cases. It can, however, be extremely useful in situations where you want to import from a common interface but the implementation is dependent on the build (prod vs dev, web vs node, etc)
import { mock as myFunction } from 'context/myFunction';
export { myFunction };
in your original exporter, do:
module.exports = { mock: function () {...}}
When importing, do:
const myFunctionMock = require('file path of exporter');
then to reexport in the same file:
module.exports = {renamedMock: myFunctionMock};
Now any changes to mock will propagate to the other modules where it's referenced (side note, this is node.js in a nutshell).

ES6 and importing issue with multiple exports

I'm trying to get an index.js working with create-index but I'm having issues getting everything to work.
I have the following:
/modules/utils.js
export function func1(){ ... }
export function func2(){ ... }
export function func3(){ ... }
/modules/index.js [auto created]
export { default as utils } from './utils.js';
/main.js
import utils from './modules';
utils.func1();
But I can't get access to just the utils no matter what i do. I've tried a fair few ways of importing from ./models but the best i can get is import * as modules from './modules' but then i can't actually use anything.
Not sure if I'm doing something stupid or if my use of an index.js is wrong in this situation.
Your utils.js module has no default export, therefor re-exporting it from the module index won't help anything.
You can use either
// main.js
import * as utils from './modules/utils';
utils.func1();
or
// modules/index.js
export * from './utils.js';
// main.js
import * as modules from './modules';
modules.func1();
or
// modules/index.js
import * as utils from './utils.js';
export { utils }
// export * as utils from './utils.js' is proposed and supported by transpilers
// main.js
import { utils } from './modules';
utils.func1();
(you could also default-export the utils from index.js, but that wouldn't really make sense)
If you want to have a utils object with the functions exported from utils.js as methods, then I would recommend either the first or the last approach. Of course if there is only a single file in the modules folder it might also be sensible to drop that and just put your utils module right in the root folder.

How to call a public method of one JS module into another, using the Revealing Module Pattern?

I've been experimenting with Javascript's Revealing Module Pattern, but I don't quite understand if and how I can call a public method of one module into another. Suppose I have these two modules (code is simplified):
1) Module A
var lazyload = ( function() {
function loadDefault() {
$('.lazy').load();
}
return {
loadDefault: loadDefault
}
})();
2) Module B
var newposts = ( function() {
function addNewPosts() {
$('.posts').append();
}
});
How do I call the loadDefault() method from Module A into the addNewPosts() method from Module B? Not sure if this has anything to do with it, but maybe it's worth mentioning that I'm using Webpack, so in my main .js file I'm importing both modules as such:
import './ModuleA';
import './ModuleB';
How do I call the loadDefault() method from Module A into the addNewPosts() method from Module B?
If you were using the old-style revealing module pattern, you'd do lazyload.loadDefault(). But keep reading...
Not sure if this has anything to do with it, but maybe it's worth mentioning that I'm using Webpack, so in my main .js file I'm importing both modules as such:
import './ModuleA';
import './ModuleB';
Then you don't want to use the RMP. Instead, use export:
lazyload.js:
export function loadDefault() {
$('.lazy').load();
}
newposts.js:
import {loadDefault} from './ModuleA';
export function addNewPosts() {
loadDefault();
$('.posts').append();
}
Or if you want the one function you're exporting to be the default:
lazyload.js:
export default function loadDefault() {
$('.lazy').load();
}
...and then the import is
import loadDefault from './ModuleA';
The RMP was way to work around the problem of JavaScript not having modules. Once you're using actual modules (introduced in ES2015), you don't need the RMP (for modules) anymore.

Typescript 'is not a module' error

I have an Angular2 project where i need to import a javascript file for use in my typescript.
I have a javascript file in app/js/d3gantt.js which contains a single function of gantt = function().
gantt = function() {
//Does lots of stuff
return gantt;
};
I then have a definition file called d3gannt.d.ts in the same folder which looks like this:
declare module 'd3Gantt' {
export module d3Gantt {
export function gantt(): any;
}
}
And then i reference it in my component as
import * as d3Gantt from '../app/js/d3gantt';
However, i get the error message stating File 'c:/Projects/RepackLog/RepackLog/RepackLog/app/js/d3gantt.d.ts' is not a module
Am i missing something that is needed for this to pick up my files properly?
Thanks,
As #FabioAntunes mentioned in one of the comments above, you just have to export gantt on your d3gantt.js file itself, in-line.
The exact syntax would be
export gantt = function() {
//Does lots of stuff
return gantt;
};
No need to declare it anywhere else.
For further note on exporting modules please refer this post (Typescript es6 import module "File is not a module error").
Declare module as below :
declare module 'd3Gantt' {
export function gantt(): any;
}
Then import module as : import * from 'path to your module file' or import * as d3 from 'path to your module file'

import from ES6 module to legacy js code

I use babel.js and have a new module foo in my code
foo.js:
export function foo(number) {
return number + 42;
}
And bunch of big old files where everything is global. And I need to call a foo function from that legacy code.
bar.js:
...
var result = foo(0);
...
But I can't just import foo cause then my bar.js will be a module and unavailable from other old code. Is there a way to import module
and retain my bar.js global?
I had a somewhat similar problem recently. I ended up polluting window object with everything I need in legacy code.
I created separate register.js module for this purpose and included it to my webpack build:
import ClassA from './ClassA'
import ClassB from './ClassB'
import * as utils from './utils'
Object.assign(window, utils)
Object.assign(window, {ClassA, ClassB})

Categories

Resources