Under the hood the ES6 engine will load bar.js when it evaluates import { Bar } from 'javascripts/bar';, and block upon return of that module over HTTP? Or is bar.js downloaded prior to evaluation of the script in index.html?
There is no correct answer to this yet, because there is no specification for how modules are loaded. ES2015 only specifies the module syntax, but how runtimes interpret that is not yet standardized. For example, it's very unlikely any loader specification that is eventually implemented will allow you to omit the .js as you do. And it's also very unlikely that <script> tags will be allowed to use import.
However, setting aside any syntactic missteps you made, I can tell you in general terms what is likely to be standardized for the browser loader. It is the latter: imports are determined and downloaded ahead of time, before any script execution happens. (For the Node.js loader, however, it is likely to be blocking.)
Because bar.js is loaded using the import keyword, the globals in bar.js are scoped to that module and are not visible globally?
That depends on what you mean by globals. If you declare a global with e.g. window.x = 5, that will still mutate the global object. Modules do not get separate global objects to mess with.
However, if you mean "accidental" globals like those declared with var or function declarations at the top-level, the answer is that in modules top-level var and function declarations do not cause global properties to be defined.
(Note that in both modules and scripts, top-level let and const declarations do not create properties on the global object.)
Now if I want to concatenate modules, I will continue to need to wrap my modules in IIFEs, so that their scopes remain distinct (or at least use a build step that does this under the hood)?
If you want to concatenate modules, you're going to have a lot bigger problems than those you describe. For example, import and export are only usable at the top level, and not inside an IIFE. Modules are not meant to be concatenated, as doing so is actively harmful to performance given modern browsers and servers.
Understanding ES6 modules
ES6 - What are good side of ES6 modules?
Is it better to use es6 modules with Node?
${JavaScript} Are there any methods to use ES6 modules locally* without violating the CORS policy?
Hello!
All or most of us know, that in ES6 world, module is an entity that export certain things. It may export either a list of named things like constants, variables, functions, or export "default" which is unnamed thing.
So now, when we write modules, we can either export some single class, function or object as "default" - this makes sense when we are exporting classes or functions as complex as they are taking whole module.
But in typical webdev, many apps are split to infrastructure layer and service layer. We know that insfrastructure is an connect point to services, and services are business models. Following SOLID, we will probably end having some modules like email notification module, authorization module, pucharses module et cetera.
Now whats the correct design way of this in Node.js and ES6? My service layer modules are typically a series of functions that are doing similar things, like email notification module has a function to send register email to client, send pucharse notification as email to client, send reminder password to client.
Following ES6 module syntax, I did it by exporting certain functions, like:
service/email.js:
export function sendRegisterEmail( client ) {...}
export function sendPucharseNotificationEmail( client , pucharse ) {...}
export function sendPasswordReminderEmail( client ) {...}Now whenever I'd want to use these service (lets skip event-based communication for now, it is just an example), I must load it using either:
import * as EmailService from 'service/mail.js';
or
import sendRegisterEmail from 'service/email.js';
I've tried both of them but noone fits me perfectly. Somebody said to me that first one is better because "in future ES6 or module loaders will only use functions you actually require". I bet this is barely possible due to overall nature of JS, as it is non deteministic at parse/compile time and it wouldnt really save much inside your application. If you have external module like lodash, importing only map and reduce from it could (if it would actually truncate dead code) save you some KB of unused code, but inside YOUR modules you will rarely have function that is not used at all, because what would be point of these? If I wouldn't need sendPucharseNotifcation in my email service, I'd just erase that function from source entirely.
There is also one thing more - it shades real source of function. In ~200+ LOC module, when you see a line "doSomething(xxx)" you must scroll source all way top in order to see that:
import doSomething from 'service/some-domain/something-manager.js
First approach make much more sense especially if your team is following convention in all files, i.e. it is always:
import * as SomethingManager from 'service/some-domain/something-manager.js';
Then when you see in your code:
SomethingManager.doSomething(xxx)
You already see whats going on here. It is just something like mm namespace? You know already source of function without needing to scroll into imports section of your code.
But this approach is quite tricky as well, because there WILL be some modules that actually work as exporting single entity, lets say model class, controller function that takes express app as param and registers its own routes there or middleware function. So you must require them using default syntax, that is:
import User from 'model/user.js'; import AuthController from 'controller/auth.js'; import AdminMiddleware from 'middleware/admin.js';
But mixing this with modules that export named functions started to make mess in my code. I was making A LOT mistakes due to incorrectly requiring certain things, like using:
import EmailService from 'service/email.js';
Which yields undefined as proper syntax in this case is: import * as EmailService from 'service/mail.js';
I am now further in developing this project and it made me a habit to open a module source file and check what and how it exports things before I will import it. It also looks bad when there are mixed styles of imports like:
import User from 'model/user.js'; import * as UserRepository from 'repository/users.js'; import AuthMiddleware from 'middleware/auth.js';
etc.
I know that I'd just do export default { ... } and put all my functions into exported object but I dont like repeating myself in code and it also looks more like a workaround than a real use case.
So what are real good sides of ES6 modules, because it has a lot drawbacks for me. I wanted to learn ES6 and I started to use ES6 modules but from what I see now it just make more mess than old commonjs require() thing.
I'd also love to listen about your guys point of view about managing modules in ES6 project. Thanks in advance!
» npm install dotenv