Javascript 使用 babel 时是否需要 require js?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31593694/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 06:53:16  来源:igfitidea点击:

Do I need require js when I use babel?

javascriptecmascript-6

提问by jason

Im experimenting with ES6, and Im using gulp to build and babel to transpile to ES5. The output is not being run in node, just linked to from a .htm file with a tag. Im thinking I need to add

我正在试验 ES6,我使用 gulp 构建并使用 babel 转译到 ES5。输出不在节点中运行,只是从带有标记的 .htm 文件链接到。我想我需要添加

<script src='require.js'></script>

or something like that.

或类似的东西。

Im trying to import / export.

我正在尝试导入/导出。

////////////////scripts.js
import {Circle} from 'shapes';

c = new Circle(4);

console.log(c.area());


/////////////////shapes.js
export class Circle {

    circle(radius) {
        this.radius = radius;
    }

    area() {
        return this.radius * this.radius * Math.PI;
    } 

}

Error is

错误是

Uncaught ReferenceError: require is not defined

Refers to this (after .pipe(babel()) in gulp)

指的是这个(gulp 中的 .pipe(babel()) 之后)

var _shapes = require('shapes');

回答by Tamas Hegedus

Do I need require js when I use babel?

使用 babel 时是否需要 require js?

You might need some module loader, but it is not necessary RequireJS. You have several options. The following will help you to get started.

你可能需要一些模块加载器,但它不是必需的 RequireJS。您有多种选择。以下内容将帮助您入门。



rollup.jswith rollup-plugin-babel

rollup.jsrollup-plugin-babel

Rollup is a next-generation JavaScript module bundler. It understands ES2015 modules natively, and will produce a bundle that doesn't need any module loader to operate. Unused exports will be trimmed from the output, it's called tree-shaking.

Rollup 是下一代 JavaScript 模块打包器。它本机理解 ES2015 模块,并将生成一个不需要任何模块加载器来操作的包。未使用的导出将从输出中修剪,这称为摇树。

Now I personally recommend using rollupjs, as it produces the clearest output, and is easy to setup, however, it gives a different aspect to the answer. All the other approaches do the following:

现在我个人建议使用 rollupjs,因为它产生最清晰的输出,并且易于设置,但是,它为答案提供了不同的方面。所有其他方法执行以下操作:

  1. Compile the ES6 code with babel, use the module format of your choice
  2. Concatenate the compiled modules alongside with a module loader OR use a bundler that will traverse the dependencies for you.
  1. 用 babel 编译 ES6 代码,使用你选择的模块格式
  2. 将编译后的模块与模块加载器连接在一起,或者使用一个打包器来为你遍历依赖项。

With rollupjs things doesn't really work this way. Here, rollup is the first step, instead of babel. It only understands ES6 modules by default. You must give an entry module of which the dependencies will be traversed and concatenated. As ES6 allows multiple named exports in a module, rollupjs is smart enough to strip unused exports, thus shrinking bundle size. Unfortunately rollupjs-s parser doesn't understand >ES6 syntax, so ES7 modules have to be compiled before rollup parses them, but the compilation should not affect the ES6 imports. It is done by using the rollup-plugin-babelplugin with the babel-preset-es2015-rolluppreset (this preset is the same as the es2015 one, except the module transformer and the external-helpers plugin). So rollup will do the following with your modules if correctly set up:

使用 rollupjs 事情并没有真正以这种方式工作。在这里,rollup 是第一步,而不是 babel。它默认只理解 ES6 模块。您必须提供一个入口模块,其中的依赖项将被遍历和连接。由于 ES6 允许在一个模块中存在多个命名导出,因此 rollupjs 足够聪明,可以去除未使用的导出,从而缩小包的大小。不幸的是,rollupjs-s 解析器不理解 >ES6 语法,所以 ES7 模块必须在 rollup 解析它们之前编译,但编译不应该影响 ES6 导入。它是通过使用rollup-plugin-babel带有babel-preset-es2015-rollup预设的插件来完成的(这个预设与 es2015 相同,除了模块转换器和外部助手插件)。因此,如果正确设置,汇总将对您的模块执行以下操作:

  1. Reads your ES6-7 module from the filesystem
  2. The babel plugin compiles it to ES6 in memory
  3. rollup parses the ES6 code for imports and exports (using acorn parser, compiled into rollup)
  4. it traverses the whole graph, and creates a single bundle (which still might have external dependencies, and the entry's exports might be exported, in a format of your choice)
  1. 从文件系统中读取 ES6-7 模块
  2. babel 插件在内存中编译成 ES6
  3. rollup 解析导入导出的 ES6 代码(使用 acorn 解析器,编译成 rollup)
  4. 它遍历整个图,并创建一个包(它仍然可能具有外部依赖关系,并且可能以您选择的格式导出条目的导出)

Example nodejs build:

示例 nodejs 构建:

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

Example grunt build with grunt-rollup

使用grunt-rollup构建示例 grunt

// 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"]
        }
      }
    }
  });
}

Example gulp build with gulp-rollup

使用gulp-rollup构建示例 gulp

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


Babelify+ Browserify

Babelify+浏览器化

