I'm new to RequireJS and it seems it might not actually be possible but I'll still go ahead and ask away in case I'm missing something.
In the docs it says..
This setup assumes you keep all your JavaScript files in a "scripts" directory in your project.
project-directory/
project.html
scripts/
main.js
helper/
util.js
But what if I have to require files from my bower installed files in bower_components:
project-directory/
bower_components/
jquery-mousewheel
jquery.mousewheel.js
lodash
dist
lodash.js
As you see, not all libraries have the same directory hierarchy and naming convention.
So I was wondering is there a simple way to require these bower libraries without actually knowing where their main files are, maybe by simply saying
require('jquery-mousewheel');
require('loadash');
?
setup your requirejs config to use paths
requirejs.config({
// ... config ...
paths: {
jquery-mousewheel: 'bower_components/jquery-mousewheel/jquery.mousewheel',
loadash: 'bower_components/lodash/dist/lodash'
}
// ... config ...
});
documentation for reference
I think this is a better solution...
requirejs.config({
baseUrl: 'bower_components/',
paths: { // path to your app
app: '../'
}
});
requirejs( [
'imagesloaded/imagesloaded',
'app/my-component.js'
], function( imagesLoaded, myComp ) {
imagesLoaded( '#container', function() { ... });
});
Related
I have a main.js file with some code and a couple of require('some_other_file.js'); lines in them (which in turn might require some other files).
The Requirement: Using Gulp 4.0, I would like to merge all these files together into one file by just supplying the main.js file as source and let some Gulp plugin figure out which other files need to be included as well (so not just simply using a combine on all the files!).
Using requirejs in gulp simply adds the require(...); lines to the output file.
gulp.task('compile_js', function(cb) {
var config = {
baseUrl: './src/js/',
include: ['main'],
out: './dist/main.js',
};
rjs.optimize(config, function(buildResponse){
console.log('build response', buildResponse);
cb();
}, cb);
});
Am I doing it wrong with requirejs or is there a Gulp plugin that can handle this?
Found it! Browserify seems to do the trick.
Browserify: http://browserify.org/
And an implementation in Gulp: https://github.com/gulpjs/gulp/blob/master/docs/recipes/browserify-uglify-sourcemap.md
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'm trying to load a library that compiles to Webpack in a require.js project. While the library exposes an object, it returns null when required from the require.js project :
define(function(require, exports, module) {
[...]
require("./ext/mylib.core.js"); // -> null
})
Is there any flags that I can use in Webpack to enable AMD compliance ? There are some references to AMD in the generated library but as it is it does not seem to do anything.
The solution was in Webpack documentation : there is an outputLibrary flag that can be set to "amd" or "umd" and in that case webpack produces amd compliant modules.
EDIT 3:/EDIT: 4
Webpack is not cooperating it may seem, so another possibility would be to expose the module with the shim config option:
require.config({
paths: {
// Tell require where to find the webpack thingy
yourModule: 'path/to/the/webpack/asset'
},
shim: {
// This lets require ignore that there is no define
// call but will instead use the specified global
// as the module export
yourModule: {
exports: 'theGlobalThatIsPutInPlaceByWebpack'
}
}
});
This obviously only works in the case that the webpack stuff is putting something in the global scope. Hope this helps!
EDIT 2:
So I got the question wrong as pointed out in the comments. I didn't find any built-in functionality to produce AMD modules from webpack - the end result seems to be a static asset js file. You could wrap the result in a
define(function () {
return /* the object that webpack produces */;
});
block, maybe with the help of some after-build event (e.g. using this after build plugin for webpack). Then you should be able to require the module with an AMD loader.
Original Answer:
require.js loads it's dependencies asynchronously, you have to declare them explicitly when you're not using the r.js optimizer or the like. So if the module exposes an AMD definition it should work like this:
// It works the way you did it ...
define(['path/to/your/module'], function (require, exports, module) {
require('path/to/your/module'); // -> { ... }
});
// ... but I personally prefer this explicit syntax + it is
// friendlier to a code minifier
define(['path/to/your/module'], function (yourModule) {
console.log(yourModule); // { ... }
});
Maybe you have to configure your require instance, there are docs for that.
EDIT1: as pointed out the way the module is being accessed is not wrong but the dependencies were missing, so I added code that is closer to the original question.
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 experiencing some issue with requireJS, to which I am not familiar
I have this tree
app/
public/
master.html
js/
main.js
app.js
lib/
jquery.js
require.js
vendor
upload/
vendor/
dependency_upload.js //a bunch of dependencies file
ulpload.js
slider/
dependency_slider.js //a bunch of dependencies file
slider.js
in master.html file :
<script data-main="js/main" src="js/lib/require.js"></script>
In my main.js file
require(['js/lib/jquery.js']);
require({
paths: {
'dependency_upload': 'vendor/upload/vendor/dependencies'
}
}, ['js/vendor/upload/upload.js'], function(App) {
App.upload();
});
require(['js/app.js']);
require({
paths: {
'dependency_slider' : 'vendor/slider/dependencies'
}
}, ['js/vendor/slider/slider.js'], function(App) {
App.slider();
});
and each of upload.js or slider.js have the following structure. Here $myfunction stands here respectively for upload and slider
define(['dependency_$myfunction'],function() {
function $myfunction(){
...
}
return{
$myfunction: $myfunction
}
}
);
I have two problems,
1) The behaviour of the js loading is unstable : once two, jquery is not recognized. Btw, upload.js and slider.js share dependencies and some function of slider.js that are set inside these shared dependencies are said to be undefined (perhaps some files are loaded twice ?). So, am I correct with my requireJS usage ?
The module loading is asynchronous, so if you really need jQuery loaded before the other module you have to do one of two things:
1 - Use the callback function from your require of jquery so that you don't try to load the other until jquery is loaded:
require(['js/lib/jquery.js'], function($) {
require({
paths: {
'dependency_upload': 'vendor/upload/vendor/dependencies'
}
}, ['js/vendor/upload/upload.js'], function(App) {
App.upload();
});
});
2 - (and this is the preferred way) use a shim configuration to tell RequireJS that any time you request upload.js it needs to load jquery first.