Is there a way to include file in coffee script? - javascript

I'd like to know if there is a way to include a file in a coffee script.
Something like #include in C or require in PHP...

If you use coffeescript with node.js (e.g. when using the commandline tool coffee) then you can use node's require() function exactly as you would for a JS-file.
Say you want to include included-file.coffee in main.coffee:
In included-file.coffee: declare and export objects you want to export
someVar = ...
exports.someVar = someVar
In main.coffee you can then say:
someVar = require('included-file.coffee').someVar
This gives you clean modularization and avoids namespace conflicts when including external code.

How about coffeescript-concat?
coffeescript-concat is a utility that preprocesses and concatenates
CoffeeScript source files.
It makes it easy to keep your CoffeeScript code in separate units and
still run them easily. You can keep your source logically separated
without the frustration of putting it all together to run or embed in
a web page. Additionally, coffeescript-concat will give you a single
sourcefile that will easily compile to a single Javascript file.

Tl;DR: Browserify, possibly with a build tool like Grunt...
Solutions review
Build tool + import pre-processor
If what you want is a single JS file to be run in the browser, I recommend using a build tool like Grunt (or Gulp, or Cake, or Mimosa, or any other) to pre-process your Coffeescript, along with an include/require/import module that will concatenate included files into your compiled output, like one of these:
Browserify: probably the rising standard and my personal favourite, lets you to use Node's exports/require API in your code, then extracts and concatenates everything required into a browser includable file. Exists for Grunt, Gulp, Mimosa and probably most others . To this day I reckon it is probably the best solution if you're after compatibility both Node and the browser (and even otherwise)
Some Rails Sprocket-like solutions like grunt-sprockets-directives or gulp-include will also work in a consistent way with CSS pre-processors (though those generally have their own importing mechanisms)
Other solutions include grunt-includes or grunt-import
Standalone import pre-processor
If you'd rather avoid the extra-complexity of a build tool, you can use Browserify stand-alone, or alternatives not based on Node's require like coffeescript-concat or Coffee-Stir
[Not recommended] Asynchronous dynamic loading (AJAX + eval)
If you're writing exclusively for the browser and don't mind, or rather really want, your script being spread across several files fetched via AJAX, you can use a myriad of tools like:
yepnope.js or Modernizr's .load based on yepnope: Please note that yepnope is now deprecated by its maintainer, who recommend using build tools and concatenation instead of remote loading
RequireJS
HeadJS
jQuery's $.getScript
Vanilla AJAX + eval
your own implementation of AMD

You can try this library I made to solve this same problem coffee-stir
its very simple.
Just type #include and the name of the file that you want to include
#include MyBaseClass.coffee
For details
http://beastjavascript.github.io/Coffee-Stir/