Babel has a neat package called babelify. It's usage is simple and straightforward:

Babel 有一个简洁的包叫做babelify。它的用法简单明了:

$ 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:

或者你可以从 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 transpile and concatenate your code at once. Browserify's .bundlewill include a nice little CommonJS loader, and will organize your transpiled modules into functions. You can even have relative imports.

这将立即转换和连接您的代码。Browserify.bundle将包含一个漂亮的小 CommonJS 加载器,并将您的转换模块组织成函数。你甚至可以有相对导入。

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 just run node build.jsin your project root.

要编译只需node build.js在您的项目根目录中运行。



Babel+ WebPack

Babel+ WebPack

Compile all your code using babel. I recommend you to use the amd module transformer (called babel-plugin-transform-es2015-modules-amdin babel 6). After that bundle your compiled sources with WebPack.

使用 babel 编译所有代码。我建议您使用 amd 模块转换器(babel-plugin-transform-es2015-modules-amd在 babel 6 中调用)。之后,将您编译的源代码与 WebPack 捆绑在一起。

WebPack 2 is out!It understands native ES6 modules, and will perform (or rather simulate) tree shakingusing babili-s builtin dead code elimination. For now (September 2016) I would still suggest to use rollup with babel, although my opinion might change with the first release of WebPack 2. Feel free to discuss your opinions in the comments.

WebPack 2 出来了!它理解原生 ES6 模块,并将使用babili-s 内置死代码消除来执行(或更确切地说模拟)树摇动。目前(2016 年 9 月)我仍然建议使用 rollup 和 babel,尽管我的观点可能会随着 WebPack 2 的第一个版本而改变。请随时在评论中讨论您的意见。



Custom compilation pipeline

自定义编译管道

Sometimes you want to have more control over the compilation process. You can implement your own pipeline like this:

有时您希望对编译过程有更多的控制。您可以像这样实现自己的管道:

First, you have to configure babel to use amd modules. By default babel transpiles to CommonJS modules, which is a little complicated to handle in the browser, although browserify manages to handle them in a nice way.

首先,您必须配置 babel 以使用 amd 模块。默认情况下 babel 转译为 CommonJS 模块,这在浏览器中处理有点复杂,尽管 browserify 设法以一种很好的方式处理它们。

  • Babel 5: use { modules: 'amdStrict', ... }option
  • Babel 6: use the es2015-modules-amdplugin
  • Babel 5:使用{ modules: 'amdStrict', ... }选项
  • Babel 6:使用es2015-modules-amd插件

Don't forget to turn on the moduleIds: trueoption.

不要忘记打开该moduleIds: true选项。

Check the transpiled code for generated modul names, there are often mismatches between defined and required modules. See sourceRoot and moduleRoot.

检查生成的模块名称的转译代码,定义的模块和所需的模块之间经常不匹配。请参阅sourceRoot 和 moduleRoot

Finally, you have to have some kind of module loader, but it isn't necessairy requirejs. There is almondjs, a tiny require shim that works well. You can even implement your own:

最后,你必须有某种模块加载器,但这不是必需的 requirejs。有almondjs,一个运行良好的小需求垫片。您甚至可以实现自己的:

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

At the end, you can just concatenate the loader shim and the compiled modules together, and running an uglify on that.

最后,您可以将加载器 shim 和已编译的模块连接在一起,并在其上运行 uglify。



Babel's boilerplate code is duplicated in every module

Babel 的样板代码在每个模块中都是重复的

By default, most of the above methods compile each module with babel individually, and then concatenate them together. That's what babelify does too. But if you look at the compiled code, you see that babel inserts lots of boilerplate at the beginning of each file, most of them are duplicated across all files.

默认情况下,上述大多数方法都会单独使用 babel 编译每个模块,然后将它们连接在一起。这也是 babelify 所做的。但是如果你查看编译后的代码,你会发现 babel 在每个文件的开头插入了很多样板,其中大部分在所有文件中都是重复的。

To prevent this you can use the babel-plugin-transform-runtimeplugin.

为了防止这种情况,您可以使用babel-plugin-transform-runtime插件。

回答by Isaac Pak

barebones webpack 2

准系统 webpack 2

1) If this is your root directory:

1) 如果这是您的根目录:

index.html

索引.html

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

scripts.js

脚本.js

import { Circle } from './shapes.js';
  ...

shapes.js

形状.js

export class Circle {
  ...
}

2) have node installed node

2)有节点安装节点

3) run the following command in your terminal:

3)在终端中运行以下命令:

$ npm install -g webpack

5) in your root directory run the following:

5) 在您的根目录中运行以下命令:

$ webpack scripts.js bundle.js

You should now have a file called bundle.js in your root directory which will be the file your index.html will consume. This is a minimalistic bundling feature from webpack. You can learn more here

您现在应该在根目录中有一个名为 bundle.js 的文件,该文件将是您的 index.html 将使用的文件。这是 webpack 的一个极简捆绑功能。你可以在这里了解更多

回答by djechlin

requiredoes not exist in the browser, so this error is expected. You need to use something like require.js or Browserify.

require浏览器中不存在,因此会出现此错误。你需要使用 require.js 或 Browserify 之类的东西。