How do I assign a namespace using ES6 modules? I'd like to do with for example jQuery does, where the namespace is $ but doing it the intended ES6 way. All my modules are structured in separate files which export the classes/functions/whatever as default (e.g. export default class Pikachu). How do I import it into another (main) file so that a user can access this class using e.g. Namespace.Pikachu?
I have come to understand that it might have to do with named exports but I'm not quite totally sure how. Any help please?
If you use modules, you don't need namespaces.
The point of namespaces is to prevent conflicts between different files that define the same names.
Modules eliminate this problem entirely by letting the callsite choose a name to give each module it needs.
You just export a simple object with the things you want, and other files can import that to any name they choose.
Related
I have a file with defined interfaces I'd like to share with my app's global namespace. My first attempt to do this was that I imported the interfaces.ts file into my app.module.ts and placed the interface into the exports array, but types/interfaces cannot be used in this way, so I thought of a few questions related to this small issue.
Does app.module.ts need to be involved for exporting to the global namespaces?
Is there a different way to do it (probably a native javascript way)?
If app.module.ts is required to do this, how do I import an interface in a way that my app.module.ts shares it with the rest of my app, so that I wont have to constantly import it in my components?
Checkout the global namespace here: https://www.typescriptlang.org/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html
/*~ Note: If your global-modifying module is callable or constructable, you'll
*~ need to combine the patterns here with those in the module-class or module-function
*~ template files
*/
declare global {
/*~ Here, declare things that go in the global namespace, or augment
*~ existing declarations in the global namespace
*/
interface String {
fancyFormat(opts: StringFormatOptions): string;
}
}
Beware though:
This pattern is somewhat dangerous due to the possibility of runtime conflicts, but we can still write a declaration file for it.
It's better to have a SharedModules for everting that you want to use in the entire application more than one place according to the Angular official document. In this SharedModules you can have different directory app structure for all common things such as Models, Services, Interceptors, Pipe, components and etc.
Then Use this module on your main app.module.ts and import what you need.
For more information study this helpful & quick guide on PluralSight.
I would like to use javascript classes with one class per file. It is part of a larger project using eslint. I started with:
/*global CSReport*/
/*global CSManager*/
class CSMain {
constructor() {
this.report = new CSReport();
this.manager = new CSManager(this.report);
}
launchReport(...
}
However, eslint generates an error saying CSMain is defined but never used. This led to the idea of using export and import which seemed better than making everything global (side note: CS in front of main is the old style method to avoid global conflicts)
The question is how to put this together. The release version will be a single (uglified) file, so the class file names will no longer exist when they are all concatenated together in (say) csCompiled.js.
Questions:
Import uses a file name. Should I use the CSCompiled.js name rather than the file names before concatenation?
Do I want a single module or a module for each class?
Do I need to export every class and import every class it uses?
I am not fully sure how angular accesses this code but am thinking to import csMain.
I tried to find an answer to this but am only finding older posts that don't use ecmascript 6 and classes. If an answer to this exists, I am not sure how to get to it.
Background:
The main project uses angular 1. This code is separate for legacy reasons. It is currently written in java using gwt, but we want to move to javascript to remove the reliance on gwt. It is about 30-40 files (classes) total to convert.
The code gets and handles data from the server for report requests. There is a lot of pre-processing done before it is handed back to the rest of the UI.
I have used javascript for an established project using angular, but lack expertise on how to create new projects.
I am trying to use basic javascript for this, so it won't need updating if (for example) we go from angular 1 to the current versions. I do not yet know if this is a good way to do it.
ESLint is complaining because you are not exporting the class you created, therefore, it can't be accessed by other modules. You can fix that with a simple line at the end
export default CSMain;
Import uses a file name. Should I use the CSCompiled.js name rather
than the file names before concatenation?
Use the file name before you compile/transpile/uglify/etc. After that it will all become 1 file and the bundler will take care of that for you.
Do I want a single module or a module for each class?
Completely optional, I like to have 1 class per file and then 1 file for the module (index.js) that lists all classes in that module.
Do I need to export every class and import every class it uses?
Yes, you need to import everything your module will use and export everything that should be public or "importable" for other modules.
I am not fully sure how angular accesses this code but am thinking to import csMain.
It all depends on how you export your file. Make sure to import the same name your module/file is exporting.
I am using webpack to transpile/bundle/etc my js files. Im using the import/export syntax ( as opposed to the CommonJS way of require and export.module ). This means i need to import each class and all subclasses of it however many times if i need to use them in the context of a specific script.
The question:
Even though classes arent natively supported in js, why do we need to import them all the time? Wouldnt it be easier if ( and im only speaking for classes ) they were available to all scopes?
EDIT: To avoid polluting the global scope one could do something like global.myLibs and be done with that issue. I personally prefix my classes with something unique but this method would serve even those that dont i suppose.
For example:
window.myClasses could serve as a container for all my classes. I come from an iOS background where all the classes in a main "bundle", in java i think that would be a "package" are available to everyone. Re-importing the class itself doesnt seem like it serves any purpose.
See here:
Why do i need to import modules everytime in webpack bundle?
and here: Bundling js files with webpack class undefined
Adding things in the global scope can lead you to naming conflicts. What if you created a class named Node, add it to global scope by doing window.Node = Node ? You lose the reference to the browser's global Node object.
You can argue that you will never use names that are already used for global objects. But now, what if in a year or so, a new object is added to the spec with the same name as one of yours, and you want to use it alongside your own object ? You have to make a choice, or rename your own object. This is not future proof.
Importing the same module in every module that uses it is a best practice. Because by doing it, you never pollute the global scope. Don't be afraid that it imports the code of this module n times in your final bundle. Webpack imports it only one time, then uses a reference to the module everytime you are importing it.
See these resources :
JavaScript Modules: A Beginner’s Guide by Preethi Kasireddy on Medium
Eloquent Javascript Modules chapter
Declaration
declare module "MyModule" {
export function Foo() {...}
export function Bar() {...}
}
I just need Foo somewhere, how should I import it ?
import * as MyModule from "MyModule";
MyModule.Foo();
or
import {Foo} from "MyModule";
Foo()
Which one is better than another ? Are there any performance implications of importing all the exports in the first way?
Some references which I read before posting questions:
https://www.exratione.com/2015/12/es6-use-of-import-property-from-module-is-not-a-great-plan/
Importing only what is necessary to your code is, of course, good practice. Say someone writes some thousand-line code importing everything, and then you try to analyze it. Do you think you would easily know which functions used in your code are imported or which is not? Obviously it is dubious and bad practice.
With regards performance, I suppose not much affected.
The import {} from ... syntax makes stubbing and spying on functions very difficult and normally requires additional libraries such as rewire.js. The caveat is tree shaking doesn't work as well. I'm inclined to keep my util modules small and maybe only include 2-3 functions per module. That way I can use the import * as ... syntax for my modules and import {} ... when possible for third party modules. Thus minimising the need for tree shaking.
If you need to use only Foo, I think it's better to import just Foo. This makes your code clearer, because by looking at that import you can tell which elements of MyModule that code is using.
It doesn't affect performance, because either way you have to read/download the whole file.
Also, it doesn't matter which option you choose when using a bundler like Rollup.js―even if you import everything from MyModule, the bundle will include only things that you actually use in your code.
In case anyone is still looking for answers, i have shared my thoughts on this.
Let say you have a JSON file and you want to import the entire module as a variable then go with import *.
If you have a module with multiple exported methods (That can be 3rd party packages), then you should go with import {} approach.
Any default export should be imported as "import any name".
About a year ago I have used Meteor, and now I want to use it again, but many things have changed.
When I follow the Blaze tutorial on Meteor.com, they add imports on top of their files:
import { Meteor } from 'meteor/meteor';
import { Template } from 'meteor/templating';
import { ReactiveDict } from 'meteor/reactive-dict';
I got the app working. But when I comment the imports out, the app keeps working like it should work. Why are these imports needed?
I am still using the regular Javascript, not ES6.
Thanks!
The import statement is used to import functions, objects or primitives that have been exported from an external module, another script, etc.
The name parameter is the name of the object that will receive the exported members. The member parameters specify individual members, while the name parameter imports all of them. name may also be a function if the module exports a single default parameter rather than a series of members. Below are examples to clarify the syntax.
Import an entire module's contents. This inserts myModule into the current scope, containing all the exported bindings from "my-module.js".
For more detail about the different ways we can use import along with their usage, please check this.
They still use the old globals for backwards compatibility. However it is recommended to use the imports so if in some future release they remove the globals your code will still work. You can read more in the appropriate section of the guide.
Ok you know import is to import an exported object from another file already.
The point that you may have missed is that MDG heard the need to stop loading everything by default, or at least to provide a mean to control what is loaded in memory and what is not.
Look for the /imports special directory.
Files in that folder are no longer loaded automatically, but only through import statement.
As for the tutorial, I guess they did not explained this functionality, and because it imports only standard functionalities which are still loaded eagerly for backward compatibility, it does not change anything removing those statements.