This repository has been archived by the owner on Jul 1, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 24
examples_javascript
Marcel Kloubert edited this page May 6, 2017
·
8 revisions
Home >> Examples >> JavaScript
The following example shows how to use a data transformer script to uglify JavaScript files with build-in UglifyJS BEFORE they are uploaded to a SFTP server.
The example is also compatible with all other targets that support transformer
setting.
First setup your settings.json
file inside your .vscode
folder with a package definition:
{
"deploy": {
// ...
"packages": [
{
"name": "My JavaScript files to uglify",
"files": [
"/**/*.js"
]
}
],
// ...
}
}
Then define the target to deploy to:
{
"deploy": {
// ...
"targets": [
{
"name": "My SFTP server",
"type": "sftp",
"host": "mysite.example.com",
"user": "mkloubert", "password": "P@assword123!",
"transformer": "./.deploy/uglifyjs.js",
"transformerOptions": {
"exclude": [
"/**/*.min.js",
"/**/*.pack.js"
]
}
}
],
// ...
}
}
As you can see, the transformer
property defines a script, called uglifyjs.js
, in the .deploy
sub folder of your workspace:
var FS = require('fs'); // https://nodejs.org/api/fs.html
var Path = require('path'); // https://nodejs.org/api/path.html
var vscode = require('vscode'); // https://code.visualstudio.com/docs/extensionAPI/vscode-api
/**
* Is invoked BEFORE file is going to
* be send to remote target.
*
* @return {Promise} The promise with the (uglyfied) data.
*/
exports.transformData = function(ctx) {
return new Promise(function(resolve, reject) {
var compilers = ctx.require('./compilers'); // https://mkloubert.github.io/vs-deploy/modules/_compilers_.html
var glob = ctx.require('glob'); // https://www.npmjs.com/package/glob
var helpers = ctx.require('./helpers'); // https://mkloubert.github.io/vs-deploy/modules/_helpers_.html
var tmp = ctx.require('tmp'); // https://www.npmjs.com/package/tmp
var workflows = ctx.require('node-workflows'); // https://www.npmjs.com/package/node-workflows
// from "transformerOptions" property
// of the underlying target
var options = ctx.options || {};
var completed = function(err, resultData) {
if (err) {
reject(err);
}
else {
resolve(resultData);
}
};
var session = {};
var destroySession = function(err, resultData) {
var destroyWF = workflows.create();
// remove temp files
[ session.sourceFile, session.outputFile ].filter(function(tempFile) {
return !helpers.isEmptyString(tempFile);
}).forEach(function(tempFile) {
// first check if 'tempFile' exists
destroyWF.next(function(wfCtx) {
return new Promise(function(res, rej) {
FS.exists(tempFile, function(exists) {
res( exists ); // s. wfCtx.previousValue
// below
});
});
});
// now remove 'tempFile'
// if exists
destroyWF.next(function(wfCtx) {
var exists = wfCtx.previousValue;
return new Promise(function(res, rej) {
if (exists) {
FS.unlink(tempFile, function(err) {
if (err) {
//TODO: log
}
res();
});
}
else {
res(); // does not exist (anymore)
}
});
});
});
destroyWF.start().then(function() {
completed(err, resultData);
}, function(e) {
//TODO: log
completed(err, resultData);
});
};
// define the tasks todo
var wf = workflows.create();
// [1] initialize workflow result with
// input data
wf.next(function(wfCtx) {
wfCtx.result = ctx.data; // initialize with input data
});
// [2] check if file is excluded
wf.next(function(wfCtx) {
return new Promise(function(res, rej) {
if (options) {
// collect glob patterns and files
var excludePatterns = helpers.asArray(options.exclude)
.map(function(p) {
return helpers.toStringSafe(p);
})
.filter(function(p) {
return '' !== p.trim();
});
excludePatterns = helpers.distinctArray(excludePatterns);
var excludedWF = workflows.create();
excludedWF.next(function(wfCtx2) {
wfCtx2.result = false; // isExcluded
});
// create a glob check
// for each pattern
excludePatterns.forEach(function(pattern) {
excludedWF.next(function(wfCtx2) {
return new Promise(function(res2, rej2) {
glob(pattern, {
absolute: true,
cwd: vscode.workspace.rootPath,
dot: true,
nodir: true,
root: vscode.workspace.rootPath,
}, function(err, filesToExclude) {
if (err) {
rej2(err);
}
else {
// normalize paths of
// found files
filesToExclude = filesToExclude.map(function(f) {
return normalizePath(ctx, f);
});
if (filesToExclude.indexOf( normalizePath(ctx, ctx.context.file) ) > -1) {
// marked as "excluded"
// and stop next patterns
wfCtx2.result = true;
wfCtx2.finish();
}
res2();
}
});
});
});
});
excludedWF.start().then(function(isExcluded) {
if (isExcluded) {
wfCtx.finish(); // do not uglify this
}
res();
}, function(err) {
rej(err); // check failed
});
}
else {
res(); // nothing defined
// for exclusion
}
});
});
// [3] define temp files for the compiler
wf.next(function(wfCtx) {
return new Promise(function(res, rej) {
tmp.tmpName({
keep: true,
prefix: 'vsd-uglifyjs-',
postfix: '.js',
}, function(err, tempFile) {
if (err) {
rej(err); // could not define temp
// file for source data
}
else {
session.sourceFile = tempFile;
var tempFileDir = Path.dirname(tempFile);
var tempFileExtension = Path.extname(tempFile);
var tempFileBaseName = Path.basename(tempFile, tempFileExtension);
// the generated output file
// will have '.min.js' as extension
session.outputFile = Path.join( tempFileDir,
tempFileBaseName + '.min' + tempFileExtension );
res();
}
});
});
});
// [4] fill source file with unhandled
// data from ctx.data
wf.next(function(wfCtx) {
return new Promise(function(res, rej) {
FS.writeFile(session.sourceFile, ctx.data, function(err) {
if (err) {
rej(err); // could not write to source file
}
else {
res();
}
});
});
});
// [5] run UglifyJS for
// session.sourceFile
wf.next(function(wfCtx) {
return new Promise(function(res, rej) {
compilers.compileUglifyJS({
files: [ session.sourceFile ],
deleteSources: true,
}).then(function() {
res();
}, function(err) {
rej(err); // compiler error
});
});
});
// [6] read generated, ugly JavaScript
wf.next(function(wfCtx) {
return new Promise(function(res, rej) {
FS.readFile(session.outputFile, function(err, resultData) {
if (err) {
rej(err); // could not read generated
// data by UglifyJS compiler
}
else {
wfCtx.result = resultData; // update with
// uglified data
res();
}
});
});
});
// start "uglify" workflow
wf.start().then(function(resultData) {
destroySession(null, resultData);
}, function(err) {
//TODO: log
destroySession(err); // something went wrong
});
});
};
/**
* Is invoked after file
* has been downloaded from remote.
*
* @return {Buffer} Currently: The source data from remote.
*/
exports.restoreData = function(ctx) {
// currently there is no chance
// to beautify the data back
return ctx.data;
};
function normalizePath(ctx, p) {
var helpers = ctx.require('./helpers'); // https://mkloubert.github.io/vs-deploy/modules/_helpers_.html
var vscode = require('vscode'); // https://code.visualstudio.com/docs/extensionAPI/vscode-api
if (helpers.isNullOrUndefined(p)) {
return p;
}
p = helpers.toStringSafe(p);
if (!Path.isAbsolute(p)) {
p = Path.join(vscode.workspace.rootPath, p);
}
p = Path.resolve(p);
p = helpers.replaceAllStrings(p, Path.sep, '/');
return p;
}
That's all.
Now all of your .js
files will be uglified, except the ones defined by the glob patterns in the transformerOptions.exclude
property of the upper target.
It also works for single files.