How to invoke a javascript function (generated from typescript) trapped within “System.register()” module while using Google protobuf?

后端 未结 1 1312
无人及你
无人及你 2021-01-14 11:08

Update: It seems that, the problem is coming due to protobuf. I am fine with other solution as well, which help me to fix the Google protobuf issues. This p

1条回答
  •  萌比男神i
    2021-01-14 11:51

    With "google-protobuf" there are issues when used in the fashion of systemjs. It seems that Google has created it only for the nodejs. :-)
    To be able to use the protobuf in Javascript for the browser, there are few things which we have to do manually. Such manual boilerplate work can be done using some scripts as well.

    I am giving an iterative way, on how to achieve this:

    1. The first step is to generate the protobuf for both JS and TS. Use following command for the same:

      protoc ...
      --proto_path= \
      --cpp_out= \
      --js_out=import_style=commonjs,binary: \
      --ts_out=import_style=commonjs,binary:

    2. Note that, we are using the commonjs (and not systemjs). Legends:

      • = folder path where all these file1/2/N.proto files are stored
      • = folder path where you want the c++ file1/2/N.pb.cc/h files to be stored
      • = folder where you want the file1/2/N_pb.js files to be stored
      • = folder where you want the file1/2/N_pb.d.ts files to be stored
    3. Now in all the .d.ts (Typescript definition) files, there are certain code lines, which will give compiler errors. We need to comment these lines. Doing manually, is very cumbersome. Hence you may use sed (or ssed in Windows, gsed in Mac). For example, the lines starting with,

      • sed -i "s/^ static extensions/\/\/ static extensions/g" *_pb.d.ts;
      • same as above for static serializeBinaryToWriter
      • same as above for static deserializeBinaryFromReader
      • sed -i "s/google-protobuf/\.\/google-protobuf/g" *_pb.d.ts; // "./google-protobuf" is correct way to import
    4. Now, while generating the *_pb.d.ts, the protoc compiler doesn't follow the packaging for Typescript. For example, if in your fileN.proto, you have mentioned package ABC.XYZ, then the fileN.pb.h will be wrapped in namespace ABC { namespace XYZ { ... } }. The same doesn't happen in the case of Typescript. So we have to manually add these in the file. However, here it won't be a simple find/replace as above. Rather, we have to find only the first occurance of any export class (which is of generated proto) and wrap the namespaces. So below is the command:

      • sed -i "0,/export class/{s/export class/export namespace ABC { export namespace XYZ {\\n &/}" fileN_pb.d.ts;
      • sed -i -e "\$a} }" fileN_pb.d.ts;
    5. Initial importing of the google-protobuf package has to be prefixed with ./ in the case of generated _pb.js file as well

      • sed -i "s/google-protobuf/\.\/google-protobuf/g" *_pb.js;
    6. Now compile the the custom Typescript files with tsc -p "", where the tsconfig.json may look like (see arrow):

      { "compileOnSave": true, "compilerOptions": { "removeComments": true, "preserveConstEnums": true, "module": "CommonJS", <======= "outDir": "", }, "include": ["../*"], "files": ["", ..., "" }

    7. Now a very important step. All the references to the the generated *_pb.d.ts files, should be referred in 1 of your custom file. That custom file may contain the wrappers around the generated classes if it's required. This will help in limiting string replacement only in that file, which is explained in the upcoming step. For example, create a custom file name as MyProtobuf.ts and import your proto as following:

      • import * as proto from './fileN; // from fileN.d.ts
    8. In above step, it's important to note that the name "proto" is crucial. With that name, the .js files are auto generated. If there are several proto files in your project, then you may have to create yet 1 more file which exports all of them and then import that 1 file:

      • // in 'MyProtobufExports.ts' file
        export * from './file1'
        export * from './file2'
        export * from './fileN'
      • import * as proto from './MyprotobufExports // in MyProtobuf.ts file
    9. With above 2 steps, the usage of the protobuf as, var myClass = new proto.ABC.XYZ.MyClass;

    10. Now the continuation of the important step we discussed above. When we generate the equivalent _pb.js and our custom .js files, still the special name-symbol proto will not be found somehow. Even though everything is wrapped. This is because the autogenerated JS files (from TS files), will declare a var proto. If we comment that then, that issue is gone.

      • sed -i "s/var proto = require/\/\/ &/g" Protobuf.js;
    11. The final step is to put the browserify on all the .js files into a single file, as below. Due to this, there will be only single .js file, we have to deal with [good or bad]. In this command, the ordering is very important. file1_pb.js should come before file2_pb.js, if file1.proto is imported by file2.proto or vice a versa. If there is no import then the order doesn't matter. In any case the _pb.js should come before the custom .js files.

      • browserify --standalone file1_pb.js fileN_pb.js MyProtobuf.js myfile1.js myfileN.js -o=autogen.js
    12. Since the code is browserified, the calling of function can be done in following way:

      • window.main = function (...) { ... } // entry point somewhere in the fileN.ts file
        // in the index.html

    With the above steps only, I am able to make the "google-protobuf" work within my project for the browser.

    0 讨论(0)
提交回复
热议问题