How to namespace modules in the browser but not in node - node.js

I have seen many examples of the self-invoking pattern that detects the global object (module.export / window) -- but I am not sure how to do namespacing with this pattern and still have it work in node the same way.
(function(exports) {
'use strict';
// how do i do something like this and have it work in node as well
// exports Namespace.Models.HelloWorld = function () {}
exports.say = function() {
return 'hello world';
};
}(typeof exports === 'undefined' ? this.helloworld = {} : exports));

After looking at the code some more I think you're code should work fine. What you want is to namespace all your code so that it doesn't pollute the global namespace right? So what you need is a single object in the global namespace that you then put all your code under.
Note: The global namespace in the browser is window in case you didn't know.
For example, JQuery creates only two global objects: jQuery and $. Everything you do with JQuery involves only those two global objects. JQuery even has a compatibility mode that disables the dollar sign so then you only have the jQuery object. The pattern people use to get the dollar sign back even when it's been disabled is to do this:
(function ($) {
// Do stuff with $
})(jQuery);
It's a self-invoking function that passes the jQuery object into itself which then becomes the $ argument. That way you can still have the convenience of the dollar sign without clogging up the global window object with yet another property. In your code (this.helloWorld) the this keyword refers to the global namespace (unless your code is wrapped inside another function or something and you didn't post it). What you've done is create a property on the window object (global namespace) called helloWorld, you set it to an empty object, and you pass it in. But you only do this if exports is undefined. That's the part that identifies if you're in node or not. exports will only be undefined if you're in the browser because exports is only available in node modules (just don't add an exports property to the global namespace in the browser, lol).
Note: Node has no application-wide "global" namespace that things get put into by default. Everything in node is scoped to the module level. So even if you define a variable on the first line of your module you can still define the exact same variable on the first line of another module and they won't conflict with each other. There is however, a global object in node that truly is global and you can access its properties from any module. I do not encourage you to use the global object, like, ever. If you need to use that object then you should probably reconsider your application structure.
Whatever you attach to exports in node becomes available to any other module that requires it.
// helloWorld.js
exports.message = "Hello, world!";
and then...
// main.js
var helloWorld = require('./helloWorld.js');
// Now all the properties are available on the variable `helloWorld`.
console.log(helloWorld.message);
// Prints "Hello, world!" to the console.
In the browser you want to do something similar by attaching a single uniquely named object to window and then whomever uses your script should access all your functions through that "namespace". So finally we have this:
// helloWorld.js
(function (myNamespace) {
myNamespace.message = "Hello, world!";
})(typeof exports === 'undefined' ? this.helloWorld = {} : exports)
If exports does not exist then add helloWorld to this (which refers to window when in the global scope like it is in this example) and pass that in. If exports does exist then pass it in instead. Now inside the function we can attach properties and methods to myNamespace and they'll either be attached to window.helloWorld or exports depending on the environment.
I could add the above helloWorld.js file to my node application and use it like this:
// nodeScript.js
var helloWorld = require('./helloWorld.js');
console.log(helloWorld.message);
Or I could add the above helloWorld.js file to my web app. Your page might look like this:
// index.html
<html>
<head>
<title>My Site</title>
<script src="helloWorld.js" />
<script src="clientScript.js" />
</head>
<body>
<div id="messageBox"></div>
</body>
</html>
And your script might look like this:
// clientScript.js
document.getElementById('messageBox').innerHTML = helloWorld.message;
The above page would end up with "Hello, world!" inside the div because it read the message from our module's exposed properties :)
Hopefully that clears things up. Sorry for jumping in with browserify at first instead of directly answering your original question. I do highly recommend browserify though :)

