Browserify plugin for compiling TypeScript files with seamless integration and incremental compilation support
—
Integration patterns and examples for using tsify with popular build tools and Browserify extensions.
Incremental compilation support using watchify for fast development builds.
/**
* Watchify integration provides:
* - Incremental TypeScript compilation
* - File change detection
* - Fast rebuild times
* - Development server compatibility
*/Basic Watchify Setup:
const watchify = require('watchify');
const browserify = require('browserify');
const tsify = require('tsify');
const b = browserify({
entries: ['src/main.ts'],
cache: {}, // Required for watchify
packageCache: {}, // Required for watchify
plugin: [watchify]
});
b.plugin(tsify, {
target: 'es5',
strict: true
});
b.on('update', bundle); // Rebuild on file changes
b.on('log', console.log); // Log rebuild messages
function bundle() {
return b.bundle()
.on('error', console.error)
.pipe(fs.createWriteStream('dist/bundle.js'));
}
bundle(); // Initial buildAdvanced Watchify with Error Recovery:
const fs = require('fs');
const path = require('path');
function createWatcher(entryFile, outputFile) {
const b = browserify({
entries: [entryFile],
cache: {},
packageCache: {},
plugin: [watchify],
debug: true // Enable source maps
});
b.plugin(tsify, {
project: './tsconfig.json'
});
let building = false;
b.on('update', function(files) {
console.log('Files changed:', files);
bundle();
});
b.on('log', function(msg) {
console.log('Watchify:', msg);
});
function bundle() {
if (building) return;
building = true;
const start = Date.now();
console.log('Building...');
const stream = b.bundle();
stream.on('error', function(error) {
console.error('Build failed:', error.message);
building = false;
});
stream.on('end', function() {
const time = Date.now() - start;
console.log(`Build completed in ${time}ms`);
building = false;
});
return stream.pipe(fs.createWriteStream(outputFile));
}
return { bundle, browserify: b };
}
// Usage
const watcher = createWatcher('src/main.ts', 'dist/bundle.js');
watcher.bundle();Integration with Gulp build system for complex build pipelines.
/**
* Gulp integration provides:
* - Stream-based processing
* - Task orchestration
* - Multiple output formats
* - Development/production modes
*/Basic Gulp Task:
const gulp = require('gulp');
const browserify = require('browserify');
const tsify = require('tsify');
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');
const uglify = require('gulp-uglify');
const sourcemaps = require('gulp-sourcemaps');
gulp.task('typescript', function() {
return browserify({
entries: 'src/main.ts',
debug: true
})
.plugin(tsify, {
target: 'es5',
strict: true
})
.bundle()
.pipe(source('bundle.js'))
.pipe(buffer())
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(uglify())
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('dist'));
});Gulp with Multiple Entries:
const merge = require('merge2');
gulp.task('build-all', function() {
const entries = ['src/main.ts', 'src/worker.ts'];
const tasks = entries.map(function(entry) {
const filename = path.basename(entry, '.ts') + '.js';
return browserify({ entries: entry, debug: true })
.plugin(tsify)
.bundle()
.pipe(source(filename))
.pipe(buffer())
.pipe(gulp.dest('dist'));
});
return merge(tasks);
});Gulp Development Server:
const connect = require('gulp-connect');
gulp.task('serve', ['typescript'], function() {
connect.server({
root: 'dist',
livereload: true,
port: 8080
});
gulp.watch('src/**/*.ts', ['typescript']);
});
gulp.task('typescript', function() {
return browserify({
entries: 'src/main.ts',
debug: true
})
.plugin(tsify)
.bundle()
.on('error', function(error) {
console.error('TypeScript Error:', error.message);
this.emit('end');
})
.pipe(source('bundle.js'))
.pipe(gulp.dest('dist'))
.pipe(connect.reload());
});Integration with Grunt task runner using grunt-browserify.
/**
* Grunt integration provides:
* - Task configuration
* - File watching
* - Multi-target builds
* - Plugin ecosystem compatibility
*/Gruntfile.js Configuration:
module.exports = function(grunt) {
grunt.initConfig({
browserify: {
dev: {
src: 'src/main.ts',
dest: 'dist/bundle.js',
options: {
plugin: [
['tsify', {
target: 'es5',
strict: true
}]
],
debug: true
}
},
prod: {
src: 'src/main.ts',
dest: 'dist/bundle.min.js',
options: {
plugin: [
['tsify', {
target: 'es5',
strict: true,
removeComments: true
}]
]
}
}
},
watch: {
typescript: {
files: ['src/**/*.ts'],
tasks: ['browserify:dev']
}
}
});
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', ['browserify:dev']);
grunt.registerTask('build', ['browserify:prod']);
grunt.registerTask('dev', ['browserify:dev', 'watch']);
};Guidance for projects migrating from webpack to Browserify + tsify.
Webpack ts-loader equivalent:
// webpack.config.js (old)
module.exports = {
entry: './src/main.ts',
module: {
rules: [{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}]
}
};
// Browserify equivalent
browserify('src/main.ts')
.plugin(tsify, {
exclude: ['node_modules/**']
})
.bundle();Using tsify with Babelify for modern JavaScript features.
/**
* Babel integration for:
* - ES6+ syntax transformation
* - JSX processing (alternative to TypeScript JSX)
* - Polyfill injection
* - Plugin ecosystem access
*/ES6 Output with Babel:
const babelify = require('babelify');
browserify('src/main.ts')
.plugin(tsify, {
target: 'es6', // Output ES6 from TypeScript
module: 'es6'
})
.transform(babelify, {
extensions: ['.tsx', '.ts'],
presets: ['@babel/preset-env'],
plugins: ['@babel/plugin-proposal-class-properties']
})
.bundle();React/JSX with Babel:
browserify('src/App.tsx')
.plugin(tsify, {
jsx: 'preserve', // Let Babel handle JSX
target: 'es6'
})
.transform(babelify, {
extensions: ['.tsx', '.ts'],
presets: [
'@babel/preset-env',
'@babel/preset-react'
]
})
.bundle();Integration with testing frameworks and tools.
Jest Configuration:
// jest.config.js
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
setupFilesAfterEnv: ['<rootDir>/test/setup.js'],
collectCoverageFrom: [
'src/**/*.ts',
'!src/**/*.test.ts'
]
};Karma + Browserify:
// karma.conf.js
module.exports = function(config) {
config.set({
frameworks: ['browserify', 'mocha'],
files: [
'test/**/*.ts'
],
preprocessors: {
'test/**/*.ts': ['browserify']
},
browserify: {
plugin: [
['tsify', {
target: 'es5'
}]
],
debug: true
}
});
};Integration with development servers and hot reloading.
Express Development Server:
const express = require('express');
const browserify = require('browserify');
const tsify = require('tsify');
const app = express();
app.get('/bundle.js', function(req, res) {
res.setHeader('Content-Type', 'application/javascript');
browserify('src/main.ts')
.plugin(tsify, { target: 'es5' })
.bundle()
.on('error', function(error) {
console.error('TypeScript Error:', error.message);
res.status(500).send(`console.error(${JSON.stringify(error.message)});`);
})
.pipe(res);
});
app.use(express.static('public'));
app.listen(3000);interface IntegrationOptions {
/** Watchify-specific options */
watchify?: {
ignoreWatch?: string[];
poll?: boolean | number;
};
/** Gulp stream options */
gulp?: {
sourcemaps?: boolean;
minify?: boolean;
livereload?: boolean;
};
/** Development server options */
devServer?: {
port?: number;
host?: string;
hot?: boolean;
};
}
interface BuildContext {
/** Build mode (development/production) */
mode: 'development' | 'production';
/** Source map generation */
sourceMap: boolean;
/** Output directory */
outputDir: string;
/** Entry points */
entries: string[];
}Install with Tessl CLI
npx tessl i tessl/npm-tsify