Giter Site home page Giter Site logo

dryice's Introduction

DryIce

DryIce is a CommonJS/RequireJS packaging tool for browser scripts.

It is basically just a copy function. It takes input from a set of input files, which can be specified in various ways, optionally filters them and outputs them to something else.

DryIce is licensed under the Apache License version 2

Why?

RequireJS has a build tool which is nice and works well, but it requires Rhino and therefore Java. With DryIce, your whole build process can be in JavaScript.

DryIce produces a single file output that can include binary files (by base64 encoding them)

How to install DryIce

sudo npm install dryice

How does it work?

To copy a single file:

copy({
  source: 'foo.txt',
  dest: 'bar.txt'
});

To cat a bunch of files together:

copy({
  source: [ 'file1.js', 'file2.js' ],
  dest: 'output.js'
});

To cat together all the files in a directory:

copy({
  source: { root:'src' },
  dest: 'built.js'
});

As above, but only use the JavaScript files:

copy({
  source: { root:'src', include:/.*\.js$/ },
  dest: 'built.js'
});

As above, but exclude tests:

copy({
  source: { root:'src', include:/.*\.js$/: exclude:/test/ },
  dest: 'built.js'
});

If your set of files is very custom:

copy({
  source: function() {
    var files = [ 'file1.js' ];
    if (baz) files.push('file2.js');
    return files;
  },
  dest: 'built.js'
});

We can filter the files on the way:

copy({
  source: /src/.*\.js$/,
  filter: copy.filter.uglifyjs,
  dest: 'built.js'
});

This includes running multiple custom filters:

copy({
  source: 'src/index.html',
  filter: [
    function(data) {
      return data.replace(/Sun/, 'Oracle');
    },
    htmlCompressor
  ],
  dest: 'war/index.html'
});

Results can be stored and then used/reused:

var sources = copy.createDataObject();
copy({
  source: { root: 'src1' },
  dest: sources
});
copy({
  source: { root: 'src2' },
  dest: sources
});
copy({
  source: sources,
  dest: 'sources-uncompressed.js'
});
copy({
  source: sources,
  filter: copy.filter.uglifyjs,
  dest: 'sources.js'
});

Data objects are just JS objects with a 'value' member, so you can do all sorts of things with them:

var test = copy.createDataObject();
copy({
  source: 'README.txt',
  dest: test
});
console.log(test.value);

Or:

copy({
  source: { value: 'Hello, World!' },
  dest: 'basic.txt'
});

And you can mix and match your inputs:

copy({
  source: [
    'somefile.txt',
    thingDataObject,
    { root: 'src', include: /.*\.js$/ },
    function() { return 'wibble.sh'; }
  ],
  dest: 'mess.bin'
});

Common JS project dependency tracking:

var project = copy.createCommonJsProject({
    roots: [
        '/path/to/source/tree/lib',
        '/some/other/project/lib'
    ]
});
copy({
    source: copy.source.commonjs({
        project: project,
        require: [ 'main', 'plugin/main' ]
    }),
    dest: ''
});

This digs around in the project source trees specified in the project for modules named in the 'require' statement. When it finds them it looks through them for require statements, and finds those, and so on.

Formal Parameter Description

The copy function takes a single parameter which is an object with 2 or 3 members: source, dest and optionally filter.

source

There are 6 ways to specify the input source(s)

  • A string is expected to point to a filename. At some stage we may allow them to point at directories too, however this can be achieved today using a find object (see below)

  • A find object points to a directory with 2 optional RegExps specifying what to exclude and include. e.g.

    { root: '/' } -> The entire filesystem { root: 'src', include: /.*.js$/ } -> All the JavaScript files in 'src' { root: 'src', exclude: /test/ } -> All non-test files under 'src'

  • A data object - something with a 'value' property. The implementation of copy.createDataObject() is simply return { value: '' };. We've batted around some ideas which involve making copy.createDataObject() smarter than it currently is, so it is advised to use this method rather than doing it yourself.

  • A based object. A based object is one with base and path members. They are roughly the same as the string baseObj.base + baseObj.path. Based objects are important when using CommonJS filters, because it tells the filter where the root of the hierarchy is, which lets us know the module name. For example:

    { base: '/etc', path:PATH } where BASE+PATH = filename

  • An array containing input source entries. The array does not have to be homogeneous.

  • A function which returns any input source entries.

filter

The filter member is optional. If it exists, it should contain either a function or an array of functions. The function should have the following signature:

function filter(value, location) {
  ..
  return 'some string';
}

Where the parameters are as follows:

  • value. Either a string or a node Buffer. Most filters will work only with strings, so they should begin:

    if (typeof value !== 'string') {
        value = value.toString();
    }
    

    Some filters will only work with Buffers (for example the base64 encoding filter) so they should begin:

    if (typeof value === 'string') {
        throw new Error('base64 filter needs to be the first in a filter set');
    }
    

    At some stage we may allow filters to be marked up as to their requirements.

  • location. This will be (where possible) a based object or it could be a string if a based object is not available. It will be common to use one of the following idioms to work on a filename:

    if (location.base) {
        location = location.path;
    }
    

    or

    if (location.base) {
        location = location.base + location.path;
    }
    

