Shared modues with NodeJS and Web Javascript - javascript

Sharing modules between Node JS and standard web application.
Hi,
I have a library of classes which I want to use both in a NodeJS and a simple Web page. To that purpose, I created module to export my functions (mode.export ...) and I can call it in my NodeJS code (var func = require("module.js"). However, when I want to use the same module in a Web javascript with the syntax:
<script type="module">
import { Function1 } from './libmain.js';
</script>
I have an error: Import not found (Function1).
Is this something doable or client and server side can't have commonalities?
Many thanks - Christian

Try
exports.Function1 = function() {
return "something";
};

you can use it in the same way as node var func = require("module.js"),
but you need "compile the code" you can use browserify, it's similar to how to use node modules in HTML
see Hello World for JavaScript with npm modules in the browser

Related

Using GRPC-Web without NodeJS

How do you use GRPC-Web on the browser?
I mean, in pure browser code, without any NodeJS involved.
Official example from here: https://github.com/grpc/grpc-web/tree/master/net/grpc/gateway/examples/helloworld are mainly NodeJS oriented.
Is there way to use GRPC-Web in pure Javascript form without:
const {HelloRequest, HelloReply} = require('./helloworld_pb.js');
const {GreeterClient} = require('./helloworld_grpc_web_pb.js');
Meaning, just standard <script>-way of adding Javascript dependencies?
And be able to do: var client = new GreeterClient('http://localhost:8080');
Use grpc-web, not #grpc/grpc-js npm package.
The example provided in Write Client Code uses #grpc/grpc-js, which only works on NodeJS.
To use your protobufs and gRPC services defined in your .proto files, you need to generate your code using grpc-web. Then, import those generated files and use them.
Some things I learnt along the way:
You can't really use protobufjs with gprc-web in browsers, you need to use grpc-web and google-protobuf. If someone has an alternative solution, let me know please.
The generated code in grpc-web is not very nice - it is difficult to read and doesn't have all the features of protobufs. You need to have a lot of Javascript and bundling experience to use it.
grpc-web is more limited than gRPC. NodeJS runs gRPC, but in the browser, you have to use grpc-web, and must run a gRPC proxy to translate gRPC-web into/from gRPC.
Yes. You need to bundle your sources with webpack. This step is also described in the documentation you mentioned. At the bottom of the readme:
Just config your webpack to expose variable:
client.js
...
export function instantiateGreeterClient(...) {
return new GreeterClient(...)
};
webpack.config.js
module.exports = {
...
entry: './path/to/client.js',
output: {
path: './bundle/js/',
filename: 'grpc.js',
library: {
name: 'grpc',
type: 'umd',
},
...
}
And after that import your bundle as usual. Now you be able to use all defined variables in your script tag code as
<script src="path/to/grpc.js"></script>
<script>
const client = grpc.instantiateGreeterClient(...)
...
</script>
More information can be found in webpack documentation

Why is require module in JavaScript not able to import the fs library?

The javascript code is as follows:
const fs = require('fs');
function init() {
alert("Done!");
}
init();
While executing the Javascript code, I am not able to get the alert Done! on my webpage. On further analysis I came to a conclusion that it is most probably because the require statement is not working (there was an alert when I commented the require statement). Why is it so?
require is not available in the browser but is used in NodeJS. If you want to use it in your browser, you'll need a building tool like Browserify or Webpack.
By the way, the File System package is available in NodeJS only.

How can I use a typescript file in multiple projects some using modules (node.js) and some don't?

I used typescript in the past mainly for client side code to run in the browser. Now I am trying to reuse some classes of my library for node.js. My setup looks like this:
SharedLibrary Project with multiple classes
Client Project using the SharedLibrary
Server Project with node.js using the SharedLibrary
Node.js seems to force me to use commonjs as module library for typescript. Thus my code on the server side will be forced to use modules as well. How can I include my SharedLibrary now in this project? It seems modules are unable to access anything outside of the module except if it is itself a module but I also can't change my SharedLibrary to a module as this would force me to change my whole code base. Is there any way out of this without having to change everything?
Example code:
Library file A.ts:
class A {
public call() {
console.log("class A");
}
}
Server file C.ts:
export class C {
public call(): void {
console.log("class c");
let a = new A(); //this will compile but crash during runtime
a.call();
}
}
node.js main file:
import * as myodule from "./C";
var s = new myodule.C();
s.call();
It will print "class c" and then crash as it can't find class A. It works just fine if I add export to "class A" and then import it but then my client side code stops working.
What I tried so far:
using the files directly doesn't work
using the export keyword to export class A outside of its .ts file doesn't seem to work either
C style defines might work that optionally define the shared library as export or not should work but I couldn't find anything like that in typescript
Is there any way out of this without having to change everything?
Just use commonjs everywhere and use a module loader/bundler like webpack. Here is a quickstart : https://basarat.gitbooks.io/typescript/content/docs/quick/browser.html
Example
Here is a fairly large project that uses this method http://alm.tools/

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.

Loading modules with require in Cordova

I am new to javascript trying out cordova which heavily makes use of the module require(). I went through some tutorials for this like here .
I tried out a very simple example from this tutorial and there is something missing it seems.
This is my html code.
<script>
var abc = require("js/greeting.js");
function mod() {
try{
var g = abc.sayHelloInEnglish();
console.log("reached the call");
document.getElementById("modl").innerHTML = g;
}
catch(err){
console.log("error is" + err.message);
}
}
</script>
<button onclick="mod()">click</button>
This is the code for my greeting.js
//var exports = module.exports = {};
exports.sayHelloInEnglish = function() {
return "HELLO";
};
exports.sayHelloInSpanish = function() {
return "Hola";
};
When I click on the button click, it gives an error that abc is not defined. Is there something I am missing here to use the module?
Thanks a lot.
Actually module.require is not for browser. You can't use it like you do right inside script-tag. The require is for node.js (server-side javascript).
If you want to use it inside a browser you should use preprocessing. For example you can use browserify.
To learn more - great 3 min video CommonJS modules
You cannot use require/module.exports natively in the browser. It is built into Node.js/io.js and can be run on the server.
If you want to use require()/CommonJS modules in the browser, look at RequireJS.
If you want to run Node/io.js code in the browser in general (including but not limited to require()/CommonJS), look at Browserify or webpack.
Since you say you are using cordova, my guess is that you don't really need require() at all. Just write your HTML/CSS/JavaScript like you would normally and use cordova to package it up. cordova uses require() a lot but that should not affect your app's code.
Now you can use this npm package
https://www.npmjs.com/package/cordova-import-npm
Import files from npm packages into your cordova www/ directory
automatically, upon cordova prepare, cordova build or cordova run, and
before anything else is processed.
Oftentimes we want to import the latest files available in npm
packages into our www/ directory in cordova projects. With this module
you can do it automatically without building your own scripts.
You could use define in require.js is a way of passing a function or the result of. I was struggling with cordova cause one needs to be very carefull the Code needs to be clean. Define will help you if you only need to put your result as a object or anything inside the defined function and call it at a later time.
// obj.js script
define(function(){
{name: "joe",
lastname:"doe"}
})
In the other script you only require the file and pass it to a variable. I guess you could even get rid of the inner brackets in obj script.
//other.js
var string = require(["obj"])
console.log(string.name) // joe

Categories

Resources