browserify and browserify-shim, do we really need browserify-shim? - javascript

I am trying to figure out what the difference between browserify and browserify-shim. After reading a few tutorial, the only difference I found that is to make required function or libraries to global scope?
browserify makes all js files to one single file without dependency conflict or issues.
var $ = require('jquery');
$('body').css('background','red');
browserify main.js -o bundle.js
so we can just include bundle.js in html file, but we are unable to use $ in html, as jQuery is not in global environment.
browserify-shim is for making jQuery to global scope?
"browserify-shim": {
"jquery": "$"
}
But if only for making jQuery to global scope, I think we can simply done by using this
var $ = window.jQuery = require("jquery"); in browserify
So my question is that, do we really need browserify-shim or if there is something else we need from browserify-shim but we are unable to do it though browserify?

Related

how to import a standalone module build with browserify?

My question is how do I achieve importing a standalone module obtained with browserify, inside another javascript file. Here are some specific details:
I created a standalone module with browserify like this:
browserify module.js --s module_name > output.js
The file module.js contains at the end the line
module.exports = module_name;
Inside a file "use_module.js", I can now use the module module_name, with this code in some html file:
<sctipt src="output.js">
<sctipt src="use_module.js">
But what I would like is to specify just the script "use_module.js" in my html file, and somehow import "output.js" inside "use_module.js" directly in the javascript code. I tried two different approaches :
I tried javascript import module_name from './output.js' inside use_module.js, but then it cannot find the module module_name. Somehow I'm not sure module.exports is the same as export, neither with what browserify does with my module.exports anyway. (I'm very confused about all that).
I tried with require(./output.js) and then re-using browserify, but I then get a lot of weird errors with browserify, about tons of missing modules. Maybe I should specify some module informations in a file next to "output.js", that browserify can process, but I don't know really.
I understood what was failing in both approaches :
As I thought, import works only with export and not modules.exports. Also I read that browserify cannot work with the import/export syntax which is still too new.
More interestingly : a browserified file contains plenty of require(...) calls, which refers to a function created by browserify, and not to the CommonJS require keyword. Of course browserify does not know the difference, and thus look for tons a module to import a second time. All that needs to be done is to rename the word "require" into something else, and browserify can be applied a second time...
I however do not find my answer completely satisfactory : there must be a proper way to do this...

Can I use unpkg or browserify to include single NPM packages in a frontend project?

So I'm working with JS on the frontend, building something for a client. Details aren't super important except that I do not have access to node.
I'm using unpkg to include various NPM packages in the browser (like React/ReactDOM/Babel for instance). These packages have a UMD build so they work out of the box.
However, there are a few packages I'd like to use that do not have a UMD build (namely react-dates or react-datepicker). I've tried serving different files via unpkg and referencing the exported modules. Since they don't have UMD builds, I'll either get an error module is not defined which makes sense, or that the module I'm referencing DatePicker is not defined.
So I thought maybe I could build a single file with browserify but I've never used it before and any docs I could find are lacking. Heres what I did
var DatePicker = require("react-dates");
In a file called test.js and then:
browserify test.js -o bundle.js
Output that, upload it to the client assets, reference it like:
<script src="/js/bundle.js"></script>
But var DatePicker = require("DatePicker") throws error require is not defined (I thought that was the point of browserify?) and console.log(DatePicker) throws is not defined as well.
At this point I'm at a loss. I'm being stubborn but I really really just want to use a react datepicker and avoid adding jQuery to this project for the sole purpose of a datepicker. As far as I can tell unpkg is not an option but I feel like browserify could work and I'm just doing something wrong.
Any help is greatly appreciated!
You don't have to do this, you can find the needed files in the dist folder (New folder\node_modules\react-datepicker) after you "npm install react-datepicker" within a folder, but be sure you have a package file into that, otherwise the install won't work.
The files should look like this
EDIT:
The requirejs code that you need is
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.2/require.min.js"></script>
<script>
requirejs.config({
paths: {
'react': 'https://unpkg.com/react#15.3.2/dist/react',
'react-dom': 'https://unpkg.com/react-dom#15.3.2/dist/react-dom',
'prop-types': 'https://unpkg.com/prop-types#15.6.0/prop-types',
'react-onclickoutside': 'https://unpkg.com/react-onclickoutside#6.7.0/dist/react-onclickoutside',
'react-popper': 'https://unpkg.com/react-popper#0.7.4/dist/react-popper',
'moment': 'https://unpkg.com/moment#2.19.3/moment',
'datepicker': 'https://unpkg.com/react-datepicker#0.61.0/dist/react-datepicker'
}
});
requirejs(['react', 'react-dom', 'prop-types', 'react-onclickoutside', 'react-popper', 'moment', 'datepicker'], function(React, ReactDOM, PropTypes, onClickOutside, Popper, moment, DatePicker) {
ReactDOM.render(
React.createElement('p', {}, 'Hello, World!'),
document.getElementById('root')
)
});
but as far as I got, datepicker requested for "module" which is not defined, this can be the same problem as here. I will investigate more about this issue.

