Do I need to use js when using babel?
You may need some module loader, but this is not required by RequireJS. You have several options. The following will help you get started.
Drive is the next generation JavaScript block module. He understands ES2015 modules initially and creates a package that does not require any module loader. Unused exports will be separated from the result, it is called tree shake.
Now I personally recommend using rollupjs as it gives the clearest output and is easy to configure, however it gives a different aspect of the answer. All other approaches do the following:
- Compile ES6 code with babel, use the module format of your choice.
- Combining compiled modules with a module loader OR using a middleware that will cross your dependencies.
With rollups, things really don't work that way. Here rollup is the first step, not babel. By default, it understands ES6 modules. You must provide an input module in which dependencies will be passed and contested. Since ES6 allows multiple export by name to a module, rollupjs is smart enough to strip unused exports, thereby reducing the size of the package. Unfortunately, the rollupjs-s analyzer does not understand> ES6 syntax, so ES7 modules must be compiled before rollup parses them, but compilation should not affect ES6 imports. This is done using the rollup-plugin-babel with the preset babel-preset-es2015-rollup (this preset is the same as es2015, except for the transformer module and the external helpers plugin). Thus, when configured correctly, the drive will perform the following actions with your modules:
- Reads your ES6-7 module from the file system
- The babel plugin will compile it in ES6 in memory
- rollup parses ES6 code for import and export (using an acorns analyzer compiled into a cumulative file).
- it moves the entire graph and creates a single package (which can still have external dependencies, and the export of records can be exported in the format you choose)
Nodejs build example:
// setup by `npm i rollup rollup-plugin-babel babel-preset-es2015 babel-plugin-external-helpers --save-dev` // build.js: require("rollup").rollup({ entry: "./src/main.js", plugins: [ require("rollup-plugin-babel")({ "presets": [["es2015", { "modules": false }]], "plugins": ["external-helpers"] }) ] }).then(bundle => { var result = bundle.generate({ // output format - 'amd', 'cjs', 'es6', 'iife', 'umd' format: 'iife' }); require("fs").writeFileSync("./dist/bundle.js", result.code); // sourceMaps are supported too! }).then(null, err => console.error(err));
Grunt build example with grunt-rollup
// setup by `npm i grunt grunt-rollup rollup-plugin-babel babel-preset-es2015 babel-plugin-external-helpers --save-dev` // gruntfile.js module.exports = function(grunt) { grunt.loadNpmTasks("grunt-rollup"); grunt.initConfig({ "rollup": { "options": { "format": "iife", "plugins": [ require("rollup-plugin-babel")({ "presets": [["es2015", { "modules": false }]], "plugins": ["external-helpers"] }) ] }, "dist": { "files": { "./dist/bundle.js": ["./src/main.js"] } } } }); }
Gulp build example with gulp-rollup
// setup by `npm i gulp gulp-rollup rollup-plugin-babel babel-preset-es2015 babel-plugin-external-helpers --save-dev` // gulpfile.js var gulp = require('gulp'), rollup = require('gulp-rollup'); gulp.task('bundle', function() { gulp.src('./src/**/*.js') // transform the files here. .pipe(rollup({ // any option supported by Rollup can be set here. "format": "iife", "plugins": [ require("rollup-plugin-babel")({ "presets": [["es2015", { "modules": false }]], "plugins": ["external-helpers"] }) ], entry: './src/main.js' })) .pipe(gulp.dest('./dist')); });
Babel has a neat package called Babelify . This is a simple and clear use:
$ npm install --save-dev babelify babel-preset-es2015 babel-preset-react $ npm install -g browserify $ browserify src/script.js -o bundle.js \ -t [ babelify --presets [ es2015 react ] ]
or you can use it from node.js:
$ npm install --save-dev browserify babelify babel-preset-es2015 babel-preset-react ... var fs = require("fs"); var browserify = require("browserify"); browserify(["./src/script.js"]) .transform("babelify", {presets: ["es2015", "react"]}) .bundle() .pipe(fs.createWriteStream("bundle.js"));
This will transfer and merge your code immediately. Browserify .bundle will contain a beautiful little CommonJS loader and organize your converted modules into functions. You even have relative imports.
Example:
// project structure . +-- src/ | +-- library/ | | \-- ModuleA.js | +-- config.js | \-- script.js +-- dist/ \-- build.js ... // build.js var fs = require("fs"); var browserify = require("browserify"); browserify(["./src/script.js"]) .transform("babelify", {presets: ["es2015", "react"]}) .bundle() .pipe(fs.createWriteStream("dist/bundle.js")); // config.js export default "Some config"; // ModuleA.js import config from '../config'; export default "Some nice export: " + config; // script.js import ModuleA from './library/ModuleA'; console.log(ModuleA);
To compile, simply run node build.js in the root of your project.
Compile all your code with babel. I recommend using the amd module module (called babel-plugin-transform-es2015-modules-amd in babel 6). Then compile your compiled sources using WebPack.
WebPack 2 does not work! He understands native ES6 modules, and will perform (or rather simulate) tree shake using babili - built-in dead code removal. At the moment (September 2016), I still suggest using the cumulative package with babel, although my opinion may change from the first release of WebPack 2. Feel free to discuss your opinions in the comments.
Custom compilation console
Sometimes you want more control over the compilation process. You can implement your own pipeline as follows:
First you need to configure babel to use amd modules. By default, babel translates CommonJS modules, which is a bit difficult to handle in the browser, although the browser manages to handle them beautifully.
- Babylon 5: use the
{ modules: 'amdStrict', ... } option - Babel 6: use the
es2015-modules-amd plugin
Remember to enable the moduleIds: true parameter.
Check the passed code for the generated module names, often there are inconsistencies between the specific and required modules. See sourceRoot and moduleRoot .
Finally, you should have some kind of loader module, but it is not a requirement. There is almondjs , a tiny block that works well. You can even implement your own:
var __modules = new Map(); function define(name, deps, factory) { __modules.set(name, { n: name, d: deps, e: null, f: factory }); } function require(name) { const module = __modules.get(name); if (!module.e) { module.e = {}; module.f.apply(null, module.d.map(req)); } return module.e; function req(name) { return name === 'exports' ? module.e : require(name); } }
In the end, you can simply concatenate the boot loader gasket and compiled modules together and perform a workaround for this.
Babel template code is duplicated in each module
By default, most of the above methods combine each module with a buffer separately, and then combine them together. What babelify does, too. But if you look at the compiled code, you will see that babel inserts many templates at the beginning of each file, most of which are duplicated in all files.
To prevent this, you can use the babel-plugin-transform-runtime .