I'm currently learning how to set up React-projects with npm, Babel and Browserify.
The usage of Babel seems sufficient clear to me: It translates JSX- and ES6-code to ES5-code, which can be run in all browsers.
The same with Browserify: It bundles the npm-packages which I use (React-DOM, React etc.) together with my own code into one large file. These file can then be used for to be deployed to production.
But I struggle to understand what Babelify is for.
I have read that it "allows to use Babel with Browserify". A sitepoint-article says that it is "Babel transformer for Browserify".
All these explanations are a bit weird to me because if:
Babel is a transpiler which transpiles JSX, ES6, TypeScript, ... -code to browser-compatible code.
Why do I need an additional "transformer" for the output of Babel?
babelify it's browserify transform package.
You can not use plain babel package with browserify. Therefore you should use babelify package, which contains babel inside to be able transform es6 code to es5 using browserify.
Related
Are the defaults the same? Do they have different targets? Is babel-loader contingent on webpacks targets?
Reason I ask is I am using babel-loader with webpack and when running in production mode, the code is being transpired correctly, expect the const keyword, that word is not being changed to 'var'. However when transpiling with babel directly on the file using babel and not babel-loader through webpack, the output obviously is changing the const keyword to var.
The only time it transpiles const to var, is when I set the webpack.config.js file to have
target: ["web", "es5"] however, I feel that should not matter, since babel-loader is just loading the transpiled code from the babel runtime...right? Which contains the var keyword. Or is it not?
What is babel-loader doing different than when running babel on the file directly?
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/
I have monorepo built with Lerna. It has following structure:
packages
- create-react-app-example
- utils
create-react-app-example is like what create-react-app produces. I.e. it uses webpack for transpiling ES6/ES7 code, has hot-module-replacement on files changes etc;
utils package has just 1 file with some utility function. And this function is used from inside create-react-app-example package; It doesn't use Webpack, Babel or any other tool;
So, all pretty simple.
But I have hard times trying to configure comfortable development environment.
So there few things I want:
to be able to use es6/es7 code inside utils package (code of this package should be transpiled somehow);
automatic hot updates of main module when something changes in utils package;
The only thing came to my mind is to tweak webpack.config.js of create-react-app-example:
change setting of babel loader, so it will not exclude node_modules/utils folder and will transpile it;
and change parameters of webpack watch so it will detect changes in both packages
But I don't like solution above, it looks dirty for me.
May be there some more elegant solution?
Or may be I should also add webpack.config to utils package and somehow use it as library? If I remember correctly Webpack has such functionality.
Thanks
to be able to use es6/es7 code inside utils package (code of this
package should be transpiled somehow);
If you really want to keep utils as a separate package, just configure babel to transpile it separately from the CRA app. You can do this using the babel cli, here is an example of how to do it: https://github.com/babel/example-node-server
automatic hot updates of main module when something changes in utils
package;
Your idea to configure webpack watch sounds right. Docs here
You will likely end up with 2 watches: babel transpiling the utils package, and webpack for building and bundling the CRA app.
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.
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.