简体   繁体   English

在 Google Apps Script => ReferenceError 中使用转译的 ES6:未定义“SomeClass”

[英]Using transpiled ES6 in Google Apps Script => ReferenceError: "SomeClass" is not defined

I'm trying to use ES6 in a Google Spreadsheet (in the script.google.com part).我正在尝试在 Google 电子表格(在 script.google.com 部分)中使用 ES6。 I'm pretty new to JavaScript and maybe the error is trivial ...我对 JavaScript 还很陌生,也许这个错误是微不足道的......


  • 28/09: The error for the post as changed as I was just using a Google Apps Script library name (Logger), I switch to SomeClass . 28/09:由于我只是使用 Google Apps 脚本库名称(Logger),帖子的错误发生了变化,我切换到SomeClass I'm looking to module as my declaration is not the good one我正在寻找模块,因为我的声明不是好的

What I have done:我做了什么:

  • Created a webpack project创建了一个 webpack 项目
  • Created a Logger class创建了一个记录器类
  • Created a main.js where I import the Logger class创建了一个 main.js,我在其中导入了 Logger 类
  • WebPack generate a bundle from my main.js WebPack 从我的 main.js 生成一个包
  • I copy/paste the bundle.js in a bundle file on script.google我将 bundle.js 复制/粘贴到 script.google 上的捆绑文件中
  • I try to run a test in script.google but got ReferenceError: SomeClass is not define.`我尝试在 script.google 中运行测试,但得到了ReferenceError: SomeClass is not define.`

Here is my code:这是我的代码:

SomeClass.js SomeClass.js

export default class SomeClass {
    constructor() {
        this.loggerSheet = SpreadsheetApp.getActiveSpreadsheet()
                                    .getSheetByName("ImportLog");
    }

    LogInfo(data) {
      Logger.log(data);
      loggerSheet.appendRow([new Date(), "INFO", data]);
    }
}

Main.js主程序

import SomeClass from './SomeClass.js';

Test in script.google在 script.google 中测试

function test_bundle() {
  var someClass = new SomeClass(); //<== breaks here
}

Bundle.js => copy/paste to script.google Bundle.js => 复制/粘贴到 script.google

/******/ (function(modules) { // webpackBootstrap
/******/    // The module cache
/******/    var installedModules = {};

/******/    // The require function
/******/    function __webpack_require__(moduleId) {

/******/        // Check if module is in cache
/******/        if(installedModules[moduleId])
/******/            return installedModules[moduleId].exports;

/******/        // Create a new module (and put it into the cache)
/******/        var module = installedModules[moduleId] = {
/******/            exports: {},
/******/            id: moduleId,
/******/            loaded: false
/******/        };

/******/        // Execute the module function
/******/        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/        // Flag the module as loaded
/******/        module.loaded = true;

/******/        // Return the exports of the module
/******/        return module.exports;
/******/    }


/******/    // expose the modules object (__webpack_modules__)
/******/    __webpack_require__.m = modules;

/******/    // expose the module cache
/******/    __webpack_require__.c = installedModules;

/******/    // __webpack_public_path__
/******/    __webpack_require__.p = "";

/******/    // Load entry module and return exports
/******/    return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

    'use strict';

    function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

    var _SomeClassJs = __webpack_require__(4);

    var _SomeClassJs2 = _interopRequireDefault(_SomeClassJs);

/***/ },
/* 1 */,
/* 2 */,
/* 3 */,
/* 4 */
/***/ function(module, exports) {

    "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 SomeClass = (function () {
        function SomeClass(option) {
            _classCallCheck(this, SomeClass);

            this.loggerSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("ImportLog");
        }

        _createClass(SomeClass, [{
            key: "logInfo",
            value: function logInfo(data) {
                loggerSheet.appendRow([new Date(), "INFO", data]);
            }
        }]);

        return SomeClass;
    })();

    exports["default"] = SomeClass;
    module.exports = exports["default"];

/***/ }
/******/ ]);