I found that using "gulp-concat" to merge my coffee scripts before processing them did the trick. It can be easily installed to your project with npm.
npm install gulp-concat
Then edit your gulpfile.js:
var gulp = require('gulp')
,coffee = require('gulp-coffee')
,concat = require('gulp-concat');
gulp.task('coffee', function(){
gulp.src('src/*.coffee')
.pipe(concat('app.coffee')
.pipe(coffee({bare: true}).on('error', gulp.log))
.pipe(gulp.dest('build/')
})
This is the code I used to concatenate all my coffee scripts before gulp processed it into the final build Javascript. The only issue is the files are processed in alphabetical order. You can explicitly state which file to process to achieve your own file order, but you lose the flexibility of adding dynamic .coffee files.
gulp.src(['src/file3.coffee', 'src/file1.coffee', 'src/file2.coffee'])
.pipe(concat('app.coffee'))
.pipe(coffee({bare: true}).on('error', gulp.log))
.pipe(gulp.dest('build/')
gulp-concat as of February 25th, 2015 is available at this url.

Rails uses sprockets to do this, and this syntax has been adapted to https://www.npmjs.org/package/grunt-sprockets-directives. Works well for me.

Related

Bazel auto generate dependencies for ts_library

Is it possible to auto-generate the dependencies of a bazel target? It seems like there should be a way to look at the imports of the module and know which bazel dependencies are needed at least in a lot of cases common cases. This could save a lot of boilerplate code.
load("#npm_bazel_typescript//:index.bzl", "ts_library")
ts_library(
name = "lib",
srcs = glob(include = ["**/*.ts"]),
# Is there any easy way to generate this list?
deps = [],
)
I know there are packages for Java that do this. https://github.com/johnynek/bazel-dep. I haven't been able to find anything for any other languages.
If it doesn't exist I think it could be pretty straightforward to write. Create a template file for you to work off of creating the real BUILD file. Then run typescript to pull the AST of the module. Look through the imports. The 3rd part imports will be easier since they should resolve to an npm module.
For other files that may or may not be in this library then there might be a way to query what package they live int. That could probably work. Any pointers would be very much appreciated.
Disclosure: I am one of the authors of this library.
https://github.com/evertz/bzlgen
It can generate BUILD files (or, more precisely it generates buildozer commands) for Angular (ng_module) and SCSS (scss_library and scss_binary) libs.
I've just moved this in to opensource from our internal repo. It works in a similar way to what you suggest, however it doesn't query for labels. It uses a file or directory as a starting point, parse into an AST, query the AST to fetch imports and reexports, convert the paths into labels.
Adding ts_library support is a logical next step.
It doesn't always get you a 100% working BUILD file currently, but it will get you ~80-90% of the way there, and do the boilerplate parts for you.
Another approach would be to interact with the Gazelle API, and manipulate the BUILD files directly.
A previous version of this tool generated the BUILD files from a string and it got difficult to work with when manipulating the files in other ways.

Creating a JS library and declare what other libraries in depends on

So I'm writing a php-package which will be put on github&packagist. It generates and writes data to a file, and the package will also come with a js-library which job is to read that data-file and display it to the user.
Now, this js-library depends on other libraries, jquery being one among a couple others.
What would be a clean way of declaring those dependencies?
I don't mind using require.js and I have in fact used it for several other projects. But those projects have been complete "apps", not libraries that others are to include in their projects. So in those cases it was no concern adding dependencies and configuring require.js, and it only had to be done once. But this time I want to be able to include this library with minimal amount of code, preferbly without long instructions on how to load it correctly and what other libraries the developer would need to load in as well.
In short: I want to distribute a library that depends on other libraries, which me or another developer can include in another project with minimal amount of code and without knowledge of what other libraries this one depends on.
I'm sure this has been asked before, but I can't seem to find anything on it. I do find lot of information on how to declare dependencies in main projects, but not in libraries.
You have two options:
Bundle your application into a single file(including 3th party libraries)
Just bundle your application into a single file (without including 3th party libraries)
In both cases you will need to create an automated build. You can use gulp to create tasks to concatenate all your files into a single file like framework.js and framework.min.js files that other developers will import.
You can use If you are using require.js you could use the gulp-requirejs plugin to run the requirejs optimizer:
var gulp = require('gulp'),
rjs = require('gulp-requirejs');
gulp.task('requirejsBuild', function() {
rjs({
baseUrl: 'path/to/your/base/file.js',
out: 'FILENAME\_TO\_BE\_OUTPUTTED',
shim: {
// standard require.js shim options
},
// ... more require.js options
})
.pipe(gulp.dest('./delpoy/')); // pipe it to the output DIR
});
If you decide to include the 3th party libraries as well, use the No conflict fucntion to avoid problems if somebody has already loaded jquery.
If you decide to don't include the libraries you can look for some variables in the global scope in your library and throw errors if the dependencies are not available.
if(typeof $ === "undefined") throw new Error("Framework requires > Jquery 1.9.0");
You can usually find the version of a library with ease, for example in jquery:
$.prototype.jquery
Update
I would personally recommend to use Browserify. If you are using requirejs, you can use browserify-ftw to automatically migrate your project from AMD to CommonJS.
The Browserify optimizer will generate a bundle.js file that your users will be able to import directly without having to download 3th party dependencies or configuring a module loader.
Hope it helps :)

Module definition to work with node.js, require.js and with plain scripttags too

I am working on a javascript module/library that should work in 3 environments:
in node.js
in requirejs
when simply included using tags into the webpage. In this case the whole module should be hooked up under window.myModule
Do you have any suggestions as to how to write the structure of the library so that it works in all these environments?
EDIT: basically I mean some sort of wrapper code around the library so that I can call the file form any of those three methods and I'm fine...
This requirement and its solution is known as Universal Module Definition (UMD). It is currently a draft proposal. Background and current status is described in Addy Osmani - Writing Modular JavaScript With AMD, CommonJS & ES Harmony article. Look for "UMD" link pointing to various templates you can use.
Quite many other templates can be found on the web - UMD is the search keyword.
(did not find the final link myself yet :)
We're working on the same thing, I think.
And we have some success. We have library (we call it 'slib'), compiled to AMD js files. It does not depend on npm modules or browser, so it can be called from node and from browser.
1) To call it from node, we use requirejs:
file require.conf.js
module.exports = function(nodeRequire){
global.requirejs = require('requirejs');
requirejs.config({
baseUrl: __dirname+"/../web/slib/",
paths: {
slib: "."
},
nodeRequire: nodeRequire
});
}
In any other serverside (nodejs) file we add this line at the beginning
require("./require.conf")(require);
then we call slib's code by:
var Computation = requirejs("slib/Computation");
2) To call slib from browser, we just use requirejs. It handles everything fine.
3) We do not need to call slib from < script > directly.
For production, we use r.js to make a bundle js file with most of dependencies and use it on the page with one < script >. And this script downloads all other deps, if they are not included, using standard requirejs and it does not need requirejs (as far as I remember), it just works alone. This is very flexible for large projects: use requirejs while development, use r.js to bundle core files in production to speed up page load, use whole bundle if you need only one < script > without any other requests. r.js bundles all dependencies correctly, including old js libraries, which were commonly loading using only < script > and accessible by window.myOldLibrary using shim param on config.
It seems you can use browserfy to make some npm modules accessible from slib's code, but we did not tried yet.
Also, using requirejs on node's side, I think, can be simpler (why we need second 'requirejs' function together with node's one?) We just have not investigated it well, but this works.
In any slib module you can write
if (window)
window.module1 = this // or whatever
and it will be exported as old js lib upon load

