0

I am using imports and exports because references are said to be outdated. However, I want to compile to one file, and I'm using the "system" module, but it is turning everything into a module even if nothing is being exported. If anything is imported, the code is not executed, but if nothing is imported or exported, the code is executed. I need to import files to be able to use them, but I cannot because the code becomes a module function.

This is my tsconfig.json:

{
    "compilerOptions": {
        "module": "system",
        "noImplicitAny": true,
        "removeComments": true,
        "preserveConstEnums": true,
        "sourceMap": false,
        "outFile": "{PATH}"
    }
}

My TypeScript code:

import { Button } from "UI/Button";

new Button("Hello World!");
console.log("HELLO!");

The compiled code turns it into this:

System.register("Main/main", ["UI/Button"], function (exports_4, context_4) {
    "use strict";
    var Button_1;
    var __moduleName = context_4 && context_4.id;
    return {
        setters: [
            function (Button_1_1) {
                Button_1 = Button_1_1;
            }
        ],
        execute: function () {
            new Button_1.Button("Hello World!");
            console.log("HELLO!");
        }
    };
});

If I remove the import and only keep the console.log:

console.log("HELLO!");

It removes everything without the import, even the previous modules because I guess it does not detect them being used.

I am assuming I am misunderstanding how the import/export system works? I want to be able to run functions and import/export files, but as of now it looks like I can only import/export files, not run them. I want all of it to be compiled into one file, too. Any help would be appreciated!

Ripper
  • 97
  • 8
  • Are you using webpack? You need to disable tree-shaking or re-export Button by doing `import { Button } from "UI/Button";` in your index. – Win Oct 05 '21 at 08:37
  • @Win I'm not even sure what webpack is. I simply want to split up my TypeScript project into multiple files and then compile it down into a single .js file. I'll look into what webpack is and get back to you. – Ripper Oct 05 '21 at 08:39
  • how are you bundling the final file? Are you using ts-loader? – Win Oct 05 '21 at 08:39
  • @Win I'm running the TypeScript compiler and referencing the compiled .js file in the HTML page. I'm assuming I'm missing a step? – Ripper Oct 05 '21 at 08:43
  • You should just be able to replace `import { Button } from './Button';` to `export * from './Button';` in the main `ts` file and it will compile like how you would expect as this mean you means make the Button available outside the module – Win Oct 05 '21 at 08:54
  • @Win If I do that, the IDE says it cannot find name 'Button' – Ripper Oct 05 '21 at 09:08
  • are you sure you exported Button as a const and not just export default. `const Button` to `export const Button` – Win Oct 05 '21 at 09:38

1 Answers1

1

You'll need to run these scripts from your HTML file, invoking them using SystemJS (as in your tsconfig.json).

The presence of import or export is one of the ways that TypeScript can infer whether you are writing a script versus a module. The drastic change in compiled output comes from TypeScript interpreting your file as a module if and only if it has import or export statements.

The idea behind modules, from Mozilla's cartoon introduction:

Modules give you a better way to organize these variables and functions. With modules, you group the variables and functions that make sense to go together.

This puts these functions and variables into a module scope. The module scope can be used to share variables between the functions in the module.

But unlike function scopes, module scopes have a way of making their variables available to other modules as well. They can say explicitly which of the variables, classes, or functions in the module should be available.

The whole idea behind Modules is that you can defer the loading that happens as part of your UI/Button module (or any others that you write) until you need it. That UI/Button initialization happens exactly once, and only gives you access to the variables, functions, and classes that you export. (That said, modules can also have "side effects" like your console.log: Those aren't exported values, they're just visible things that happen when the module is executed.) Furthermore, each module executes within its own namespace (here, its own execute function), so if one module defines a counter variable it won't interfere with a separate module's counter variable.

You've chosen the system TypeScript module format, otherwise known as SystemJS. In doing so, you're signing up to have SystemJS manage your module loading, which would allow you to call System.import to load your Main/main module from the compiled Javascript you've posted. At that point you would see the output you expect because you've specifically requested it. When specifying an outFile as you have, you can also pick AMD (which will also require specifying your "entry point") or "None" (which will prohibit import and export).

Once you have a better understanding of modules, you can look into a "bundler" like Webpack. These systems traverse all of your modules--which might be one file, or might be many--and bundle them together into a single file as you've described. You can even tell Webpack which module you intend as an entry point, and it will run that automatically as soon as the script loads--exactly like an old-fashioned JS script would.

Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251
  • Thank you for the detailed response. I got Webpack to work with the system module. I even set the entry point to my main.ts file, however, it doesn't seem to run the code. It compiles it into what I previously had, except it added in some stuff, and it seems to be calling a function via an auto-generated dictionary, but it never calls the main.js file that is produced from the .ts. – Ripper Oct 05 '21 at 09:41
  • 1
    I figured it out! I used ts-loader for Webpack and in tsconfig.json I used the CommonJS module. No need to use outFile in tsconfig.json because Webpack will handle compiling code into a single file anyway. Now it works as I needed! Thank you! – Ripper Oct 05 '21 at 11:55