lib/web/asset/bundle.js
var fs = require('fs')
var path = require('path')
var jspm = require('./jspm')
var logger = require('../../logger')('micromono:asset:bundle')
var assign = require('lodash.assign')
exports.prepareBundleInfo = function(assetInfo, publicPath, bundleOptions) {
// Prepare bundleOptions for jspm/systemjs builder
bundleOptions.name = assetInfo.name
bundleOptions = getDefaultBundleOptions(bundleOptions)
var entryFile = assetInfo.main
var bundleCmd = ''
// ignore or include dependencies
var operator = true === bundleOptions.bundleDeps ? ' + ' : ' - '
var deps = assetInfo.dependencies && Object.keys(assetInfo.dependencies)
deps = deps || []
// First we filter all dependencies found in `bundleDeps` and `ignoreDeps` in
// assetInfo. Then add them back with correct operator accordingly.
if (assetInfo.bundleDeps) {
deps = deps.filter(function(dep) {
return -1 === assetInfo.bundleDeps.indexOf(dep)
})
}
if (assetInfo.ignoreDeps) {
// Ignore service bundled deps.
deps = deps.filter(function(dep) {
return -1 === assetInfo.ignoreDeps.indexOf(dep)
})
}
if (deps.length > 0)
bundleCmd += deps.join(operator)
if (assetInfo.bundleDeps && 0 < assetInfo.bundleDeps.length)
// We should include the dependencies regardless the value of `bundleOptions.bundleDeps`
bundleCmd += ' + ' + assetInfo.bundleDeps.join(' + ')
if (assetInfo.ignoreDeps && 0 < assetInfo.ignoreDeps.length)
// We should exclude the dependencies regardless the value of `bundleOptions.ignoreDeps`
bundleCmd += ' - ' + assetInfo.ignoreDeps.join(' - ')
bundleCmd = 'bundle ' + (entryFile ? [entryFile, deps.length > 0 ? operator : ''].join('') : '') + bundleCmd
var outFile = bundleOptions.outFile
if ('/' !== outFile[0])
outFile = path.join(publicPath, outFile)
// override to make sure systemjs use the correct `outFile` path
bundleOptions.outFile = outFile
bundleCmd += exports.convertBundleOptionsToStr(bundleOptions)
return {
bundleCmd: bundleCmd,
bundleOptions: bundleOptions
}
}
exports.bundle = function(assetInfo, packagePath, jspmBinPath, bundleCmd, bundleOptions, set) {
var publicURL = assetInfo.publicURL[0]
jspm.runJSPM(packagePath, jspmBinPath, bundleCmd.split(' '), function(err) {
if (err)
return set('error', err)
var outFileJs = bundleOptions.outFile
logger.debug('Check js output file', {
outFile: outFileJs
})
fs.stat(outFileJs, function(err, stats) {
if (stats && stats.isFile()) {
logger.debug('JSPM js file bundled', {
outFile: outFileJs
})
assetInfo.bundleJs = path.join(publicURL, path.basename(outFileJs))
} else {
assetInfo.bundleJs = false
}
set('bundleJs', assetInfo.bundleJs)
})
var outFileCss = outFileJs.replace(/\.js$/, '.css')
logger.debug('check css output file "%s"', {
outFile: outFileCss
})
fs.stat(outFileCss, function(err, stats) {
if (stats && stats.isFile()) {
logger.debug('JSPM css file bundled', {
outFile: outFileCss
})
assetInfo.bundleCss = path.join(publicURL, path.basename(outFileCss))
} else {
assetInfo.bundleCss = false
}
set('bundleCss', assetInfo.bundleCss)
})
})
}
exports.bundleDevDependencies = function(assetInfo, publicPath, packagePath, jspmBinPath, set) {
logger.info('Bundle development dependencies', {
publicPath: publicPath,
}).debug({
jspmBinPath: jspmBinPath,
packagePath: packagePath
}).trace(assetInfo)
if (assetInfo.dependencies) {
var main = assetInfo.main
assetInfo.main = ''
var bundleInfo = exports.prepareBundleInfo(assetInfo, publicPath, {
bundleDeps: true,
sourceMaps: false,
sourceMapContents: false,
minify: false,
inject: false,
buildCss: true,
separateCss: true,
outFile: 'bundle-' + assetInfo.name + '-dev-deps'
})
assetInfo.main = main
bundleInfo.bundleCmd = bundleInfo.bundleCmd.replace(new RegExp(assetInfo.main + '\s\+'), '')
logger.debug('bundleInfo', bundleInfo)
exports.bundle(assetInfo, packagePath, jspmBinPath, bundleInfo.bundleCmd, bundleInfo.bundleOptions, set)
}
}
exports.convertBundleOptionsToStr = function convertBundleOptionsToStr(options) {
var str = ' ' + options.outFile
if (!options.sourceMaps)
str += ' --skip-source-maps'
if (options.sourceMapContents)
str += ' --source-map-contents'
if (options.inject)
str += ' --inject'
if (options.minify)
str += ' --minify'
if (!options.mangle)
str += ' --no-mangle'
return str
}
/**
* Private functions
*/
function getDefaultBundleOptions(opts, env) {
opts = opts || {}
var _opts = {
bundleDeps: false,
outFile: 'bundle' + (opts.name ? '-' + opts.name : '') + '.js',
sourceMaps: 'inline',
sourceMapContents: true,
lowResSourceMaps: true,
inject: false,
minify: false,
mangle: false,
buildCss: true,
separateCss: false
}
env = env || process.env.NODE_ENV
// Set default options for production.
if ('production' === env) {
_opts.bundleDeps = true
_opts.sourceMaps = false
_opts.sourceMapContents = false
_opts.lowResSourceMaps = false
_opts.inject = true
_opts.minify = true
_opts.mangle = true
_opts.buildCss = true
_opts.separateCss = true
}
_opts = assign(_opts, opts)
// make sure we have the `.js` suffix for outFile
var ext = path.extname(_opts.outFile)
if (!ext) {
_opts.outFile += '.js'
} else if ('.js' !== ext) {
// Replace it with the .js suffix. e.g. `.jsx`.
_opts.outFile = _opts.outFile.slice(0, -ext.length) + '.js'
}
return _opts
}