简体   繁体   English

如何在网页中使用ECMAScript6模块

[英]How to use ECMAScript6 modules within webpages

I'm pretty excited about using ECMAScript 6 features now via Babeljs - in particular, I'd love to start making my JavaScript code more modular using the new modules feature. 我很高兴现在通过Babeljs使用ECMAScript 6功能 - 特别是,我很乐意使用新的模块功能开始使我的JavaScript代码更加模块化。

Here's what I've written so far: 这是我到目前为止所写的内容:

// 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));

I understand that I can transpile this code from ES6 to ES5 via babel on the command line: 据我所知,我可以通过命令行上的babel将此代码从ES6转换为ES5:

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

But what do I need to do to use this code within my HTML? 但是,在HTML中使用此代码需要做什么?

For example, what would this index.html file look like: 例如,这个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>

Thank you 谢谢

Without using Modules: If you are not using modules (imports/exports), then you can simply transpile your code into ES5 and include those ES5 files in your html. 不使用模块:如果您不使用模块(导入/导出),那么您只需将代码转换为ES5并将这些ES5文件包含在您的html中。 Example: 例:

// 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);

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

In index.html , include <script src="es5.js"></script> Will print out the following in console: index.html ,包含<script src="es5.js"></script>将在控制台中打印出以下内容:

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

Using Modules: Now if you are using modules (which is your case with lib.js and main.js ), after converting your code into ES5 you also have to bundle them (from AMD/CommonJS/Modules to code that your browser can understand). 使用模块:现在,如果您正在使用模块(这是您的lib.jsmain.js ),在将代码转换为ES5之后,您还必须将它们捆绑(从AMD / CommonJS / Modules到您的浏览器可以理解的代码) )。 You can do this with various build systems like gulp , webpack , browserify , etc. I'm going to use browserify as an example here. 你可以用不同的生成系统,如这样做一饮而尽的WebPackbrowserify ,等我将使用browserify在这里举例。

Say my folder structure looks like this: 说我的文件夹结构如下所示:

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

I run babel to transpile my files /src to /compiled folder: babel src --out-dir compiled . 我运行babel将我的文件/src/compiled文件夹: babel src --out-dir compiled

Now I have my ES5 code in the compiled folder. 现在我在编译的文件夹中有我的ES5代码。 I install browserify in the cmd line and then bundle my main.js (entry point) in my compiled folder 我在cmd行中安装browserify,然后将我的main.js(入口点)捆绑在我编译的文件夹中

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

Now I have bundle.js which is look like this: 现在我有了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]);

Then in your index.html: 然后在index.html中:

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

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

  </head>
  <body>

  </body>
</html>

Then simply open up your index.html , and your console should give you the following: 然后只需打开index.html ,您的控制台就会给您以下内容:

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

[ Note : I realise my answer is poor as it doesn't fully reflect the questioners intention to use ES6 modules via babeljs in a front-end workflow. [ 注意 :我意识到我的答案很差,因为它没有完全反映提问者在前端工作流程中通过babeljs使用ES6模块的意图。 Keeping the answer her for those that want to use ES6 modules within a webpage] 为那些想要在网页中使用ES6模块的人保留答案]

Try using jspm.io for loading the ES6 modules in the browser without transpiling upfront with babel. 尝试使用jspm.io在浏览器中加载ES6模块,而无需事先与babel进行转换。 A plunker can be found here 可以在这里找到一个plunker

jspm works on top on of system.js which tries to be a loader for any module format (ES6, AMD, CommonJS).. JSPM作品上的顶部system.js它试图对任何模块格式(ES6,AMD,CommonJS的)加载器..

To make this work in my browser, I based myself on this jspm ES6 demo . 为了在我的浏览器中工作,我基于这个jspm ES6演示 Just copied System.js and es6-module-loader.js in a js/lib folder and copied your es6 js files in the js folder. 刚刚在js / lib文件夹中复制了System.jses6-module-loader.js ,并将你的es6 js文件复制到了js文件夹中。 Then the html just looks like this: 然后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>

A plunker can be found here 可以在这里找到一个plunker

I started out by trying the same thing, but eventually found that Gulp really helped out a lot. 我从尝试同样的事情开始,但最终发现Gulp确实帮了很多忙。

One thing to keep in mind: babel source.js > destination.js won't polyfill new ES6 syntax . 要记住一件事: babel source.js > destination.js不会填充新的ES6语法 Your code right now isn't using any let statements, destructured assignment, generator functions, or anything like that; 你的代码现在没有使用任何let语句,结构化赋值,生成器函数或类似的东西; but if you do add that at a later stage, you will need a more sophisticated transformation. 但如果你在稍后阶段添加它,你将需要更复杂的转换。

Here is an answer that explains how to setup the gulp file: Javascript 6to5 (now Babel) export module usage (Disclaimer: It is one of my answers :P) 这是一个解释如何设置gulp文件的答案: Javascript 6to5(现在Babel)导出模块用法 (免责声明:这是我的答案之一:P)

Here are the steps specific to your case: 以下是针对您的案例的具体步骤:

  1. Create a file called gulpfile.js in your directory with the following in it: 在您的目录中创建一个名为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']);
  1. Run npm install gulp browserify babel babelify gulp-util vinyl-buffer vinyl-source-stream gulp-uglify gulp-sourcemaps to install the needed dependencies. 运行npm install gulp browserify babel babelify gulp-util vinyl-buffer vinyl-source-stream gulp-uglify gulp-sourcemaps来安装所需的依赖项。
  2. Run gulp to bundle everything together. 运行gulp将所有内容捆绑在一起。
  3. Use the bundled script in your HTML with this element: <script src="app.js"></script> 使用HTML中的捆绑脚本和此元素: <script src="app.js"></script>

The nice thing in addition to polyfills being added is that the code is minified, and you get sourcemaps, which means even in your developer tools, you can debug the ES6 code itself. 除了添加polyfill之外,还有一个好处是代码缩小了,你得到了源图,这意味着即使在你的开发人员工具中,你也可以自己调试ES6代码。


Note: While the import statement you are using is correct according to the ES6 draft specification, Babel won't like it. 注意:虽然您使用的import语句根据ES6草案规范是正确的,但Babel不会喜欢它。 You will need to add a ./ , so that it looks something like this: 您需要添加./ ,以便它看起来像这样:

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

I suspect this is because the transformation happens in Node.js, and this differentiates a file from a node module. 我怀疑这是因为转换发生在Node.js中,这将文件与节点模块区分开来。 As a side point, you can write ES6 for node do requires with import statements :) 作为一个侧面,您可以使用import语句编写ES6 for node do requires :)

Would one of the --modules switches compile into JS that can be directly included in a web page in the same way that the --script flag will compile to browser JS ( --script can not be used with modules)? 其中一个--modules切换编译成JS,可以直接包含在网页中,就像--script标志将编译到浏览器JS一样( --script不能与模块一起使用)? See https://github.com/google/traceur-compiler/wiki/Options-for-Compiling 请参阅https://github.com/google/traceur-compiler/wiki/Options-for-Compiling

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM