typescriptnpm

Build and distribute a Typescript project


I have a typescript project, that when I develop it, the code is spread among many files.

I want to distribute that project a a single js and d.ts file - what's the best way to do that?


Solution

  • When you package your file, there is normally no need to combine it into a single file. Using a package manager (such as NPM) your files will be bundled into a package that you can keep private, or make public, and that package has all the files needed to run your module.

    With TypeScript in particular, you would package the .js and .d.ts files, which means your package will work for both TypeScript and JavaScript consumers. You wouldn't add the .ts files to the package.

    If you are targeting both browser and Node environments, you can use UMD modules, which work in both environments.

    Practical example - TypeSpec.

    Please note - I have put entire files below to ensure the context is there, but the important bits are usually one or two lines, which I have highlighted.

    TypeScript config file - the important bits are the "module" kind, and emitting "declaration" files.

    {
      "compileOnSave": true,
      "compilerOptions": {
        "target": "ES5",
        "module": "umd", // <--
        "strict": true,
        "experimentalDecorators": true,
        "noEmitOnError": false,
        "noFallthroughCasesInSwitch": true,
        "noImplicitReturns": true,
        "sourceMap": true,
        "removeComments": false,
        "declaration": true, // <--
        "downlevelIteration": true,
        "noUnusedLocals": true,
        "noUnusedParameters": false
      }
    }
    

    Gulp file - this moves the files into a dist folder, incuding the package.json and readme files, but most importantly all of the JavaScript and type definitions.

    var gulp = require('gulp');
    
    gulp.task('default', function () {
        gulp.src('./node_modules/requirejs/require.js')
            .pipe(gulp.dest('./lib'));
    
        // This bit moves type definitions
        gulp.src('./Scripts/TypeSpec/*.d.ts')
            .pipe(gulp.dest('./dist/src'));
    
        // And this bit moves the JavaScript
        gulp.src('./Scripts/TypeSpec/*.js')
            .pipe(gulp.dest('./dist/src'));
    
        gulp.src('../README.md')
            .pipe(gulp.dest('./dist'));
    
        gulp.src('./package.json')
            .pipe(gulp.dest('./dist'));
    });
    

    The package.json file hints where the main source file and type information can be found in the "main" and "types" sections:

    {
      "author": "Steve Fenton",
      "name": "typespec-bdd",
      "description": "BDD framework for TypeScript.",
      "keywords": [
        "typespec",
        "typescript",
        "bdd",
        "behaviour",
        "driven"
      ],
      "version": "0.7.1",
      "homepage": "https://github.com/Steve-Fenton/TypeSpec",
      "bugs": "https://github.com/Steve-Fenton/TypeSpec/issues",
      "license": "(Apache-2.0)",
      "files": [
        "src/"
      ],
      "repository": {
        "url": "https://github.com/Steve-Fenton/TypeSpec"
      },
      "main": "./src/TypeSpec.js", <-- main file
      "types": "./src/TypeSpec.d.ts", <-- type information starts here
      "dependencies": {},
      "devDependencies": {
        "gulp": "^3.9.1",
        "requirejs": "^2.3.5"
      },
      "optionalDependencies": {},
      "engines": {
        "node": "*"
      }
    }
    

    You now have a "dist" folder with just the files you need to package. You can try it out without publishing to NPM using.

    npm pack