1

I am writing a web application in TypeScript, which is compiled using Gulp.js, Tsify, and Browserify. This makes sure that several hundreds of TypeScript files are bundled together into a single JavaScript file.

This worked fine for a while, but then trouble arose when my codebase became so large that I decided to split up the separate parts of the application into different modules. (Also, it's quite a hassle to include modules as ../../../../mountain, instead of just mountain.) For this, I decided to use the default node_modules directory and Node.js's module resolution; hoping this would work for browser applications as it does for Node.js applications. It didn't.

I created a smaller similar project that adheres to a similar directory structure and setup, which I will illustrate here.

Directory structure:

build/               # Destination directory
  - script.js        # File that should be created by Gulp
client/
  - src/
    - main.ts        # Application main
  - node_modules/    # Contains all my self-written modules
    - mountain/      # Example module
      - index.ts     # Module main
      - package.json # Module package.json (states index.ts as main)
node_modules/        # Contains all build-modules. (Gulp.js, etc.)
  - ...
gulpfile.js
package.json

client/src/main.ts contains:

import { foo } from 'mountain';
foo( );

client/node_modules/mountain/index.ts contains:

export function foo( ) {
  console.log( 'Hello World' );
}

gulpfile.js contains:

var gulp = require('gulp');
var source = require('vinyl-source-stream');
var browserify = require('browserify');
var tsify = require('tsify');

function compile( ) {
  var bundler = browserify( './client/src/main.ts', { debug: true } )
      .plugin( 'tsify', { target: 'es6', project: './client/src/' } );

  bundler.bundle()
      .on('error', function(err) { console.error(err); this.emit('end'); })
      .pipe(source( 'script.js' ))
      .pipe(gulp.dest( './build' ));
}

gulp.task('default', ( ) => compile( ) );

If the mountain module in node_modules is not there, and is instead included inside the src directory (and references as ./mountain), then this works fine. However, having this module defined externally, it results in the following error:

export function foo( ) {
^
ParseError: 'import' and 'export' may appear only with 'sourceType: module'

Now this seems to be caused by the fact that Browserify does not compile and include the TypeScript files located in node_modules. Though I do not know what the exact cause of this problem is, nor how it can be resolved.

What is the experience with setting up a development environment like this? How can I resolve my issue, such that it compiled properly? Or are there alternatives of keeping my module dependencies cleanly separate?

Note that I am aware of previous posts in which the same error message is presented:

However, my problem is not with setting up Browserify in its default setup. As this worked fine previously. Instead, this question is concerned with setting it up such that it works with self-written modules. Also, I tried applying those solutions to my problem, albeit with no success.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dennis
  • 323
  • 7
  • 17
  • 3
    Consider using WebPack instead. – SLaks Nov 15 '17 at 23:07
  • @SLaks Wow. I disregarded WebPack before, but don't remember why. I just set it up for the test project and it seems to do the trick. Will soon apply it to the actual project. It seems really promising. Thanks. – Dennis Nov 15 '17 at 23:33
  • To not have to write `../../../../../..` you could you tsconfig paths section. To let webpack know about you paths there is a handy plugin as a part of awesome-ts-loader, which works independently from the loader itself (i'm using it with ts-loader at the moment). Like this https://gist.github.com/rasdaniil/b1b9bbd4b9fd12332ffe08301b30f491 – Daniel Khoroshko Nov 16 '17 at 01:11

0 Answers0