How can I configure Visual Studio Code to compile typescript files on save?
I see it is possible to configure a task to build the file in focus using the ${file}
as an argument. But I would like this to be done when a file is saved.
As of May 2018 you no longer need to create tsconfig.json
manually or configure task runner.
tsc --init
in your project folder to create tsconfig.json
file (if you don't have one already).tsc: watch - tsconfig.json
.You can have several tsconfig.json
files in your workspace and run multiple compilations at once if you want (e.g. frontend and backend separately).
You can do this with Build commands:
Create a simple tsconfig.json
with "watch": true
(this will instruct compiler to watch all compiled files):
{
"compilerOptions": {
"target": "es5",
"out": "js/script.js",
"watch": true
}
}
Note that files
array is omitted, by default all *.ts
files in all subdirectories will be compiled. You can provide any other parameters or change target
/out
, just make sure that watch
is set to true
.
Configure your task (Ctrl+Shift+P -> Configure Task Runner
):
{
"version": "0.1.0",
"command": "tsc",
"showOutput": "silent",
"isShellCommand": true,
"problemMatcher": "$tsc"
}
Now press Ctrl+Shift+B to build the project. You will see compiler output in the output window (Ctrl+Shift+U).
The compiler will compile files automatically when saved. To stop the compilation, press Ctrl+P -> > Tasks: Terminate Running Task
I've created a project template specifically for this answer: typescript-node-basic
If you want to avoid having to use CTRL
+SHIFT
+B
and instead want this to occur any time you save a file, you can bind the command to the same short-cut as the save action:
[
{
"key": "ctrl+s",
"command": "workbench.action.tasks.build"
}
]
This goes in your keybindings.json - (head to this using File -> Preferences -> Keyboard Shortcuts).
If pressing Ctrl+Shift+B seems like a lot of effort, you can switch on "Auto Save" (File > Auto Save) and use NodeJS to watch all the files in your project, and run TSC automatically.
Open a Node.JS command prompt, change directory to your project root folder and type the following;
tsc -w
And hey presto, each time VS Code auto saves the file, TSC will recompile it.
This technique is mentioned in a blog post;
http://www.typescriptguy.com/getting-started/angularjs-typescript/
Scroll down to "Compile on save"
Write an Extension
Now that vscode is extensible, it is possible to hook into the on save event via an extension. A good overview of writing extensions for VSCode can be found here: https://code.visualstudio.com/docs/extensions/overview
Here's a simple example that just calls echo $filepath
and outputs stdout in a message dialogue:
import * as vscode from 'vscode';
import {exec} from 'child_process';
export function activate(context: vscode.ExtensionContext) {
vscode.window.showInformationMessage('Run command on save enabled.');
var cmd = vscode.commands.registerCommand('extension.executeOnSave', () => {
var onSave = vscode.workspace.onDidSaveTextDocument((e: vscode.TextDocument) => {
// execute some child process on save
var child = exec('echo ' + e.fileName);
child.stdout.on('data', (data) => {
vscode.window.showInformationMessage(data);
});
});
context.subscriptions.push(onSave);
});
context.subscriptions.push(cmd);
}
(Also referenced on this SO question: https://stackoverflow.com/a/33843805/20489)
Existing VSCode Extension
If you want to just install an existing extension, here is one that I wrote available in the VSCode gallery: https://marketplace.visualstudio.com/items/emeraldwalk.RunOnSave
Source code is available here: https://github.com/emeraldwalk/vscode-runonsave/blob/master/src/extension.ts
Instead of building a single file and bind Ctrl+S to trigger that build I would recommend to start tsc in watch mode using the following tasks.json file:
{
"version": "0.1.0",
"command": "tsc",
"isShellCommand": true,
"args": ["-w", "-p", "."],
"showOutput": "silent",
"isWatching": true,
"problemMatcher": "$tsc-watch"
}
This will once build the whole project and then rebuild the files that get saved independent of how they get saved (Ctrl+S, auto save, ...)
In your tsconfig.json
"compileOnSave": true, // change it to true and save the application
if problem is still there then apply step-2
Restart your editor
if still problem not resolved then apply step-3
Change any route, revert it back and save the application. It'll start compiling. i.e.
const routes: Routes = [
{
path: '', // i.e. remove , (comma) and then insert it and save, it'll start compiling
component: MyComponent
}
]
I implemented compile on save with gulp task using gulp-typescript and incremental build. This allows to control compilation whatever you want. Notice my variable tsServerProject, in my real project I also have tsClientProject because I want to compile my client code with no module specified. As I know you can't do it with vs code.
var gulp = require('gulp'),
ts = require('gulp-typescript'),
sourcemaps = require('gulp-sourcemaps');
var tsServerProject = ts.createProject({
declarationFiles: false,
noExternalResolve: false,
module: 'commonjs',
target: 'ES5'
});
var srcServer = 'src/server/**/*.ts'
gulp.task('watch-server', ['compile-server'], watchServer);
gulp.task('compile-server', compileServer);
function watchServer(params) {
gulp.watch(srcServer, ['compile-server']);
}
function compileServer(params) {
var tsResult = gulp.src(srcServer)
.pipe(sourcemaps.init())
.pipe(ts(tsServerProject));
return tsResult.js
.pipe(sourcemaps.write('./source-maps'))
.pipe(gulp.dest('src/server/'));
}
Select Preferences -> Workspace Settings and add the following code, If you have Hot reload enabled, then the changes reflect immediately in the browser
{
"files.exclude": {
"**/.git": true,
"**/.DS_Store": true,
"**/*.js.map": true,
"**/*.js": {"when": "$(basename).ts"}
},
"files.autoSave": "afterDelay",
"files.autoSaveDelay": 1000
}
I can say with the latest version of TypeScript 1.8.X and 1.0 of Visual Studio code, the technique I showed is obsolete. Simply use a tsconfig.json at the root level of your project and all works automatically for syntax checking. Then use tsc -w on the command line for watching / recompiling automatically. It will read the same tsconfig.json file for options and config of ts compile.
// tsconfig.json
{
"compilerOptions": {
"module": "amd",
"target": "ES5",
"noImplicitAny": false,
"removeComments": true,
"preserveConstEnums": true,
"inlineSourceMap": true
},
"exclude": [ "node_modules" ]
}
You need to increase the watches limit to fix the recompile issue on save, Open terminal and enter these two commands:
sudo sysctl fs.inotify.max_user_watches=524288
sudo sysctl -p --system
To make the changes persistent even after restart, run this command also:
echo fs.inotify.max_user_watches=524288 | sudo tee /etc/sysctl.d/40-max-user-watches.conf && sudo sysctl --system
tried the above methods but mine stopped auto-compile when it felt like it, due to maximum files to watch have passed the limit.
run cat /proc/sys/fs/inotify/max_user_watches
command .
if it's showing fewer files count including node_modules then open the file
/etc/sysctl.conf
in root privilege and append
fs.inotify.max_user_watches=524288
into the file and save
run again the cat command to see the result. It will work! hopefully!
I use automatic tasks run on folder (should work VSCode >=1.30) in .vscode/tasks.json
{
"version": "2.0.0",
"tasks": [
{
"type": "typescript",
"tsconfig": "tsconfig.json",
"option": "watch",
"presentation": {
"echo": true,
"reveal": "silent",
"focus": false,
"panel": "shared"
},
"isBackground": true,
"runOptions": {"runOn": "folderOpen"},
"problemMatcher": [
"$tsc-watch"
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
If this still not work on project folder open try Ctrl+shift+P and Tasks: Manage Automatic Tasks in Folder and choose "Allow Automatic Tasks in folder" on main project folder or running folder.
tsc <filename> --watch
in the terminal – Daniel C Jacobs