sharing code from a browserify file - javascript

I have a JavaScript library that is using Browserify to keep the code modular.
The library itself uses basic Browserify functionality to require other JS files.
myLibrary.js
var utils = require('helpers/utils.js')
console.log("Hello, I am logging from myLibrary")
function my_api(){
utils.someFn()
}
I'm using Gulp to browserify myLibrary.js and it is being built correctly, I've put several logs into myLibrary.js and when I load the file in an example html file I can see the logs.
I have an example index.html file that uses myLibrary.js and I expect my_api to be accessible from index.html.
index.html
<script src="my_url/myLibrary.js"></script>
<script src="app.js"></script>
app.js
my_api()
Chrome console
Hello I am logging from myLibrary (myLibrary.js)
Uncaught ReferenceError: my_api is not defined (app.js)
I've tried to defer the loading of app.js until myLibrary.js was ready but I'm beginning that that is not the problem.

You need to export your public functions.
module.exports = {my_api: my_api};

The solution I ended up using was to expose one global object that contains all the methods I want to expose through myLibrary using the window object.
myLibrary.js is requiring a utility function file and using them as helpers in the methods that I want to expose.
myLibrary.js
var util = require("utils.js")
window.myGlobalObjWithAUniqueName = {
myFn: function(){
util.someHelper()
}
}
Then I use Browserify to create the new browserified_myLibrary.js and use its methods in any file I want to load it in.
index.html
<script src="browserified_myLibrary.js"></script>
<script src="app.js"></script>
app.js
myGlobalObjWithAUniqueName.myFn()
Not sure if this is the best way of doing this but this seems to suit my need to modularize a client side library and use it without having to use Browserify every time I use it.

You may also want to look into the --standalone option exposed by browserify:
When opts.standalone is a non-empty string, a standalone module is created with that name and a umd wrapper. You can use namespaces in the standalone global export using a . in the string name as a separator, for example 'A.B.C'. The global export will be sanitized and camel cased.
From https://github.com/substack/node-browserify#usage

Related

Properties file in JavaScript / Angular

In Java I usually create application.properties in my resource folder and put configs in there.
And when I need it I just do Properties prop = new Properties(); prop.load(... my file) and then use prop.getProperty("Something")
I want to do something similar in Javascript
In my js code I have this:
// REST API Base URL
var baseUrl = "http://localhost:8083/api";
I want this to be in a application.properties file and then load the value.
How can I achive this?
Thanks
In angular 2+ projects and for a good practices you should create environments folder with one file per env like: environment.js, environment.prod.js.
and into file you can export a constant or by default like that
export const environment = {
apiUrl: '',
googleApiKey: '',
}
and you can import this environment in every file you will needed like
import { environment } from '{relativePath}/environment/environment.js'
If you create different files for every env like prod. You need to replace environment.js for env that you will be build. You have lot of info about this with webpack or other compilers.
I recommend you strongly to develop into a common.js project. It will be more friendly for you importing modules and you will have powerful possibilities of scalable app.
But the easy(Ugly) solution is:
index.html
<head>
<script src="environment.js">
<script src="app.js">
</head>
environment.js
// Declaring environment like that you will have window scoped the variable
// and you will have global access to environment with window.environment
var environment = {apiUrl: 'https://api.url:4100'}
app.js
function example(){
console.log(window.environment.apiUrl); // out https://api.url:4100
}
The approach depends on how you build and/or bundle your AngularJs application. But regardless of that, you'll need to create a config.json file to contain your settings.
If using browserify or webpack, you can import that file via require(...), otherwise you can simply request it via ajax before your app bootstraps.
In any of these cases, the best way to use the configuration data throughout your app is to define it as a constant at the bootstrap phase: app.constant('CONFIG', configData);, assuming that configData is a variable that contains the data from your config.json file.
Then you can use dependency injection to provide CONFIG to all your controllers, services and directives.

How to compile a TypeScript project to a single JS file so it is usable in browser

