Transpiling dynamic ES6 System.import to ES5 (amd or other) - javascript

I'm stuck with dynamic requering es6 modules by invoking them through:
System.import('SOME_PATH').then(function (MODULE_FROM_SOME_PATH) {});
It works well with es6-module-loader and babel runtime compilation in browser, but when i want to precompile it to ES5 syntax (for production uses) it just passes System.import expression in code, leaving in practically untouched, just replacing System.import with equivalent System['import'].
I've tried gulp-babel and babel npm package. So when opened in browser it gives expected module loading error. How can i transpile my code to AMD syntax for ES5. Hoping for your help.

Just pushed babel-plugin-system-import-transformer that replaces System.import to the equivalent UMD import (AMD, CommonnJS & Global module imports).
I have also created a separate localforage branch that uses System.import statements as an example.
Hope this helps.

Related

How does ESM tree-shaking / dead code elimination work?

I'm curious how tree-shaking/dead code elimination of ESM works. I'm using Typescript for various Node.js projects and I started to export my own ESM packages (tsc --module es2015 --target es5 --outDir dist/esm) instead of CJS packages. Moreover, I tried to replace dependencies (like lodash) that are only available as CJS module with libraries that are available as ESM.
When I build a project, my entire TS codebase (./src) is transpiled to JS (./dist); dependencies are still taken from (./node_modules). No tree-shaking performed.
I guess I'd still need a bundler (like Webpack) that needs (at least) an entry point so that it can shake away everything that's not needed, so that I can reduce the package size of (e.g.) an AWS lambda? Is this something you would do?
When you use import instead of require, the transpiler is able to build the dependency tree on compile time (that is why you cannot dynamically import code).
For example, if you write this:
import { myfunc } from 'mylib';
The transpiler understands that you only need the myfunc function from mylib. If mylib includes other functions that are not used by myfunc, the transpiler can remove them from the bundle.
This is the short version. Tree-shaking is actually more complex than that. Webpack has a good article about it if you want to learn more:
https://webpack.js.org/guides/tree-shaking/

function exported into global scope is undefined (webpack + babel)

I have three separate libraries -
Lib A - Hosts shared code and uses babel to transpile the code into a /lib folder
Lib B - which uses libA (imports the babel transpiled code) and it uses webpack to generate the bundle in a dist folder (dist/index.js). It also exports a global function "myGlobalFunction" by attaching it to a window.
Lib C - Uses both A and the global "myGlobalFunction".
Issue is, the window.myGlobalFunction when accessed from lib C, prints undefined.
In Library B, if I import the contents of Lib A from src/ instead of the transpiled lib/, my issue gets resolved automatically.
Not sure why this is happening.
Also, I have disabled the es modules transpilation in babel by setting
{modules: false}
in babelrc of the libA.
I have a problem similar to this one but the solution posted there didnt work either as I need to use the global in some another library by directly looking in the Window object.
All the libraries are separate npm packages.
I figured out the issue being how babel was transpiling the code from LibA - especially the code including async...await.
It uses the preset env and fb's regenerator runtime to transpile async..await into Promises using generators.
I disabled the "transform-regenerator", "transform-async-to-generator" plugins and used fast-async plugin to do the job and my issue was resolved.
Another way is to use the babel's transform runtime plugin which also solved my issue.
I suspect the main issue was the code which uses regeneratorRuntime was not being resolved, not sure about that, but the workaround solved my problem.

Babel v7? Is it core-v7, cli-v7? or all packages are upgraded?

