babel gulp
ECMAScript 6 (a.k.a ECMAScript 2015 or ES6), the specification for next version of JavaScript has been approved and browser vendors are hard at work implementing it. Unlike the previous versions of ECMAScript, ES6 comes with a huge set of changes to the language to make it a good fit for the scale at which it is used today. Sitepoint has a number of articles covering these features.
ECMAScript 6(又名ECMAScript 2015或ES6),下一版本JavaScript的规范已获得批准 ,浏览器供应商正在努力实现它。 与早期版本的ECMAScript不同,ES6对该语言进行了大量更改,使其非常适合当今使用的规模。 Sitepoint有许多有关这些功能的文章 。
Although browsers haven’t implemented all of the features yet, we can already take advantage of ES6 during development and convert it to a version that browser understands before shipping the application. Babel and Traceur are two of the leading transpilers used for this purpose. Microsoft’s typed superset of JavaScript, TypeScript can also be used as an ES6 transpiler.
尽管浏览器尚未实现所有功能,但是我们已经可以在开发过程中利用ES6,并将其转换为浏览器可以理解的版本,然后再交付应用程序。 Babel和Traceur是用于此目的的两个领先的编译器。 Microsoft的类型化JavaScript超集TypeScript也可用作ES6编译器。
I covered how ES6 can be used today to write Angular 1.x applications in one of my previous articles. In that article I used Traceur’s on-the-fly transpiler to run the application. Although it works, it is always better to transpile beforehand and reduce the amount of work to be done in the browser. In this article, we will see how the same sample application can be transpiled to ES5 and the modules into either CommonJS or, AMD using Babel to make it run on today’s browsers. Though the sample is based on Angular, the techniques of transpilation can be used with any valid ES6 code.
在上一篇文章中,我介绍了如何今天使用ES6编写Angular 1.x应用程序。 在那篇文章中,我使用了Traceur的即时编译器来运行该应用程序。 尽管可以工作,但最好事先进行翻译并减少浏览器中要做的工作量。 在本文中,我们将看到如何将相同的示例应用程序转换为ES5,并将模块转换为CommonJS或AMD,并使用Babel使其在当今的浏览器上运行。 尽管示例基于Angular,但转译技术可以与任何有效的ES6代码一起使用。
As ever, you can find the code to accompany this article on our GitHub repo.
与往常一样,您可以在我们的GitHub repo上找到本文随附的代码。
One of the key features in any language used to write large applications, is the ability to load different pieces of the application in the form of modules. Modules not only help us keep the code cleaner but they also play a role in reducing the usage of global scope. The contents of a module are not made available to any other module unless the other module explicitly loads it.
任何用于编写大型应用程序的语言的主要功能之一就是能够以模块的形式加载应用程序的不同部分。 模块不仅帮助我们保持代码更整洁,而且在减少全局范围的使用方面也发挥了作用。 除非另一个模块显式加载该模块的内容,否则该模块的内容不可用于任何其他模块。
The importance of modules is not limited to applications. Even large JavaScript libraries can take advantage of the module system to export their objects as modules and the applications using the libraries import these modules as required. Angular 2 and Aurelia have started using this feature.
模块的重要性不仅限于应用程序。 即使是大型JavaScript库,也可以利用模块系统将其对象导出为模块,并且使用该库的应用程序会根据需要导入这些模块。 Angular 2和Aurelia已开始使用此功能。
If you’d like a quick primer on using modules in ES6, please read: Understanding ES6 Modules
如果您想快速入门在ES6中使用模块,请阅读: 了解ES6模块
The subject of our sample application is a virtual book shelf. It consists of the following pages:
我们的示例应用程序的主题是虚拟书架。 它包含以下页面:
The application is built using AngularJS 1.3 and ES6. If you look at any of the files in the app
folder, you will see the keywords export
and import
used to export objects from the current module and to import objects from other modules. Now, our job is to use Babel’s Gulp tasks to convert these modules to one of the existing module systems.
该应用程序是使用AngularJS 1.3和ES6构建的。 如果查看app
文件夹中的任何文件,将看到关键字export
和import
这些关键字用于从当前模块导出对象以及从其他模块导入对象。 现在,我们的工作是使用Babel的Gulp任务将这些模块转换为现有模块系统之一。
No worries! We got you covered. With a minor amount of tweaking the recipes demonstrated below can be used in any project involving ES6 modules. Angular is quite unimportant here.
别担心! 我们得到了你的覆盖。 只需进行少量调整,以下演示的配方就可以用于任何涉及ES6模块的项目。 Angular在这里并不重要。
CommonJS is a module system defined by the CommonJS group. It is a synchronous module system, in which the modules are loaded using the require
function and exported using the exports
property of the module
object. The module
object is expected to be available in all modules by default.
CommonJS是CommonJS组定义的模块系统。 它是一个同步模块系统,其中使用require
函数加载模块,并使用module
对象的exports
属性导出module
。 默认情况下, module
对象应该在所有模块中都可用。
Node.js uses this module system, so it defines the module
object natively and makes it available to your application. As browsers don’t have this object defined, we need to use a utility called Browserify to fill the gap.
Node.js使用此模块系统,因此它本地定义了module
对象,并使它可用于您的应用程序。 由于浏览器未定义此对象,因此我们需要使用名为Browserify的实用程序来填补空白。
Before we start, we will also need to install a few npm packages. These will enable us to use Babel and Browserify in conjunction with Gulp to convert our ES6 modules to one of the common module formats and package the application as a single file for the browser to consume.
在开始之前,我们还需要安装一些npm软件包。 这些将使我们能够将Babel和Browserify与Gulp结合使用,以将我们的ES6模块转换为一种常见的模块格式,并将该应用程序打包为一个文件供浏览器使用。
gulp-babel — converts ES6 code into vanilla ES5
gulp-babel —将ES6代码转换为原始ES5
Browserify — lets you require('modules')
in the browser by bundling up all of your dependencies
Browserify-通过捆绑所有依赖项 ,使您在浏览器中require('modules')
vinyl-source-stream — handles the Browserify module directly, avoiding need for gulp-browserify wrapper
Vinyl-Source-Stream —直接处理Browserify模块,避免使用gulp - browserify包装器
vinyl-buffer — converts stream to a buffer (necessary for gulp-uglify which doesn’t support streams)
Vinyl-Buffer —将流转换为缓冲区(对于不支持流的gulp-uglify是必需的)
gulp-uglify — minifies files
gulp - uglify-缩小文件
del — lets you delete files and folders
del-可让您删除文件和文件夹
gulp-rename — a plugin to let you rename files
gulp-rename-一个让您重命名文件的插件
You can get this lot by typing:
您可以通过输入以下内容来获得很多:
npm install gulp-babel browserify gulp-browserify vinyl-source-stream vinyl-buffer gulp-uglify del gulp-rename --save-dev
Now let’s start using these packages in our gulpfile.js
. We need to write a task to take all ES6 files and pass them to Babel. The default module system in Babel is CommonJS, so we don’t need to send any options to the babel function.
现在让我们开始在gulpfile.js
使用这些包。 我们需要编写一个任务来获取所有ES6文件并将它们传递给Babel。 Babel中的默认模块系统是CommonJS,因此我们不需要向babel函数发送任何选项。
var babel = require('gulp-babel'),
browserify = require('browserify'),
source = require('vinyl-source-stream'),
buffer = require('vinyl-buffer'),
rename = require('gulp-rename'),
uglify = require('gulp-uglify'),
del = require('del');
gulp.task('clean-temp', function(){
return del(['dest']);
});
gulp.task('es6-commonjs',['clean-temp'], function(){
return gulp.src(['app/*.js','app/**/*.js'])
.pipe(babel())
.pipe(gulp.dest('dest/temp'));
});
Hopefully there is nothing too confusing here. We are declaring a task named es6-commonjs
which grabs any JavaScript files in the app directory and any of its sub directories. It then pipes them through Babel, which in turn converts the individual files to ES5 and CommonJS modules and copies the converted files into the dest/temp
folder. The es6-commonjs
task has a dependency named clean-temp
, which will remove the dest
directory and any files in it, before the es6-commonjs
task runs.
希望这里没有太混乱的地方。 我们正在声明一个名为es6-commonjs
的任务,该任务将抓取app目录及其子目录中的所有JavaScript文件。 然后,它将它们通过Babel进行管道传输,Babel随后将各个文件转换为ES5和CommonJS模块,并将转换后的文件复制到dest/temp
文件夹中。 es6-commonjs
任务具有一个名为clean-temp
的依赖项,它将在es6-commonjs
任务运行之前删除dest
目录及其中的任何文件。
If you want to make the code more explicit and specify the module system, you may modify usage of Babel as:
如果要使代码更明确并指定模块系统,则可以将Babel的用法修改为:
.pipe(babel({
modules:"common"
}))
Now we can create a single bundled file from these individual files by applying Browserify and then minifying the output using the uglify package. The following snippet shows this:
现在,我们可以通过应用Browserify,然后使用uglify软件包最小化输出,从这些单独的文件中创建一个捆绑文件。 以下代码片段显示了这一点:
gulp.task('bundle-commonjs-clean', function(){
return del(['es5/commonjs']);
});
gulp.task('commonjs-bundle',['bundle-commonjs-clean','es6-commonjs'], function(){
return browserify(['dest/temp/bootstrap.js']).bundle()
.pipe(source('app.js'))
.pipe(buffer())
.pipe(uglify())
.pipe(rename('app.js'))
.pipe(gulp.dest("es5/commonjs"));
});
The above task has two dependencies: the first is the bundle-commonjs-clean
task, which will delete the directory es5/commonjs
, the second is the previously discussed es6-commonjs
task. Once these have run, the task places the combined and minified file app.js
in the folder es5/commonjs
. This file can be referenced directly in index.html
and the page can be viewed in a browser.
上面的任务有两个依赖项:第一个是bundle-commonjs-clean
任务,它将删除目录es5/commonjs
,第二个是前面讨论的es6-commonjs
任务。 这些文件运行后,任务会将合并并缩小的文件app.js
放置在es5/commonjs
文件夹中。 可以在index.html
直接引用此文件,并且可以在浏览器中查看页面。
Finally, we can add a task to kick things off:
最后,我们可以添加一个任务来开始工作:
gulp.task('commonjs', ['commonjs-bundle']);
The Asynchronous Module Definition (AMD) system is, as the name suggests, an asynchronous module loading system. It allows multiple dependent modules to load in parallel and it doesn’t wait for one module to be completely loaded before attempting to load other modules.
顾名思义, 异步模块定义(AMD)系统是异步模块加载系统。 它允许多个从属模块并行加载,并且无需等待一个模块完全加载再尝试加载其他模块。
Require.js is the library used to work with AMD. RequireJS is available through Bower:
Require.js是用于AMD的库。 可通过Bower获得RequireJS:
bower install requirejs --save
We also need the Gulp plugin for require.js to bundle the application. Install the gulp-requirejs
npm package for this.
我们还需要Gulp插件用于require.js来捆绑应用程序。 为此安装gulp-requirejs
npm软件包。
npm install gulp-requirejs --save-dev
Now we need to write the tasks for converting the ES6 code to ES5 and AMD and then to bundle it using RequireJS. The tasks are pretty much similar to the tasks created in the CommonJS section.
现在,我们需要编写将ES6代码转换为ES5和AMD,然后使用RequireJS进行捆绑的任务。 这些任务与CommonJS部分中创建的任务非常相似。
var requirejs = require('gulp-requirejs');
gulp.task('es6-amd',['clean-temp'], function(){
return gulp.src(['app/*.js','app/**/*.js'])
.pipe(babel({ modules:"amd" }))
.pipe(gulp.dest('dest/temp'));
});
gulp.task('bundle-amd-clean', function(){
return del(['es5/amd']);
});
gulp.task('amd-bundle',['bundle-amd-clean','es6-amd'], function(){
return requirejs({
name: 'bootstrap',
baseUrl: 'dest/temp',
out: 'app.js'
})
.pipe(uglify())
.pipe(gulp.dest("es5/amd"));
});
gulp.task('amd', ['amd-bundle']);
To use the final script on index.html page, we need to add a reference to RequireJS, the generated script and then load the bootstrap
module. The bootstrap.js
file inside app
folder bootstraps the AngularJS application, so we need to load it to kick start the AngularJS application.
要在index.html页面上使用最终脚本,我们需要添加对RequireJS(生成的脚本)的引用,然后加载bootstrap
模块。 该bootstrap.js
内部文件app
文件夹中引导了AngularJS应用程序,所以我们需要加载它来启动的AngularJS应用。
<script src="bower_components/requirejs/require.js" ></script>
<script src="es5/amd/app.js"></script>
<script>
(function(){
require(['bootstrap']);
}());
</script>
Modules are a long overdue feature in JavaScript. They will be arriving in ES6, but unfortunately, their native browser support is currently poor. That does not however, mean that you cannot use them today. In this tutorial I have demonstrated how to use Gulp, Babel and a variety of plugins to convert ES6 modules to the CommonJS and AMD format that you can run in your browser.
模块是JavaScript中早就应该使用的功能。 他们将在ES6中推出,但是不幸的是,它们对本机浏览器的支持目前很差。 但是,这并不意味着您今天不能使用它们。 在本教程中,我演示了如何使用Gulp,Babel和各种插件将ES6模块转换为可在浏览器中运行的CommonJS和AMD格式。
And as for ES6? ES6 has gained a lot of attention in the community since it was announced. It is already used by several JavaScript libraries or, frameworks including Bootstrap’s JavaScript plugins, Aurelia, Angular 2 and several others. TypeScript has also added support for a handful number of ES6 features including modules. Learning about and using ES6 today, will reduce the effort required to convert the code in future.
至于ES6? 自发布以来,ES6在社区引起了很多关注。 它已经被多个JavaScript库或框架(包括BootstrapJavaScript插件,Aurelia,Angular 2以及其他一些框架)使用。 TypeScript还增加了对包括模块在内的少数ES6功能的支持。 今天学习和使用ES6将减少将来转换代码所需的工作。
翻译自: https://www.sitepoint.com/transpiling-es6-modules-to-amd-commonjs-using-babel-gulp/
babel gulp