You need browserify. Write your modules in the node-style and then let browserify turn them into proper client-side scripts :)
From browserify home page:
Write your browser code with node.js-style requires:
// main.js
var foo = require('./foo');
var gamma = require('gamma');
var n = gamma(foo(5) * 3);
var txt = document.createTextNode(n);
document.body.appendChild(txt);
Export functionality by assigning onto module.exports or exports:
// foo.js
module.exports = function (n) { return n * 11 }
Install modules with npm:
npm install gamma
Now recursively bundle up all the required modules starting at main.js into a single file with the browserify command:
browserify main.js -o bundle.js
Browserify parses the AST for require() calls to traverse the entire dependency graph of your project.
Drop a single <script> tag into your html and you're done!
<script src="bundle.js"></script>
Not only is it fun to write client-side scripts like this but browserify will bundle it all together into a nice and tidy minified single script file :D

Related

How do you export specific Svelte components as individual classes with specified names?

If you have an existing JS app that doesn't use ESM, CJS, but instead is just a bunch of vanilla JS, how do you export Svelte components to be used from random places in the app? I'd ideally like to have vanilla JS files that look like this:
import AddressComponent from './AddressComponent.svelte';
import DifferentComponent from './DifferentComponent.svelte';
// ... my js app code
const address = new AddressComponent({target: ...});
// ... more vanilla JS code
const address = new DifferentComponent({target: ...});
// ... more vanilla JS code
Or even without the imports, which I can manage as a list elsewhere for generating the Svelte components standalone if necessary.
Using rollup, it seems the only way things work is by specifying 'iife'. However, this bundles my entire app as an IIFE and breaks a lot of the code renaming things and what not. Seems to be no way around it.
I have gotten nice compiled components using this method Exporting Separate Custom Elements from Svelte Components, however that generates esm or cjs svelte components. Possibly there a tool to easily convert this format to vanilla JS? I've searched with no luck
I've used many combos of settings with gulp and rollup together with no success.
The bundle.js create by svelte automatically exports the app root component to the browser (unless you changes its name),
you can write in your bundle.js right before the return app; statement the following line:
app.Child = Child // or whatever your component is called
Then in your javascript:
var child = new app.Child({ target: document.body });
using the props you want.
Your HTML page should eventually look like this:
<script src="public/build/bundle.js"></script>
<link href="public/build/bundle.css" rel='stylesheet'></link>
<script>
var child = new app.Child({ target: document.body });
</script>

nodejs: how to use literals in external require?

Here is my example:
var name="Doe";
var template = require('./template.txt');
and template.txt contains:
`hello ${name}`
I got the error: name is not defined.
Any idea ?
Well you literally want to take JS code from a .txt file and run it, so you need the infamous eval
var name="Doe";
var template = require('fs').readFileSync('./template.txt');
template = template.toString().trim();
console.log(eval(template)) // will output: hello Doe
Although it can be dangerous to run JS code like this, if the templates are files that are in your control and written by you, then I guess it can be done.
Ofcourse you could simply use a template engine like EJS or nunjucks
From the Node.js documentation:
The module wrapper
Before a module's code is executed, Node.js will
wrap it with a function wrapper that looks like the following:
(function(exports, require, module, __filename, __dirname) {
// Modulecode actually lives in here
});
By doing this, Node.js achieves a few
things:
It keeps top-level variables (defined with var, const or let) scoped
to the module rather than the global object.
It helps to provide some
global-looking variables that are actually specific to the module,
such as:
The module and exports objects that the implementor can use to export
values from the module.
The convenience variables __filename and
__dirname, containing the module's absolute filename and directory path.
and globals:
In browsers, the top-level scope is the global scope. This means that
within the browser var something will define a new global variable. In
Node.js this is different. The top-level scope is not the global
scope; var something inside a Node.js module will be local to that
module.
So when we define a variable in one module, the other modules in the program will not have access to that variable, but you can declare your variable without var and it will be defined as a global.
More info in this thread: Where are vars stored in Nodejs?

not able to load jquery via require [duplicate]

I'm getting this error when I browse my webapp for the first time (usually in a browser with disabled cache).
Error: Mismatched anonymous define() module: function (require) {
HTML:
<html>
.
.
.
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script> var require = { urlArgs: "v=0.4.1.32" }; </script>
<script data-main="assets/js/main" src="assets/js/libs/require.js"></script>
<script src="assets/js/ace/ace.js?v=0.4.1.32"></script>
</body>
</html>
JS:
$(function () {
define(function (require) {
// do something
});
});
Anyone know exactly what this error means and why its happening?
source file, a short discussion about it in the github issues page
Like AlienWebguy said, per the docs, require.js can blow up if
You have an anonymous define ("modules that call define() with no string ID") in its own script tag (I assume actually they mean anywhere in global scope)
You have modules that have conflicting names
You use loader plugins or anonymous modules but don't use require.js's optimizer to bundle them
I had this problem while including bundles built with browserify alongside require.js modules. The solution was to either:
A. load the non-require.js standalone bundles in script tags before require.js is loaded, or
B. load them using require.js (instead of a script tag)
In getting started with require.js I ran into the issue and as a beginner the docs may as well been written in greek.
The issue I ran into was that most of the beginner examples use "anonymous defines" when you should be using a "string id".
anonymous defines
define(function() {
return { helloWorld: function() { console.log('hello world!') } };
})
define(function() {
return { helloWorld2: function() { console.log('hello world again!') } };
})
define with string id
define('moduleOne',function() {
return { helloWorld: function() { console.log('hello world!') } };
})
define('moduleTwo', function() {
return { helloWorld2: function() { console.log('hello world again!') } };
})
When you use define with a string id then you will avoid this error when you try to use the modules like so:
require([ "moduleOne", "moduleTwo" ], function(moduleOne, moduleTwo) {
moduleOne.helloWorld();
moduleTwo.helloWorld2();
});
I had this error because I included the requirejs file along with other librairies included directly in a script tag. Those librairies (like lodash) used a define function that was conflicting with require's define. The requirejs file was loading asynchronously so I suspect that the require's define was defined after the other libraries define, hence the conflict.
To get rid of the error, include all your other js files by using requirejs.
Per the docs:
If you manually code a script tag in HTML to load a script with an
anonymous define() call, this error can occur.
Also seen if you
manually code a script tag in HTML to load a script that has a few
named modules, but then try to load an anonymous module that ends up
having the same name as one of the named modules in the script loaded
by the manually coded script tag.
Finally, if you use the loader
plugins or anonymous modules (modules that call define() with no
string ID) but do not use the RequireJS optimizer to combine files
together, this error can occur. The optimizer knows how to name
anonymous modules correctly so that they can be combined with other
modules in an optimized file.
To avoid the error:
Be sure to load all scripts that call define() via the RequireJS API.
Do not manually code script tags in HTML to load scripts that have
define() calls in them.
If you manually code an HTML script tag, be
sure it only includes named modules, and that an anonymous module that
will have the same name as one of the modules in that file is not
loaded.
If the problem is the use of loader plugins or anonymous
modules but the RequireJS optimizer is not used for file bundling, use
the RequireJS optimizer.
The existing answers explain the problem well but if including your script files using or before requireJS is not an easy option due to legacy code a slightly hacky workaround is to remove require from the window scope before your script tag and then reinstate it afterwords. In our project this is wrapped behind a server-side function call but effectively the browser sees the following:
<script>
window.__define = window.define;
window.__require = window.require;
window.define = undefined;
window.require = undefined;
</script>
<script src="your-script-file.js"></script>
<script>
window.define = window.__define;
window.require = window.__require;
window.__define = undefined;
window.__require = undefined;
</script>
Not the neatest but seems to work and has saved a lot of refractoring.
Be aware that some browser extensions can add code to the pages.
In my case I had an "Emmet in all textareas" plugin that messed up with my requireJs.
Make sure that no extra code is beign added to your document by inspecting it in the browser.
Or you can use this approach.
Add require.js in your code base
then load your script through that code
<script data-main="js/app.js" src="js/require.js"></script>
What it will do it will load your script after loading require.js.
I was also seeing the same error on browser console for a project based out of require.js. As stated under MISMATCHED ANONYMOUS DEFINE() MODULES at https://requirejs.org/docs/errors.html, this error has multiple causes, the interesting one in my case being: If the problem is the use of loader plugins or anonymous modules but the RequireJS optimizer is not used for file bundling, use the RequireJS optimizer. As it turns out, Google Closure compiler was getting used to merge/minify the Javascript code during build. Solution was to remove the Google closure compiler, and instead use require.js's optimizer (r.js) to merge the js files.

jasmine-node - including helper

I am trying to test my Meteor application with jasmine-node. I've stubbed out some methods of Meteor framework in the helper (spec_helper.js):
var Meteor = {
startup: function (newStartupFunction) {
Meteor.startup = newStartupFunction;
},
Collection: function (collectionName) {
Meteor.instantiationCounts[collectionName] = Meteor.instantiationCounts[collectionName] ?
Meteor.instantiationCounts[collectionName] + 1 : 1;
},
instantiationCounts: {}
};
At this point I need to run the code in spec_helper.js (something equivalent of including a module in other languages). I've tried the following, but no success:
require(['spec_helper'], function (helper) {
console.log(helper); // undefined
describe('Testing', function () {
it('should test Meteor', function () {
// that's what I want to call from my stubs...
// ...it's obviously undefined
Meteor.startup();
});
});
});
Any help would be greatly appreciated.
jasmine_node will autoload helpers (any file containing the word helpers) from within your spec directory.
NOTE: you can cheat and use helper instead since it's a substring of helpers...makes more sense if you split helpers out across multiple files...singular vs plural.
If you're executing your specs from specs/unit, then create a file named specs/unit/meteor-helper.js, and jasmine_node will automagically source it for you. It will load files with the extension .js if your specs are written in vanilla JavaScript. If you pass the --coffee switch on the command line or via your grunt task config (you may even be using gulp if you're ambitious), then it will load helpers with the extensions js|coffee|litcoffee.
You should export a hash from each helper file as follows:
specs/unit/meteor-helper.js
// file name must contain the word helper
// x-helper is the convention I roll with
module.exports = {
key: 'value',
Meteor: {}
}
Then, jasmine_node will write each key to the global namespace.
This will allow you to simply type key or Meteor from your specs, or any system under test (typically code inside your lib folder that the specs are executing assertions against).
Additionally, jasmine_node will also allow you to suppress the loading of helpers via the --nohelpers switch (see code or README for more details).
This is the proper way to handle helpers for jasmine via node. You may come across some answers/examples that reference a jasmine.yml file; or maybe even spec_helper.js. But keep in mind that this is for ruby land and not node.
UPDATE: It appears jasmine-node will only source your file if it contains the word helpers. Naming each helper file x-helper.js|coffee|litcofee should do the trick. i.e. meteor-helper.coffee.

node mean.io syntax what the purpose of expose app?

In the server.js file of mean.io
I can see
//expose app
exports = module.exports = app;
Can anyone explain me the meaning, what is it for ?
File in Question: https://github.com/linnovate/mean/blob/master/server.js
I would write something up, but I found an article that covers it nicely:
[ . . . ] In /src/node.js you can see that your
code is wrapped in a closure and passed both exports and module. Of
course, further inspection will show you that exports contains a
pointer to module.exports and suddenly everything makes sense.
Overwriting exports overwrites the pointer to module.exports which
disconnects exports from the Node.js environment!
What’s the point?
Exports is a helper function that points to module.exports. This is
meant to make your life easier. That is all. Use it to expose
functions of your module, but if your module needs to replace what is
exposed, you must use module.exports.
Open up that article and take a look at the examples that are provided for more information.
In short, it's a way of making the app variable be referenced directly when it's required from another module instead of being nestled into an object, e.g.
// hello.js
module.exports = 'hello';
// foo.js
exports.foo = 'bar';
// testing it out
console.log(require('hello.js')); // outputs 'hello'
console.log(require('foo.js')); // outputs { foo: 'bar' }

Resources