Skip to content

Instantly share code, notes, and snippets.

@KevinWang15
Last active April 1, 2018 01:58
Show Gist options
  • Save KevinWang15/dd06c3106ec88535c02b64cca685a647 to your computer and use it in GitHub Desktop.
Save KevinWang15/dd06c3106ec88535c02b64cca685a647 to your computer and use it in GitHub Desktop.
Upload JS/CSS to qiniu cdn for production in index.html, cache bust according to checksum
module.exports = {
qiniu_ak: '',
qiniu_sk: '',
qiniu_bucket: '',
qiniu_domain:'http://cdn.example.com'
};
#!/usr/bin/env node
const INDEX_FILE_NAME = './www/index.html';
const FILE_PREFIX = "_myproject-min-build";
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const qiniu = require('qiniu');
const UglifyJS = require("uglify-js");
const CleanCSS = require('clean-css');
const config = require('./config');
const INDEX_DIR = path.dirname(INDEX_FILE_NAME);
/** ngAnnotate **/
// const ngAnnotate = require("ng-annotate");
let qiniuConfig = new qiniu.conf.Config();
qiniuConfig.zone = qiniu.zone.Zone_z0;
qiniuConfig.useCdnDomain = true;
let putExtra = new qiniu.form_up.PutExtra();
let mac = new qiniu.auth.digest.Mac(config.qiniu_ak, config.qiniu_sk);
let options = {
scope: config.qiniu_bucket,
};
let putPolicy = new qiniu.rs.PutPolicy(options);
let uploadToken = putPolicy.uploadToken(mac);
let bucketManager = new qiniu.rs.BucketManager(mac, qiniuConfig);
function getMimeType(fileName) {
if (fileName.endsWith('css')) {
return 'text/css';
}
if (fileName.endsWith('js')) {
return 'application/javascript';
}
}
function upload(fileName, minificationType) {
let localFile = path.join(INDEX_DIR, fileName);
return new Promise((resolve, reject) => {
fs.readFile(localFile, { encoding: 'utf8' }, function (err, data) {
if (err) {
throw(err);
}
if (minificationType === "js") {
/** ngAnnotate **/
// data = ngAnnotate(data, {
// add: true,
// });
// if (err || (data.errors && data.errors.length)) {
// throw JSON.stringify(err || data.errors);
// }
// data = data.src;
// console.log(data);
console.log("minify js: ", fileName);
data = UglifyJS.minify(data);
if (data.error) {
throw data.error;
}
data = data.code;
} else if (minificationType === "css") {
console.log("minify css: ", fileName);
data = new CleanCSS(options).minify(data);
if (data.errors.length) {
throw JSON.stringify(data.errors);
}
data = data.styles;
}
let cs = checksum(data, 'sha1');
let key = FILE_PREFIX + '-' + cs + '-' + fileName.replace(/[/\\]/g, '_');
let formUploader = new qiniu.form_up.FormUploader(config);
console.log(" - upload: ", fileName);
formUploader.put(uploadToken, key, data, putExtra,
function (respErr, respBody, respInfo) {
if (respErr) {
console.log(respErr);
reject(respErr);
}
if (respInfo.statusCode === 200) {
bucketManager.changeMime(config.qiniu_bucket, key, getMimeType(fileName), function (err, _respBody, respInfo) {
if (err) {
console.log(err);
reject(err);
} else {
if (respInfo.statusCode === 200) {
resolve(respBody);
} else {
console.log([respInfo.statusCode, _respBody]);
reject([respInfo.statusCode, _respBody]);
}
}
});
} else {
console.log([respInfo.statusCode, respBody]);
reject([respInfo.statusCode, respBody]);
}
});
});
})
}
function checksum(str, algorithm, encoding) {
return crypto
.createHash(algorithm || 'md5')
.update(str, 'utf8')
.digest(encoding || 'hex')
}
const fileOptions = { encoding: "utf8" };
let indexContents = fs.readFileSync(INDEX_FILE_NAME, fileOptions);
async function prod(regexp, minificationType) {
let match = regexp.exec(indexContents);
let results = [];
let replacements = [];
while (match != null) {
let matchedText = match[0];
let before = match[1];
let fname = match[2];
let after = match[3];
if (fname.indexOf('?') >= 0) {
fname = fname.substring(0, fname.indexOf('?'))
}
results.push(
await upload(fname, minificationType).then(_ => {
let url = config.qiniu_domain + '/' + _.key;
console.log(" - - done " + url);
replacements.push([matchedText, before + url + after]);
})
);
match = regexp.exec(indexContents);
}
replacements.forEach(replacement => {
indexContents = indexContents.replace(replacement[0], replacement[1]);
});
return results;
}
(async () => {
await prod(/(<script .*?src\s*=\s*['"]\s*)(.+?)(\s*['"].*?>)/img, 'js');
await prod(/(<link .*?href\s*=\s*['"]\s*)(.+?)(\s*['"].*?>)/img, 'css');
fs.writeFileSync(INDEX_FILE_NAME, indexContents, fileOptions);
console.log("\n\nwriting to ",INDEX_FILE_NAME);
console.log("done");
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment