RequireJs optimizer ignore plugin - javascript

I would like to ignore the use of a require js plugin when I use the optimizer
define(["css!styles.css"])
This always gives me this error
Cannot read property 'normalize' of undefined.
I've set this options to the require optimizer
{
paths : {
'css' : 'empty:'
}
}
But it keeps giving me the error.

I don't know if that is what you want, but you could stub out the css plugin.
//Specify modules to stub out in the optimized file. The optimizer will
//use the source version of these modules for dependency tracing and for
//plugin use, but when writing the text into an optimized bundle, these
//modules will get the following text instead:
//If the module is used as a plugin:
// define({load: function(id){throw new Error("Dynamic load not allowed: " + id);}});
//If just a plain module:
// define({});
//This is useful particularly for plugins that inline all their resources
//and use the default module resolution behavior (do *not* implement the
//normalize() method). In those cases, an AMD loader just needs to know
//that the module has a definition. These small stubs can be used instead of
//including the full source for a plugin.
stubModules: ['text', 'bar'],
So in your case:
stubModules: ['css']
More details, see Requirejs Optimizer Config options

Related

exports=>false in imports-loader in Webpack

If I use imports-loader, what does it mean exports=>false part in configuration? It should inject variable var exports = false, but I don't know when and why I need this variable.
module : {
loaders : [
{
test : /eonasdan-bootstrap-datetimepicker/,
loader : 'imports?define=>false,exports=>false,moment=moment'
}]
}
Imports is for shimming third party code that is expecting global to be defined such as jQuery $ or AMD's define. The reason you might want to do this is because module bundlers often bundle to formats that both AMD and CommonJS understand aka universal module definition UMD format. When importing a UMD module it will first check to see if define (AMD) exists and then exports (CommonJS). Webpack has an easier time parsing CommonJS (nodes native format) so setting define to false explicitly tells webpack to not parse it as an AMD module.
UPDATE
It seems like they are likely disabling all module exports and defining moment as the moment js library. I would guess that the code in that library is extending the bootstrap datepicker control with features from moment.

How to bundle isomorphic commonJS code with webpack

I have a project that uses nodeJS module format (commonJS) and should also (in parts) run in the browser.
I do have non-isomorphic code paths where I conditionally include modules:
var impl;
try {
// in node, use node-impl
impl = require('../node-impl');
} catch (err) {
// running in browser, use browser-impl
impl = require('../browser-impl');
}
Now, I want to use webpack to create a bundle that runs in the browser. I therefore need to defined the external (nodeJS specific) modules as external in the webpack.config.js so that they don't get included in the bundle:
external: {
'../node-impl': true
}
I verified that the '../node-impl' code is actually not included in bundle, but the emitted code looks like this:
/***/ },
/* 33 */
/***/ function(module, exports) {
module.exports = ../node-impl;
/***/ },
This is syntactically wrong JS and the browser will throw a syntax error there.
How is this scenario properly handled with webpack.js? Be aware that I do not wish to use webpack for running with nodeJS, only the browser bundles should be created with webpack.
// Your actual situation:
var impl;
try {
impl = require('../node-impl');
} catch(e) {
impl = require('../browser-impl');
}
You need to refactor this snippet to:
var impl = require('../node-impl');
After this rework, your code is able to work only in a node js environment, that's is good because we are going to mock this request when bundling for browsers...
// webpack.browser.config.js
module.exports = {
resolve: {
alias: {
'../node-impl': '../browser-impl'
}
}
};
Webpack - Resolve.Alias
Or using a package.json#browser, or https://webpack.github.io/docs/configuration.html#resolve-packagealias
I don't think this is the intended purpose of the externals config. Per the docs,
Specify dependencies that shouldn’t be resolved by webpack, but should become dependencies of the resulting bundle. The kind of the dependency depends on output.libraryTarget.
So you're telling webpack that your build requires that module, but not to bundle it in. It's leaving it out, but attempting to require it.
There are probably a couple of ways to do what you want. Worth mentioning that you can easily have webpack produce multiple builds, with different/shared config, from a single config file, which opens up a lot of possibilities. But the way I'd suggest is to use the DefinePlugin to define a boolean 'constant' that represents the execution context (e.g. IN_BROWSER = true). Check that constant in your conditional around the require(). Webpack's parser isn't that smart but it can evaluate boolean variables, so it will resolve the conditional correctly and only require the appropriate module. (Using a non-boolean, like CONTEXT = 'browser' is too confusing for webpack, and it will parse each require statement.) You can then use the Uglify plugin to remove the 'dead code' in the conditional so it doesn't bloat your production build.
With the help of #Hitmands I could come up with a solution that is still not perfect, but fits my needs. I introduce a fictious nonexistingmodule and declare it as external; I then declare the node-impl specific modules to be available as nonexistingmodule:
externals: {
'nonexistingmodule': true,
'../node-impl': 'nonexistingmodule'
}
This way I can keep the try/catch pattern to load specific implementations and it will still run on node. In the browser the loading of nonexistingmodule fails, and the browser-impl module is loaded - just as I intended.
I am a big fan of "don't refactor your code to match a tool", so I am going with this solution.

