Indeed gulp - in this case - is what you need. There are some other javascript task automators but I guess gulp is a good choice. With gulp you are able to compile your typescript and scss files, copy resources like images and so on.
First you need to install gulp via npm
npm install gulp --save-dev
furthermore you need "gulp sourcemaps" for compiling typescript "gulp-typescript", for compiling scss "gulp-sass", and "gulp-minify" for minifying:
npm install gulp-sourcemaps gulp-typescript gulp-sass gulp-minify
My source (typescript files) are in "/src/client" and the compiled project should be in "/dist/client", also I delete the dist folder every time before building the project again. I think its cleaner. For this you will also need the "del" module
npm install del
Now its time to build your gulpfile.js with your tasks, this badass should start with importing your modules:
var _gulp = require('gulp')
var _sourcemaps = require('gulp-sourcemaps')
var _typescript = require('gulp-typescript')
var _sass = require("gulp-sass")
var _minify = require('gulp-minify');
Then, the first task should be cleaning:
_gulp.task('clean-frontend', function(done) {
return _del(['./dist/client'], done);
});
Here you create a gulp task called "clean-frontend". All you do here is to remove the "dist/client" directory.
The Next task is to copy your frontend resources like images, or stuff like that in our client directory - in short: everything that is no scss, or typescript file. You call your task "copy-frontend-resources" and create it with:
_gulp.task('copy-frontend-resources', () => {
_gulp.src([config.frontend.sourceFolder + '/**/*', "!**/*.ts", "!**/*.scss"]).pipe(_gulp.dest('./dist/client'))
})
The next step is to copy your javascript libraries you use like underscore, angular, jquery, systemjs, and what ever you need. If you need a library like underscore in the browser frontend you simply install it with npm like:
npm install underscore
after that you can import it in your typescript files (import * as _ from "underscore") and use it in development. The browser has no access to your /node_modules folder in the project root directory, because his root directory is /dist/client and because of this you will need to copy your libraries as well. For that you create an array of npm modules you use like:
let usedLibs = [
'systemjs/dist/*.js',
'@angular/**/bundles/**',
'rxjs/**/*.js',
'zone.js/dist/*.js',
'reflect-metadata/*.js',
'jquery/dist/*.js',
'underscore/*.js'
]
You just have to check for every library where its javascript files are located, as you can see systemjs has his in /dist, while underscore has his in his root. Okay, now let's do the task which will copy all of the libraries of the node_modules to the "/dist/client/lib" folder:
_gulp.task('copy-frontend-libraries', () => {
_gulp.src(usedLibs, {
cwd: "node_modules/**"
}).pipe(_gulp.dest('./dist/client/lib'));
})
The Next task is pretty simple, it compiles all scss in our "src/client" folder to css files:
_gulp.task('build-frontend-css', () => {
_gulp.src(['src/client/**/*.scss'])
.pipe(_sass({ style: 'expanded' }))
.pipe(_gulp.dest('./dist/client'));
})
The last task is compiling the typescript files, you can adjust the compiler properties to your needs:
let compilerOptions = {
removeComments: true,
target: "es6",
moduleResolution: "node",
module: "commonjs", // you can choose "AMD" too
experimentalDecorators : true,
allowSyntheticDefaultImports : true
}
And create the task:
_gulp.task('build-frontend-angular', () => {
var typescriptProject = _typescript.createProject(compilerOptions);
var typescriptResult = _gulp.src(['./src/client/**/*.ts'])
.pipe(_sourcemaps.init())
.pipe(typescriptProject())
.pipe(_sourcemaps.write())
.pipe(_gulp.dest('./dist/client_debug'))
})
Note, that you copy your files here to "client_debug" directory, because you want to minify them before copying in the client folder.
The minifier does its job with:
_gulp.task('compress-frontend', function() {
_gulp.src('./dist/client_debug/*.js')
.pipe(_minify({
ext:{
src:'-debug.js',
min:'.js'
},
}))
.pipe(_gulp.dest('./dist/client'))
});
Now we have all our tasks complete and need a function to run all of them at once and we do that with creating a root task called "build". Note, that the "clean-frontend" is not inside the gulp.start array, it caused an error (gulp.start runs all at once and not one after another):
_gulp.task('build', [
'clean-frontend',
], (done) => {
// Alles gecleaned, weiter mit build
_gulp.start(
[
'copy-frontend-resources',
'copy-frontend-libraries',
'build-frontend-css',
'build-frontend-angular',
'compress-frontend'
], () => {
done()
}
)
});
Okay! Puh, long way, but now we want to test it! Lets go into the command line and cd in your project directory. Here you can run now every gulp task from the gulpfile.js with gulp NAMEOFTASK
in our example: gulp build
but you could also run one of the single tasks like gulp compress-frontend
.
The last step would be adding a watcher, which does all the stuff above automated if you change a file in your src directory. For this case you would add another task like:
_gulp.task('watch', function () {
// Watch frontend
_gulp.watch(
['./src/**/*'],
[
'copy-frontend-resources',
'build-frontend-css',
'build-frontend-angular',
'compress-frontend'
]
).on('change', function (e) {
console.log('File ' + e.path + ' has been changed. Updating/Compiling.');
});
});
The task "copy-frontend-libraries" won't be needed here, because I guess you did not changed something inside the npm modules. You can run the watch task with
gulp watch
You see, there is no really "integrating" in VS studio code, all you do is to use the terminal of it and run "gulp watch", or "gulp build". That's all.
BUT! There's more! More cooler is it when you modify your package.json to something linke that:
(...)
"scripts": {
"build": "gulp build",
"watch": "gulp watch",
}
(...)
Now you can run "npm run build" or "npm run watch". instead of the gulp command.
I hope I could help!