24

I have a small Typescript project of about 10 ts files. I want to compile all my files into es5 and into a single es5 file called all.js.

Currently, with my tsconfig.json set up as

{
  "compilerOptions": {
    "module": "system",
    "target": "es5",
    "outFile": "./all.js"
}

everything is getting compiled, but each file is being wrapped by

System.register("SomeTSFile", [], function(exports_4, context_4) {
...
}

SystemJS looks cool but I am not in the mood to learn it now and I don't believe it is necessary. If I could get all my JS into one file, that will be perfectly sufficient for my needs.

If I remove "module": "system",from my compiler options, my all.js file comes out completely blank. Apparently, this is because for some reason, you cannot use "modules": none when outputting to one file. (I don't get why)

How can I compile all the TS into one JS file without having to involve SystemJS or any other complications?

reduckted
  • 2,358
  • 3
  • 28
  • 37
CodyBugstein
  • 21,984
  • 61
  • 207
  • 363
  • Every .ts file is a module. If one .ts file references another, you can not make it work without module loading system. If you don't want it, concatenate all your .ts file into one and compile that file. This might require changing your code though. – artem Sep 07 '16 at 05:13
  • Another option is to set `"module": "amd"`, then you will need AMD loader instead of SystemJS. – artem Sep 07 '16 at 05:25

6 Answers6

8

The contents of your .ts files determines if this is possible or not...

If you avoid turning your TypeScript code a module (by avoiding top-level import or export declarations), the output from single-file compile will not include any dependency on a module loader.

For example: typescript compiler itself is written without any top-level import or export declarations, and thus compiles into a single-file .js without any loader dependency.

Note that its use of export within a namespace is not a "top level" export. Imports inside a namespace are possible but severely limited: an example here

"In TypeScript, just as in ECMAScript 2015, any file containing a top-level import or export is considered a module."

The typescript handbook

Burt_Harris
  • 6,415
  • 2
  • 29
  • 64
  • Hmmm so I can have imports within a module section but not outside? – CodyBugstein Sep 13 '16 at 02:29
  • I don't think its that simple @CodyBugstein. Some forms of import are OK, but importing from a module isn't (if you are trying to avoid depending on a module loader.) – Burt_Harris Sep 13 '16 at 02:52
  • Note that you **can** use [triple-slash directives](http://www.typescriptlang.org/docs/handbook/triple-slash-directives.html) to reference types in other typescript files without using imports, but that this does not take care of loading the other files (but of course compiling down to a single .js can make that moot.) – Burt_Harris Sep 13 '16 at 03:09
  • Ok i will try that – CodyBugstein Sep 13 '16 at 03:10
7

Use triple slash directives for the typescript-compiler (tsc)

Triple-slash references instruct the compiler to include additional files in the compilation process.

index.ts:

/// <reference path="./domHelpers.ts" />

function add(a: number, b: number): number {
    return a + b;
}

q('#sum').textContent = add(2, 5).toString();

domHelpers.ts

function q(query: string): Element {
    return document.querySelector(query);
}

function qa(query: string): NodeListOf<Element> {
    return document.querySelectorAll(query);
}

Build step:

tsc --out bundle.js ts/index.ts

Will produce bundle.js with contents

function q(query) {
    return document.querySelector(query);
}
function qa(query) {
    return document.querySelectorAll(query);
}
/// <reference path="./domHelpers.ts" />
function add(a, b) {
    return a + b;
}
q("#sum").textContent = add(2, 5).toString();
Peheje
  • 12,542
  • 1
  • 21
  • 30
2

Here's the method I ended up using. This process will create a file that can be linked with a <script src="myModuleName.min.js"></script> tag on an HTML page for use in a browser.

  1. Install rollup and plugins (many plugins listed here are optional but this config should cover any way in which you use modules)

npm install rollup-plugin-buble rollup-plugin-commonjs rollup-plugin-node-resolve rollup-plugin-typescript rollup-plugin-uglify typescript --save-dev


  1. This example rollup configuration file shows how to prevent rollup from also bundling your dependencies. In this case, I'm using jQuery and Angular, but I don't want to include that in the package I'm providing to users--so I list them as external, and they both happen to have a global variable--this example file shows how to deal with that scenario:

rollup.config.js

'use strict';

import 'rollup';
import typescript from 'rollup-plugin-typescript';
import buble from 'rollup-plugin-buble';
import commonjs from 'rollup-plugin-commonjs';
import nodeResolve from 'rollup-plugin-node-resolve';
import uglify from 'rollup-plugin-uglify';
import {minify} from 'uglify-js';

/**
 * Default/development Build
 */
const config = {
    entry: 'src/index.ts',
    exports: 'auto',
    globals: {
        'jquery': '$',
        'angular': 'angular'
    },
    external: ['angular', 'jquery'],
    targets: [{dest: 'dist/myModuleName.js', format: 'umd', moduleName: 'myModuleName', sourceMap: true}],
    plugins: [

        typescript({
            typescript: require('typescript')
        }),
        buble(),
        nodeResolve({
            jsnext: true,
            main: true
        }),
        commonjs({
            namedExports: {
                'node_modules/jquery/dist/jquery.min.js': ['jquery'],
                'node_modules/angular/angular.min.js': ['angular']
            }
        })
    ]
}

// Minified JS Build
if (process.env.BUILD === 'minify') {
    config.targets = [{dest: 'dist/myModuleName.min.js', format: 'umd', moduleName: 'myModuleName', sourceMap: false}];
    config.plugins.push(
        uglify({}, minify)
    );
}

// Report destination paths on console
console.info(`\u001b[36m\[Rollup ${process.env.BUILD} build\]\u001b[97m \nConverting Typescript from ${
config.entry} to javascript, exporting to: ${config.targets[0].dest}`);

export default config

  1. Add scripts to package.json
    "scripts": {
        "build": "rollup -c rollup.config.js --no-conflict --environment BUILD:development",
         "minify": "rollup -c rollup.config.js --environment INCLUDE_DEPS,BUILD:minify"
    }

  1. Provide a file for rollup to consume:

src/index.ts

`export * from './myModule';`

  1. Optionally use a file to collect your modules for export if you're writing a library, these are the functions you intend to be publically available.

src/myModule.ts

export {myOtherClass, myFunction} from './myUtils/myFile';
export * from "./myUtils/myOtherFile";

  1. run npm run build or npm run build && npm run minify to also get the minified version.
Benson
  • 4,181
  • 2
  • 26
  • 44
2

Using TypeScript 3.4, I have no problem transpiling many *.ts scripts into a single .js output file.

Here is the minimalist version of the tsconfig.json I am using with tsc --project src/test/tsconfig.json

{
  "compilerOptions": {
    "outFile": "../../build/test/Code.js",
    "module": "none",
    "skipLibCheck": true,
  },
  "include": ["**/*.ts"],
}
PopGoesTheWza
  • 558
  • 4
  • 12
  • 1
    but then how do you import from one file to the other? – CodyBugstein Jul 17 '19 at 17:52
  • You don't have to use `import` less `require` with this settings. The output `Code.js` will be the concatenation of all valid source files. Valid source files are defined with the `include` and `files` properties of your `tsconfig.json`. The order in which files are concatenated can be controlled using the `files` property and `/// ` directives. You can look at [this repository](https://github.com/PopGoesTheWza/ts-gas-project-starter) for complete sample. – PopGoesTheWza Jul 18 '19 at 18:15
1

Can you use the compiler itself? - as a post build process. TSC takes arguments allowing you to do this.

tsc --out compiledSingleFile.js one.ts two.ts

Or by using Gulp in your build pipeline -

https://www.npmjs.com/package/gulp-tsc

KnowHoper
  • 4,352
  • 3
  • 39
  • 54
1

This is how i did it

  1. tsconfig file should set moduleResolution to classic
  2. tsconfig file should set module to none
  3. use Typescript namespace syntax and keep all your files in same namespace

Done !!!

this sol will only work who want no module system, with this sol you won't be able to use import export module system syntaxes

Pranay Dutta
  • 2,483
  • 2
  • 30
  • 42