如何在网页中使用ECMAScript6模块

时间:2015-02-27 09:05:27

标签: javascript ecmascript-6 babeljs

我很高兴现在通过Babeljs使用ECMAScript 6功能 - 特别是,我喜欢使用新的模块功能开始使我的JavaScript代码更加模块化。

这是我到目前为止所写的内容:

// ECMAScript 6 code - lib.js
export const sqrt = Math.sqrt;
export function square (x) {
  return x * x;
}

export function diag (x, y) {
  return sqrt(square(x) + square(y));
}

// ECMAScript 6 code - main.js
import { square, diag } from 'lib';
console.log(square(11));
console.log(diag(4, 3));

据我所知,我可以在命令行上通过babel将此代码从ES6转换为ES5:

babel lib.js > lib6to5.js
babel main.js > main6to5.js

但在HTML中使用此代码需要做什么?

例如,这个index.html文件是什么样的:

<!-- index.html -->
<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>ECMAScript 6</title>

    <!-- What goes here? 
     How do I include main6to5.js and lib6to5.js to make this work in the browser? -->
    <script src="?????"></script>

  </head>
  <body>

  </body>
</html>

谢谢

4 个答案:

答案 0 :(得分:23)

不使用模块: 如果您不使用模块(导入/导出),那么您只需将代码转换为ES5并将这些ES5文件包含在您的html中。 例如:

// ES6 - index.js
// arrow function
var result = [1, 2, 3].map(n => n * 2);
console.log(result);

// enhanced object literal
var project = "helloWorld";
var obj = {
    // Shorthand for ‘project: project’
    project,
    // Methods
    printProject() {
     console.log(this.project);
    },
    [ "prop_" + (() => 42)() ]: 42
};
console.log(obj.printProject());
console.log(obj);

透明到es5:babel index.js > es5.js

index.html中,加入<script src="es5.js"></script> 将在控制台中打印出以下内容:

[2,4,6]
helloWorld
{"project":"helloWorld","prop_42":42}

使用模块现在,如果您正在使用模块(lib.jsmain.js就是这种情况),在将代码转换为ES5之后,您还必须将它们捆绑在一起(从AMD / CommonJS / Modules到您的浏览器可以理解的代码)。您可以使用gulpwebpackbrowserify等各种构建系统执行此操作。我将在此处使用browserify作为示例。

假设我的文件夹结构如下:

es6
|- src
  |- lib.js
  |- main.js
|- compiled
|- index.html

我运行babel将我的文件/src转换为/compiled文件夹:babel src --out-dir compiled

现在我在编译文件夹中有我的ES5代码。我在cmd行中安装了browserify,然后将我的main.js(入口点)捆绑在我编译的文件夹中

~/es6 » npm install --global browserify
~/es6 » browserify ./compiled/main.js -o ./bundle.js

现在我有bundle.js,如下所示:

(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
"use strict";

exports.square = square;
exports.diag = diag;
var sqrt = exports.sqrt = Math.sqrt;

function square(x) {
    return x * x;
}

function diag(x, y) {
    return sqrt(square(x) + square(y));
}

Object.defineProperty(exports, "__esModule", {
    value: true
});
},{}],2:[function(require,module,exports){
"use strict";

var _lib = require("./lib");

var square = _lib.square;
var diag = _lib.diag;

console.log(square(11)); // 121
console.log(diag(4, 3)); // 5
},{"./lib":1}]},{},[2]);

然后在你的index.html:

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>ECMAScript 6</title>

    <script src="./bundle.js"></script>

  </head>
  <body>

  </body>
</html>

然后只需打开index.html,您的控制台就会显示以下内容:

 121           bundle.js:27
 5             bundle.js:28

答案 1 :(得分:2)

[注意:我意识到我的答案很差,因为它没有完全反映出来 提问者打算在前端工作流程中通过babeljs使用ES6模块。 为那些想在网页中使用ES6模块的人保留答案]

尝试使用jspm.io在浏览器中加载ES6模块,而无需事先与babel进行转换。 可以找到一个plunker here

jspm在system.js的顶部工作,它试图成为任何模块格式的加载器(ES6,AMD,CommonJS)..

为了在我的浏览器中完成这项工作,我基于this jspm ES6 demo。只需在js / lib文件夹中复制 System.js es6-module-loader.js ,然后将es6 js文件复制到js文件夹中。然后html看起来像这样:

<html>
    <body>
        Test .. just open up the Chrome Devtools console to see the ES6 modules output using jspm
        <script src="js/lib/system.js"></script>
        <script>System.import("main");</script> </body>
</html>

可以找到一个plunker here

答案 2 :(得分:2)

我从尝试同样的事情开始,但最终发现Gulp确实帮了很多。

要记住一件事: babel source.js > destination.js赢得了填充新的ES6语法。您的代码现在不使用任何let语句,结构化赋值,生成器函数或类似的东西;但是如果你在以后的阶段添加它,你将需要更复杂的转换。

以下是解释如何设置gulp文件的答案:Javascript 6to5 (now Babel) export module usage(免责声明:这是我的答案之一:P)

以下是针对您的案例的具体步骤:

  1. 在您的目录中创建一个名为gulpfile.js的文件,其中包含以下内容:
  2. var gulp = require('gulp');
    var browserify = require('browserify');
    var babelify= require('babelify');
    var util = require('gulp-util');
    var buffer = require('vinyl-buffer');
    var source = require('vinyl-source-stream');
    var uglify = require('gulp-uglify');
    var sourcemaps = require('gulp-sourcemaps');
    
    gulp.task('build', function() {
      browserify(['./lib.js', './main.js'], { debug: true })
      .add(require.resolve('babel/polyfill'))
      .transform(babelify)
      .bundle()
      .on('error', util.log.bind(util, 'Browserify Error'))
      .pipe(source('app.js'))
      .pipe(buffer())
      .pipe(sourcemaps.init({loadMaps: true}))
      .pipe(uglify({ mangle: false }))
      .pipe(sourcemaps.write('./'))
      .pipe(gulp.dest('./'));
    });
    
    gulp.task('default', ['build']);
    
    1. 运行npm install gulp browserify babel babelify gulp-util vinyl-buffer vinyl-source-stream gulp-uglify gulp-sourcemaps以安装所需的依赖项。
    2. 运行gulp将所有内容捆绑在一起。
    3. 将HTML中的捆绑脚本与此元素一起使用:<script src="app.js"></script>
    4. 除了添加polyfill之外,还有一个好处是代码缩小了,你得到了源图,这意味着即使在你的开发人员工具中,你也可以自己调试ES6代码。


      注意:虽然根据ES6草案规范,您使用的import语句是正确的,但Babel不喜欢它。您需要添加./,以便它看起来像这样:

      import { square, diag } from './lib';
      

      我怀疑这是因为转换发生在Node.js中,这将文件与节点模块区分开来。作为一个侧面,您可以使用import语句为节点do require编写ES6:)

答案 3 :(得分:0)

其中一个--modules开关是否可以编译成JS,可以直接包含在网页中,就像--script标志将编译到浏览器JS一样(--script不能与模块一起使用)?见https://github.com/google/traceur-compiler/wiki/Options-for-Compiling