Requirejs optimizer and locale setting that is set dynamically - javascript

I am using requirejs optimizer (r.js) through grunt and here is my requirejs config :
requirejs.config
baseUrl: '/scripts'
locale: window.localStorage.getItem('locale') || null
...
The thing is that the grunt r.js plugin (https://github.com/gruntjs/grunt-contrib-requirejs) throw an error everytime I try to use a variable inside my requirejs config.
The main config file cannot be used because it cannot be evaluated correctly while running in the optimizer. Try only using a config that is also valid JSON, or do not use mainConfigFile and instead copy the config values needed into a build file or command line arguments given to the optimizer.
Have you managed to use a variable as a locale and r.js at the same time ?

Your locale setting acquires a real value only at runtime. For parts of RequireJS' config that can only be given values at runtime, what I do is:
Just call require.config (or requirejs.config) once with the information which is static. The config does not contain any variables. I point r.js to this static information.
At runtime, I have at least one additional call to require.config that sets those values that are to be computed. RequireJS combines multiple calls to require.config into one configuration.
r.js will only use the first configuration it recognizes in a file. So you may be able to just split your single requirejs.config call into a static and dynamic part and leave them in the same file.

Related

Noticed a context property being passed to webpack along with my configuration. Where does it come from?

I'm trying to understand how the internals of webpack work in order to contribute in the future. I noticed that when running webpack the webpack function in /lib/webpack.js fires with an options argument.
The value of this argument is my configuration object defined in webpack.config.js PLUS a context property that I never defined. Where does this context property come from? Is there a step that occurs before the webpack function fires?
Webpack needs to know where to start looking for files, which you will reference in either your Webpack config file or your JS source files that will be processed by Webpack.
By default, it reverts to the current working directory of where the CLI was used -- commonly the same directory where your Webpack config file exists -- however, you should always define this manually using the context key in your Webpack Config file (see https://webpack.js.org/configuration/entry-context/#src/components/Sidebar/Sidebar.jsx).
Webpack also uses this directory path (absolute path) as the prefix for any module resolution / aliasing used throughout in your source files, etc.

RequireJS: optimizer generates name for define module

I'm using gulp.js and an optimization tool for requirejs (gulp-requirejs) it combines all scritps into one file. I have one define module with no name but it generates a name for it. The problem is I don't know how to call that module from another file.
For example in page1.js:
...
define("map",["jquery"],function($){
...
});
define("lib", ["jquery"],function($){
...
});
and in page2.js I would like to call page1.js lib module but I am not sure how to do it? I would prefer if the optimization tool did not set a name then my code works but this way I have no idea how to make it work. Any ideas?
It is not possible to use multiple modules in a single file, unless these modules are named. Otherwise RequireJS won't know how to relate a request for a module with the actual code that defines it.
The typical scenario when optimizing all modules into a single bundle is that there is going to be one specific module in the bundle which serves as the entry point of your application, and then you can just put that module name in paths:
require.config({
paths: {
lib: 'path/to/page1',
}
});
If you do not have a single entry point but may in fact also have code outside the bundle that will initiate loading modules that are in the bundle, then you need to list those modules in bundles:
require.config({
paths: {
lib: 'path/to/page1',
},
bundles: {
lib: ['map', ...],
}
});
The bundles setting I have shown above says essentially "when you look for the module named map, fetch the module lib, and you will have the definition of map."

Does RequireJS provide a dependency api?

I would like to pass a requireJS config.json and a source file like my main.js and receive a list of all its dependencies.
This is probably part of the r.js optimization application however I couldn't find any documentation about its inner structure.
Does RequireJS provide such an api to generate a dependency list?
There is no API that I know of. However, if you run r.js (the optimizer) with a build configuration like this:
({
baseUrl: ...,
dir: ...,
mainConfigFile: ".../config.js",
findNestedDependencies: true,
name: "main",
optimize: "none"
})
then you'll get a build.txt file in the directory where you specify to store the optimized build (the value of dir). The general format of this file is:
<output-file1>
----------------
<module A>
<module B>
<output-file2>
----------------
<module C>
<module D>
This tells you that the output file output-file1 contains modules A and B, output-file2 contains modules C and D.
With the configuration I suggested above, you should have only one output file listed in the build.txt file for your main module, and the list of modules listed under it are all the modules it depends on.
In the configuration above I've set optimize: "none" because it would save time if the only thing you care about is dependencies. In a real build you'd want to let r.js use uglifyjs to minify your code. Also, findNestedDependencies: true is there to tell r.js to find dynamic calls to require in the middle of your code. And thins brings up a major warning. If you have this:
if (blah)
require(["foo"], function (foo) {...});
then findNestedDependencies: true will be able to detect that there is a dependency on the module foo. However, there is no way for r.js to handle this:
var module_name = obj[key];
require([module_name], function (module) {...});
To know what module this code is loading, r.js would have to execute the code (and even then there's a limit to what code execution can discover).

How to to use require.js and optimizer to build a library

I'm thinking about using require.js and it's optimzier to combine and minify a library that consists of more then one js-file. Every js-file contains one single module. But there is no main-module that requires (imports) all modules/js-files.
I want to combine all files in one file, that could be used as a library. In that way I could ship the library in one single file instead of several files.
Is this possible, or do I have to create some kind of a main-module that requires /imports all other modules?
Thanks for your help!
treeno
I've not tried it myself but you should be able to pass a build configuration to r.js that contains the following:
modules: [{
name: "my-lib.js",
create: true,
include: ["moduleA", "moduleB", ...]
}]
This tells r.js to put into a single file named my-lib.js all of the dependencies listed in include and tells it that there is no corresponding file named my-lib.js in your sources but that r.js should create it in the output. So the key is:
List all the modules you want in include.
Use create: true.
The documentation on the optimizer does not mention create but you can find it documented here.

RequireJS - Omitting testing code from optimized build

I have been looking into integrating testing into my app based on RequireJS. I have found this example of how QUnit testing could be integrated into the RequireJS structure. Obviously you don't want the testing code to be lying around in the Production build. How can you keep testing out of the final production build in RequireJS?
There are lots of options you can set in the build file. See the full example on GitHub (https://github.com/jrburke/r.js/blob/master/build/example.build.js)
What you want to do is exclude certain items from your module:
//This module entry combines all the dependencies of foo/bar/bip into one file,
//but excludes foo/bar/bop and its dependencies from the built file. If you want
//to exclude a module that is also another module being optimized, it is more
//efficient if you define that module optimization entry before using it
//in an exclude array.
{
name: "foo/bar/bip",
exclude: [
"foo/bar/bop"
]
},
//This module entry shows how to specify a specific module be excluded
//from the built module file. excludeShallow means just exclude that
//specific module, but if that module has nested dependencies that are
//part of the built file, keep them in there. This is useful during
//development when you want to have a fast bundled set of modules, but
//just develop/debug one or two modules at a time.
{
name: "foo/bar/bin",
excludeShallow: [
"foo/bar/bot"
]
}
You can also exclude items with a regular expression, but this is probably overkill:
//When the optimizer copies files from the source location to the
//destination directory, it will skip directories and files that start
//with a ".". If you want to copy .directories or certain .files, for
//instance if you keep some packages in a .packages directory, or copy
//over .htaccess files, you can set this to null. If you want to change
//the exclusion rules, change it to a different regexp. If the regexp
//matches, it means the directory will be excluded. This used to be
//called dirExclusionRegExp before the 1.0.2 release.
//As of 1.0.3, this value can also be a string that is converted to a
//RegExp via new RegExp().
fileExclusionRegExp: /^\./,

Categories

Resources