如何在网页中使用 ECMAScript6 模块
How to use ECMAScript6 modules within webpages
我对现在通过 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>
谢谢
[注意:我意识到我的回答很差,因为它没有完全反映
提问者打算在前端工作流中通过 babeljs 使用 ES6 模块。
为那些想在网页中使用 ES6 模块的人保留答案]
尝试使用 jspm.io 在浏览器中加载 ES6 模块,而无需预先使用 babel 进行转译。
可以找到一个 plunker here
jspm 在 system.js 之上工作,它试图成为任何模块格式(ES6、AMD、CommonJS)的加载器..
为了在我的浏览器中运行,我基于 this jspm ES6 demo。刚刚将 System.js 和 es6-module-loader.js 复制到 js/lib 文件夹中并复制了你的 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
不使用模块:
如果您不使用模块 (imports/exports),那么您可以简单地将您的代码转换为 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.js
和 main.js
就是您的情况),在将您的代码转换为 ES5 之后,您还必须将它们捆绑在一起(从 AMD/CommonJS/Modules 到您的浏览器可以理解的代码)。您可以使用 gulp, webpack, browserify 等各种构建系统来执行此操作。我将在此处使用 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
我开始尝试同样的事情,但最终发现 Gulp 真的帮了很多忙。
要记住一件事:babel source.js > destination.js
不会填充新的 ES6 语法。您的代码现在没有使用任何 let
语句、解构赋值、生成器函数或类似的东西;但如果您在稍后阶段添加它,您将需要更复杂的转换。
这是一个解释如何设置 gulp 文件的答案:(免责声明:这是我的答案之一:P)
以下是针对您的案例的具体步骤:
- 在您的目录中创建一个名为
gulpfile.js
的文件,其中包含以下内容:
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']);
- 运行
npm install gulp browserify babel babelify gulp-util vinyl-buffer vinyl-source-stream gulp-uglify gulp-sourcemaps
安装所需的依赖项。
- 运行
gulp
将所有内容捆绑在一起。
- 将 HTML 中的捆绑脚本与此元素一起使用:
<script src="app.js"></script>
除了添加了 polyfill 之外,还有一个好处是代码被缩小了,并且你得到了 sourcemaps,这意味着即使在你的开发者工具中,你也可以调试 ES6 代码本身。
注意:虽然根据 ES6 规范草案,您使用的导入语句是正确的,但 Babel 不会喜欢它。您需要添加一个 ./
,使其看起来像这样:
import { square, diag } from './lib';
我怀疑这是因为转换发生在 Node.js 中,这将文件与节点模块区分开来。作为一个方面,你可以为节点编写 ES6 do requires with import statements :)
--modules
开关之一是否会编译成可以直接包含在网页中的 JS,就像 --script
标志将编译成浏览器 JS 一样(--script
不能与模块一起使用)?参见 https://github.com/google/traceur-compiler/wiki/Options-for-Compiling
我对现在通过 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>
谢谢
[注意:我意识到我的回答很差,因为它没有完全反映 提问者打算在前端工作流中通过 babeljs 使用 ES6 模块。 为那些想在网页中使用 ES6 模块的人保留答案]
尝试使用 jspm.io 在浏览器中加载 ES6 模块,而无需预先使用 babel 进行转译。 可以找到一个 plunker here
jspm 在 system.js 之上工作,它试图成为任何模块格式(ES6、AMD、CommonJS)的加载器..
为了在我的浏览器中运行,我基于 this jspm ES6 demo。刚刚将 System.js 和 es6-module-loader.js 复制到 js/lib 文件夹中并复制了你的 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
不使用模块: 如果您不使用模块 (imports/exports),那么您可以简单地将您的代码转换为 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.js
和 main.js
就是您的情况),在将您的代码转换为 ES5 之后,您还必须将它们捆绑在一起(从 AMD/CommonJS/Modules 到您的浏览器可以理解的代码)。您可以使用 gulp, webpack, browserify 等各种构建系统来执行此操作。我将在此处使用 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
我开始尝试同样的事情,但最终发现 Gulp 真的帮了很多忙。
要记住一件事:babel source.js > destination.js
不会填充新的 ES6 语法。您的代码现在没有使用任何 let
语句、解构赋值、生成器函数或类似的东西;但如果您在稍后阶段添加它,您将需要更复杂的转换。
这是一个解释如何设置 gulp 文件的答案:
以下是针对您的案例的具体步骤:
- 在您的目录中创建一个名为
gulpfile.js
的文件,其中包含以下内容:
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']);
- 运行
npm install gulp browserify babel babelify gulp-util vinyl-buffer vinyl-source-stream gulp-uglify gulp-sourcemaps
安装所需的依赖项。 - 运行
gulp
将所有内容捆绑在一起。 - 将 HTML 中的捆绑脚本与此元素一起使用:
<script src="app.js"></script>
除了添加了 polyfill 之外,还有一个好处是代码被缩小了,并且你得到了 sourcemaps,这意味着即使在你的开发者工具中,你也可以调试 ES6 代码本身。
注意:虽然根据 ES6 规范草案,您使用的导入语句是正确的,但 Babel 不会喜欢它。您需要添加一个 ./
,使其看起来像这样:
import { square, diag } from './lib';
我怀疑这是因为转换发生在 Node.js 中,这将文件与节点模块区分开来。作为一个方面,你可以为节点编写 ES6 do requires with import statements :)
--modules
开关之一是否会编译成可以直接包含在网页中的 JS,就像 --script
标志将编译成浏览器 JS 一样(--script
不能与模块一起使用)?参见 https://github.com/google/traceur-compiler/wiki/Options-for-Compiling