This is a portion of my build configuration for requireJS's optimizer, r.js.
exclude: [
'widgets/cr-log-display',
'widgets/cr-pager',
'widgets/cr-time-input'
My question is simply this: is it possible to exclude ALL dependencies starting with widgets/.
The docs don't seem to indicate that a regex, or anything similar can be passed here. Is there another configuration parameter that I'm missing?
I'm pretty sure you cannot pass a regular expression to exclude. I'm saying this from having read the source of r.js. The processing of exclude uses an internal function named findBuildModule, which compares what is passed to exclude against module names with ===. And by the same token, there is no way to tell r.js "exclude all modules under this directory".
The one avenue I see you might be able to use is onBuildWrite, which is a global setting that takes a function. I've used it for other purposes than what you want but perhaps this would do the trick:
onBuildWrite: function (moduleName, path, contents) {
return /^widgets\//.test(moduleName) ? "" : contents;
}
If the module name starts with widgets/ then the contents that will be written to the bundle will be the empty string, otherwise the contents will be whatever the module's contents happen to be.
Note that this will not do exactly what exclude does. The exclude setting excludes the listed modules and their dependencies. The onBuildWrite example above is an analogue to excludeShallow in that the modules that match the regular expression will be excluded but their dependencies won't be excluded. There is no way to easily write an onBuildWrite function that will extend the exclusion to dependencies of the modules that you'd like to exclude. r.js does not give an API to query dependencies of a module.
Related
What does HashedModuleIdsPlugin do?
From Webpack docs:
This plugin will cause hashes to be based on the relative path of the module, generating a four character string as the module id. Suggested for use in production.
After reading it couple of times, I still can't understand why and when to use it and how it is related to the way I define a name to each bundle in output section:
filename: '[contenthash].[name].js',
I understand it this way, webpack 4.3 added contenthash, but before that, you can use HashedModuleIdsPlugin, I am not quite sure.
https://github.com/webpack/webpack/releases/tag/v4.3.0
By default, Webpack will create a list of modules (all the imported packages you have, as well as project files) and this list will be an array. The "module ID" (the pointer to the actual module code) will be the array index.
HashedModuleIdsPlugin will define this module list as an object, where the keys are the generated hash (from the relative file name) and the values will be the actual module code.
There is also the NamedModulesPlugin (if we're talking Webpack 3), which does the same thing but instead of a hash, the key is the actual relative path, for example:
"./node_modules/tiny-relative-date/lib/factory.js": function(e, t, n) {
In Webpack 4+, this was replaced by: https://webpack.js.org/configuration/optimization/#optimizationmoduleids
it may sounds strange, but when I change the module name in my application, webpack changes the bundle output and makes it wrong. I have windows, it means that module paths should be case insensitive and the bundles must be the same all the time. Webpack shows me that some modules have ambiguous names and it can affect if you are using case-sensitive OS, but nevertheless the bundle works correct.
Then I fixed by changing the names in require from lower-case component to uppercase Component and after that webpack begins making invalid bundle, and there are a lot of diffs if you compare these two output bundles. My questions are: why does webpack behave different with case-sensitive names in case-insensitive environment and how to fix it? Maybe it changes the modules order or something like this.
P.S. The app is big: ~2.5 mb.
P.S.S. The problem is in inheritance. I use TypeScript and the error is that I try to extend from undefined.
Thanks!
why does webpack behaves different with case-sensitive name in case-insensitive environment
The true enviroment for webpack is the web and the web is case sensitive. Also it's probably just ordering e.g. alphabetically and that will change the ordering with changing names.
The problem is in inheritance. I use TypeScript and the error is that I try to extend from undefined
You might have a circular reference in there. The fact that it worked before is conincidental (e.g. the ordering by file names satisfied what was expected).
Fix
Remove the circular reference. E.g. use atom-typescript to find it : https://github.com/TypeStrong/atom-typescript/blob/master/docs/dependency-view.md#circular
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.
Is it possible to determine the directory where required scripts come from?
My ultimate goal is to...
// return the directory where `mysql` module is found
var mysqldir = requiredir('mysql')
if(fs.existsSync(mysqldir+"/README.md")){
console.log(fs.readFileSync(mysqldir+"/README.md").toString())
}
So I can have a handy reference for all these modules, and hopefully people in the enlightened future, will include module docs/cheatsheets intended to be accessed in this manner
required.resolve(...) may be what you're looking for:
function requiredir(id) {
return path.dirname(require.resolve(id));
}
Though, this will follow the main setting:
> requiredir('grunt')
.../node_modules/grunt/lib/
(Update: Documentation for the API isn't available anymore, so its use likely isn't supported.) Another option may be to use npm's view, though this is limited to registered packages:
npm.load({}, function (err) {
npm.commands.view(['mysql', 'readme'], true, function (err, readme) {
console.log(readme);
});
});
If you want to determine the absolute path of a module you can use require.resolve('module')
http://nodejs.org/api/globals.html#globals_require_resolve
You can extract the folder path by a regular expression
If you'd like to know programmatically, the module main directory which nodejs is using, this works
require.resolve('module_name').replace(/(.*node_modules.)(.*?)(\/)(.*)/, `$1$2`)
Example
For example, if you want to know where is the module main directory of module jquery which you're using in your nodejs code, the first part
require.resolve('jquery')
returns (in my case)
/home/jfolpf/autocosts/node_modules/jquery/dist/jquery.js
Pay attention that jquery.js is not stored in the module main directory; nonetheless
require.resolve('jquery').replace(/(.*node_modules.)(.*?)(\/)(.*)/, `$1$2`)
returns
/home/jfolpf/autocosts/node_modules/jquery
This takes into account that to resolve a module's path, node always seeks recursively for the folder named node_modules, as can be seen in documentation.
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: /^\./,