There are 2 points in a copy run where filters could be used, either before the individual sources are concatenated, or after. Some filters should be used in before (like common-js munging filters) and some afterwards (like compressors).

The default is to run filters after concatenation (when the location parameter will be undefined). To run filters before concatenation, the filter should be marked with onRead = true. For example:

function makeBlank(value, location) {
  return '';
}
makeBlank.onRead = true;

DryIce currently comes with 4 filters:

  • copy.filter.uglifyjs: Calls uglify on the input.
  • copy.filter.addDefines: Wraps the input to inline files fetched using RequireJSs text import feature.
  • copy.filter.base64: Similar to addDefines, but assumes the input is binary and should be base64 encoded.
  • copy.filter.moduleDefines: Replaces define lines to include the module name e.g. define(function(export, require, module) { ... }); is turned into define('module/name', function(export, require, module) { ... });

dest

The dest property should be either a filename to which the output should be written (existing files will be over-written without warning), or a data object to which the data should be appended.

CommonJS Projects

CommonJS projects take a single object with the following properties:

  • roots: This is required. An array of directories that should be searched for your required modules and dependencies.

  • ignores: This is optional. An array of modules or dependencies that are required by your project that you would not like to be included in the build. For example, if you were making a build which did not need to support IE, you could do something like the following

      copy.createCommonJsProject({
          roots: [ '/path/to/project' ],
          ignores: [ 'dom/ie-compat', 'event/ie-compat' ]
      });
    

    then wherever you had require('dom/ie-compat') or require('event/ie-compat') inside your build, undefined would be returned by require.

Where (is the project going)?

DryIce is useful in combining scripts for the browser, but it could also be used in a similar role on the server, we just need to enable 'pass through requires'.

There are some tweaks we'd still like to make to enable more filters and multiple destinations:

To recursively copy a directory:

copy({ source: 'foo', destDir: 'bar' });

To rename files as we copy them:

copy({
  source: { root:'src', include:/.*\.png$/ },
  destDir: { root:'built', replace:/png$/, with:'png.bak' }
});

To create a tarball (this is only missing the targz filter):

var version = copy.createDataObject();
copy({ source: 'VERSION.txt', dest: version });
copy({
  source: { root:'.' },
  filter: [ targz ],
  dest: 'scp://example.com/upload/myproject-' + version + '.tar.gz'
});

I don't suppose you would ever actually want to do this, but in theory you could even do this:

copy({
  source: { root:'src', include:/.*\.java$/ },
  filter: javac,
  destDir: { root:'classes', replace:/java$/, with:'class' }
});

(Actually there would be issues with ordering that would make this hard, and Ant/Maven/etc is probably better. This is an illustration dammit!)

dryice's People

Contributors

berkerpeksag avatar dangoor avatar fitzgen avatar fjakobs avatar janodvarko avatar joewalker avatar mihaisucan avatar mikedeboer avatar nightwing avatar paulb777 avatar stasm avatar tonistiigi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dryice's Issues

Please update to Uglify JS version 2.x

Hi,

we packaged your module in Debian.. However we cannot have different version of UglifyJS in our repository. The UglifyJS we ship is updated to the branch 2.x, which makes your module incompatible with.

Can you please consider an update to support only UglifyJS 2.x?

Here a patch I started to work on, can you review it ?

--- a/lib/dryice/index.js
+++ b/lib/dryice/index.js
@@ -828,7 +828,7 @@
   var code = fs.readFileSync(module.fullname).toString();
   var ast;
   try {
-    ast = ujs.parser.parse(code, false);
+    ast = ujs.parse(code, {strict: false});
   }
   catch (ex) {
     console.error('- Failed to compile ' + module.path + ': ' + ex);
@@ -882,10 +882,8 @@
     }
   };

-  var walker = ujs.uglify.ast_walker();
-  walker.with_walkers(walkers, function() {
-    return walker.walk(ast);
-  });
+  var walker = new ujs.TreeWalker(walkers.call);
+  ast.walk(walker);

   return reply;
 }
@@ -999,27 +997,18 @@
   }

   var opt = copy.filter.uglifyjs.options;
-  var ast;
+
   try {
-    ast = ujs.parser.parse(input, opt.parse_strict_semicolons);
+    return ujs.minify(input, {
+                      fromString: true,
+                      mangle: opt.mangle,
+                      output: { beautify: opt.beautify }
+    });
   }
   catch (ex) {
-    console.error('- Failed to compile code: ' + ex);
+    console.error('- Failed to compile code: ', ex);
     return input;
   }
