Working on a project that gets its content with ProtoBuff. Made it work once with the loading of the JavaScripts in the HTML. Now refactoring to use requirejs to load the scripts. But when I try to use the scripts, it gives an error telling me the scripts are not loaded.
Require.js is loaded in the index.html
Bower is used to manage dependencies.
I am pretty sure I am missing a (simple) thing here, hope some one can help.
requirejs.config({
long : "long",
ByteBuffer : "ByteBuffer",
ProtoBuf : "ProtoBuf"
});
requirejs([ "long", "ByteBuffer", "ProtoBuf" ],
function( long, ByteBuffer, ProtoBuf ) {
});
the files long.js, ByteBuffer.js and ProtoBuf.js are all in the same map as the App.js, where this is called.
*While this question about requirejs and ByteBuffer looks promising, I think I am missing something here.
This does work, the functions in those files are accessible within the rest of the scope:
requirejs([ "otherPage", "differentPage" ],
function( util ) {
});
You need to make sure you have requirejs hooked up correctly and that you have the relevant proto library loaded.
You can use bower to manage dependencies. Install bower and
bower install long byteBuffer protobuf requirejs-text requirejs-proto
The final code can then look something like this:
require.config({
paths: {
'Long': '../../bower_components/long/dist/Long',
'ByteBuffer': '../../bower_components/byteBuffer/dist/ByteBufferAB',
'ProtoBuf': '../../bower_components/protobuf/dist/ProtoBuf',
'text': '../../bower_components/requirejs-text/text',
'proto': '../../bower_components/requirejs-proto/proto'
},
proto: {
ext: 'proto',
convertFieldsToCamelCase: false,
populateAccessors: true
}
});
require(['proto!test'], function(builder) {
var pack = builder.build('pack');
var Message1 = builder.build('pack.Message1');
});
require(['proto!test::pack.Message1', 'proto!test::pack.Message2'], function(Message1, Message2) {
...
});
some code from https://www.npmjs.com/package/requirejs-proto
Related
So I'm trying to set up Typescript and Chutzpah for testing purposes. Typescript is set up to output in this format:
define(['require', 'exports', './someModule'], function(require, exports, someModule) {
//examplecode
});
Which works fine, the problem occurs when someModule is actually a directory with an index.js.
/app
app.js
/someModule
index.js
require.js is unable to resolve someModule in this way and the test fails.
Is there any way to tell require.js that this is a module?
RequireJS won't automatically check for the presence of index.js and load that as your module. You need to tell RequireJS that when you want to load someModule, it should load someModule/index. I'd set a map in my call to require.config:
require.config({
[ ... ]
map: {
'*': {
someModule: 'someModule/index',
}
},
});
You have to adjust the name you give there so that it is a path relative to your baseUrl. It's not clear from the information you give in your question what it should be.
(For the record, there's also a packages setting that you could probably tweak to do what you want but putting something packages says "this is a package", which is not what you appear to have here. So I would not use it for what you are trying to do.)
I didn't like the configuration in map either. The most simple way I accomplished this was writing a plugin for require.
Let's name the plugin mod, where it is to be used as mod!module/someModule, you can also call it index as in index!module/someModule, whatever suits you best.
define(function(require, exports, module) {
// loading module/someModule/index.js with `mod!`
var someModule = require('mod!module/someModule');
// whatever this is about ..
module.exports = { .. };
});
So lets assume you have paths set in require's configuration with some sort of project structure:
- app
- modules
- someModule/index.js // the index we want to load
- someModule/..
- someModule/..
- etc
- plugins
- mod.js // plugin to load a module with index.js
Requires config:
require.config({
paths: {
'module': 'app/modules',
// the plugin we're going to use so
// require knows what mod! stands for
'mod': 'app/plugins/mod.js'
}
});
To read all the aspects of how to write a plugin, read the docs at requirejs.org. The simplest version would be to just rewrite the name of the requested "module" you are attempting to access and pass it back to load.
app/plugins/mod.js
(function() {
define(function () {
function parse(name, req) {
return req.toUrl(name + '/index.js');
}
return {
normalize: function(name, normalize) {
return normalize(name);
},
load:function (name, req, load) {
req([parse(name, req)], function(o) {
load(o);
});
}
};
});
})();
This is not production code, it's just a simple way to demonstrate that requires config wasn't meant to solve problems like this.
I've read through the documentation and the example app.build.js file but just can't get my js files to concatenate and minify into one single file. I think I'm just not understanding exactly what settings I need in the build script and was hoping for some help.
My app is set up like this:
src >
js >
build.js
r.js
config.js
app >
main.js
lib >
module1.js
module2.js
module3.js
vendor >
require.js
jquery.js
jquery.validation.js
build >
// Where concat and minified file would go
config.js looks like this:
requirejs.config({
"baseUrl" : "src/js/lib", // Used because when setting dependencies in modules, this is used
"paths" : {
"app" : "../app",
"jquery" : [
"https://code.jquery.com/jquery-1.11.1.min",
"../vendor/jquery"
],
"validate" : "../vendor/jquery.validate.min"
},
"shim" : {
// Allow plugins with dependencies to load asynchronously
validate : ["jquery"]
}
});
// Load the main app module to start the app
requirejs(["app/main"]);
main.js looks like this:
require(["module1", "module2", "module3"], function(Module1, Module2, Module3) {
return [
Module1.init(),
Module2.init(),
Module3.init(),
Module4.init()
];
});
And then the build.js is where I'm lost. I thought I should load a mainConfigFile because I'm using the shim, but I'm not sure. If I do load that config file, it uses the baseUrl from that config file. I'm not sure what name: is supposed to refer to exactly and whether I'm missing some necessary configuration options.
({
//baseUrl: ".",
paths: {
jquery: "empty:",
//main: "../app/main",
//app: "app"
},
name: "app/main",
out: "../build/main.js",
//mainConfigFile: "config"
})
If I run that build file as it is (with those lines commented out) I get:
Error: ENOENT, no such file or directory
'/Users/davidpaul/Sites/require/src/js/module1.js' In module tree:
app/main
I'm not really sure what's being referred to when it says 'module tree'. I keep making changes to paths in the build file but not making progress so hoping for someone to explain this a bit to me.
The builder parses all paths relative to the build file location (unless changed via the baseUrl property). If you look relative to src/js/build.js, your main.js is in ./app/ and module1/2/3.js are in ./lib/. All paths inside modules have to be specified relatively to the common root, so to make your example work it's enough to change the signature of main.js to:
require(["lib/module1", "lib/module2", "lib/module3"], function(M1, M2, M3) {
// (...)
})
Note that config.js doesn't take part in the build process, you may need to change it as well to make your application work both "raw" and optimized.
I am trying to set up unit testing for a SPA using karma/jasmine
First of all, the following test runs just fine in karma:
/// <reference path="../../definitions/jasmine/jasmine.d.ts" />
/// <reference path="../../src/app/domain/core/Collections.ts"/>
define(["app/domain/core/Collections"], (collections) => {
describe('LinkedList', () => {
it('should be able to store strings for lookup', () => {
var list = new collections.Collections.LinkedList<string>();
list.add("item1");
expect(list.first()).toBe("item1");
});
});
});
However, collections is of type anyso that I can not use it for type declarations, thus I'm missing intellisense and whatnot when I am writing my tests. No good!
The problem arises when I try to re-write the test to a more TypeScript friendly format:
/// <reference path="../../definitions/jasmine/jasmine.d.ts" />
/// <reference path="../../src/app/domain/core/Collections.ts"/>
import c = require("./../../src/app/domain/core/Collections");
describe('LinkedList', () => {
it('should be able to store strings for lookup', () => {
var list: c.Collections.LinkedList<string> = new c.Collections.LinkedList<string>();
list.add("item1");
expect(list.first()).toBe("item1");
});
});
This compiles just fine, I get my type information for handy intellisense etc, but now karma throws an error.
It turns out it is trying to load the module without the .js postfix, indicated by the following error messages:
There is no timestamp for /base/src/app/domain/core/Collections!
Failed to load resource: the server responded with a status of 404 (Not Found)
(http://localhost:9876/base/src/app/domain/core/Collections)
Uncaught Error: Script error for: /base/src/app/domain/core/Collections
I'm gonna stop here for now, but if it will help I am glad to supply my karma config file, test-main and so on. But my hope is that someone has encountered this exact problem before and might be able to point me in the right direction.
My typescript is compiled with the AMD flag.
It is not a TypeScript problem. We encountered the same problem. Turns out that karma "window.__karma__.files" array includes all files included in the test, including the .js extenstion.
Now requireJS does not work when supplying the .js extension. To fix it, in our main-test.js file, we created a variable "tests" by filtering all the *Spec.js files and then we removed the .js from the file name as requireJS needs it to be. More information here: http://karma-runner.github.io/0.8/plus/RequireJS.html
Below is how we did it (based on the info supplied in the link above):
main-test.js
console.log('===========================================')
console.log('=================TEST FILES================')
var tests = Object.keys(window.__karma__.files).filter(function (file) {
return /\Spec\.js$/.test(file);
}).map(function (file) {
console.log(file);
return file.replace(/^\/base\/|\.js$/g, '');
});
console.log('===========================================')
console.log('===========================================')
require.config({
baseUrl:'/base',
paths: {
jquery :["http://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min", "lib/jquery"],
angular : ["https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.14/angular.min", "lib/angular"],
angularMocks: 'app/vendors/bower_components/angular-mocks/angular-mocks',
},
shim: {
'angularMocks': {
deps: ['angular'],
exports: 'angular.mock'
}
},
deps: tests,
callback: window.__karma__.start
});
Also make sure you have supplied the files to be tested in your karma.config.js file, more details here: http://karma-runner.github.io/0.8/plus/RequireJS.html same as the link above.
Hope it helps
It turns out it is trying to load the module without the .js postfix,
That is the perhaps not the actual source of the error. Actually it is looking at /base/src/app/domain/core/Collections and not app/domain/core/Collections (as in your manual type unsafe way). Notice base/src/ that shouldn't be there.
Backbone app works fine pre-optimized. After using r.js (with almond), I succesfully generate a single output file that always seems to throw the 'TypeError: Backbone is undefined' error in the module immediately following backbone.
For example, when the output from r.js looks like this:
/consumer/public/javascripts/vendor/almond.js
/consumer/public/javascripts/vendor/jquery-1.7.2.js
/consumer/public/javascripts/vendor/underscore.js
/consumer/public/javascripts/vendor/bootstrap.js
/consumer/public/javascripts/vendor/backbone.js
/consumer/public/javascripts/rjs/src/mnp/prop_m.js
/consumer/public/javascripts/rjs/src/mnp/prop_c.js
/consumer/public/javascripts/vendor/play-mustache.js
...
/consumer/public/javascripts/main.js
Upon loading the optimized file in the browser, the error above will be thrown in the 'prop_m.js' module when referencing Backbone. Using require 2.0.5, Backbone 0.9.2, and almond 0.1.4. Thanks in advance for any help.
PS: build.js looks like this:
({
baseUrl: "./",
mainConfigFile: "main.js",
paths: {
'almond': 'vendor/almond',
// need a path to the cs-compiled .js file
'app' : '../../target/scala-2.9.1/resource_managed/main/public/javascripts/rjs/src/app',
'mnp/router' : '../../target/scala-2.9.1/resource_managed/main/public/javascripts/rjs/src/mnp/router',
'mnp/search_form_v' : '../../target/scala-2.9.1/resource_managed/main/public/javascripts/rjs/src/mnp/search_form_v',
'mnp/prop_c' : '../../target/scala-2.9.1/resource_managed/main/public/javascripts/rjs/src/mnp/prop_c',
'mnp/prop_m' : '../../target/scala-2.9.1/resource_managed/main/public/javascripts/rjs/src/mnp/prop_m',
'mnp/prop_list_v' : '../../target/scala-2.9.1/resource_managed/main/public/javascripts/rjs/src/mnp/prop_list_v',
'mnp/prop_item_v' : '../../target/scala-2.9.1/resource_managed/main/public/javascripts/rjs/src/mnp/prop_item_v'
},
/*not compatible with modules*/
name: 'vendor/almond',
include: ["main"],
out: "dist/app.js",
/*not compatible with modules*/
keepBuildDir: false,
preserveLicenseComments: false,
optimize: "none",
wrap: {
start: "(function(global, define) {\n"+
// check for amd loader on global namespace
" var globalDefine = global.define;\n",
end: " var library = require('main');\n"+
" if(typeof module !== 'undefined' && module.exports) {\n"+
// export library for node
" module.exports = library;\n"+
" } else if(globalDefine) {\n"+
// define library for global amd loader that is already present
" (function (define) {\n"+
" define(function () { return library; });\n"+
" }(globalDefine));\n"+
" } else {\n"+
// define library on global namespace for inline script loading
" global['main'] = library;\n"+
" }\n"+
"}(this));\n"
}
})`
FWIW: If anyone runs into this issue...using the amd versions of backbone and underscore seemed to solve things. ie. the amd-versions worked and the shim didn't
Loading Backbone and Underscore using RequireJS
I had this problem when I forgot to include my shims. I solved it by setting the mainConfigFile to my main.js file in the build config, e.g. as shown here: https://github.com/jrburke/r.js/blob/master/build/example.build.js
you could try to use inlineText: true to make sure that backbone is in your compiled .js file
furthermore, to avoid having to keep an eye on 2 objects storing the paths, I would recommend something like mainConfigFile: "main.js" - works like a charm ;)
EDIT: why do you set a mainConfigFile option and the paths?
I'm having issues trying to load ckeditor via requirejs (I've tried converting the main ckeditor js file into individual modules but that has just caused all hell to break loose) and so I'm now checking to see if there is a very simple way to do this that I've missed.
I know requirejs allows you to load normal js scripts so maybe just loading the ckeditor.js file (un-edited, so it's still an IIFE/self-executing function) - would that work with requirejs or if you're using requirejs for loading modules, does the entire project then need to be module based?
Any help appreciated.
Kind regards,
Mark
Alternatively, you can create a RequireJS shim to load things in the correct order, and alias proper RequireJS module names to the CKEditor distribution files.
This means your module still declares it is dependant on CKEditor, which is a lot nicer than having it just show up by magic.
require.config({
shim: {
'ckeditor-jquery':{
deps:['jquery','ckeditor-core']
}
},
paths: {
"jquery": '/javascript/jquery-1.7.1/jquery.min',
'ckeditor-core':'/javascript/ckeditor-3.6.4/ckeditor',
'ckeditor-jquery':'/javascript/ckeditor-3.6.4/adapters/jquery'
}
});
then in a module you can depend on ckeditor-jquery (or ckeditor-core for that matter, if you don't need the jQuery integration) and know it'll be available:
require(
[
"jquery",
"ckeditor-jquery"
],
function( _jquery_ ) {
$('#editorContent2').ckeditor({
customConfig : '',
skin:'office2003'
});
}
}
Another way to do that:
var require = {
"shim": {
"path/foo/ckeditor/ckeditor": { "exports": "CKEDITOR" }
}
};
define(['moduleX', 'path/foo/ckeditor/ckeditor'], function (x, ckeditor) {
ckeditor.editor.prototype.fooFunc = function() {
};
});
OK, it seems I answered my own question here.
Instead of trying to break ckeditor down into modules I just used RequireJs to load the script in it's entirety.
require(['require', 'dependancy-A', 'dependancy-B', 'dependancy-C'], function(require, A, B, C){
// this = [object DOMWindow]
// CKEDITOR_BASEPATH is a global variable
this.CKEDITOR_BASEPATH = '/ckeditor/';
require(['/ckeditor/ckeditor'], function(){
// Code to create a new editor instance
});
});
```