Using Jade Templates (jade-lang.com) client-side - javascript

I'd like to use Jade templates client-side. Preferably generated using the Rails 3.1 asset pipeline. I can't really figure out how to do this.
Anyone who've stumbled upon the same problem and found a great solution? Any thoughts are much appreciated.
http://jade-lang.com/
http://ryanbigg.com/guides/asset_pipeline.html

If you use browserify you can use this handy jade middleware: jadeify.
Then you can just call jadeify("foo.jade", { x : 4, y : 5 }) browser-side after pointing a views directory at the middleware and you get back a jquery handle.

P.S: Probably right now Substack's answer is better.
browserify
Maybe you can use https://github.com/substack/node-browserify
Browser-side require() for your node
modules and npm packages
Just point a javascript file or two at
browserify and it will walk the AST to
read all your require()s recursively.
The resulting bundle has everything
you need, including pulling in
libraries you might have installed
using npm!
Browser
http://jsperf.com/dom-vs-innerhtml-based-templating/53 => The performance isn't that great according to this benchmark => http://gist.github.com/raw/550723/12d176698628e30a1df398c7ac7aea93924e1294/jade.js. But according to TJ it was never supposed to be used in the browser, but node.js instead. In that case it is going to be pretty fast. There are a lot of alternatives which you can use in the browser instead.

Checkout Blade. It is a Jade-like HTML template engine that is designed for client-side (and server-side) use. There are some other features that you guys might like, as well.
EDIT: But, only for Node.js servers. There is no Ruby implementation at this time.

This feature is now available in Jade.
http://jade-lang.com/api/
From their API Documentations:
var jade = require('jade');
// Compile jade file to a function
var fn = jade.compileClient('string of jade', options);
// Later in client site, render the function to HTML
var html = fn(locals);
You should pass the compiled javascript function to the client, for example by writing the function (fn in the example) to a .js file and then include the .js file in the html file with script tag.
Another option is using templatizer, which compiles jade to a .js file for you.

I wrote a gem called tilt-jade to do this within the asset pipeline. It's made to work exactly like EJS does with sprockets by default - it renders Jade templates down into functions so they can be called client side. I'm not sure it's a great solution, but it has worked okay for my needs.

I've just made a library for making jade available in client-side html. It is as simple as < jade>...< /jade>. Check it out: https://github.com/charlieamer/jade-query

Jade now supports compiling for the client by default; use the -c --client option. See http://jade-lang.com/command-line.

Here's a hacky but simple version for browserify using gulp-jade.
var jade = require('gulp-jade'),
replace = require('gulp-replace');
gulp.task('jade-client', function() {
gulp.src('./views/**/*.jade')
.pipe(jade({
client: true
}))
.pipe(replace(/function template/g, 'var jade = require("gulp-jade/node_modules/jade/lib/runtime");\n\nmodule.exports = function'))
.pipe(gulp.dest('./client/templates'));
});
Then in my client side JS file...
var template = require('./path_to_compiled_template_file');
var renderedTemplateHtml = template({ aLocal: 'blah blah'});
So you only send to the client the specific templates you need and browserify makes sure you only have one copy of the runtime.

Related

How to use simple-peer module in Node.js?

I am new in Node.js platform and want to use https://www.npmjs.com/package/simple-peer module in my application. But can not figure out how to implement that in my application. I can't figure out their documentation. Is there any resource that can show the procedure of using that module with Node.js or Node+Express?
Might be late but :
If you do not want to, it's not compulsory to use browserify or webpack for this very module to work, but is a good practice though, atleast for now.
In simple-peer package it is mentioned :
Note: If you're NOT using browserify, then use the included standalone file simplepeer.min.js. This exports a SimplePeer constructor on window.
This means you can get SimplePeer() on the window object by adding a script tag in your html file like :
<script src="<path to your node_modules>/simple-peer/simplepeer.min.js"></script>
For me this works :
<script src="<path to your node_modules>/simple-peer/simplepeer.min.js"></script>
<script src="/index.js"></script> <!-- Keep this script tag below simplepeer.min.js-->
Now use SimplePeer() inside index.html as :
const peer = new SimplePeer({
// Code ...
});
Hope this helps :)
As explained in the documentation,
This module works in the browser with browserify.
Basically you need to write nodeJS (i.e. commonJS) code - as shown in the examples - then using browserify, generate a bundle file which can be used browser side.
Most likely, webpack can be used as an alternative to browserify

Yii2: Registering Asset Bundle vs registering external Js file