-
-  if (opt.mangle) {
-    ast = ujs.uglify.ast_mangle(ast, opt.mangle_toplevel);
-  }
-
-  if (opt.squeeze) {
-    ast = ujs.uglify.ast_squeeze(ast, opt.squeeze_options);
-    if (opt.squeeze_more) {
-      ast = ujs.uglify.ast_squeeze_more(ast);
-    }
-  }
-
-  return ujs.uglify.gen_code(ast, opt.beautify);
 };
 copy.filter.uglifyjs.onRead = false;
 /**

Cheers.

Quiet "Failed to find module" errors

I have a couple modules in my app that are either included on the page from another part of the app, or only get conditionally included when in a nodejs environment.

I would like a way to pass in a few modules to be ignore, sort of like how NullModules currently will add that module as undefined. Except, I don't want them to be undefined, I just want dryice to not spit out "err: " during our build script.

dependency management

dryice should be able to gather files either by a module's dependencies or a package's dependencies. (We can start with whichever is easier and then tackle the other in a separate issue).

How to install?

I cannot figure out how to install this. It's not documented anywhere the requirements. It has some makefile, when i run it on OS X it just gives a bunch of errors. What do you require? I have node, I have npm. Where are the details on how this runs?

UglifyJS filter ast_mangle

Hi guys,

seeing the source code i found something not compatible with UglifyJS documentation ...

source code says ...

copy.filter.uglifyjs = function(input) {
    if (typeof input !== 'string') {
        input = input.toString();
    }

    var opt = copy.filter.uglifyjs.options;
    var ast = ujs.parser.parse(input, opt.parse_strict_semicolons);

    if (opt.mangle) {
        ast = ujs.uglify.ast_mangle(ast, opt.mangle_toplevel);
    }

    if (opt.squeeze) {
        ast = ujs.uglify.ast_squeeze(ast, opt.squeeze_options);
        if (opt.squeeze_more) {
            ast = ujs.uglify.ast_squeeze_more(ast);
        }
    }

    return ujs.uglify.gen_code(ast, opt.beautify);
};

but the "ast_mangle" method will be need this way (not boolean value):

ast_mangle(ast, options)

where the options will be:

  • toplevel – mangle toplevel names (by default we don’t touch them).
  • except – an array of names to exclude from compression.
  • defines – an object with properties named after symbols to replace.

checkout:

https://github.com/mishoo/UglifyJS/blob/master/README.org

thks, asssssssom ... lib!

npm install error with dryice

Hi,
for what it is worth:
$npm install dryice
runs into errors (see below). I reported this to the npm developers. However,
$npm install [email protected]
installs ok, so I thought I'd let you know.
Regards,
Joop Ringelberg

npm ERR! Failed creating the tarball.
npm ERR! This is very rare. Perhaps the 'gzip' or 'tar' configs
npm ERR! are set improperly?
npm ERR!
npm ERR! couldn't pack /tmp/npm-1333633517568/1333633517568-0.9729797199834138/contents/package to /home/joop/.node_libraries/.npm/.cache/dryice/0.4.5/package.tgz
npm ERR! Error installing [email protected]
npm ERR! Error: Failed tar "-cvf" "-" "--exclude" ".git" "-X" "/tmp/npm-1333633517568/1333633517568-0.9729797199834138/contents/package/.npmignore" "package/"
npm ERR! exited with 2
npm ERR! at ChildProcess. (/usr/share/npm/lib/utils/exec.js:42:19)
npm ERR! at ChildProcess.emit (events.js:67:17)
npm ERR! at ChildProcess.onexit (child_process.js:192:12)
npm ERR! Report this entire log at http://github.com/isaacs/npm/issues
npm ERR! or email it to [email protected]
npm ERR! Just tweeting a tiny part of the error will not be helpful.
npm not ok

RequireJS configuration support

Having some built-in support for configuring RequireJS based on built paths (when some modules will be dynamically loaded) would be useful.

dryice bundling

Make it so that dryice can be turned into a single .js file with its dependencies built-in. This can use the mini-require.js that is currently in Ace. The idea here is that we can have a dryice tool that just requires nodejs and nothing more to run. (With a small amount of work, it may be possible to make a dryice tool that works on either Rhino or Node! but that's for another day)

destDir feature

Hi, once ...

destDir feature still working ??

thats my source:

dryice.copy({
  source: {
    root: src_directory,
    include: /.*\.js$/
  },
  destDir: {
    root: dist_directory
  }
});

output ... bang !

TypeError: Cannot read property 'value' of undefined
    at Object.copy (/Users/outaTiME/Development/projects/skycop/skyweb-mvc/node_modules/dryice/lib/dryice/index.js:62:24)
    at [object Object].action (/Users/outaTiME/Development/projects/skycop/skyweb-mvc/Jakefile:130:12)
    at [object Object].runNextTask (/usr/local/lib/node_modules/jake/lib/jake.js:363:27)
    at /usr/local/lib/node_modules/jake/lib/api.js:58:10
    at [object Object].runNextTask (/usr/local/lib/node_modules/jake/lib/jake.js:368:15)
    at /usr/local/lib/node_modules/jake/lib/api.js:58:10
    at [object Object].runNextTask (/usr/local/lib/node_modules/jake/lib/jake.js:309:11)
    at [object Object].runTask (/usr/local/lib/node_modules/jake/lib/jake.js:208:10)
    at [object Object].invoke (/usr/local/lib/node_modules/jake/lib/jake.js:56:10)
    at [object Object].action (/Users/outaTiME/Development/projects/skycop/skyweb-mvc/Jakefile:67:30)

thks !

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.