基本理解 – TypeScript和如何正确将JS模块实现到Web项目中

huangapple go评论78阅读模式
英文:

Basic Understanding - TypeScript and HowTo properly implement JS-Modules into Webproject

问题

I am struggling with the current situation. Up to today I had my own JavaScript implementation with my own methods to load single JS files per website - when needed. This way, I had a tiny loader script with an SCP SHA-256 checksum in the header, which then loaded the "master" script that controlled everything else. Now I want to take a few steps further:

  1. Switch over to modules, because most libraries do so too.
  2. Implement TypeScript into my system.

What starts my script implementation:

/scripts/modules-loader.js
<html>
    ...
    <script async type=module>
        "use strict";
        import {master} from '/scripts/modules/master-28021723540.js';
        new master();
    </script>
    ...
</html>

So far, so good. This loader executes as expected, the JS file is loaded, and the SHA-256 hash from the header is valid.

And now where the struggle begins. This file is compiled to:

/master.ts
export class master {
    constructor() {
        this.init();
    }

    async init() {
        console.log("Hello, let's get started...");
    }
}

Compiled file:

define("wkwussmxlyk4d7ainbsq93pnpnugjs5g", ["require", "exports"], function (require, exports) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.master = void.0;
    class master {
        constructor() {
            this.init();
        }
        async init() {
            console.log("Hello, let's get started...");
        }
    }
    exports.master = master;
});

This results in the browser not being able to find the module called "master":

Uncaught SyntaxError: The requested module '/scripts/modules/master-28021723540.js' 
does not provide an export named 'master' (at (Index):11:9)

However, I also tried this, which I found on the internet:

"use strict";
module master {
    class master {
        constructor() {
            this.init();
        }

        async init() {
            console.log("Hello, let's get started...");
        }
    }
}

This gets compiled into this:

"use strict";
var master;
(function (master_1) {
    class master {
        constructor() {
            this.init();
        }
        async init() {
            console.log("Hello, let's get started...");
        }
    }
})(master || (master = {}));

This leads to the same result. How can I get my class compiled from TypeScript to be able to call it from the loader or in the file itself?

Just for understanding, I don't want to use "tsc --watch" over my entire project. I am using single JS/TS files and compile/optimize them in the request thread and put them into static optimized files afterward (if in production). Keeping this in mind, I am also open to different implementations. I am aiming for maximum page speed without compromises, and my current solution was working very well but just limited because it was unable to load modules, so now I want to switch over to modules only.

I am compiling like this:

/usr/bin/tsc --alwaysStrict --strict --module amd --target es2020 /srv/http/domain.local/tmp/domain.local/ncumh5cnk5uq2s7b64oa31cv19agr2s9.ts --outfile /srv/http/domain.local/tmp/domain.local/compiled-ncumh5cnk5uq2s7b64oa31cv19agr2s9.ts

Thanks in advance.

Response to the answer from @Quentin:

/usr/bin/tsc --alwaysStrict --strict --target es6 /srv/http/domain.local/tmp/domain.local/ncumh5cnk5uq2s7b64oa31cv19agr2s9.ts --outfile /srv/http/domain.local/tmp/domain.local/compiled-ncumh5cnk5uq2s7b64oa31cv19agr2s9.ts

I am getting this compilation:

"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || []).next());
    }
};
class master {
    constructor() {
        this.init();
    }
    init() {
        return __awaiter(this, void 0, void 0, function* () {
            console.log("Hello, let's get started...");
        });
    }
}

And with

export class ()

I am getting this:

Cannot compile modules using option 'outFile' unless the '--module' flag is 'amd' or 'system'.
英文:

I am struggeling with the current situation. Up to today i had my own JavaScript implementation with own methods to load single js files per website - when needed. This way i had a tiny loader script with an scp sha256-checksum in the header which then loaded the "master" script which controlled everything else.
Now i want to go some steps further and a) switch over to modules, because most libs do so too, i was unable to load modules from normal scripts and b) implement typescript into my system.

What starts my script implementation:

/scripts/modules-loader.js
&lt;html&gt;
    ...
    &lt;script async type=module&gt;
        &quot;use strict&quot;;
        import {master} from &#39;/scripts/modules/master-28021723540.js&#39;;
        new master();
    &lt;/script&gt;
    ...
&lt;/html&gt;

So far so good. This loader executes as expected, the js file is been loaded and the sha-256 hash from the header is valid.

And now where the struggle begins. This file is been compiled to

/master.ts
export class master {
    constructor() {
        this.init();
    }

    async init() {
        console.log( &quot;Hello, lets get started...&quot;);
    }
}

compiled file:

define(&quot;wkwussmxlyk4d7ainbsq93pnpnugjs5g&quot;, [&quot;require&quot;, &quot;exports&quot;], function (require, exports) {
    &quot;use strict&quot;;
    Object.defineProperty(exports, &quot;__esModule&quot;, { value: true });
    exports.master = void 0;
    class master {
        constructor() {
            this.init();
        }
        async init() {
            console.log(&quot;Hello, lets get started...&quot;);
        }
    }
    exports.master = master;
});

with the result that the browser cannot find the module called "master"

Uncaught SyntaxError: The requested module &#39;/scripts/modules/master-28021723540.js&#39; 
does not provide an export named &#39;master&#39; (at (Index):11:9)

However i also tried this, which i found in the internet:

&quot;use strict&quot;;
module master {
    class master {
        constructor() {
            this.init();
        }

        async init() {
            console.log( &quot;Hello, lets get started...&quot;);
        }
    }
}

which gets compiled into this

&quot;use strict&quot;;
var master;
(function (master_1) {
    class master {
        constructor() {
            this.init();
        }
        async init() {
            console.log(&quot;Hello, lets get started...&quot;);
        }
    }
})(master || (master = {}));

which leads to the same result.
How can i get my class get compiled from ts to be able to call it from the loader or in the file itself?

Just for understanding, i dont want to use the "tsc --watch" over my entire project. I am using single js/ts files and compile/optimize them in the request thread and put them into static optimized files afterwards ( if in production ). Keeping this in mind i am also open into different implementations. I am aiming for maximum pagespeed without compromises and my current solution was working very good but just limited because it was unable to load modules, so now i want to switch over to modules only.

i am compiling like this

/usr/bin/tsc --alwaysStrict --strict --module amd --target es2020 /srv/http/domain.local/tmp/domain.local/ncumh5cnk5uq2s7b64oa31cv19agr2s9.ts --outfile /srv/http/domain.local/tmp/domain.local/compiled-ncumh5cnk5uq2s7b64oa31cv19agr2s9.ts

Thanks in advance

Response on answer from @Quentin

/usr/bin/tsc --alwaysStrict --strict --target es6 /srv/http/domain.local/tmp/domain.local/ncumh5cnk5uq2s7b64oa31cv19agr2s9.ts --outfile /srv/http/domain.local/tmp/domain.local/compiled-ncumh5cnk5uq2s7b64oa31cv19agr2s9.ts

i am getting this compilation

&quot;use strict&quot;;
var __awaiter = (this &amp;&amp; this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator[&quot;throw&quot;](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
class master {
    constructor() {
        this.init();
    }
    init() {
        return __awaiter(this, void 0, void 0, function* () {
            console.log(&quot;Hello, lets get started...&quot;);
        });
    }
}

and with

export class()

i am getting this:

Cannot compile modules using option &#39;outFile&#39; unless the &#39;--module&#39; flag is &#39;amd&#39; or &#39;system&#39;.

答案1

得分: 3

--module amd

这是你的问题1

AMD 模块使用 define 语法,在浏览器中没有原生支持。要使用它们,你需要像 Require.JS 这样的工具。

相反,告诉 TypeScript 生成一个 es6 模块。

英文:

> --module amd

This is your problem.

AMD modules use the define syntax and do no have native support in browsers. To use them you’ll need to use something like Require.JS.

Instead, tell TypeScript to generate an es6 module.

huangapple
  • 本文由 发表于 2023年2月18日 01:37:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/75487561.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定