Quick question. I am a bit confused about ES2015(ES6).
Let's say I use Babel to compile to ES6 Javascript to compliant ES5 for current browsers.
The import/export functions are already available in ES6 by using Babel. So why would I need something like Browserify or Webpack if I were to simply use these just to bundle my modules, when ES6 could do it for me?
Everywhere I go I see people using Babel in combination with Browserify or Webpack. Although I know something like Webpack can be used for more, but I wonder if it is also possible to bundle files using the ES6 syntax.
I might be totally in the wrong here and I might have gotten lost in the Javascript Jungle of 2016, so I hope someone can clarifty this for me.
Edit
Am I right to assume that the native ES6 import / export functionality simply does not bundle files? From what I have read so far I think you still need to include all the separate Javascript files but you simply import modules into each-others namespace by using the native import functionality?
Yes, using babel to transpile your ES6 imports into ES5 will work.
However, one advantage of using webpack is that creates one static file to be served up in your production environment.
Pre-ES6 has no native module system, so there are multiple systems constructed in userland code (e.g. CommonJS / Node modules and AMD). Those are what Babel converts ES6 module syntax to (and yes, you're correct that ES6 module syntax has no native bundling story anyway). Browsers have no knowledge of those userland APIs. Node implements its module system by wrapping a "module" in a function that injects require() etc. In a browser require() would just be a reference error. Browserify (or another bundler) makes it work in the browser, and bundles a whole dependency graph into a single script. So if the code is for the browser you're likely going to want to bundle it. If it's for Node you may not need to.
The import/export functions
Not functions, declarations.
if I were to simply use these just to bundle my modules, when ES6 could do it for me?
I wonder if it is also possible to bundle files using the ES6 syntax.
Am I right to assume that the native ES6 import / export functionality simply does not bundle files?
Yes. There's no native way to bundle ES6 modules. You can transpile ES6 module syntax to something like Node modules and bundle those.
From what I have read so far I think you still need to include all the separate Javascript files but you simply import modules into each-others namespace by using the native import functionality?
It's important to realize that while the syntax is standardized, a lot of the behavior isn't. There's a Loader spec under development to specify how modules will actually be located and loaded.
See also https://stackoverflow.com/a/33044085/1034448.
Related
Create-React-App uses Babel that converts my ES6 modules to CommonJS module and Webpack will bundle everything in single file that my browser can understand.
1) Why not use CommonJS modules directly and use Webpack as bundler?
2) Now that ES6 modules are supported in browsers, why don't we transpile React CommonJS modules to ES6 modules.
Go to your Chrome console and type in require, you will get the message require not defined.
Our browser, in particular Chrome, has no idea what CommonJS is, it has no idea what modules are.
But if you are looking to remove those restrictions in your project, you can make use of Electron.
If you run require inside of the Electron browser window you will get this:
f require(path) {
try {
exports.requireDepth += 1;
return mod.require(path);
} finally {
exports.requireDepth -= 1;
}
}
Chrome the browser has no idea what the above is, but the Electron browser window does. It has some additional capabilities that Chrome does not.
The Electron browser has a MainWindow object which has access to all the available modules the belong to the Nodejs runtime and access to all modules inside the browser as well. So access to CommonJS as well as fs, crypto, etcetera.
You can do `require('fs') and access the filesystem directly from the Electron browser console.
In short, I am saying that with Electron you can directly require in modules like you want without having to use Webpack.
CommonJS code will not allow you to write code using imports, arrow functions, destructuring, generators, class etc... This makes your developer's life easy and I do see below advantages:
Less code more for same functionality.
Less time required for writing same functionality.
As of chrome 61 + can process your ES6 code but other browser will not be supporting it. So you need to transpile ES6 code to common js code so that it is consistent across browsers.
I know that if there are multiple JS files to be rendered by the browser, which apparently have identifiers inside, the global scope is polluted by this identifiers. I also know that one way to avoid this is using modules which(in my understanding) are just objects which have the aformentioned identifiers as members, thus sort of imitating C++ namespaces. I am also learning Node.js and there is a built in module system which eases this task so my question is: how to use modules in js files that are sent to the browser to be rendered?
Thanks.
Tools like browserify and WebPack are exactly what you are looking for (I personally prefer browserify over WebPack). Have a look at this answer, it explains a lot of your concerns.
In Node.JS, you can export a module using module.exports keyword, but you cannot just import those modules in your browser by just requiring them in a <script> tag. That's because, the browser doesn't understand the module system and everything works in the context of a global window object there, so module.exports simply becomes window.module.exports which I'm sure you'll not want. Hence you use tools like browserify that process the Node.JS scripts into something that your browser will understand.
This problem is usually solved by module bundlers or module loaders (e.g Webpack, Browserify, RequireJS). They are able to understand relations between your JS modules, skip unused modules and produce output that just works in your browser. All of that without the need to worry too much about global scope if you follow some conventions.
Some time ago, before ES6, two different approaches to this problem were widely used:
CommonJS:
var module = require('my-module');
widely known from Node.js
AMD:
define(['jquery'] , function ($) {
return function () {};
});
Which was suited for browser usage since it by design supported asynchronous loading of modules.
Then ES6 was introduced with native support for modules:
import * as lib from 'lib';
Main problem with new technology in web is that you often have variety of browsers to support which for a long time prevented developers from using new features. Nowadays, we have code transpilers and sophisticated code bundlers (e.g. Webpack). With their help you can use latest version of language, compile and bundle your code and at the end single "bundle.js" file is emitted which supports older browsers at the cost of slower execution times.
I'm trying to create an npm package that could be used by web apps or other node modules.
If I were to only support browsers, I would just assign to window window.myExport = myExport; (unless there's a more modern way I'm not aware of?).
If I were to only support node modules, I would just use export, module.exports = myExport; (again, if there's a better way I'm not aware of, please let me know).
But I want to support both. Currently, what I'm doing is
var window, module;
if (window)
window.myExport = myExport;
if (module)
module.exports = myExport;
This looks very ugly, but works so far.
What's a better approach?
This is very lightweight node module, so I don't want to bring in some builder like webpack or something unless un-avoidable. I am already using babel though to create an es5 compatible version of my code, so if babel can solve this issue for me, that would work.
If someone is already using npm to manage their dependencies than it is logical to assume that they will be using something like webpack or browserify that will allow them to import/require the module. It would be unusual for someone to download a library from NPM and manually include it in their page. I would also consider it a gross violation for an npm library to add itself to the window object. This could cause all sorts of issues especially if different versions of your library are included on the same page.
The real question is ES module exports or commonJS exports. Of which I currently favor CommonJS because ES modules are not natively implemented in nodejs yet so you have to use babel to easily import them.
I've noticed some web projects using typescript and webpack also use babel to finish off the compilation. For example, they use ts to compile to ES2015 and then use babel to compile to es5. Why not just use ts directly to compile to es5?
Is it in the case the project also has js that needs to be compiled so they just use babel for everything? Or what am I missing?
Thanks.
There's a few possible reasons for this.
They're using Babel to automatically polyfill - TypeScript only performs syntactic transformations, leaving the user to figure out what runtime libraries they'll need to be around (e.g. Promise, Symbol, etc). This allows you to decide which implementation of these polyfills will work the best for you, but it can be a pain. Babel spares you the burden of thinking about that. It's a tradeoff.
They need it for a custom transformation - TypeScript has a transform pipeline, but it's only accessible when you use the TypeScript API at this point in time. If you're already using Babel and want to start using TypeScript, but you're already using a transform, this is a reasonable compromise.
It was created when TypeScript didn't support compiling generators to ES5 (or even back when TypeScript didn't support async/await in ES5) - TypeScript has supported async/await in ES5 since 2.1, and has supported generators behind the downlevelIteration flag since 2.3. Before that, users often relied on Babel to pick up the slack, but Babel isn't needed here anymore.
It was created before Webpack 2 and the project used a specific way of importing modules - TypeScript has an allowSyntheticDefaultImport option which tells TypeScript that default imports can be used to import certain modules. Babel supports this behavior, but Webpack didn't until Webpack 2 came out. Babel isn't needed here anymore for newer versions of Webpack.
This might not be the complete set of reasons, but it's a few I can think of off the top of my head.
Why not just use ts directly to compile to es5?
That is what I do.
About mixing Babel and TypeScript
There is no flaw in using the both together. Since both do:
(non js OR js) => standard js
You can do
(non js OR js) => standard js => es5
Either by TS -> JS -babel> ES5 or Babel -> JS -ts> ES5
The reason people do it is for varied syntax support : https://kangax.github.io/compat-table/
Personally
As mentioned. I don't use Babel as I TypeSafety is big for me and don't need to use syntax that isn't yet type safe 🌹
Typescript is the evolution frOM ES2016 onwards. Typescript helps the developer from c# and java background to become javascript developers using various tools. Visual Studio code, WebStorm, Sublime etc.
Why: We can not use Typescript alone for converting ts to ES5
Compiling to ES5 with TypeScript is not as complete as it is with Babel. Some modern language features, such as Array.prototype.find, cannot be compiled to ES5 with TypeScript.
Here is the link that will help you out: https://www.stackchief.com/blog/TypeScript%20or%20Babel%3F
I've got a browserify javascript project, where I include modules with the require statement. I'm now adding in some typescript, and it's working fine when I simply require the compiled javascript.
But typescript also has its own module statement. How does this relate to browserify/node's modules? Should I be using both? That seems redundant. Which type of modules should be used, and under what circumstances?
Thanks.
In newer versions of TypeScript (1.5) the module is deprecated in favour of namespace keyword. The keyword is to be used to create internal modules - allows you to organise your code internally.
So now it is more obvious that those are different things. Still TypeScript provides ability to create browserify/node's modules - external modules. For that you can use ES6 module syntax or older TypeScript's syntax. Then use browserify plugin (such as tsify) for more convenient builds.
More documentation about TypeScript modules and namespaces can be found here (also describing the older external modules syntax)
Which type of modules should be used depends on the project and taste of developers. If you target Node.js it worth to use CommonJS modules (IMHO ES6 syntax in TS and transpile it to CommonJS). If you are using browserify it is reasonable to use external modules, too. Namespaces is recommended to use only inside one file - hence internal modules.