Use Browserify with JavaScript libraries such as Backbone or Underscore?

I know I can install underscore using npm but that's not what I can do in my work environment. I need to be able to download the Underscore.js library and then make it "browserify-compatible".
So let's assume Underscore.js looks something like this:
(function() {
var root = this;
// Rest of the code
}.call(this));
I downloaded that file on my hard drive and saved it as under.js.
My file that requires underscore looks like this:
var underscore = require("./under");
console.log(underscore);
And then I run browserify from the cli.
I have an HTML page called test.html and basically all it does is load the generated bundle.js.
However, the console.log(underscore) line fails - says that underscore is undefined.
What have I tried?
Obviously I added module.exports to the first line - right before the function definition in under.js, and that's how I got the error mentioned above. I also tried the method from this answer , still got the same error.
So, how would I use Browserify to load libraries such as Underscore.js or Backbone without using npm-installed modules?
That's because browserify does not add variables to the global scope. The version you download is identical to the version that you install via NPM.
You need to explicitly attach it to the window to export it to the top level scope.
If you create a file called "expose_underscore.js" and put this in it:
var _ = require('./under');
window._ = _;
Will do it, followed by: browserify expose_underscore.js > bundle.js and then add bundle.js as a <script> tag you will be able to do the following in your console:
HOWEVER, you shouldn't do this if you're using browserify. The point behind it (and Node's version of commonJS) is that you explicitly require it everywhere you need it. So every file you have that needs underscore should import it to a local variable.
Don't worry -- you will still only have one copy loaded.
I typically add my vendor libs like Underscore as script tags. Underscore will attach itself to the global scope, so then you don't need to require it anywhere to use it.
If you do want to use it in a Browserified fashion, verify that you have the correct path in your require statement (browserify requires are relative paths) and move the module.exports statement to the end of the file.

Immediately invoked expression in browserify

I use browserify in combination with node.js so that I can use require() in my js files.
I have this piece of code in my game.js:
var game = new Phaser.Game(800, 600, Phaser.AUTO, 'snakeGame');
var menuState = require('./menuState.js');
var gameState = require('./gameState.js');
game.state.add('menuState', menuState);
game.state.add('gameState', gameState);
game.state.start('menuState');
If i do a browserify game.js -o bundle.js, this piece of code is wrapped inside of an immediately invoked expression and all the required js files are more or less concatenated to this bundle.js
How can I achieve to use the game variable in all my required js files? Since the bundle.js the var game is in the IIFE scope, I cannot access it. How can I put it outside this scope?
EDIT: i think mike c's solution would have worked too. But i was a bit stupid so i just had to define game globally without var infront, that did the trick...
By attaching it to the window object.
window.game = game;
If you want to access your game object elsewhere, export it:
module.exports = game;
If that gives you cyclic dependencies, you have something to improve in the architecture of your application (In case your architecture is fine and you have cyclic dependencies, you can still ask questions)
From that point:
If you want to access the game object from other files also bundled in bundle.js,
Simply do var game = require('game');
If you want to access in other scripts loaded in the same page
With require:
Build with browserify -r ./game.js -o bundle.js
Access in other scripts with var game = require('./game.js');
Example
With require, give an alias to the module:
Build with browserify -r ./game.js:game -o bundle.js
Access in other scripts with var game = require('game');
Example
Without require:
Build with browserify -s game ./game.js -o bundle.js
Access in other scripts with window.game
Example

Browserify External Requires with Grunt-Browserify

The Browserify docs section on external requires shows how to make a module within a bundle available to the global environment:
browserify -r through -r duplexer -r ./my-file.js:my-module > bundle.js
But I'm having trouble configuring this to work with Grunt-Browserify.
The -r flag seems to correspond to the require option in Grunt-Browserify, but the docs description for this option doesn't make any mention of external requires or exporting a require() function.
In my Gruntfile, I've tried setting the require option to the module I need to expose (which is already in the bundle, by the way):
options: {
require: ['./dev/js/foomod.js'],
}
And then in my page script, I try to require() the module as shown in the docs:
<script>
var Foomod = require('./foomod.js');
Foomod.init({foo: 'bar'});
</script>
But that logs the error require is not defined.
My goal is to call the module's init() method as shown so that I can pass in runtime data without putting it in a window global.
Using browserify version 5.11.1 and grunt-browserify version 3.0.1, I have managed to get similar setup to work:
options:{
preBundleCB: function (b) {
b.require("./dev/js/foomod.js",{expose: 'foomod'});
}
}

Categories

Resources