So I've been playing with this for a while now;所以我已经玩了一段时间了; using transpiled ES6 (even ES7/next features) in GAS.在 GAS 中使用转译的 ES6(甚至 ES7/next 特性)。 The main hurdle you need to overcome is exposing the functions in the modules to the global scope.您需要克服的主要障碍是将模块中的函数暴露给全局范围。

In browsers this could be window , or document .在浏览器中,这可能是windowdocument In GAS there is no such global.在 GAS 中没有这样的全局。 What I've tagged it to is the this context in the main Code.gs .我将它标记为主Code.gsthis上下文。

Webpack allows you to build stand alone modules to distribute libraries, etc. This is the link to the Webpack docs that covers changing the output module type . Webpack 允许您构建独立模块以分发库等。 这是 Webpack 文档的链接,该文档涵盖了更改输出模块类型

output: {
    libraryTarget: "this",
    path: __dirname + '/dist',
    filename: 'Code.gs'
},

This is what your output config should look like.这就是您的输出配置应该是什么样子。

You should then export functions from your main .js file to have them attach to the global context, like so:然后,您应该从主.js文件中导出函数以将它们附加到全局上下文,如下所示:

export function onInstall(e) {
  onOpen(e);
}

From here you should copy and paste the script as you normally would into the GAS Script Editor and have it run the onInstall function to give it access to your drive/sheets/etc.从这里,您应该像往常一样将脚本复制并粘贴到 GAS 脚本编辑器中,并让它运行onInstall函数以使其访问您的驱动器/工作表/等。

Hope this helps!希望这可以帮助!

I tried several of the suggested ways mentioned above.我尝试了上面提到的几种建议方法。 However, utilizing this plugin with webpack 2.X is the only thing that worked for me.然而,在 webpack 2.X 中使用这个插件是唯一对我有用的东西。

https://github.com/fossamagna/gas-webpack-plugin https://github.com/fossamagna/gas-webpack-plugin

Please Note: This does not yet work with webpack 4.X.请注意:这还不适用于 webpack 4.X。

I could regurgitate their Readme.md here, but I find that unnecessary.我可以在这里反省他们的 Readme.md,但我觉得这是不必要的。

In a nutshell you need to add this plugin to your webpack config and then add functions to global .简而言之,您需要将此插件添加到您的 webpack 配置中,然后将函数添加到global These functions get added as top level functions.这些函数被添加为顶级函数。

Update as on 2018: 2018 年更新:

If you are craving for modern Javascript within GAS, you can either use Webpack as described by James or if you are comfortable using Typescript , you can use clasp for this.如果您渴望在 GAS 中使用现代 Javascript,您可以按照 James 的描述使用 Webpack,或者如果您习惯使用Typescript ,您可以使用clasp

Clasp is an official GAS deployment toolkit that lets you to develop your Apps Script projects locally and deploy it to Apps Script when you're done. Clasp 是官方的 GAS 部署工具包,可让您在本地开发 Apps Script 项目,并在完成后将其部署到 Apps Script。 Since the code is local, you can use your favorite IDE and development tools like git when building Apps Script projects.由于代码是本地的,您可以在构建 Apps Script 项目时使用您喜欢的 IDE 和开发工具,例如 git。

As I told in the comments, GAS isn't your everyday Javascript, to overcome that error you can create a Global Var 'SomeClass', then remove the var keyword before the function you declare inside the main function.正如我在评论中所说,GAS 不是您日常使用的 Javascript,要克服该错误,您可以创建一个全局变量“SomeClass”,然后在您在主函数中声明的函数之前删除var关键字。 This will get rid of this error, but another one will arise.这将消除此错误,但会出现另一个错误。

What's your final goal with this webpack?你对这个 webpack 的最终目标是什么? Why it's important within GAS?为什么它在 GAS 中很重要?

使用新的 Apps Script v8 运行时,您可以通过在appsscript.json文件中设置"runtimeVersion": "V8"来使用现代 javascript 而无需任何转换。

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

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