Require JS files dynamically on runtime using webpack

I am trying to port a library from grunt/requirejs to webpack and stumbled upon a problem, that might be a game-breaker for this endeavor.
The library I try to port has a function, that loads and evaluates multiple modules - based on their filenames that we get from a config file - into our app. The code looks like this (coffee):
loadModules = (arrayOfFilePaths) ->
new Promise (resolve) ->
require arrayOfFilePaths, (ms...) ->
for module in ms
module ModuleAPI
resolve()
The require here needs to be called on runtime and behave like it did with requireJS. Webpack seems to only care about what happens in the "build-process".
Is this something that webpack fundamentally doesn't care about? If so, can I still use requireJS with it? What is a good solution to load assets dynamically during runtime?
edit: loadModule can load modules, that are not present on the build-time of this library. They will be provided by the app, that implements my library.
So I found that my requirement to have some files loaded on runtime, that are only available on "app-compile-time" and not on "library-compile-time" is not easily possible with webpack.
I will change the mechanism, so that my library doesn't require the files anymore, but needs to be passed the required modules. Somewhat tells me, this is gonna be the better API anyways.
edit to clarify:
Basically, instead of:
// in my library
load = (path_to_file) ->
(require path_to_file).do_something()
// in my app (using the 'compiled' libary)
cool_library.load("file_that_exists_in_my_app")
I do this:
// in my library
load = (module) ->
module.do_something()
// in my app (using the 'compiled' libary)
module = require("file_that_exists_in_my_app")
cool_library.load(module)
The first code worked in require.js but not in webpack.
In hindsight i feel its pretty wrong to have a 3rd-party-library load files at runtime anyway.
There is concept named context (http://webpack.github.io/docs/context.html), it allows to make dynamic requires.
Also there is a possibility to define code split points: http://webpack.github.io/docs/code-splitting.html
function loadInContext(filename) {
return new Promise(function(resolve){
require(['./'+filename], resolve);
})
}
function loadModules(namesInContext){
return Promise.all(namesInContext.map(loadInContext));
}
And use it like following:
loadModules(arrayOfFiles).then(function(){
modules.forEach(function(module){
module(moduleAPI);
})
});
But likely it is not what you need - you will have a lot of chunks instead of one bundle with all required modules, and likely it would not be optimal..
It is better to define module requires in you config file, and include it to your build:
// modulesConfig.js
module.exports = [
require(...),
....
]
// run.js
require('modulesConfig').forEach(function(module){
module(moduleAPI);
})
You can also try using a library such as this: https://github.com/Venryx/webpack-runtime-require
Disclaimer: I'm its developer. I wrote it because I was also frustrated with the inability to freely access module contents at runtime. (in my case, for testing from the console)

Loading jQuery plugins using RequireJS -- jQuery undefined intermittently even after specifying deps?

I am attempting to load jQuery.jstree through RequireJS. You can see the exact source of the plugin here: https://gist.github.com/MeoMix/7882144
As I understand it, jQuery.jstree has three dependecies: jQuery, jQuery UI, and jQuery.cookie.
I begin with by loading my RequireJS shim config and then call an initial 'require' to kick things off:
require.config({
// Set the base URL to the Scripts directory of CSWeb
baseUrl: '/csweb/Scripts/',
shim: {
'jquery-ui': ['jquery'],
'jquery.jstree': ['jquery', 'jquery-ui', 'jquery.cookie'],
'jquery.cookie': ['jquery']
}
});
Here, I define my base URL relative to the root of my JavaScript files. The file jquery.js is located at the baseUrl. I also define dependencies for both plugins. Note: I have tried playing around with more explicit shim declarations including defining exports. I noticed no difference in effect.
After defining my config, I call:
require([
'jquery',
'jquery-ui',
'jquery.cookie',
'jstree/jquery.jstree'
], function () {
'use strict';
});
Doing so yields an error intermittently. Clearly an async-loading issue. The error reads:
Uncaught ReferenceError: jQuery is not defined jquery.jstree.js:978
Line 978 of jquery.jstree is simply where jQuery is passed into the closure to begin initialization of the plugin:
// 978 jquery.jstree.js: })(jQuery);
What am I not understanding here? I don't seem to experience this issue with most of my plugins. Is there something especially crappy about how this jstree plugin was written such that it is giving RequireJS fits? Or am I not understanding a core mechanic of RequireJS shim configuration?
UPDATE 1: It appears that it is something to do with the fact that I load jquery.jstree from a path. If I load another, empty file (jstree/jquery.test) -- I am able to replace the issue. However, if I then move test up a directory such that it is level with the other plugins -- it all loads fine.
The whole path you give to the shim configuration has to match the whole path of the module you require.
You name the shim jquery.jstree but you require it as jstree/jquery.jstree, so RequireJS does not use the shim and thus does not know that the plugin depends on jquery, etc. and so you get intermittent errors.
For things like plugins that I might want to use globally, I prefer to give them a well-known name that I can use throughout my application without worrying about paths. So in your case, I'd fix the problem by adding this to my config:
paths: {
"jquery.jstree": "jstree/jquery.jstree"
}
and I would then require it jquery.jstree.

compile RequireJS to remove AMD dependency

I'm using RequireJS to manage my dependencies in development, but at production I would like to remove all dependencies on an AMD loader. It looks like the RequireJS optimizer creates a file that still uses an AMD load at runtime - I'm just looking to have a static (non-AMD dependent, but still AMD compatible) file, such as what jquery produces (from looking at jquery source, it appears they manually order their dependencies in their grunt file). Is this possible?
I'm open to using other libraries other than RequireJS as well.
Note: This is similar to my other question Javascript requirejs in development but compiled in production, but in this case I want to remove AMD all together.
If you want to have your script loadable via a <script> tag or AMD then you might want to use something based on how my EventEmitter class exposes its self.
// Expose the class either via AMD, CommonJS or the global object
if (typeof define === 'function' && define.amd) {
define(function () {
return EventEmitter;
});
}
else if (typeof module !== 'undefined' && module.exports){
module.exports = EventEmitter;
}
else {
this.EventEmitter = EventEmitter;
}
This exposes the object via AMD, CommonJS (node) and the global object (i.e. window). This has one main caveat, it is intended for single file scripts that just want to expose their class via AMD.
If you have a lot of modules then you may want to first compile the script with r.js, shim AMD with Almond and then use something like the above to expose it in multiple ways above.
https://github.com/kodmax/grunt-stonejs is the answer.
Compiles requirejs based project to a JS Stone.
Basicly zero overhead.
I had the same problem that you.
Finally I solved it, and I have created a basic structure of requireJS project and a Gruntfile that perform the automatization.
Process LESS
Optimize requireJS.
Remove AMD
Replace the scripts tags in the HTML from the require syntax to the script tag sintax.
I hope this helps you.
https://github.com/sheldorn/require-base-structure

Categories

Resources