Code Monkey home page Code Monkey logo

steal-tools's Introduction

steal-tools

Build Status Build status npm version Coverage Status

steal-tools is a collection of command-line utilities that:

  • makes building ES6, CommonJS, AMD, applications and plugins easy, and
  • writes those builds so your apps load fast.

It is one half of the StealJS project. It's other half, steal provides client-side dependency management.

For more information on steal-tools, visit stealjs.com.

For information on contributing and developing steal-tools, go here.

steal-tools's People

Contributors

alexisabril avatar alfredo-delgado avatar asavoy avatar bigab avatar bmomberger-bitovi avatar chasenlehara avatar cherifgsoul avatar daffl avatar dezigntime avatar frank-dspeed avatar greenkeeper[bot] avatar icarito avatar ilyavf avatar janeori avatar julia-allyce avatar justinbmeyer avatar m-mujica avatar marshallswain avatar matthewp avatar mehiel avatar mjstahl avatar phillipskevin avatar pyr0x avatar reinaldoarrosi avatar retro avatar wclr 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

Watchers

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

steal-tools's Issues

Set up JSHint and release

JSHint should be part of the Travis test script. Also need to set up a release process to get things published on NPM and Bower.

Names generated for main bundles may override one another

When building an app with several main modules, the main module's filename is used as the name for its bundle filename. Since all bundles are put into one folder, it's possible for one to override another.

Take a hypothetical app that builds two main modules, users/edit/edit and tasks/edit/edit:

  1. tasks/edit/edit.js is built into bundle dist/bundles/edit.js
  2. users/edit/edit.js is built into bundle dist/bundles/edit.js, overriding the first bundle.

Multi-build in legacy-steal avoided this by naming the bundle production.js and putting in the same directory as the originating bundle. (But I do prefer this new behavior of keeping all production files in one dist folder, though.)

Some potential solutions:

  1. Use the relative path of the main bundle, replacing each "/" with "__", for the name of the bundle. That is, tasks/edit/edit.js would become dist/bundles/tasks__edit__edit.js. This is what I have hacked into my test project.
  2. Recreate the paths in the dist/bundles folder. That is, tasks/edit/edit.js would become dist/bundles/tasks/edit/edit.js.

Important to note that I believe StealJS would need to be updated to do the same thing in production mode, too, so whatever naming scheme is used, it must be possible for a client to do also. That means we can't use incrementing numbers or such.

Debug messages

By default, steal-tools should be log messages to let you know what it's doing. There should be a {silent: true} options that turns them off.

Build API

Here's some build API proposals:

JAVASCRIPT API

@function StealTools.build

@Signature StealTools.build( buildConfig, buildOptions )

@param {buildConfig} buildConfig SystemJS configuration options. config and main must be passed.

@return {Promise} A deferred with build data.

Use

var StealTools = require('steal-tools');
StealTools.build( {
  config: __dirname+"/stealconfig.js",
  main: "main.js"
} , buildOptions );

@typedef {} buildConfig

@option {String} config The path to stealconfig.js. This also determines the root.
@option {moduleName} main The main module name.

All other properties of buildConfig are set on System.

@typedef {} buildOptions

@option {String} [distdir='~/dist'] The location of where the build files should be outputted.
@option {Boolean} [bundleSteal=false] Include steal in the bundle.
@option {Boolean} [debug=false] Turns on debug messages
@option {Boolean} [quiet=false] No logging.
@option {Boolean} [dataOnly=false] Prevents writing out the bundles.
@option {Object} [uglifyOptions]
@option {Object} [lessOptions]

@typedef {} buildData

@option {buildGraph} graph A map of moduleNames to node.
@option {steal} steal The steal function used to load the main module.
@option {Loader} loader The loader used to load the main module.
@option {Array} bundles The builds written out.

GRUNT API

Use cases:

  • In-place build - A build that works within the current development environment. Images will not need to be moved.
  • Dest build - A build that is self contained. All necessary static resources are built and copied to a specific folder.
  • Inline JS / CSS
  • Top Load CSS
  • Versioning
module.exports = function (grunt) {
  grunt.initConfig({
    stealBuild: {
      options: {
        system: {
          main: "foo",
          config: "stealconfig.js"
        },
        buildOptions: {
          debug: true
        }
      }

    }
  });
  grunt.registerTask('build',['stealBuild']);
};

Allow main to be defined in config

In dev mode, I have:

steal.config({ main:"main" });

and

<script src="path/to/steal.js" data-config="stealconfig.js" data-env="development"></script>

and it works.

But when I try to build with:

stealTools.build({ config:"stealconfig.js", bundlesPath:"build/" });

I get this error:

OPENING: undefined
error [ReferenceError: jQuery is not defined] ReferenceError: jQuery is not defined

I don't know exactly why jQuery was involved in this, but I do know that it should read "OPENING: main". Somewhere in the code, config.main (pseudo) is not checked for.

Standardize API for build/pluginify

The first argument to build/pluginify should both be the system config. For build, provide a second argument of options, for pluginify the options are provided after the Promise is fulfilled by calling the returned pluginify function.

Support running multiple builds at the same time.

You can't currently call two builds one after another. I'm pretty sure this has to do with what System / steal is global. Hopefully this is something wrong in our code and not SystemJS.

I'll submit a test shortly.

Error when running built app

My app works fine in dev, but after running a production build, I get this error when attempting to initialize:

[Error] TypeError: 'undefined' is not an object (evaluating 'System.paths') (init.js, line 4)

This is lines 3โ€“5 in init.js:

/*[system-bundles-config]*/
System.paths["bundles/*.css"] = "../build/*css";
System.paths["bundles/*"] = "../build/*.js";

and here're lines 1โ€“2 of the same file:

/*[traceur-runtime]*/
this._System=this.System,function(t){"use strict"; ...

Support cleanOptions for CleanCSS

I need to be able to configure the CSS minification step, or disable it entirely.

With the current defaults, it performs merging of properties, which is often undesirable. Example here is a common pattern for high DPI images:

background-image: url(image.png);
background-image: -webkit-image-set(url(image.png) 1x, url([email protected]) 2x);

After running a build, becomes:

background-image: -webkit-image-set(url(image.png) 1x, url([email protected]) 2x);

CommonJS module/exports behaves differently when built

Let's say i have main.js that looks like this

var conf = require('conf');
console.log(conf);

and conf.js

module.exports = { foo: 'bar' };

When the application is not built, it logs

{foo: 'bar'}

but once built, it logs

{exports: { foo: 'bar' } }

Pluginify doesn't know about mappings

It's possible for a module to be mapped (as is done in CanJS for can/util) to another module. Because pluginify's shim doesn't know about mappings it will fail to provide a module's dependencies that is relying on the mapping.

I have an idea of what might need to be done to fix this but want to talk about it.

Possibly the same fix as this will fix #30

Pluginifying to global includes System.set calls

When attempting to pluginify (to a "global") a file that uses the system Stache plugin I am seeing this in the output:

System.set('can/view/stache/system', System.newModule({}));

Which throws an error because we do not shim these 2 functions. I think we can safely exclude these from the build, right?

Jquery is not minimized while build

I have defenition in path:

"jquery": "bower_components/jquery/dist/jquery.js",

after build my bundle js is is 394K

So I replace it with

"jquery": "bower_components/jquery/dist/jquery.min.js",

after build my js is 225K is

it correct behaviour?

There is also a problem with minified file in production: some times app in production tries to load jquery.min.map

http://localhost:5000/jquery.min.map 404 (Not Found) 

Support UMDish AMD files

A file like:

document.SOMETHING
if(define){
  define("d3", d3)
} else {
  window.d3 = d3
}

will break building. We need another form of AMD that doesn't need to run (similar to CJS) to get all the dependencies.

Need a way to get css build with pluginify

Since pluginify provides a small shim it is an ideal way to build small apps. However currently pluginify only works with js, if you have css in the file you'll get this in the build:

/*styles.less!$less*/
undefined

Perhaps the pluginify function should have an option to get the css back instead of the js? Or perhaps an option to get both?

Watch mode

It would be nice if we could produce a "watch mode". This would be part of the build and pluginify. It would watch for changes in the files in your graph and reload just those files (and their dependencies). It would be a very fast build.

Along with this we should also support node_modules just for watch mode (not in the browser). This would be very simple to implement, it would just be a fetch hook that, if the fetch fails, uses require.resolve to look-up the path in node_modules, if present, and then retry with that path.

These 2 things would give us 90% of the things people like about Browserify and WebPack; near-instant builds in development mode and using npm so it "just works".

Specify bundles locations

Allow someone to specify an alternative folder where the bundles should be:

{bundlesDir: __dirname+"/to/here/"}

Pluginify includes plugins with build

Unlike the multi build, pluginify doesn't remove plugins not marked as includeInBuild so you get things like this in the build:

System.set("$less", System.newModule({}));

This causes errors when you run the built file.

Build is not working with stache and can#minor

I'm using stache templates in my app (and canjs#minor) and when I'm trying to build the app I've got an error:

error [ReferenceError: document is not defined] ReferenceError: document is not defined

Currently as workaround around I replace stache with mustache engine in stealconfig.js:

stache: "can/view/mustache/system"

Backslash path in on windows

On windows in build bundle module we have dist\bundles:

System.paths["bundles/*.css"] ="dist\bundles/*css";

to be more correct and consistent there should be slash dist/bundles

Build failure if builder runs into `can.view` on an html element

Rhino steal is able to support stuff like can.view("#some-id"), but steal-tools crashes

Steps

  1. Set up an app file with can.view("#body-template") in the steal callback.
  2. Run steal build app.js
  3. Try again using rhinosteal instead

Results

ERROR CALLING src/app.js : can.view: No template or empty template:body-template.mustache

Expected

I'm not sure exactly what Rhinosteal does, but it's able to support this. I resolved this particular one locally by preventing the code from executing using steal.isBuilding, but we should be more compatible than this.

Support building apps from `.html` file

If I target the page's .html file with steal-tools when I build, it fails silently. Rhino steal usually targets the webpage itself, since it scans it for <link> and <style> tags that will be included in the final production.css file.

Steps

  1. Install steal-tools
  2. Set up an .html page that refers to steal/steal.js?some-app
  3. Create a valid some-app.js file
  4. Add a <link> and a <style> tag to it in <head>
  5. Run steal build path/to/app.html

Results

Building to ./
  opening app.html

(exit 0)

Expected

The full, proper build should run, just like it does with Rhinosteal.

Error handling and messages

Error handling seems a little off still at the moment. For example, if you run a build with the command line tool and it fails, you get several error messages and a warning and it says "Build completed sucessfully".

The promises should be able to bubble errors all the way to the top where the end user (programatically, command line, Grunt) can handle it. We should add tests for common error cases.

Investigate if we can exclude the traceur runtime

This is dependent on stealjs/steal#227 being complete, but writing this down so it doesn't get forgotten.

The newer versions of Traceur no longer compile import statements with the assertObject runtime call that they previous did. This means we might be able to exclude the runtime for code that doesn't need it. Need to:

  • Investigate what code causes runtime to be needed
  • Find a way to check if the runtime is needed during the build
  • If the runtime isn't being used by user-code, don't include it in the final build (multi build and pluginify)

Pluginify doesn't work with CommonJS transpiled modules

CommonJS modules are transpiled by transpile using the define wrapper, but the pluginify shim doesn't know about this style of define.

It's pretty easy to patch this, just check that there are no dependencies in the dependencies array and that the callback has a length (at least 1 argument, as many as 3).

I'll send a fix with test.

Pluginify doesn't work with relative path dependencies

In foo.js

steal('./something.js', function(something) {});

Compiles to:

define('path/to/something', [], function(){})

define('foo', ['./something'], function(something) {});

Should update foo's dependencies I believe. Breaking test to come.

Output file sizes while build

It would be convenient to have sizes of all file included in the build outputted while build process and maybe compress ratio. And also sizes of result bundles.

Consider renaming exports option for pluginify

Pluginify has an option called exports that you use like this:

pluginify(system, {
  exports: {
    "jquery": "jQuery"
  }
}).then(function() { ... })

jQuery being any object on the window. Exports is an inappropriate name here. Perhaps imports?

Also we might want to have an actual exports option where you export your module's definitions onto the window.

Generated file names for bundles can exceed file system limit

I tried updating a large project to test the latest Steal and discovered the build won't complete because the filename generated for a widely shared bundle is too long for the file system.

This is the same issue that I proposed a pull-request on in legacy StealJS in stealjs/steal#170 - NOTE: GitHub seems to have mangled that page with history from a separate issue. The relevant comments are Justin's and my response.

In that PR I suggest taking truncating long file names and appending a hash, which I think is still reasonable.

bundle: false

We should be able to tell a module that it should not be packaged in production. We should explore how requirejs does this. If requirejs doesn't have an API for it, I suggest putting it on meta:

System.meta.html5Shiv = {bundle: false};

CI integration

Travis is failing because it is running grunt test which is not used any more. Since Mocha is a dev-dependency we can make npm test trigger mocha test/test.js and everything should be good.

Support UMD export

This would be nice. Currently pluginify has a global format that is useful for people not using a module loader at all. A umd format would just be the UMD shim wrapped around global's output.

UX: Shouldn't be forced to leave off .js extension.

I've been getting the following error when building:

error { [Error: ENOENT, open '/Users/marshallthompson/Sites/grm/public/apps/main/components/fleet-editor.js.js']
  errno: 34,
  code: 'ENOENT',
  path: '/Users/marshallthompson/Sites/grm/public/apps/main/components/fleet-editor.js.js' } Error: ENOENT, open '/Users/marshallthompson/Sites/grm/public/apps/main/components/fleet-editor.js.js'

This only happens when instead of putting the module name I put the filename. I think it's supposed to work this way, so it doesn't technically qualify as a bug, but I can't think of any reason it HAS to be this way. It seems to me like we should be able to make steal recognize if a .js extension is already present, and therefore not append another one.

Since we're using the file extension plus a bang (.css!) to require/import other files, it would be more consistent to allow javascript to be imported with or without the extension. This would make even more sense if we get it to the point that the bang is optional for non-js files.

Here is one thing that's interesting about this problem that I think does qualify as a bug. This is my main.js file that throws the error:

require('./main.css!');
require('./components/fleet-editor.js');

If I change the css require to use import like this:

// No error thrown this way.
import './main.css!';
require('./components/fleet-editor.js');

It doesn't try to add the extra .js extension, so it doesn't throw the error upon building. If I do it the other way around, like this:

require('./main.css!');
import './components/fleet-editor.js';

The error still occurs on build. If both are imported, it still throws an error. But of course, if I do it this way and leave off the .js extension:

require('./main.css!');
require('./components/fleet-editor'); // No .js, let the party go on!

The build completes without a problem.

I think I'm smart enough to figure out how to leave the extension off of .js files, but for new-comers, if it's going to be required to stay this way, it ought to have a more useful message on how to fix it rather than just throw an error for them to decipher.

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.