Hi I wanted to know the advantage of registering Asset Bundle following the process described in the docs like
Process one
in AppAsset.php
public $js = [
'js/myjsfile.js'
];
then in the view file
adding Namespace like
namespace app\assets;
and then adding the use statement like
use app\assets\AppAsset;
AppAsset::register($this);
Instead of doing all this if I use
Process Two
$this->registerJs('js/myjsfile.js', $this::POS_READY);
it works fine.
So why should I use Process One.
Any advantage and reason for this will be greatly appreciated.
If I follow the process one Do I need to add all the js files in
AppAsset.php individually.
Thanks.
Asset Bundles have some advantages over normal registering. Apart from what #deacs said in his/her answer here are others:
Assets Bundles can publish the file to assets if its not in web accessible directory
Assets Bundle can deal with less files (in case of CSS) as well as compressing the assets.
Makes Code Elegant especially in solving dependencies and hence reusability
All the features that makes bundles shine are found in docs
One of the main reasons for using an Asset Bundle is that your assets' paths will always be correct. Consider:
$this->registerJsFile('js/myjsfile.js', ['position'=>$this::POS_READY]);
will generate something like:
<script src="js/myjsfile.js"></script>
Which works great for non urlManager enabled urls, e.g. http://localhost/yiiproject/index.php?r=user/update&id=8 because your browser looks for the js file at: /yiiproject/js/myjsfile.js
But if you enable urlManager, your url will look like http://localhost/yiiproject/user/update/8, which means your browser will look for your js file at: /yiiproject/user/update/8/js/myjsfile.js.
You could overcome this problem by using:
$this->registerJsFile(Yii::$app->request->baseUrl.'/js/myjsfile.js', ['position'=>$this::POS_READY]);
But the Asset Bundle basicly does that for you.
Using Asset Bundles, you can also get the latest version from 'vendor' folder, so if you need to update some lib you don't need to manually do this since composer already do this.

Browserify: prevent including the same npm-module more then once in the same application

For learning purposes I am working on a small chat application, based on jQuery. I want to make it a CommonJS Module, which I can reuse in other projects, just doing something like:
var Chat = require('chat'),
mainChat = new Chat({/* ...params... */})
I am also using browserify for bundling all my dependencies. In my "chat.js" file I am doing:
var $ = require('jquery');
it gives me a local jquery object, and I don't have to worry about whether jQuery was included somewhere in the project earlier, or not. But if somewhere in my project, in another "*.js" file I will do the same thing - it will create another local jQuery object and my bundle would become really huge. My question: is there some method or tool to prevent including some npm-module more then once in the same application?
If both versions of jQuery are exactly the same, browserify will detect it in its dedupe step and include it just once.
See https://github.com/substack/browserify-handbook#dedupe for details.

node.js load javascript library client side

I am fairly new to Node.js and I want to load a few javascript files in the browser but I can't seem to find anywhere how I can simply get libraries to be loaded inside the browser.
So, my question is, how would I be able to load javascript libraries client side with Node.js?
I'm fairly new to node as well, but I've been using browserify to deal with node packages. There are a quite a few node packages that won't work in a browser - if they will work in a browser they will usually say it in their description.
Browserify is really easy to use - you just require() a module just as you would when writing a non-browser script (as far as I can tell). When you're ready to test the script on a browser, you just run
browserify input.js -o output.js
and it pulls all of the dependencies from your require()'s into output.js, so then your require()s actually reference what you want it to.
--Updated for new comment--
As I see in your answer, you are talking about node.js packages? I am
talking about standalone random javascript libraries (so, for example
just one of my own js files that I want to load client side). Can you
also load random javascript libraries with browserify? (I googled a
bit but can't figure that out)
Yeah, you can do that; although I'm afraid I can't help you with the technicalities of it (like I said, new to it myself). Here's an example:
Bar.js (my library)
module.exports = bar; //tells node what to export in this file
var bar = {
message: function(msg) {
console.log(msg)
}
}
Foo.js (my script)
var bar = require('./bar');
bar.message("foo"); //logs "foo" to console
And keep in mind that require() refers to a file. So Bar.js would need to be in the same directory as Foo.js. If Bar.js was in a different folder, you would just do require('./folder/bar'). To tie it all together, you would run browserify on Foo.js, and it would automatically grab Bar.js' contents.
There are a lot of different ways you can define exports, so you'll need to google around to see exactly how to do it for how your lib is formatted. But that's the gist of it.

Using browserify with typescript to include a node module

I'm attempting to use a node module in a typescript application and I've included it in my TypeScript code via require().
I build my typescript to JS and all works well if I run it through node which is great.
I'm looking for a way to use the same code and run it through the browser. Browserify seemed like a sensible solution.
I popped a post build action on my VS project and I'm building a 206KB file via browserify (so it's certainly doing something!). Unfortunately my tiny bit of Typescript doesn't seem to be accessible when it's been browserified.
I'm not that familiar with what browserify should be generating so not quite sure whether what it's wrapped my .js code in is correct (can post snippets if it helps).
So my question is twofold really, I'm looking for the answer to either:
Is there a recommended way to write TypeScript post 0.9 to allow it to be run after it's been browserified?
Is there a way to simple tell TypeScript to pull in the 'require' dependency on its own?
Any thoughts or info in this area would be greatly appreciated.
EDIT:
Just to clarify, I'm generating my .js from the .ts during save/build, and in a post build action, pointing browserify to the output. An abridged js output looks like this:
var TestModule;
(function (TestModule) {
function launchDrone() {
var exports = require('ar-drone');
var client = exports.createClient();
}
})(TestModule || (TestModule = {}));
When I generate the browserified file from that, I can't access TestModule or launchDrone in any context (or certainly not from window. ) is there some trick to accessing the browserified code?
It looks like you potentially are not exporting TestModule? Your TestModule file should look like this:
module TestModule {
export function launchDrone() {
var exports = require('ar-drone');
var client = exports.createClient();
}
}
export = TestModule;
This way you should be able to launch TestModule and TestModule.launchDrone from the window.

Categories