Meteor: importing whole module doesn't work - javascript

I am trying to make my Meteor code ES6 compatible. I had a file called /both/global.js containing functions and constants that I wanted to be accessible globally. For ES6 purposes, I moved it to /both/imports/global.js and prefaced all the functions and constants with export const.
I haven't changed the whole directory structure yet. The template javascript files are still in /client/controller/. I have added to them import statements for the exported functions and constants. When I write the import statements in the form:
import { fn1, fn2, ... } from '../../both/imports/global.js';
they work fine.
I would rather import all the functions and constants with a single:
import from '../../both/imports/global.js';
but that doesn't seem to do anything.
What am I doing wrong?

It's to do with the way imports and exports work.
What you need is
import * from '/both/imports/global.js'
Alternatively...
import something from '/both/imports/global.js'
Will look for the default export, and assign it to the variable called something.
import { fn1, fn2, ... } ...
Will import the named variables into your namespace
Another way is to do this:
import globalFunctions from '/both/imports/global.js'
Then your functions are callable like this:
globalFunctions.fn1()
globalFunctions.fn2()

Related

Globally importing ReactJS components in all files

In React when you wanna import components from other files we use:
import ComponentName from 'somePlace';
That works fine, but I wanna know if there is a way to import the content of a file instead of the exports. I wanna put all import statements for components in a single file (e.g. imports.js) and have a statement like:
import './import.js' to all documents;
so all my components are automatically imported everywhere.
Is there a way to do that?
Globally import modules? Not really, no. And neither should you need to.
A hacky "solution" would be assigning all imports to the global context (e.g. window in the browser) so it's accessible that way. That's possible, but definitely not recommended. It'll also prevent your bundler (most likely Webpack) from optimizing a lot of code.
Apart from the technical aspect, there are other reasons not to do so. If you specify the imports in each file, you know exactly what imports that file needs and under what variables it is imported as for that file.
If you still want to simplify importing the same components over and over again, you can have this setup:
imports.js
// For default exports
import ComponentA from 'wherever';
export { ComponentA };
// For regular exports
//import { ComponentB } from 'wherever';
export { ComponentB } from 'wherever';
// For whole modules
//import * as wherever from 'wherever';
export * as wherever from 'wherever';
someOtherFile.js
// Either import as a namespace
import * as Imports from './imports';
console.log([
Imports.ComponentA,
Imports.ComponentB,
Imports.wherever.someFieldFromTheWhereverModule,
]);
// Or partial import
import { ComponentA, ComponentB } from './imports';

How to import a file that already imports another file?

Javascript, ES6. I have three files:
inline-functions.js
\*
Bunch of small functions.
*/
some-module.js
import './inline-functions.js'
// uses many inline functions
main.js
import './inline-functions.js'
import './some-module.js'
// uses inline functions as well as classes from some-module.js
Now, I use Visual Studio Code and I would like Intellisense working but when I am editing main.js, it only shows functions from inline-functions.js and everything from 'some-module.js' is unreachable even though there is an import statement. However, when I comment the import out of some-module.js like this:
// import './inline-functions.js'
// tries to use inline functions which are now not callable
Intellisense suddenly shows correct names and documentation for all objects. This is of course unusable because some-module.js now can't call any of the inline functions.
What is the correct way of importing these modules?
You can access the module function only if you export it from the module.
Export the function form the module then you will see it in main js.
Example:
some-module.js
import './inline-functions.js'
const someFuncion1 = () => 1;
const someFuncion2 = () => 2;
export {
someFuncion1,
someFuncion2
}
main.js
import * as inline './inline-functions.js'
import * as some './some-module.js'
//Access it like
inline.<function name>
some.<function name>

When do we use '{ }' in javascript imports? [duplicate]

