Import global as ES6 module - javascript

Let's say I have an old school 3rd party javascript library in the following format, which effectively creates the global SomeModule:
SomeModule.js
(function() {
this.SomeModule = ...
})();
I'd rather avoid the global and use ES6 syntax to import SomeModule into just the files where I need it. I figure I can wrap the 3rd party library using something like this:
SomeModuleES6.js
var dummy;
(function(){
require("SomeModule.js");
}.bind(dummy))();
export default dummy.SomeModule;
Files where SomeModule is needed
import SomeModule from "SomeModuleES6";
There's gotta be a better way though. Is there a standard practice for this situation? How would this work through WebPack and package.json? Should I just fork the 3rd party library and use my own updated version instead?

Related

How to include functions of JavaScript files in the Node.js server?

I have a typescript file in which some functions have been added.
The following shows the actual address of the typescript file :
../myproject/src/util/validation/user-validation
All the functions are exported from the file. For instance,
export function validateSignUpData(userDetail:UserDetail):Array<String>{
let errorMessages = new Array<String>();
/* Some Code */
Now I am trying to use the exported function in Node server, though it throws an error which I do not comprehend.
Error: Cannot find module '../myproject/src/util/validation/user-validation'
This is how I tried to get the functions inside my Node server file:
app.post('/users',(req,res)=>{
let validator = require('../myproject/src/util/validation/user-validation');
let errorMessages = validator.validateSignUpData(req.body);
I googled require function, and it seemed that my code must work properly. Some forums suggests that typescript must be installed to resolve the issue, though I have already installed typescript!
I will be glad, if you help me!
Thank you.
The export keyword is used for ES6 modules (Related article also covering node.js). This is a new language feature that was shipped in 2015.
It uses export function name() {...} to export a function and import {name} from './path/to/file'; to import it somewhere else.
Node uses the CommonJs syntax (which is still largely popular).
The idea behind it is that any module (i.e. js-file) can export an object like this: module.exports = {key: "value"}. This object can then be imported using require('./path/to/file').
You can use es6 modules in node like this: How can I use an es6 import in node?.
There are 2 methods of modules in node js, es6 modules and requrejs
require is used together with module.exports
add this to your module
module.exports.validateSignUpData=validateSignUpData
and then the require function will export it.
The other way is to use es6 modules but it doesn't work under all circumstances
https://nodejs.org/docs/latest-v13.x/api/esm.html#esm_enabling

Add an external script to React and create new instance

I am trying to implement this github project to my React web app. It is an external script to put a fancy canvas in the background.
I have tried to load it:
import {WarpSpeed} from './warpspeed.js'
import WarpSpeed from './warpspeed.js'
And then create a new instance:
let x = new WarpSpeed("canvasID")
But it throws an error:
TypeError: __WEBPACK_IMPORTED_MODULE_4__helpers_warpspeed___default.a is not a constructor
I also tried to use react-load-script, but it does not make sense I cannot call new WarpSpeed after, because it is undefined.
The module you are trying to use will not work with commonjs importing. You will need to wrap the whole thing inside of a universal module definition.
Please use the one here:
https://gist.githubusercontent.com/tameemsafi/0d909a4060640b948f37ec59460f20d4/raw/c7f4e9020ccb1fb0a9dcf54221c67249030640eb/warpspeed-umd.js
I have wrapped it in a UMD IFFE which will allow you to use ES6 import. I also changed the window.requestAnimationFrame polyfill to a better version.
You can place the code inside of a file warpspeed.js.
CommonJS:
const WarpSpeed = require('./warpspeed.js');
ES6 (Requires transpiling to commonjs):
import WarpSpeed from './warpspeed.js'
According to this:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Import_a_module_for_its_side_effects_only
other info I've found and after checking source code of WarpSpeed.js, what you want seems impossible.
You can also confirm it here:
ES6 import equivalent of require() without exports
You should probably add proper export to WarpSpeed.js file.
Maybe fork the project, modify it so it is ES5+ compatibile and create pull request. Probably lib creator will be greateful ;)

Multiple TypeScripts Files Configuration

Here comes silly and simple question:
I am new to this whole webpack tools.
I have been trying to build a simple web-app using typescript and webpack. In the old days, I created typescript and compile them without bundling them.
With webpack, I already installed necessary loaders, typescript, and jQuery.
The problem is, I have 3 typescript files:
main.ts -> imports all assets (images, css) and other typescripts
functions.ts -> consist all of my custom functions/modules
ui-controller.ts
in functions.ts I always created namespaces such as:
module Functions{
export module StringTools{
export function IsEmpty(): boolean{
//some code
}
}
}
in the browser, I knew that the snippet code above will be called, but it is not recognized in the main.ts (in the run time) even thou I already import it.
This is how I import it in main.ts:
import '.src/functions'
Any suggestion how I can resolve this?
Typescript module keyword is confusing, and in version 1.5 it was indeed changed to namespace to better reflect it's meaning. Look here.
Namespaces are also called internal modules. They are meant to be used when your files are evaluated at the global scope. You can use typescript playground to see how namespaces are transpiled. The point is - namespaces are not modules.
Webpack however, does not evaluate files in the global scope, it evaluates them inside a function in order to provide real module behavior.
So what does make your typescript file into a module? the keywords export and import (but not inside a namespace like in your example).
Typescript will see those keywords, and will transpile them into commonjs\AMD\es6 require or define statements, according to your configuration in tsconfig.json. Now you have "real" modules. Then it's Webpack's job to do something (lots of info about that online) with those modules so that they will work in the browser where you don't have modules, but that part is not related to typescript.
TL;DR -
So how would you do this in Webpack?
/* functions.ts */
export function IsEmpty(): boolean{
//some code
}
and
/* main.ts */
import {isEmpty} from './functions';
if you want better code organisation as suggested by your use of module StringTools, just split into different files. You can read more about es6 import syntax for more info.
The first part of this answer is that your main module (which has been replaced with the namespace keyword) is not exported... so there are no exported members for your functions file.
export namespace Functions { //...
Part two of the answer is that if you are using modules, you don't need to use namespaces as the module is enclosed within its own scope.
Working version of the file as you designed it, I'd say drop the wrapping namespace:
functions.ts
export namespace StringTools{
export function IsEmpty(): boolean{
//some code
}
}

IIFE across multiple files

Is there anyway to have javascript code defined in 2 or more separate files to run in the same IIFE? I'm open to using build tools like gulp to accomplish this.
It just seems like such a mundane problem. I want my code to be organized and separated into their own files (distinct knockout view models, by the way). But I want them all to run in the same function and not pollute global.
The modern way to do this is to use modules rather than try to put everything into an IIFE. Right now, using modules means using a module bundler like RequireJS, SystemJS, Webpack, Browserify, etc. In the medium-term future, you'll be able to use ES2015+ modules directly in the browser if you like, or again use bundlers to bundle them into a single file. (You can use ES2015+ module syntax today with transpilers like Babel, but you still need a bundler.)
You've mentioned you're using RequireJS at the moment but not using its define functionality. Just for the purposes of illustration, here's roughly how you'd define a module (I'm not a fan of Require's syntax, but you can use Babel to transpile ES2015 syntax to it):
Say I have a module that defines a KO component:
define("my-component", ["ko"], function(ko) {
// ...define the component...
// Return it
return MyComponent;
});
That:
Says the module is called my-component (module names are optional, so for instance the top-level module of an app needn't have a name)
Says it depends on the module ko (which provides Knockout); note how that dependency is then provided as an argument to the callback that you use to define your module
Returns MyComponent as the top-level thing defined by the module
Then in my app:
define(["my-component", "another-component"], function(MyComponent, AnotherComponent) {
// use MyComponent and AnotherComponent here
});
You can also have modules that group together other modules that are commonly used in groups, to simplify things.
In ES2015+ syntax instead:
my-component.js:
import ko from "./ko";
// ...define MyComponent...
export default MyComponent;
app.js:
import MyComponent from "./my-component";
import AnotherComponent from "./another-component";
// ...use them...
Obviously, both examples are very simplified and there's a lot more you can do.
This is two separate issues.
Can an IIFE span multiple files - NO!
Can classes/functions/etc in multiple files NOT polute global scope - YES!
file1
var myNS = {};
file2
myNS.MyViewModel = function(){ ... }
file3
myNS.OtherViewModel = function() { ... }
As a very simplistic example, of which there are 101 ways to achieve the same.

How Does Babel Know To Treat A Module As A Module

I have gone through 2ality article on Modules, however, I am confused, how does the system know to treat a module as a module?
import React from "react";
import { hello } from "./hello.js";
var Ctrl = React.createClass ({
render : function () {
return (
<div .... random data
></div>
);
}
});
export default Ctrl;
To me, a module is just a file with global code written in it. We reference the module via its filename.
However, I wonder how does this all gel together when we build the production build.
How does the system know that this is a module & not just global varaibles being declared?
Is it the import / export commands that actually make it say: 'aha, this is a module!'
Excuse the newbie question.
Is it the import / export commands that actually make it say: 'aha, this is a module!'
Yes!
More precisely, the import keyword instructs the JavaScript engine (or transpiler) to load an external file as a module.
if by system you mean the browser, it doesn't know, you normally use another tool that implements the idea of modules for you, and it transforms (puts in code) that act as a module system for you that the browser understands.
some tools like do this is require in node, browserify, webpack
that*, not like

Categories

Resources