New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

minifyify

Package Overview
Dependencies
Maintainers
1
Versions
98
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

minifyify - npm Package Compare versions

Comparing version 0.1.1 to 0.2.0

lib/decouple/index.js

303

lib/index.js
var Minifier
, _ = require('lodash')
, concat = require('concat-stream')
, through = require('through')
, uglify = require('uglify-js')
, atob = require('atob')
, path = require('path')
, SM = require('source-map')
, SMConsumer = SM.SourceMapConsumer
, SMGenerator = SM.SourceMapGenerator;
, optimize = require('./optimize');
Minifier = function (opts) {
/*
* Handle options/defaults
*/
opts = opts || {};
Minifier = function (cb, opts) {
return concat(function(data) {
var optimized = optimize(data, opts);
var self = this
, defaults = {
minify: true
, source: 'bundle.js'
, map: 'bundle.map'
, transformPaths: function (filePath) {
// noop
return filePath;
}
};
_.defaults(opts, defaults);
/*
* Instance variables
*/
self.registry = {}; // Keep source maps and code by file
/*
* Registers maps and code by file
*/
self.registerMap = function (file, code, map) {
self.registry[file] = {code:code, map:map};
};
/*
* Gets map by file
*/
self.mapForFile = function (file) {
if(!self.fileExists(file)) {
throw new Error('ENOFILE');
}
return self.registry[file].map;
};
/*
* Gets code by file
*/
self.codeForFile = function (file) {
if(!self.fileExists(file)) {
throw new Error('ENOFILE');
}
return self.registry[file].code;
};
self.fileExists = function (file) {
return (self.registry[file] != null);
}
/*
* Compresses code before Browserify touches it
* Does nothing if minify is false
*/
self.transformer = function (file) {
var buffs = [];
return through(write, end);
function write(data) {
if(opts.minify) {
buffs.push(data);
}
else {
this.queue(data);
}
}
function end(data) {
var unminCode = buffs.join();
if(opts.minify) {
var min = uglify.minify(unminCode, {
fromString: true
, outSourceMap: opts.map
});
this.queue(min.code);
self.registerMap(file, unminCode, new SMConsumer(min.map));
}
this.queue(null);
}
};
/*
* Consumes the output stream from Browserify
*/
self.consumer = function (cb) {
return concat(function(data) {
if(!opts.minify) {
return cb(data, null);
}
else {
var bundle;
try {
bundle = self.decoupleBundle(data);
}
catch(e) {
if(e.toString() == 'Error: ENOURL') {
throw new Error('Cannot consume when browserify is not in debug mode');
}
else {
throw e;
}
}
// Re-maps the browserify sourcemap
// to the original source using the
// uglify sourcemap
bundle.map = self.transformMap(bundle.map);
cb(bundle.code, bundle.map);
}
});
};
/*
* Given a SourceMapConsumer from a bundle's map,
* transform it so that it maps to the unminified
* source
*/
self.transformMap = function (bundleMap) {
var generator = new SMGenerator({
file: opts.source
})
// Map File -> The lowest numbered line in the bundle (offset)
, bundleToMinMap = {}
/*
* Helper function that maps minified source to a line in the browserify bundle
*/
, mapSourceToLine = function (source, line) {
var target = bundleToMinMap[source];
if(!target || target > line) {
bundleToMinMap[source] = line;
}
}
/*
* Helper function that gets the line
*/
, lineForSource = function (source) {
var target = bundleToMinMap[source];
if(!target) {
throw new Error('ENOFILE');
}
return target;
}
, missingSources = {};
// Figure out where my minified files went in the bundle
bundleMap.eachMapping(function (mapping) {
// Is this a known source?
if(self.fileExists(mapping.source)) {
mapSourceToLine(mapping.source, mapping.generatedLine);
}
// Not a known source, pass thru the mapping
else {
generator.addMapping({
generated: {
line: mapping.generatedLine
, column: mapping.generatedColumn
}
, original: {
line: mapping.originalLine
, column: mapping.originalColumn
}
, source: opts.transformPaths(mapping.source)
, name: mapping.name
});
missingSources[mapping.source] = true;
}
});
if(process.env.debug) {
console.log(' [DEBUG] Here is where Browserify put your modules:');
_.each(bundleToMinMap, function (line, file) {
console.log(' [DEBUG] line ' + line + ' "' + opts.transformPaths(file) + '"');
});
}
// Add sourceContent for missing sources
_.each(missingSources, function (v, source) {
generator.setSourceContent(opts.transformPaths(source), bundleMap.sourceContentFor(source));
});
// Map from the hi-res sourcemaps to the browserify bundle
if(process.env.debug) {
console.log(' [DEBUG] Here is how I\'m mapping your code:');
}
self.eachSource(function (file, code) {
var offset = lineForSource(file) - 1
, fileMap = self.mapForFile(file)
, transformedFileName = opts.transformPaths(file);
if(process.env.debug) {
console.log(' [DEBUG] Now mapping "' + transformedFileName + '"');
}
fileMap.eachMapping(function (mapping) {
var transformedMapping = self.transformMapping(transformedFileName, mapping, offset);
if(process.env.debug) {
console.log(' [DEBUG] Generated [' + transformedMapping.generated.line
+ ':' + transformedMapping.generated.column + '] > ['
+ mapping.originalLine + ':' + mapping.originalColumn + '] Original');
}
generator.addMapping( transformedMapping );
});
generator.setSourceContent(transformedFileName, code);
});
return generator.toString();
};
/*
* Given a mapping (from SMConsumer.eachMapping)
* return a new mapping (for SMGenerator.addMapping)
* resolved to the original source
*/
self.transformMapping = function (file, mapping, offset) {
return {
generated: {
line: mapping.generatedLine + offset
, column: mapping.generatedColumn
}
, original: {
line: mapping.originalLine
, column: mapping.originalColumn
}
, source: file
, name: mapping.name
}
};
/*
* Iterates over each code file, executes a function
*/
self.eachSource = function (cb) {
_.each(self.registry, function(v, file) {
cb(file, self.codeForFile(file), self.mapForFile(file));
});
};
/*
* Given source with embedded sourcemap, seperate the two
* Returns the code and SourcemapConsumer object seperately
*/
self.decoupleBundle = function (src) {
var marker = '//@ sourceMappingURL=data:application/json;base64,'
, offset = src.indexOf(marker)
, map;
if(offset<0) {
throw new Error('ENOURL');
}
map = atob(src.substring(offset + marker.length));
try {
map = new SMConsumer( JSON.parse(map) );
}
catch(e) {
throw e;
}
return {
code: src.substring(0, offset) + ';;;\n//@ sourceMappingURL=' + opts.map + '\n'
, map: map
};
};
return this;
cb(optimized.code, optimized.map.toString());
});
};
module.exports = Minifier;

@@ -14,3 +14,3 @@ {

],
"version": "0.1.1",
"version": "0.2.0",
"repository": {

@@ -17,0 +17,0 @@ "type": "git",

@@ -5,10 +5,6 @@ Minifyify

Before, you had to choose between sane debugging and sane load times. Now, you can have both.
Before, browserify made you choose between sane debugging and sane load times. Now, you can have both.
Browserify in debug mode tacks on a massive sourceMappingURL with your uncompressed source code, on top of the already uncompressed bundle, resulting in a single massive Javascript file **more than twice as large as your original source code.**
Minifyify minifies your bundle and pulls the source map out into a separate file. Now you can **deploy a minified bundle in production, and still have a sourcemap handy for when things inevitably break**.
**Bonus:** Since Minifyify is a transform, dead code paths are removed before Browserify processes `require()`s. You only get the modules you actually use in the final bundle. Works great with [envify](https://npmjs.org/package/envify)!
## Usage

@@ -19,27 +15,11 @@

, minifyify = require('minifyify')
, bundle = new browserify()
, minifier;
, bundle = new browserify();
// Create a new minifier object for each bundle
// (All options are optional, but highly recommended)
minifier = new minifyify({
source: 'bundle.js' // Where you intend to place the generated bundle
, map: 'bundle.map' // Where you intend to place the generated sourcemap
, transformPaths: // Great for shortening your source paths
function (filePath) {
// This will make all paths relative to 'project_dir'
return path.relative('project_dir', filePath);
}
});
bundle.add('entryScript.js');
// Note: Pass browserify the transformer, not the minifier object
bundle.transform(minifier.transformer);
// You *must* run in debug mode!
bundle.bundle({debug: true})
// Pipe to the consumer to receive your minified code and accompanying sourcemap
.pipe(minifier.consumer(function(code, map) {
// Pipe output to minifyify
.pipe(minifyify(function(code, map) {
fs.writeFileSync('www/bundle.js', code);

@@ -46,0 +26,0 @@ fs.writeFileSync('www/bundle.map', map);

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc