Building with Grunt and Requirejs - requirejs

I am creating a grunt task for building a javascript project with requirejs using grunt-contrib-requirejs
https://github.com/gruntjs/grunt-contrib-requirejs
Here is the config:
requirejs:
compile:
options:
#appDir: './'
baseUrl: "client"
mainConfigFile: "client/main.js"
name: "main"
out: "build/main.js"
wrap:
start: ""
end: ""
The main.js file requires 2 other files inside subdirectories. Althrough this task does not throw errors, the resulting built file does not run the browser. The files seem to be concatenated since the require calls still exist in the built file. I expect the js files called by require to substitute the require calls, and then be optimized. how can I achieve that?
PS: The config above is written in coffeescript.

If you want your compiled javascript file to not contain and require() or define() calls you can use the AMDclean npm package and simple add this to your options object:
onModuleBundleComplete: function (data) {
var fs = require('fs'),
amdclean = require('amdclean'),
outputFile = data.path;
fs.writeFileSync(outputFile, amdclean.clean({
'filePath': outputFile
}));
}

Related

How to combine multiple node js file into a single bundle using webpack

I am trying to create a single bundle from multiple javascript file in a nodejs application.
The configuration I am using looks somewhat like this:
const path = require('path')
const nodeExternals = require('webpack-node-externals')
'use strict';
module.exports = {
externals: [nodeExternals({})],
entry: './lib/index.js',
output: {
iife: false,
path: path.resolve(__dirname, 'lib'),
filename: 'bundle.js', // <-- Important
},
target: 'node', // <-- Important
};
The problem is when I run bundle.js command instead for it to do what the command says, i get the full source of the file streamed into the terminal.
It seems the file contains some sort of IIFE that gets executed immediately. I set iife: false to false in the webpack configuration but that also did not make any difference.
Any ideas what could be wrong?
Edit:
I am calling webpack by adding:
bundle: webpack --config webpack.config.js to script section in package.json and then I run npm run bundle
As an alternative, you could use https://www.npmjs.com/package/#vercel/ncc package to bundle all your Node.js code into one file.

How can I make webpack skip a require

How can I make webpack skip occurences of
require('shelljs/global');
in my source files? I want to make a bundle of my source files but keep the require('shelljs/global') in the files and not bundle shelljs/global.
If you store the path in a variable then IgnorePlugin will not work. Though you still could do:
const myCustomModule = eval('require')(myCustomPath)
for new comers, on webpack 2+ the way to do this is like so:
module.exports = {
entry: __dirname + '/src/app',
output: {
path: __dirname + '/dist',
libraryTarget: 'umd'
},
externals: {
'shelljs/globals': 'commonjs shelljs/global'
}
};
the bundle will contain a verbatim require:
require('shelljs/global');
read on more supported formats on webpack's config guide and some good examples here
You can use Ignore Plugin (webpack 1) / Ignore plugin (webpack 2).
Add plugin in webpack.config.js:
plugins: [
new webpack.IgnorePlugin(/shelljs\/global/),
],
If require is in the global namespace and this is why you want Webpack to ignore it, just do window.require()
This should be a last resort option, but if you are certain that your JS file is always parsed by Webpack, and nothing else:
You could replace your require() calls with __non_webpack_require__()
Webpack will parse and convert any occurrence of this and output a normal require() call. This will only work if you are executing in NodeJS OR in a browser if you have a global require library available to trigger.
If webpack does not parse the file, and the script is run by something else, then your code will try to call the non-converted __non_webpack_require__ which will fail. You could potentially write some code that checks earlier in your script if __non_webpack_require__ exists as a function and if not, have it pass the call on to require.
However, this should be temporary, and only to just avoid the build errors, until you can replace it with something like Webpack's own dynamic imports.
Here a trick
const require = module[`require`].bind(module);
Note the use of a template string
If some files contains nested requires and You want to ignore them, You can tell webpack to not do parsing for these specific files.
For example if swiper.js and vue-quill-editor.js had inner requires this would be how to ignore them.
module.exports = {
module: {
noParse: [
/swiper.js/,/quill/
],

r.js from node script?

I feel like this must be so obvious but it's escaping me.
I'd like to run requirejs's r.js compilation from a node module instead of from the command line, and every bit of documentation I've seen just shows the command line option. Something like this is what I'm looking for:
var r = require('requirejs');
r('./build/common.js');
r('./build/app-main.js');
Let me explain the underlying motivation in case there's a better way to do it:
I've got a few different build.js files that I want to run r.js on (separate bundles for common dependencies and the main app). I'd like to wrap this up inside a gulpfile or gruntfile that runs both, and without putting all the r.js config in the actual grunt/gulp file like the grunt and gulp require.js plugins all seem to do. Leaving the r.js config in the separate build/*.js files would let us use grunt/gulp OR command line when we want to.
Any way to accomplish this?
Using the optimizer as a Node module is documented but it is not in the most evident place. This is the example that the documentation gives:
var requirejs = require('requirejs');
var config = {
baseUrl: '../appDir/scripts',
name: 'main',
out: '../build/main-built.js'
};
requirejs.optimize(config, function (buildResponse) {
//buildResponse is just a text output of the modules
//included. Load the built file for the contents.
//Use config.out to get the optimized file contents.
var contents = fs.readFileSync(config.out, 'utf8');
}, function(err) {
//optimization err callback
});

Using AMDclean with grunt

I am trying to build a project with requirejs and AMDClean to completely remove the need for amd in the production version. Although I am able to get the requirejs optimizer to put my files together I am not able to remove require/define from it using amdclean. Here is my requirejs code (written in grunt using coffeescript):
requirejs:
compile:
options:
baseUrl: './client'
mainConfigFile: "client/main.js"
name: 'main'
out: 'build/main.js'
Here client/main.js is the entry point to my application.I can call this file using the script tag:
<script src="client/vendor/require.js" data-main="build/main.js"></script>
Here is the requirejs task for grunt with amdclean
fs = require 'fs'
amdclean = require 'amdclean'
module.exports = (grunt) ->
'use strict'
grunt.initConfig(
#Read Package.json
pkg: grunt.file.readJSON('package.json')
#Build task
requirejs:
compile:
options:
baseUrl: './client'
mainConfigFile: "client/main.js"
name: 'main'
out: 'build/main.js'
onModuleBundleComplete: (data) ->
outputFile = data.path
fs.writeFileSync(outputFile, amdclean.clean(
'filePath': 'client/main.js'
'globalModules': []
'wrap':
'start': '(function(){\n',
'end': '\n}());'
))
I expect to be able to call this file using this tag:
<script src="build/main.js"></script>
Which is not happening. It throws an error saying: models_MenuItem is not defined which is the error I usually get when the modules are not loaded in the right order. The file built with requirejs optimizer and the original pre-build javascript work normally. Please help me correct my amdclean configuration or identify where the problem really is.
Make sure to set your filePath AMDclean option correctly:
'filePath': outputFile
There could also be a couple of other reasons:
Make sure to set the Require.js skipModuleInsertion option to true. By default, Require.js creates a define() wrapper for files that are not wrapped in a define(). This can cause issues with AMDclean.
Make sure you are not pointing to minified files when building with AMDclean. This will definitely cause issues.

access all files in folder in nodejs

is library versioning is supported in nodeJS?
i have folder like package/version/1.0/
and files under this path
test1.js
test2.js
script.js
//access the folder package of version 1.1
var lib = require('require-all')(__dirname + '/package/version/1.0');
test1.js
========
function sum()
{ a+b ;}
exports.sum = sum;
test2.js
========
function sub()
{ a-b ;}
exports.sub = sub;
in script.js file, can require the package/version/1.1 folder. but how can i access the function sum() and sub() in my script file? and is library versioning supported in nodeJS? is the above code is a sort of library versioning ?
First of all, i haven't seen versions of libraries in one package, most common way is to release new versions of packages and upload them online, defining the required version in a package.json dependencies , npm will take care of download & install
If you want to deprecate a certain version of your library online there is npm deprecate which is the right command for that job.
When you create new npm package you can define a main script which will handle the loading of all files inside the package.
Usually its called index.js or main.js and it will be used when someone calls require('<library>');
So you can try the following to achieve the "versioning"
index.js
var fs=require('fs');
var path=require('path');
var _packageJSON=require(__dirname+'/package.json');
var defaultVersion=_packageJSON.version;
module.exports=function(whichVersion){
whichVersion=whichVersion||defaultVersion;
fs.exists(whichVersion,function(_exists){
if(_exists==null){
throw new Error('Unable to load version : '+whichVersion+' : '+_packageJSON.name);
}else{
// require , 1.0/index.js
require(path.join(whichVersion,'index.js'));
}
}
}
and any script that has that package as dependency it can load it by simply calling
require("<library name>")(<version>) ex.
require("mylib")("1.0")
under each version inside the package, you can have index.js which loads/exports variables and functions properly.
The final structure should look like
my npm package main module
index.js file
versions directory
1.0/index.js file
util.js
fn.js
var.js
2.0/index.js file
util.js
fn.js
var.js
Hope it helps.

Resources