Generating source maps for multiple concatenated javascript files compiled from Coffeescript

Has any one had any success with this?
I think it's more or less an unsolved problem:
https://github.com/jashkenas/coffee-script/issues/2779 . Last meanigingful comment was from jwalton, a month ago.
Still, it doesn't seem rocket science to add support for it, so it will probably come soon.
Michael Ficarra (creator of CoffeeScript Redux) suggested using https://github.com/michaelficarra/commonjs-everywhere .
Two caveats:
It only works for bundling CommonJS modules.
It uses CoffeeScript Redux, which is still in beta (although working quite well it seems), and not 100% compatible with original CoffeeScript compiler.
So this does not work for what you ask for specifically, "concatenation".
Added April 14
You might have luck with these: combine-source-map and/or generate-sourcemap, both by same author.
Added April 26
This looks really simple: https://npmjs.org/package/mapcat . You just have to feed it the individual source map files generated by the coffee compiler.
Added May 16
Mariusz Nowak has just released webmake-coffee. Like CommonJS Everywhere, it requires code to be organized as CommonJS modules. Unlike CommonJS everywhere, it uses regular CoffeeScript.
It also seems the Grunt Coffee-Script plugin has had source-map support for concatenated files for quite a while (two months), effectively proving my original answer to be incorrect.
The upcoming version 2.0 of Snockets will have support for it too.
I ended up going with browserify using coffeeify as the transform option, and enabling browserify's debug option. I bundle up the app on each request for my main.js file, and any runtime errors show up in my original source with pretty decent accuracy.
Sure beats mapping runtime errors in the concatenated/compiled js back to the coffee source with my eyeballs!
I needed to annotate AngularJS code before minification, but grunt-ng-annotate didn't accept input source maps, thus I would not be able to use maps generated by the CoffeeScript compiler.
Apparently, with gulp-sourcemaps this is not an issue:
var gulp = require('gulp');
var $ = require('gulp-load-plugins')(); // loading gulp plugins lazily
// remember to include them in the package.json
gulp.task('appJS', function() {
// concatenate compiled .coffee files and js files into build/app.js
gulp.src(['./app/**/*.js','./app/**/*.coffee'])
.pipe($.sourcemaps.init())
.pipe($['if'](/[.]coffee$/, $.coffee({bare: true}).on('error', $.util.log)))
.pipe($.concat('app.js'))
.pipe($.ngAnnotate())
.pipe($.uglify())
.pipe($.sourcemaps.write())
.pipe(gulp.dest('./build'))
});
The same approach works in other situations, too. In my case, this is the only approach that worked.
I have written a grunt task that does this flawless. Check it out