I understand Babel is a monorepo and contains a lot of packages like core, cli, plugins, presets etc.
When they say upgrade to Babel v7.x.x, what do they really mean. Does it mean, upgrade each of the packages in monorepo to v7.x.x?
If I upgrade my core package to babel-core-v7.x.x. Then does it mean if I still supply stage-x presets in .babelrc, core package won't understand it and hence won't transpile using the plugins in the preset.(Since stage-presets are deprecated in v7.x.x)
Babel Docs for Decorator plugin Here they say, In Babel 7, transform-decorators-legacy will be the default plugin in Stage-0. What do they mean here, if stage presets i.e. stage-x(0,1,2,3) are deprecated.
After playing around a bit, this is what I found.
Babel is a monorepo that has a lot of packages in it. The main babel package that takes the raw code and transpile to a new code is babel-core. By itself, it does not do anything, it simply returns the same code.
Babel-core or babel can accept config which could contain a lot of plugins, presets(bundled set of plugins). These plugins are responsible for transipiling code. For Eg. You may use an ES6 arrow function in your code. Then you may run babel with a plugin that transpiles arrow functions to get the resulting ES5 version of arrow function.
Now Babel v7.x.x is a major(as per semantic versioning) version change(from 6.x.x to 7.x.x), hence it is expected to have breaking changes. Hence if you just change the babel core version, the code is expected to break. Hence they supply a migration guide as well.
With version 7.x.x, the way Plugins/Presets are mandated to return a function against version 6.x.x where it could return an object or function. Hence if you try to use a v6 plugin, that return an object with v7 of babel core, it will fail. Also they have removed stage-x presets. Hence if you have those in your config, it will break as well. There are a lot of such changes. Please refer to migration guide.
To answer #3, I confirmed with the team there, and the docs are not updated yet.

Babel doesn't seem to work

I have a project built in WebStorm 2016.2.2, Node.js 6.6.0 and TypeScript 1.8.
For some reasons, which are specified here: ES6 import and export are not supported in Node.js, I need to use Babel.
I have installed Babel and babel-preset-es2015 and I have added a file watcher, but I'm still getting an "unexpected token import" error. It looks like babel doesn't work.
1) Do I need to take an additional action in order to transpile my js files to ES5?
2) What version of ES should I set the "JavaScript language version" to in WebStorm settings?
3) Is Babel supposed to generate another file with the output as TypeScript compiler does?
Any help will be profoundly appreciated!
here are the Babel file watcher settings that work for me:
Arguments: $FilePathRelativeToProjectRoot$ --out-dir $ProjectFileDir$/dist --source-maps --presets es2015
Working directory: $ProjectFileDir$
Output Paths to Refresh: $ProjectFileDir$/dist/$FileDirRelativeToProjectRoot$/$FileNameWithoutExtension$.js:$ProjectFileDir$/dist/$FileDirRelativeToProjectRoot$/$FileNameWithoutExtension$.js.map
it compiles files to separate directory, preserving original file names, so that require() work; also, WebStorm is aware of generated files, as file system is correctly refreshed once the compilation completes
1) Create a file called .babelrc in the root directory of the project, with the following content:
{
"presets": ["es2015"]
}
It is not enough to install the es6 preset, you have to tell babel to use that preset. For reference: https://babeljs.io/docs/plugins/preset-es2015/
2) Try setting ECMAScript6
Do not use babel-preset-es2015 for Node.js 6. This will transform your sources to ES5, whilst you already have 97% support for ES6 natively, causing severe performance penalties. Merely adding it doesn't enable module transformation either.
Use the babel-preset-node6 preset or just add the transform-es2015-modules-commonjs plugin.

Using traceur compiler with meteor

I would like to use Javascript generators on client code (and other ES6 features), but AFAIK it's not yet implemented in all major browsers yet or enabled by default. So I found traceur.
But I'm having trouble with Meteor integration. Traceur provides a command line compiler, which I could call as meteor-typescript (even if it's not recommended), because I couldn't find documentation about compiling a string from Javascript with traceur.
Then, I guess a runtime dependency is also required and has to be served to the client. Can I use bower for that?
Thanks in advance for any suggestions or pointers.
Edit: I could call the compiler (see my meteor-traceur), but I don't know how to add the runtime dependency. Traceur defines a RUNTIME_PATH, but I can't use it with api.add_files because the npm module isn't imported inside package.js (where Packages.on_use should be defined).
The npm depencies are installed in the .npm directoy in the package. You can add the traceur runtime by adding this to package.js:
Package.on_use(function (api) {
api.add_files(".npm/plugin/compileTraceur/node_modules/traceur/bin/traceur-runtime.js");
});
I forked your repository and fixed this: https://github.com/Sanjo/meteor-traceur
I also created a demo app: https://github.com/Sanjo/meteor-traceur-demo

Categories