Dynamic execution of TypeScript in the browser

2019-02-20 05:09发布

问题:

I have TypeScript which asynchronously downloads another TypeScript/javascript module:

(function (exports) {
    "use strict";

    var path = require('path');

    exports.convertData = function (data) {
        return "converted " + data;
    }

})(typeof exports === 'undefined' ? this['converter.someConverter'] = {} : exports);

During execution of my main app I receives this module as string and I have to use function convertData from there.

So, I'm trying the following:

eval(rendererScript);
console.log(exports.convertData("some data"));

It works well only in case if var path = require('path'); will be removed. Otherwise, the following error: Uncaught (in promise) Error: Module name "path" has not been loaded yet for context: _. Use require([])

Questions:

  1. Is it OK to use eval() in this case? (as we know eval is evil)
  2. How to be with require('path')? I'm trying to use RequireJS (http://requirejs.org/docs/node.html#2) but receiving the following error: Uncaught Error: Script error for "path"

Edited

So, in order to avoid eval() the following solution was found:

const scriptTag = document.createElement("script");
scriptTag.innerHTML = rendererScript;
document.body.appendChild(scriptTag);
this.m_rendererPlugin = (window as any)[`converter.someConverter`];

回答1:

Since in your case the input code is dynamic you need to compile at runtime probably using TypeScript compiler API. In the case you don't have a dedicated server for that, you can still compile TS projects in the browser using the TypeScript compiler API https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API .

  • here you have a playground for transpiling ts to js 100% in the browser https://cancerberosgx.github.io/typescript-in-the-browser/typescript-compiler/#example=tsTranspilingProject1

  • you could also use ts-simple-ast library also in the browser that's better documented and more easy to use - https://cancerberosgx.github.io/typescript-in-the-browser/typescript-compiler/#example=tsSimpleAst1

For transpiling, again, you don't have to do anything but to include node_modules/typescript/typescript.js in your html and you are done. But for more complex APIs like type checking and Language Service API (https://github.com/Microsoft/TypeScript/wiki/Writing-a-Language-Service-Plugin) you will need to implement some interfaces.