Client Side Dependency Management in CoffeeScript

What is the best way to do Dependency Management amongst CoffeeScript files if the resulting javascript files eventually need to be concatenated together for use on the client side?
For server side CoffeeScript I can just use the 'require' keyword to require other pieces of javascript. When this is compiled for client side apps to have the dependency tree, based on the requires, calculated and a concatenated stand alone javascript file produced. Is there anyway to do this in a generic way?
Another option is to use CoffeeToaster, which uses another approach than implementing AMD / CJS module patterns.
Take a look:
http://github.com/serpentem/coffee-toaster
Usually, for client-side packaging of JavaScript (and CSS), you want some sort of asset-packaging plugin. We use Jammit, but there are many other options: Sprockets, Django-Compress ... and more.
Villain (a CoffeeScript game engine for browsers) defines functions that do just that (dependency management and js concatenation).
The code for that is in these two files:
cake.coffee, see , determineDependencies(), wrapModule(), and bundleSources()
brequire.coffee, a require replacement for the browser, to use with wrapModule()
I use it here (see the 'bundle' Cake task).
Note: I just declare the 'main' module's build directory, and Villain scans my compiled JS files to build the dependency tree (starting with index.js), then creates a JavaScript bundle file containing Villain's require replacement and all my relevant code sorted and correctly wrapped.
Villain's author uses it in orona, a CoffeeScript game made with Villain.
For dependency management on client side, I use requirejs for javascript and coffeescript source. It'possible to use a requirejs plugin to load natively coffee files, but I prefer to "compile" into js.
requirejs also provide / work with r.js optimizer. It can be used to aggregate a set of js file into one and minified it. you don't have to specify the file to aggregate it is the dependency definition of each module require by your "main.js". (feature that match your request)
Something I like a lot with requirejs, it "promots" creating module and declare explicit dependencies.
# A.coffee
define(() ->
class A
constructor: (#c1, #c2) ->
#c2 ?= 1
m1 : () ->
"hello"
toString : () -> "#{#c1}#{#c2}"
)
# B.coffee
define(['A'], (A) ->
a = new A(33)
console.log(a, a.m1())
)
I've used (and I guess am still using) requirejs but I've started to find it to be fairly clumsy. A lot of my files end up having ~10-12 imports at the top which just take up a lot of space and don't look great.
For a new project I tried browserify. It's great! And if you use grunt (you should), you can make a watch task to browserify your code on change. grunt-browserify also provides the ability to do a coffeescript transform.
https://github.com/jmreidy/grunt-browserify
So your watch task in your Gruntfile.coffee would look something like:
watch:
files: [
"app/**/*.coffee"
]
tasks: "browserify"
browserify:
'build/app.js': ['app/**/*.coffee']
options:
transform: ['coffeeify']

Categories

Resources