I am building a complex web app and trying to use requirejs with backbone. I found out that backbonejs is a non AMD framework which restricts me to use requirejs out of the box.
I researched on internet and found that there are patches available to make backbone AMD compliant.
Please guide if patching this way is a no-issue setup. Will i run into any issues during the app development due to patching of core file in backbonejs?
I apologise if its a stupid question :)
Nope, it's not a stupid question. We actually have done this and is working fine for us, so far :)
You can follow this guide on how to do it: http://kilon.org/blog/2012/08/build-backbone-apps-using-requirejs/
Don't forget to read the chapter on unit testing it with Jasmine. Pretty nice combination all together.
Before Require.js 2.0, you have to patch Backbone to be AMD compliant. You can find some AMD-compliant forks of Backbone on github(e.g. amdjs). Fortunately, Require.js 2.0+ added support for loading non-AMD compatible scripts by using the Shim configuration. Example:
requirejs.config({
shim: {
"backbone": {
deps: ["underscore", "jquery"],
exports: "Backbone"
}
},
paths: {
// as usual
});
Related
I have an Symbol is not defined in IE so I tried to use this library as polyfill
https://github.com/medikoo/es6-symbol
As inexperienced as I am, I do not really know how to include it so that it use as global.
In detail, in my code I include it using requirejs as:
requirejs.config({
paths:
{ 'symbol': 'libs/es6-symbol/index' }
})
//define it in app entry point
require([
'symbol'],
function (sy) {
//What should I do?
}
How should i approach this?
You cannot just load the index.js of es6-symbol with RequireJS. If you just look at it, you'll see:
'use strict';
module.exports = require('./is-implemented')() ? Symbol : require('./polyfill');
This is valid CommonJS code but not valid AMD code. RequireJS supports AMD natively, not CommonJS. To use CommonJS code with RequireJS you'd have at a minimum to wrap the code above in a define call, which means having a build step.
Ultimately, you should heed the advice of the README:
To port it to Browser or any other (non CJS) environment, use your favorite CJS bundler. No favorite yet? Try: Browserify, Webmake or Webpack
Research the bundlers, pick one, write a build configuration for it, and if you still have trouble you can ask on this site.
I have project that use bare Javascript (+ Jquery + Backbone) with RequireJS. I include dependencies like:
require.config({
baseUrl: "./js/",
paths: {
jquery: 'lib/jquery-1.8.2',
underscore: 'lib/underscore-1.4.2',
backbone: 'lib/backbone-1.1.2',
'backbone.localStorage': 'lib/backbone.localStorage'
},
shim: {
underscore: {
exports: "_"
},
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
'backbone.localStorage': {
deps: ['backbone'],
exports: 'Backbone'
}
}
});
I want: move project to maven. I don't want to include all that deps in such ugly way. Moreover, I want to use Hibenate, Spring and another deps that should be imported via maven.
Problem: I haven't deep understanding of how do maven plugins or RequireJs work. I looked at this, but understand nothing.
Question: Can you write a step-by-step action points how to move my app to maven?
Maven is not really an answer to the (alleged) "ugliness" of the configuration you showed because it works on a completely different level. To begin with, Maven is a server-side tool and RequireJS is client-side (apologies if you already knew it, but -> "I haven't deep understanding of how do maven plugins or RequireJs work"). This configuration is specific to RequireJS so there's no way to go around it.
Even with Maven you still need to configure your front-end application and tell it where to find the required dependencies and how to initialise them. Client application's paths are web resources which can be arbitrarily different from the file structure of your project so it's not easy to automate the configuration process.
I've been using the RequireJS maven plugin (found it in one of the answers in the same question you posted) for wrapping r.js but it was rather painful to set up, especially with resource timestamping. I just feel that this approach is flawed due to fundamental differences between Java and JavaScript tooling - you'll always end up with a less-than-ideal compromise and any non-standard steps will eat a lot of time and research.
Another approach that's gaining popularity is to completely split your client- and server-side applications into separate projects, allowing you to use language-specific tooling to make the process as smooth as possible. Server-side uses Maven, client-side uses Grunt+Bower+RequireJS+etc. Both sides talk through well-defined interfaces using JSON over HTTP.
It should be easy to find some introductory reading material, but since you're mentioning Spring it could be worth starting by having a look at the reference Spring application: Sagan. It demonstrates how to split front- and back-end into separate Maven submodules that share the same common "core".
A stop-gap solution that makes working with JS libraries with Maven a little bit more civilised is using webjars. You define your dependencies directly in pom.xml and they're easily exposed to the front-end like other static assets. However, this limits your options when it comes to bundling or customisation of the libraries.
So in my TODO applications i used Backbone and require.js. All is cool. I separated all models, views, collections to single files and use require.js to load them. After i tried to join all files to one using console require.js optimizer r.js. As i result i get one file with all my libs and classes. But when i tryed to run i met error that Backbone undefined. I checked the file and see that r.js generated next thing:
1. First it added backbone sources to app-built.js file and after placed next string
define("lib/backbone", function(){});
So as result i have Backbone variable in the window but in my modules i use it in require.js way
define('models/todo',['jquery','underscore','lib/backbone'],function ($, _, Backbone) {
No as global and as result in my modules Backbone local variable is undefined.
And the same problem with underscore.js. R.js imported it in the same way.
So question. How to avoid this problem with othew libs in future or how to fix this now? SOme technics?
You might need to use a shim since Backbone according to the RequireJS expects Backbone to be in the base url directory. In your case, it appears to be in the /lib instead. Config Shim. Depending on the RequireJS version that you're using, you just have to make sure as well that the library that you're using is AMD compatible.
In your requireJS configuration:
shim: {
backbone: {
deps: ["underscore", "jquery"],
attach: "Backbone"
},
underscore: {
attach: "_"
}
}
Since coming across RequireJS I have started to adopt it wholeheartedly as it seems a great way of organising dependencies etc.
For my current project I have created a 'package' of requireJS-organised modules, which will provide the needed database API, to many node.js applications.
But I have come across a stumbling block ... how can I allow third party applications to use my package, without needing to faff with requireJS?
My directory structure for my applications and API is currently as follows:
api_package/node_modules
api_package/controllers/*
api_package/views/*
api_package/helpers/*
api_package/models/*
api_package/main.js
application_1/node_modules
application_1/app.js
application_2/node_modules
application_2/app.js
I need my applications to be self-contained - so they can be easily deployed - so my current work around is to copy api_package/* into the 'node_modules' directory of application_1 & 2 and setting the their requirejs config to the following:
(function() {
var requirejs;
requirejs = require('requirejs').config({
baseUrl: __dirname,
nodeRequire: require,
packages: [
{
name: 'api_package',
location: './node_modules/api_package'
}
]
});
This feels a little dirty and wrong!
Is there a better way? Am I missing some packaging feature for requireJS?
Is it even possible to hide the implementation details of my api_package (the detail being that I am using requireJS) and allow applications to use it as they would any other module:
require('api_package')
You can use the amdefine package, which allows you to code to the AMD API and have the module work in node programs without requiring those other programs to use AMD.
In addition to the documentation on the amdefine github page, this is also documented on the RequireJS website.
I am writing a Javascript application that is supposed to be hosted on various sites. The application itself uses jQuery and jQuery UI. I am aware of jQuery.noConflict(true) trick and using it currently so not to pollute the global space. My aim is to always keep jQuery and any of its plugins local to my application so as not to conflict with anything on the hosting site. It should be possible for the hosting site to load its own jQuery (maybe different version) and add some plugins.
Now, I would like to structure the app as an AMD module. It is OK with me to require from the hosting site to use an AMD loader (require.js, curl, etc.) but I wouldn't like to require any particular one - just anything conforming to AMD API (yep, I know it's not 100% ready yet).
Is it at all possible? Can I do it in an interoperable way, so that the hosting site can use e.g. either requirejs, curl or Dojo AMD loader?
For example, with this:
define(['jquery'], function($) {
var myLocaljQuery = $.noConflict(true);
... my app module implementation here ...
});
how can I specify the path for jQuery that my application wants to use? As far as I understand, I cannot do anything like this:
require.config({
paths: {
'jquery' : 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min'
}
});
define(['require'], function(require) {
require(['jquery'], function($) {
var myLocaljQuery = $.noConflict(true);
... my app module implementation here ...
});
});
because the first require is a global object and this is specific to requirejs.
After doing some more research, I think it is not feasible at the moment. At least for one thing - the module ids are global within AMD context, so I cannot simply use "jquery" or "jquery-ui" module IDs in my application and be sure that there won't be any conflict when someone hosts my application and wants to use jQuery (potentially other version) through AMD too. See for example here:
curl.js does not prevent conflicts with third-party scripts that may load other versions of jQuery as an AMD module.
As far as I understand, AMD is aimed at modularizing stuff within your own app. It doesn't have much support for integration with third-party apps, at least not when you want to do some encapsulation to avoid conflicts.