View on GitHub

Yinjie - GitHub.io

Welcome to the Yinjie's notes

nodejs V6 不能用 import/export 完美解决方法

nodejs 发布已有多时,版本 log 重点说明从此 nodejs 开始原生支持 ES6,这让许多开发者都 happy 了一下。

笔者立刻将原来的一个小 server 框架改成 ES6 语法,但是:

不支持 import

WTF!~~~说好的全部原生支持呢?import / export各种报错,加了--es_staging,也不行,人与人之前的信任呢?

回头再查查版本 log ,Modules 那一章还是 commonjs 的引用方法,网上其它人也说这个问题,那就是妥妥的不支持了。

测试文件如下:


    'use strict';
    class Main {
        constructor() {
            this.parent = 'this is parent msg';
        }

        say() {
            setTimeout(() => {
                console.log(this.parent);
            }, 500);
        }
    }

    export default Main;

简单暴力(没)有成效的解决方法

“不支持 ES6 就用 babel 转换呗~” 大多数人都是这样想的。将完全体的 ES6 通过 babel 降级转换~~~然后就 OK 了。node 运行各种顺利。

标签 es2015 转换后:

    'use strict';

    Object.defineProperty(exports, "__esModule", {
        value: true
    });

    var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

    function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

    var Main = function () {
        function Main() {
            _classCallCheck(this, Main);

            this.parent = 'this is parent msg';
        }

        _createClass(Main, [{
            key: 'say',
            value: function say() {
                var _this = this;

                setTimeout(function () {
                    console.log(_this.parent);
                }, 500);
            }
        }]);

        return Main;
    }();

    exports.default = Main;
    //# sourceMappingURL=main.js.map

……

我差点也就中了。

看着 node V6 对其它各种 es6 特性都支持的很好,真不想经转换后一下回到解放前。

注: 其实上面一句并不是真正原因啦,node 的原生支持并不是简单暴力的内置了一个 babel,是在整个内核运行机制上进行改进,尽可能符合 es6 的语言思想。 在执行流程、内存管理上都有优化。网上有不少原生 es6 运行性能的对比,有兴趣可以去看一下。

经笔者测试,以最新的 6.4 为例,好像只有 import / export 不能支持,因此,笔者试着找一下只对此进行降级转换的方法。

针对性的 babel 降级转换

通过查看 babel 的插件列表 http://babeljs.io/docs/plugins/;

babel 插件;

其中在 Modules 有一个 es2015_modules_commonjs,应该就是将 ES6 Modules 转换成 nodejs 通用的 commonjs 形式的。

立刻试用,.babelrc 文件如下:

    {
        "plugins": [
            "transform-es2015-modules-commonjs"
        ]
    }

如此经过转换后的文件:

    'use strict';

    Object.defineProperty(exports, "__esModule", {
        value: true
    });
    class Main {
        constructor() {
            this.parent = 'this is parent msg';
        }

        say() {
            setTimeout(() => {
                console.log(this.parent);
            }, 500);
        }
    }

    exports.default = Main;
    //# sourceMappingURL=main.js.map

执行通过 perfect!!! 要得就是这个效果。而且因为转换程度不深,速度也差不多减少了 2/3。

总结

如上只是一个经历,相信随着 nodejs 的不断发展,完美支持 es6 也是迟早的事。但新语法、新事物肯定也会随之出现,我们需要的是一个“增量式”的转换,希望对以后处理此类问题有所启发。