为什么 babeljs.io 输出与 gulp-babel 输出不同?
Why is babeljs.io output different than gulp-babel output?
背景
我正在尝试将我的 ES6 js 转换为 ES5 js。当我访问 https://babeljs.io/repl 网页以测试 babel 应该为预设选项 es2015
输出什么时,它输出 JavaScript 与 gulp-babel
输出不同。
输入ES6 JavaScript
// eslint-disable-next-line no-unused-vars
function getStars() {
// Round the number like "3.5k"
const round = num => (num > 999 ? `${(num / 1000).toFixed(1)}k` : num);
// Add the most recent star count to the repositories.
// eslint-disable-next-line no-undef
document.querySelectorAll('.repositories .repo a').forEach(async (a) => {
const link = a;
const name = link.getAttribute('href').split('/').slice(-2).join('/');
const url = `https://api.github.com/repos/${name}`;
const { starGazersCount } = await fetch(url).then(res => res.json());
if (!starGazersCount) return;
link.querySelector('.stars').innerText = `${'⭐️ '}${round(starGazersCount)}`;
});
}
babeljs.io
输出 ~期望的输出~
'use strict';
// eslint-disable-next-line no-unused-vars
function getStars() {
// Round the number like "3.5k"
var round = function round(num) {
return num > 999 ? (num / 1000).toFixed(1) + 'k' : num;
};
// Add the most recent star count to the repositories.
// eslint-disable-next-line no-undef
document.querySelectorAll('.repositories .repo a').forEach(async function (a) {
var link = a;
var name = link.getAttribute('href').split('/').slice(-2).join('/');
var url = 'https://api.github.com/repos/' + name;
var _ref = await fetch(url).then(function (res) {
return res.json();
}),
starGazersCount = _ref.starGazersCount;
if (!starGazersCount) return;
link.querySelector('.stars').innerText = '⭐️ ' + round(starGazersCount);
});
}
gulp-babel
输出
"use strict";
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
(function () {
function r(e, n, t) {
function o(i, f) {
if (!n[i]) {
if (!e[i]) {
var c = "function" == typeof require && require;
if (!f && c) return c(i, !0);
if (u) return u(i, !0);
var a = new Error("Cannot find module '" + i + "'");
throw a.code = "MODULE_NOT_FOUND", a;
}
var p = n[i] = {
exports: {}
};
e[i][0].call(p.exports, function (r) {
var n = e[i][1][r];
return o(n || r);
}, p, p.exports, r, e, n, t);
}
return n[i].exports;
}
for (var u = "function" == typeof require && require, i = 0; i < t.length; i++) {
o(t[i]);
}
return o;
}
return r;
})()({
1: [function (require, module, exports) {
// eslint-disable-next-line no-unused-vars
function getStars() {
// Round the number like "3.5k"
var round = function round(num) {
return num > 999 ? "".concat((num / 1000).toFixed(1), "k") : num;
}; // Add the most recent star count to the repositories.
// eslint-disable-next-line no-undef
document.querySelectorAll('.repositories .repo a').forEach(
/*#__PURE__*/
function () {
var _ref = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee(a) {
var link, name, url, _ref2, starGazersCount;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
link = a;
name = link.getAttribute('href').split('/').slice(-2).join('/');
url = "https://api.github.com/repos/".concat(name);
_context.next = 5;
return fetch(url).then(function (res) {
return res.json();
});
case 5:
_ref2 = _context.sent;
starGazersCount = _ref2.starGazersCount;
if (starGazersCount) {
_context.next = 9;
break;
}
return _context.abrupt("return");
case 9:
link.querySelector('.stars').innerText = '⭐️ '.concat(round(starGazersCount));
case 10:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
return function (_x) {
return _ref.apply(this, arguments);
};
}());
}
}, {}]
}, {}, [1]);
⚠️注意 gulp-babel
输出如何包含 polyfill 函数,例如 _asyncToGenerator
& asyncGeneratorStep
.
为什么在线babel编辑器在使用es2015
预设时不输出这个?
其他有用的文件
下面是我的.babelrc
:
{
"presets": [
"@babel/preset-env"
]
}
下面是我的package.json
:
{
"devDependencies": {
"@babel/core": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"babel-eslint": "^10.0.1",
"babel-preset-env": "^1.7.0",
"bower": "^1.8.2",
"eslint-config-standard": "^12.0.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-node": "^8.0.0",
"eslint-plugin-promise": "^4.0.1",
"eslint-plugin-standard": "^4.0.0",
"gulp-babel": "^8.0.0",
"gulp-changed": "^3.2.0",
"gulp-cssnano": "^2.1.2",
"gulp-error-handle": "^1.0.0",
"gulp-eslint": "^5.0.0",
"gulp-gh-pages": "^0.5.4",
"gulp-htmlmin": "^5.0.1",
"gulp-imagemin": "^5.0.3",
"gulp-include": "^2.3.1",
"gulp-notify": "^3.2.0",
"gulp-plumber": "^1.1.0",
"gulp-postcss": "^8.0.0",
"gulp-pug": "^4.0.1",
"gulp-rename": "^1.2.2",
"gulp-sass": "*",
"gulp-size": "^3.0.0",
"gulp-sourcemaps": "^2.6.*",
"gulp-strip-css-comments": "^2.0.0",
"gulp-strip-debug": "^3.0.0",
"gulp-surge": "^0.1.0",
"gulp-terser": "^1.1.5",
"gulp-util": "^3.0.8",
"localtunnel": "^1.8.3",
"main-bower-files": "^2.13.1",
"path": "^0.12.7",
"postcss-cli": "^6.0.1",
"run-sequence": "^2.2.1",
"yarn": "^1.12.3"
},
"dependencies": {
"animate.css": "latest",
"argv": "^0.0.2",
"autoprefixer": "^9.3.1",
"babel-polyfill": "^6.26.0",
"browser-sync": "^2.18.13",
"browserify": "^16.2.3",
"bulma": "latest",
"del": "^3.0.0",
"gulp": "^3.9.1",
"gulp-load-plugins": "^1.5.0",
"hamburgers": "latest",
"hover": "latest",
"imagemin-pngquant": "^6.0.0",
"isinviewport": "latest",
"jquery": "latest",
"lost": "^8.2.0",
"minimist": "^1.2.0",
"moment": "^2.22.2",
"node-bourbon": "^4.2.8",
"node-neat": "^2.0.0-beta.0",
"psi": "^3.1.0",
"require-dir": "^1.1.0",
"rucksack-css": "^1.0.2",
"vanilla-lazyload": "latest",
"vinyl-buffer": "^1.0.1",
"vinyl-ftp": "^0.6.0",
"vinyl-source-stream": "^2.0.0"
}
}
下面是我 js
的 gulp
任务:
'use-strict';
const gulp = require('gulp');
const $ = require('gulp-load-plugins')({ lazy: true });
const browserify = require('browserify');
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');
const paths = require('../../paths.js');
const config = require('../../config.js')();
gulp.task('eslint', () => {
console.log('-> Running eslint');
// Select files
gulp.src(`${paths.to.js.in}/**/*.js`)
// Prevent pipe breaking caused by errors from gulp plugins
.pipe($.plumber())
// Check for lint errors
.pipe($.eslint())
// eslint.format() outputs the lint results to the console.
// Alternatively use eslint.formatEach() (see Docs).
.pipe($.eslint.format())
// To have the process exit with an error code (1) on
// lint error, return the stream and pipe to failAfterError last.
.pipe($.eslint.failAfterError());
});
gulp.task('js', ['eslint'], () => {
const env = ((config.environment || process.env.NODE_ENV || 'development').trim().toLowerCase() !== 'production');
console.log(`-> Compiling JavaScript for ${config.environment}`);
// Obtain a readable stream containing the processed browserified bundle
const bundle = browserify({
entries: paths.to.js.in,
debug: env,
})
.bundle()
// Convert browserify stream to a gulp-readable steam & buffer
.pipe(source(config.js.name))
.pipe(buffer());
if (env) {
// Select bundle
bundle
// Initialize sourcemaps
.pipe($.sourcemaps.init())
// Prevent pipe breaking caused by errors from gulp plugins
.pipe($.plumber())
// Concatenate includes
.pipe($.include({
includePaths: [`${paths.to.js.in}`],
}))
// Transpile
.pipe($.babel())
// Catch errors
.pipe($.errorHandle())
// Save sourcemaps
.pipe($.sourcemaps.write('.'))
// Save unminified file
.pipe(gulp.dest(`${paths.to.js.out}`));
} else {
// Select bundle
bundle
// Prevent pipe breaking caused by errors from gulp plugins
.pipe($.plumber())
// Concatenate includes
.pipe($.include({
includePaths: [`${paths.to.js.in}`],
}))
// Transpile
.pipe($.babel())
// Catch errors
.pipe($.errorHandle())
// Show file-size before compression
.pipe($.size({ title: 'Javascript In Size' }))
// Optimize and minify
.pipe($.terser())
// Show file-size after compression
.pipe($.size({ title: 'Javascript Out Size' }))
// Append suffix
.pipe($.rename({
suffix: '.min',
}))
// Save minified file
.pipe(gulp.dest(`${paths.to.js.out}`));
}
});
@babel/preset-env
与 @babel/preset-es2015
不同 - 前者根据您的目标浏览器兼容性指标打开和关闭插件 (which you can customize).
文档说如果您没有在预设的配置中明确指定目标,将使用以下默认值:
Sidenote, if no targets are specified, @babel/preset-env
behaves exactly the same as @babel/preset-es2015
, @babel/preset-es2016
and @babel/preset-es2017
together (or the deprecated babel-preset-latest
).
另一方面,@babel/preset-es2015
单独将 仅 编译 ES2015 版本规范中添加的功能。这不包括较新的功能,例如 async/await!如果您想要添加此后的所有功能,则必须添加 all 年度预设。因此,建议您使用 env
预设。
如果您将 https://babeljs.io 切换到 @babel/preset-env
预设(这是年度预设列表下方的一个单独部分),您将获得相同的输出。
背景
我正在尝试将我的 ES6 js 转换为 ES5 js。当我访问 https://babeljs.io/repl 网页以测试 babel 应该为预设选项 es2015
输出什么时,它输出 JavaScript 与 gulp-babel
输出不同。
输入ES6 JavaScript
// eslint-disable-next-line no-unused-vars
function getStars() {
// Round the number like "3.5k"
const round = num => (num > 999 ? `${(num / 1000).toFixed(1)}k` : num);
// Add the most recent star count to the repositories.
// eslint-disable-next-line no-undef
document.querySelectorAll('.repositories .repo a').forEach(async (a) => {
const link = a;
const name = link.getAttribute('href').split('/').slice(-2).join('/');
const url = `https://api.github.com/repos/${name}`;
const { starGazersCount } = await fetch(url).then(res => res.json());
if (!starGazersCount) return;
link.querySelector('.stars').innerText = `${'⭐️ '}${round(starGazersCount)}`;
});
}
babeljs.io
输出 ~期望的输出~
'use strict';
// eslint-disable-next-line no-unused-vars
function getStars() {
// Round the number like "3.5k"
var round = function round(num) {
return num > 999 ? (num / 1000).toFixed(1) + 'k' : num;
};
// Add the most recent star count to the repositories.
// eslint-disable-next-line no-undef
document.querySelectorAll('.repositories .repo a').forEach(async function (a) {
var link = a;
var name = link.getAttribute('href').split('/').slice(-2).join('/');
var url = 'https://api.github.com/repos/' + name;
var _ref = await fetch(url).then(function (res) {
return res.json();
}),
starGazersCount = _ref.starGazersCount;
if (!starGazersCount) return;
link.querySelector('.stars').innerText = '⭐️ ' + round(starGazersCount);
});
}
gulp-babel
输出
"use strict";
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
(function () {
function r(e, n, t) {
function o(i, f) {
if (!n[i]) {
if (!e[i]) {
var c = "function" == typeof require && require;
if (!f && c) return c(i, !0);
if (u) return u(i, !0);
var a = new Error("Cannot find module '" + i + "'");
throw a.code = "MODULE_NOT_FOUND", a;
}
var p = n[i] = {
exports: {}
};
e[i][0].call(p.exports, function (r) {
var n = e[i][1][r];
return o(n || r);
}, p, p.exports, r, e, n, t);
}
return n[i].exports;
}
for (var u = "function" == typeof require && require, i = 0; i < t.length; i++) {
o(t[i]);
}
return o;
}
return r;
})()({
1: [function (require, module, exports) {
// eslint-disable-next-line no-unused-vars
function getStars() {
// Round the number like "3.5k"
var round = function round(num) {
return num > 999 ? "".concat((num / 1000).toFixed(1), "k") : num;
}; // Add the most recent star count to the repositories.
// eslint-disable-next-line no-undef
document.querySelectorAll('.repositories .repo a').forEach(
/*#__PURE__*/
function () {
var _ref = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee(a) {
var link, name, url, _ref2, starGazersCount;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
link = a;
name = link.getAttribute('href').split('/').slice(-2).join('/');
url = "https://api.github.com/repos/".concat(name);
_context.next = 5;
return fetch(url).then(function (res) {
return res.json();
});
case 5:
_ref2 = _context.sent;
starGazersCount = _ref2.starGazersCount;
if (starGazersCount) {
_context.next = 9;
break;
}
return _context.abrupt("return");
case 9:
link.querySelector('.stars').innerText = '⭐️ '.concat(round(starGazersCount));
case 10:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
return function (_x) {
return _ref.apply(this, arguments);
};
}());
}
}, {}]
}, {}, [1]);
⚠️注意 gulp-babel
输出如何包含 polyfill 函数,例如 _asyncToGenerator
& asyncGeneratorStep
.
为什么在线babel编辑器在使用es2015
预设时不输出这个?
其他有用的文件
下面是我的.babelrc
:
{
"presets": [
"@babel/preset-env"
]
}
下面是我的package.json
:
{
"devDependencies": {
"@babel/core": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"babel-eslint": "^10.0.1",
"babel-preset-env": "^1.7.0",
"bower": "^1.8.2",
"eslint-config-standard": "^12.0.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-node": "^8.0.0",
"eslint-plugin-promise": "^4.0.1",
"eslint-plugin-standard": "^4.0.0",
"gulp-babel": "^8.0.0",
"gulp-changed": "^3.2.0",
"gulp-cssnano": "^2.1.2",
"gulp-error-handle": "^1.0.0",
"gulp-eslint": "^5.0.0",
"gulp-gh-pages": "^0.5.4",
"gulp-htmlmin": "^5.0.1",
"gulp-imagemin": "^5.0.3",
"gulp-include": "^2.3.1",
"gulp-notify": "^3.2.0",
"gulp-plumber": "^1.1.0",
"gulp-postcss": "^8.0.0",
"gulp-pug": "^4.0.1",
"gulp-rename": "^1.2.2",
"gulp-sass": "*",
"gulp-size": "^3.0.0",
"gulp-sourcemaps": "^2.6.*",
"gulp-strip-css-comments": "^2.0.0",
"gulp-strip-debug": "^3.0.0",
"gulp-surge": "^0.1.0",
"gulp-terser": "^1.1.5",
"gulp-util": "^3.0.8",
"localtunnel": "^1.8.3",
"main-bower-files": "^2.13.1",
"path": "^0.12.7",
"postcss-cli": "^6.0.1",
"run-sequence": "^2.2.1",
"yarn": "^1.12.3"
},
"dependencies": {
"animate.css": "latest",
"argv": "^0.0.2",
"autoprefixer": "^9.3.1",
"babel-polyfill": "^6.26.0",
"browser-sync": "^2.18.13",
"browserify": "^16.2.3",
"bulma": "latest",
"del": "^3.0.0",
"gulp": "^3.9.1",
"gulp-load-plugins": "^1.5.0",
"hamburgers": "latest",
"hover": "latest",
"imagemin-pngquant": "^6.0.0",
"isinviewport": "latest",
"jquery": "latest",
"lost": "^8.2.0",
"minimist": "^1.2.0",
"moment": "^2.22.2",
"node-bourbon": "^4.2.8",
"node-neat": "^2.0.0-beta.0",
"psi": "^3.1.0",
"require-dir": "^1.1.0",
"rucksack-css": "^1.0.2",
"vanilla-lazyload": "latest",
"vinyl-buffer": "^1.0.1",
"vinyl-ftp": "^0.6.0",
"vinyl-source-stream": "^2.0.0"
}
}
下面是我 js
的 gulp
任务:
'use-strict';
const gulp = require('gulp');
const $ = require('gulp-load-plugins')({ lazy: true });
const browserify = require('browserify');
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');
const paths = require('../../paths.js');
const config = require('../../config.js')();
gulp.task('eslint', () => {
console.log('-> Running eslint');
// Select files
gulp.src(`${paths.to.js.in}/**/*.js`)
// Prevent pipe breaking caused by errors from gulp plugins
.pipe($.plumber())
// Check for lint errors
.pipe($.eslint())
// eslint.format() outputs the lint results to the console.
// Alternatively use eslint.formatEach() (see Docs).
.pipe($.eslint.format())
// To have the process exit with an error code (1) on
// lint error, return the stream and pipe to failAfterError last.
.pipe($.eslint.failAfterError());
});
gulp.task('js', ['eslint'], () => {
const env = ((config.environment || process.env.NODE_ENV || 'development').trim().toLowerCase() !== 'production');
console.log(`-> Compiling JavaScript for ${config.environment}`);
// Obtain a readable stream containing the processed browserified bundle
const bundle = browserify({
entries: paths.to.js.in,
debug: env,
})
.bundle()
// Convert browserify stream to a gulp-readable steam & buffer
.pipe(source(config.js.name))
.pipe(buffer());
if (env) {
// Select bundle
bundle
// Initialize sourcemaps
.pipe($.sourcemaps.init())
// Prevent pipe breaking caused by errors from gulp plugins
.pipe($.plumber())
// Concatenate includes
.pipe($.include({
includePaths: [`${paths.to.js.in}`],
}))
// Transpile
.pipe($.babel())
// Catch errors
.pipe($.errorHandle())
// Save sourcemaps
.pipe($.sourcemaps.write('.'))
// Save unminified file
.pipe(gulp.dest(`${paths.to.js.out}`));
} else {
// Select bundle
bundle
// Prevent pipe breaking caused by errors from gulp plugins
.pipe($.plumber())
// Concatenate includes
.pipe($.include({
includePaths: [`${paths.to.js.in}`],
}))
// Transpile
.pipe($.babel())
// Catch errors
.pipe($.errorHandle())
// Show file-size before compression
.pipe($.size({ title: 'Javascript In Size' }))
// Optimize and minify
.pipe($.terser())
// Show file-size after compression
.pipe($.size({ title: 'Javascript Out Size' }))
// Append suffix
.pipe($.rename({
suffix: '.min',
}))
// Save minified file
.pipe(gulp.dest(`${paths.to.js.out}`));
}
});
@babel/preset-env
与 @babel/preset-es2015
不同 - 前者根据您的目标浏览器兼容性指标打开和关闭插件 (which you can customize).
文档说如果您没有在预设的配置中明确指定目标,将使用以下默认值:
另一方面,Sidenote, if no targets are specified,
@babel/preset-env
behaves exactly the same as@babel/preset-es2015
,@babel/preset-es2016
and@babel/preset-es2017
together (or the deprecatedbabel-preset-latest
).
@babel/preset-es2015
单独将 仅 编译 ES2015 版本规范中添加的功能。这不包括较新的功能,例如 async/await!如果您想要添加此后的所有功能,则必须添加 all 年度预设。因此,建议您使用 env
预设。
如果您将 https://babeljs.io 切换到 @babel/preset-env
预设(这是年度预设列表下方的一个单独部分),您将获得相同的输出。