This question already has answers here:
When should I use curly braces for ES6 import?
(11 answers)
Closed 4 years ago.
I am learning Javascript imports and I am yet to understand when we use curly braces while importing items(functions, objects, variables) from another JS file.
import Search from './models/Search';
import * as searchView from './views/searchView';
import { elements, renderLoader } from './views/base'
//elements is an object, renderLoader is a function
The import statements are used to import the exported bindings from another module
The curly braces ({}) are used to import named bindings and the concept behind it is called destructuring assignment The concept of destructuring assignment is a process that makes it possible to unpack the values from arrays or objects into distinct variables in the imported module
The curly braces ({}) are used to import named bindings
I would like to explain different types of imports in ES6 with the help of an example
Suppose we have a module named Animals(Animals.js) let suppose the module exports a default binding Man and several other named bindings such as Cat, Dog etc
/*
Animals.js
*/
..
export Cat;
export Dog
export default Man
Import a single export from a module
In order to export a single export from another module (let's say Cat) we can write it like this
/*
Anothermodule.js
*/
import {Cat} from "./Animals"
Similarly for Dog
/*
YetAnothermodule.js
*/
import {Dog} from "./Animals"
Import multiple exports from module
You can also import multiple modules as follows
/*
Anothermodule.js
*/
import {Dog, Cat} from "./Animals"
Import an export with a more convenient alias
/*
Anothermodule.js
*/
import {Dog as Puppy} from './Animals.js';
Rename multiple exports during import
/*
Anothermodule.js
*/
import {Dog as Puppy, Cat as Kitty} from './Animals.js';
But in the case to import Man into another module since it is a default export you can write it like this
/*
Anothermodule.js
*/
import Man from './Animals.js';
You can also mix both the above variants for example
/*
Anothermodule.js
*/
import Man, {Dog as Puppy, Cat as Kitty} from '/Animals.js';
Import an entire module's contents
If you want to import everything you can use
/*
Anothermodule.js
*/
import * as Animals from './Animals.js';
Here, accessing the exports means using the module name ("Animals" in this case) as a namespace. For example, if you want to use Cat in this case you can use it like below
Animals.Cat
You can read more information about import here
you can read about destructuring here
import { elements, renderLoader } from './views/base'
is the way you need to import single, named exports from a module, in this case it is importing named exports elements and renderLoader from base.js.
The { elements, renderLoader } syntax is in many cases just syntactic sugar (called destructuring) added in recent versions of the ECMAScript standard.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Object_destructuring
In this case, though, it is necessary to get only the named exports you want.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Import_a_single_export_from_a_module
Please note that you can also pick new names for your variables like this:
import { elements as newNameForElements, renderLoader as newNameForRenderLoader } from './views/base'
which would then make the elements export available as newNameForElements etc.
import Search from './models/Search';
Imports the default exported element as Search.
import * as searchView from './views/searchView';
Imports everything into searchView that has been exported.
import { elements, renderLoader } from './views/base'
Imports a hand-picked number of named exported elements.
{} is used when you want to import part of an object. The * as searchView one will import all properties and methods in the searchView file.
Suppose './views/base' has 3 properties: elements, renderLoader, additionalParam (Assuming that all three have been exported as named exports in the file)
When doing
import { elements, renderLoader } from './views/base'
you import only those 2 specific properties
But when you do
import * as base from './views/base'
you import all three properties in the object named base
Take the following example:
File to be imported, say importedFile.js:
var defaultExport, otherExport1, otherExport2, otherExport3;
export default defaultExport = () => {
console.log("Default Export")
}
export otherExport1 = "Other non-default Export";
export otherExport2 = function() {
console.log("Some more non-default Export");
};
export otherExport3 = { msg: "again non-default Export" };
Now in your main JS file, if you would do the following:
import something from './importedFile.js;
Here the variable something would get the value of the variable/function that has been exported as default in the importedFile.js file, i.e. the variable defaultExport. Now, if you do something like the following:
import { otherExport1, otherExport2 } from './importedFile.js;
It would import specifically otherExport1 and otherExport2 variable and function and not the defaultExport and otherExport3.
You can also do something like the following to import all the variables by their names from importedFile.js:
import { defaultExport, otherExport1, otherExport2, otherExport3 } from './importedFile.js';
Conclusion:
curly braces are used to choose variables/functions/objects (using a technique called object destructuring in ES6) that need to be imported without importing all the other unnecessary exported variables/functions/objects.
If you don't specify curly braces, it would always import only the variable/function/object that has been exported as default and nothing else. It would import undefined if nothing has been exported as default export.
You can use curly braces to import implicitly and selectively from another module functions or objects and so on.
// import implicitly one function and one constant from example.js
import { a, b } from 'example'
example.js
// export a and b but kept c private to example.js
export const a => { ... }
export const b = "hello"
const c = "private, not visible to the outside"
More infos:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export
If something is exported as default it is imported without curly braces.
If multiple variables are exported it is imported using curly braces.
For example,
in somefunction.js
export default module;
import module from './somefunction.js';
in someOtherFunction.js
export func1;
export func2;
import { func1, func2 } from './someOtherFunction.js'
You can export more than 1 content from a single module.
For example at your code:
import * as searchView from './views/searchView'; //1
import { elements, renderLoader } from './views/base' //2
At //1, you import Everything from './views/searchView';
At //2, there might be more content from './views/base', but you import only elements and renderLoader
For more information: import MDN

Dynamically reference static ESNext imports

Say I have these imports:
import clearLineReporter from '../modules/clear-line-reporter';
import karmaReporter from '../modules/karma-reporter';
import metaTestReporter from '../modules/meta-test-reporter';
import stdReporter from '../modules/std-reporter';
import tapJSONReporter from '../modules/tap-json-reporter';
import tapReporter from '../modules/tap-reporter';
import webSocketReporter from '../modules/websocket-reporter';
these must be referenced like I do above, in other words, I obviously can't do this:
const imports = {
stdReporter: import(...),
tapJSONReporter: import(...),
...
webSocketReporter: import(...)
}
Is there any way I can reference imported files through some form of reflection? Because it seems like I can't group them together to reference them somehow.
Instead of import syntax, I could use require(), but I am wondering if there is some way I can do some dynamic things with import statements, for example reference them all dynamically, such that if I add or remove an import, I don't have to change any other code.
There is a great answer to this question that I discovered by asking a different question, here:
exporting imports as a namespace with TypeScript
Create a file name grouped-modules.ts for example, where you want to simply list only the modules and export each one.
export {default as clearLineReporter} from '../modules/clear-line-reporter';
export {default as karmaReporter} from '../modules/karma-reporter';
export {default as metaTestReporter} from '../modules/meta-test-reporter';
...
export {default as stdReporter} from '../modules/std-reporter';
export {default as tapJSONReporter} from '../modules/tap-json-reporter';
Then in your module you can just do :
import * as mods from './grouped-modules'
export {mods}
It will export both types and values in a namespace called s. You can then import them using :
import {mods} from 'your-module'
const anObject: mods.clearLineReporter = ...;
This allows you to dynamically group your modules into one variable.
Is there any way I can reference imported files through some form of reflection?
Answer is dependent on environment, meant in questing, because import statement can be ES native modules implementation in browser, or babel-ed to require statements in node.js, or compile-time resolved bindings in webpack.
So, in each case there is solution to do something reflection. In node.js with babel-ed code import is just require wrapper, so any information is available there.
In browser with native ES modules, all requests to them can be served via ServiceWorker, so it can provide necessary information about fetched ES modules. Also in browser ES modules can be dynamically imported that way: https://matthewphillips.info/posts/loading-app-with-script-module
Most interesting part is webpack: compile-time resolve and semi-reflection can be achieved by externals resolver in functional style (https://webpack.js.org/configuration/externals/#function), and runtime by load module API (https://webpack.js.org/api/module-variables/#webpack_modules-webpack-specific- )

How to change namespace for default member import javascript

In learning more about ES6/2015 imports, I've come across a couple of cases where I'd like to change the namespace of the default member in the import scope.
Basically the equivalent of import {myMember as name} from 'my-module', but for the default member. I expected something like import defaultMember, {defaultMember as name} from 'my-module', but that seems not to work.
It seems like this should possible:
Mozilla Docs
It is also possible to use the default syntax with the ones seen above (namespace imports or named imports). In such cases, the default import will have to be declared first...
Perhaps not the actual answer, but a solution that I'm using.
For this example, I was using Node-Simple-Schema, and did not want to track imports of it as it is often used across the global scope on the project I'm working on.
The problem is that when import SimplSchema from "simpl-schema'; is used, then "SimpleSchema" as a convention is not available globally.
So I created a code file "SS2.js" and placed the following in it:
import SimpleSchema from 'simpl-schema';
var SS2 = SimpleSchema;
export {SS2};
Then in the working file, I do a subsequent "chained" import and with the following:
import {SS2} from './imports/SS2.js';
SimpleSchema = SS2;
This gives me the default module export convention "SimpleSchema" available globally once again.

Categories

Resources