I have to write a Javascript SDK for a little project I am working on. To do that, I had thought of creating a TypeScript project and compiling it to a single Javascript file, so the users of my SDK could just inject that file in their web pages.
However, I just came to know that if I use import, and try to compile to a single file, then it only supports SystemJS.
So, how to compile a TypeScript project to a single JS file so it is usable in browser?
By usable in browser, I mean that if I create a class App in TypeScript, then I could do this in dev console:
var x = new App();
I have been at this for more than a hour now, and everything I have found seems to suggest that this is not possible.
Edit: This doesn't really answer my question. Like I said in the example, I need the functionality that if there is a class called App in my TypeScript project, it should be visible to the browser with the same name, so I could do var x = new App() in my dev console. (Or a user can do this in his JS file that he injects after injecting my SDK file). That answer is just telling how to create an outfile in SystemJS.
For this you can use webpack, it is a Node.JS utility that attempts to bundle Node.JS-like modules. Webpack doesn't automatically export modules to the global object, but generates (or attempts to generate) a function that replace the Node.JS's default require, which is used to execute the entry module and others, thus you can modify this function for exporting each module (or properties of each module) in the global object.
(In TypeScript, use the CommonJS module. Second, install and use the ts-loader plugin among with webpack, so you'll directly compile TypeScript from webpack.)
Maybe that applies to Webpack 2. For example, you modify the __webpack_require__ function. It is not inside the global object and thus you must interfere in the webpack's generated source code, at function __webpack_require__:
function __webpack_require__(moduleId) {
// [...] (After the `if (installedModules...) ...`)
/*
* You don't have access to the module name, so export each
* property to the browser's global object.
*/
var exports = module.exports;
for (var key in exports)
window[key] = exports[key];
}

How to export a require assigned to a variable?

I'm doing the following to make this require to become visible in <app></app>
index.html:
<script>
var electron = require('electron')
</script>
<app></app>
<script src="bundle.js"></script>
App.vue:
const ipc = electron.ipcRenderer
console.log(ipc)
But I get un-used and un-defined var errors with ESLint, so I decided to do this:
requires.js:
var electron = require('electron')
exports.electron = electron
index.html:
<script src="requires.js"></script>
</head>
<body>
<app></app>
<script src="bundle.js"></script>
But now I get this error: requires.js:3 Uncaught ReferenceError: exports is not defined.
What the correct way to export and import the electron require?
Note: requiring electron directly in App.vue doesn't work. You can only require electron in index.html
Full example: https://github.com/alexcheninfo/vue-electron-simple
What you seem to be trying to do here is define electron as a global variable; for that to work you can set window.electron = require('electron') in your index.html in the first example. (It will be available in you bundle.js)
However, using globals for this bad practice and not necessary. What you should do, is just use require in your code. You say this doesn't work: the reason why it doesn't is probably that you're using webpack or something similar to create bundle.js. Furthermore, you probably run the bundling process in Node and not in Electron, therefore require('electron') does not work as expected. Note that it works in your index.html which is not part of the bundle.
If you want to continue to use this setup, you could rename Electron's require to distinguish between the require resolved during bundling and the require resolved at runtime. In other words, window.electronRequire = require in the script tag of index.html and then use electronRequire('electron') in your code.
Having said that, why bundle everything in the first place? Electron has full Node integration so you can use regular Node modules; the files are not sent via HTTP either so there is little to gain from bundling everything into one file.

Is Browserify compatible with Polymer and/or AngularJS

I'd like to use a NodeJS library in my Polymer/AngularJS applications. To do so, I aim to run Browserify on the NodeJS module I wish to use and then reference it in a Polymer web component and also in an AngularJS controller. As far as I can tell, Browserify merely adds require() to the global namespace and so there should not have any naming conflicts.
Is there anything I'm missing or will these technologies work together?
Browserify works fine with Polymer. I normally expose modules using browserify's --standalone flag then integrate as a Polymer elements behavior.
I find out a way to use Polymer with webpack polymer-ext
If you want ues browserify with polymer, maybe you should try the same way.
As another, not so sophisticated approach that doesn't use standalone or behaviours but is maybe a bit more flexible, I've gone with defining a global variable APP. Then defining a get function that returns one of the global required modules.
eg
// in main index.html file before elements.html imported define global namespace
<script>
var APP = {};
</script>
Make a test module
// services/test.js
module.exports = {
test: function(){
console.log('imt the test function');
}
}
Then in main js file.
// main js file
(function(APP) {
var globalModules = {
test: require('./services/test')
}
APP.get = function(moduleName){
return globalModules[moduleName];
}
})(APP);
Then this can be used inside Polymer elements when required like
APP.get('test').test();
Not sure what the standpoint would be on whether this would be the "proper" way to do it but it works for what I was trying to achieve and may help someone.

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.

Categories

Resources