63

When building typescript in VSCode, I get the following error:

error TS6082: Only 'amd' and 'system' modules are supported alongside --out.

My settings are as follows:

tsconfig.json

{
    "compilerOptions": {
        "target": "ES5",
        "module": "commonjs",
        "out": "current/game.js",
        "removeComments": true,
        "sourceMap": false
    }
}

.vscode/tasks.json:

{
    "version": "0.1.0",

    // The command is tsc. Assumes that tsc has been installed using npm install -g typescript
    "command": "tsc",

    // The command is a shell script
    "isShellCommand": true,

    // Show the output window only if unrecognized errors occur.
    "showOutput": "silent",

    // args is the HelloWorld program to compile.
    "args": [],

    // use the standard tsc problem matcher to find compile problems
    // in the output.
    "problemMatcher": "$tsc"
}

Despite the error, the game.js file does get created and runs properly.

Anyone have any thoughts about what might cause this error?

OCDev
  • 2,280
  • 3
  • 26
  • 37
  • 43
    I just ran into this error and performed a Google search to find the solution and I was happy to see that someone else had asked about this. Lo and behold, it was me who asked it! Thank you self! – OCDev Dec 10 '17 at 01:49
  • 3
    the circle is complete when you search Google and find your own StackOverflow answers – Shaun Wilson Apr 11 '21 at 23:02

2 Answers2

48

It means what it says. You can’t use --out/--outFile to bundle modules together for Node.js/CommonJS, since there is no bundle format for CommonJS. Simply don’t use that option for CommonJS and corresponding JS files will be emitted for each input TS module file.

C Snover
  • 17,908
  • 5
  • 29
  • 39
  • 18
    Simply removing "module": "commonjs", made this work. Thanks! – OCDev Mar 13 '16 at 00:17
  • 3
    Likewise, you can also change to "module":"none". – Ryan Pelletier Mar 13 '17 at 02:34
  • VS 2017 complains about the choice of "none" – StingyJack Mar 22 '17 at 11:37
  • instead of removing commonjs, you should use the other instead, such as amd if you want to be bundled. – O.O May 27 '17 at 07:11
  • This is a great solution. Thank you once again! – OCDev Dec 10 '17 at 01:50
  • But there is a bundle format for CommonJS. Webpack bundles CommonJS modules. – Ozymandias Apr 28 '19 at 17:04
  • @AjaxLeung CommonJS modules are a standardised format. The standard does not include a bundle format. Webpack is a tool like Browserify, Rollup, Brunch, or r.js. It doesn’t generate “CommonJS module bundles”, since there is no such thing, and trying to load a Webpack-generated JS file into a compliant CommonJS module loader would not work. – C Snover May 02 '19 at 00:45
  • 4
    I get `error TS6131: Cannot compile modules using option 'outFile' unless the '--module' flag is 'amd' or 'system'.` – CodyBugstein Jul 17 '19 at 15:43
1

The outFile option in the tsconfig.json file is only available if you set the module option to system or amd.

As described in "Code Generation for Modules", only modules created for system or amd can be simply concatenated together while keeping the same functionality.

That means, if you are using a different module system, then you could migrate all you files into AMD modules (or SystemJs), otherwise bundling is not possible with tsc, and you would have to use a different solution for bundling.

What is "bundling" with tsc

tsc can "bundle" files together, but only by simply concatenating them. I assume they provide that functionality only because it's very easy to do.

But in order to bundle e.g. CommonJs files, the files would have to be transpiled into something completely different, e.g. wrap each file into an individual scope, removing the module.exports and create the appropriate relations between the scopes, ... That is hard work to do, and there are other libraries that are specialized into doing it.

Why AMD modules do work

E.g. AMD works by defining modules by calling the function define( myModule ). These function calls can simply be concatenated, like:

module 1:

define( { x: 1, y: 2 } );

module 2:

define( function(){ return { hello: 'world' }; } );

Can be just concatenated to:

define( { x: 1, y: 2} );
define( function(){ return { hello: 'world' }; } );

and would still run in the same way. Similar with SystemJs.

Why CommonJs modules don't work

CommonJs modules on the other hand look like this:

module 1:

module.exports = { x: 1, y: 2 };

module 2:

module.exports = ( function(){ return { hello: 'world' }; } )();

When simply concatenated, the bundle would look like this:

module.exports = { x: 1, y: 2 };
module.exports = ( function(){ return { hello: 'world' }; } )();

That obviously doesn't work, because module.exports would be overwritten repeatedly.

Other module systems would cause similar or worse difficulties.

How to bundle OR use modules

You can bundle, but not use modules:

You can make tsc bundle your files, but if they use CommonJs modules, then the javascript just wouldn't work.

Therefore tsc prints a warning if you state module: commonjs. If your files don't contain conflicting code, then your code will run fine anyway, but then you don't need the module: commonjs setting.

E.g. these settings in your tsconfig.json would output the concatenated (but not working with CommonJs modules) bundle.js file:

"moduleResolution": "nodenext",
"outFile": "./dist/bundle.js",
// "module": "CommonJS", <-- DON'T set the `module` property

You can use modules, but not bundle:

You can make tsc keep the functionality of the CommonJs modules, but then e.g. the module.exports assignments need to be kept separate:

tsconfig.json:

"moduleResolution": "nodenext",
// "outFile": "./dist/bundle.js", //  <-- DON'T set the `outFile` property
"module": "CommonJS",
kca
  • 4,856
  • 1
  • 20
  • 41