【问题标题】:Native support for ES6 in PhantomJSPhantomJS 中对 ES6 的原生支持
【发布时间】:2016-01-20 14:20:24
【问题描述】:

有没有办法让 PhantomJS 原生支持 ES6,我有一堆 ES6 代码通过 Babel 转换为 ES5,我需要完成的是对 ES6 代码而不是 ES5 的代码覆盖率的准确测量。这是客户的要求,所以我不能告诉他停止要求这样的事情......

Afaik NodeJS 已经原生支持 ES6,有没有办法用 PhantomJS 做到这一点?

【问题讨论】:

  • 我认为使用 PhantomJS 2 可以更轻松地使用更新的 WebKit 版本,这可能还有很多工作要做。祝你好运。使用已经支持 ES6 的浏览器可能更容易。
  • Babel 也可以在旧系统上运行。 Phantom 失败的原因是什么?听起来您在问两个问题: 1. 如何填充 Phantom? 2. 如何获得 ES6 代码的覆盖率?
  • 它为代码覆盖提供了错误的视角,当使用 babel 时,代码覆盖的结果是为 ES5 调用生成的......
  • 您使用什么工具进行覆盖?
  • 本来打算用istanbul,应该支持es6

标签: phantomjs code-coverage ecmascript-6 babeljs


【解决方案1】:

我最终使用了原始 NodeJS(没有 PhantomJs)+ Express + JSDom (https://github.com/tmpvar/jsdom),POC 看起来像这样:

"use strict"

const $module = require('module');
const path = require('path');
const babel = require("babel-core");
const Jasmine = require('jasmine');
const reporters = require('jasmine-reporters');
const express = require('express');
const jsdom = require("jsdom");
const app = express();
const vm = require('vm');
const fs = require("fs");

app.get('/', function (req, res) {
    res.sendFile('index.html', { root: __dirname });
});

app.use('/bower_components', express.static('bower_components'));

const load = function (filename) {
    return fs.readFileSync(`./bower_components/${filename}`, "utf-8");
};

const packages = [
    fs.readFileSync('./bower_components/jquery/dist/jquery.js', "utf-8"),
    fs.readFileSync('./bower_components/angular/angular.js', "utf-8"),
    fs.readFileSync('./bower_components/angular-mocks/angular-mocks.js', "utf-8")
];

const sut = {
    './js/code.js': fs.readFileSync('./js/code.js', "utf-8")
};

const tests = {
    './tests/test.js': fs.readFileSync('./tests/test.js', "utf-8")
};

function navigate(FakeFileSystem, root, cwd, filename) {
    // Normalize path according to root
    let relative  = path.relative(root, path.resolve(root, cwd, filename));
    let parts = relative.split(path.sep);
    let iterator = FakeFileSystem;

    for (let part of parts) {
        iterator = iterator[part] || (iterator[part] = { });
    }

    return iterator;
}

const server = app.listen(3333, function () {
    const host = server.address().address;
    const port = server.address().port;

    const url = `http://${host === '::' ? 'localhost' : host}:${port}`;

    console.log(`Server launched at ${ url }`);
    console.log(`Running tests...`)

    jsdom.env({
        url: url,
        src: packages,
        done: function (err, window) {
            let jasmine = new Jasmine();

            let FakeFileSystem = {};

            let descriptors = [];

            jasmine.configureDefaultReporter({ showColors: true });

            let env = jasmine.env;

            for (let propertyName in env) {
                if (env.hasOwnProperty(propertyName)) {
                    window[propertyName] = env[propertyName];
                }
            }

            let context = vm.createContext(window);
            let collections = [sut, tests];

            for (let collection of collections) {
                for (let filename in collection) {
                    let descriptor = navigate(FakeFileSystem, __dirname, '.', filename);
                    let source = collection[filename];
                    let transpiled = babel.transform(source, { "plugins": ["transform-es2015-modules-commonjs"] });
                    let code = $module.wrap(transpiled.code);

                    let _exports = {};
                    let _module = { exports: _exports };

                    descriptor.code = vm.runInContext(code, context);
                    descriptor.module = _module;
                    descriptor.exports = _exports;
                    descriptor.filename = filename;

                    descriptors.push(descriptor);
                }
            }

            for (let descriptor of descriptors) {
                let cwd = path.dirname(path.relative(__dirname, descriptor.filename));

                descriptor.code.call(
                    undefined,
                    descriptor.exports,

                    // Closure is used to capture cwd
                    (function (cwd) {
                        return function (filename) { // Fake require function
                            return navigate(FakeFileSystem, __dirname, cwd, filename).exports;
                        }
                    })(cwd),

                    descriptor.module,
                    descriptor.filename
                );
            }

            jasmine.execute();

            server.close();
        }
    });
});

这种方法的美妙之处在于不需要使用 babel 转译代码,它允许 Angular 等前端包从 bower 加载,而所有配置内容都来自 npm...

编辑

我偶然发现 NodeJS 还不支持所有 ES6 特性,而且像 ES6 模块这样的特性真的很痛苦,它们在任何地方都不受支持,所以我最终做了部分翻译使用 babel 编写代码,期望随着 NodeJS 开始为 ES6 提供越来越丰富的支持,我最终将逐步关闭 babel 功能,并在可用时切换到原生支持...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-23
    • 2017-02-15
    • 2020-06-07
    • 1970-01-01
    • 2011-04-03
    • 2020-02-11
    相关资源
    最近更新 更多