Webpack change window globale object scope - javascript

I am importing the npm module JSEncrypt in my module to encrypt data. JSEncrypt has window exported global object window.Base64. I am using webpack to bundle all modules. After bundling I run the code on the browser I can write on console window.Base64 to get the value of this object. For security and compatibility reasons I would like to prevent that by changing window.Base64 to local scope instead of window. Is that possible through webpack?

You can look at the various options available for shimming modules, specifically the exports-loader.
This will bind the global to a module scope and it won't be overwriteable outside of Webpack's runtime.

Related

Sharing global between JavaScript files without using modules/exports

I have a self contained JavaScript function in one file, and some Mocha BDD tests in another file that reference it using [nodejs] require(). So in my function under test I export using module.exports. That's all well and good, in the IDE/build.
Now my function under test is actually an external virtual endpoint, which when deployed into a cloud instance, runs standalone inside a JSVM sandbox (Otto) which has no support for exports or modules, and is ES5 based (it does however embed a version of the Underscore library). If I leave the nodejs module definition in there when I deploy to cloud, it kicks off an error at runtime (as Otto doesn't recognise modules). So I want to remove it, and use some vanilla JS mechanism for the linkage back to the Mocha tests and test runner.
So my question is, if I can't use nodejs or requirejs modules, how can I link my Mocha tests in one file to a JS function in another? I had a play with placing a function closure (which most module implementations use) in the file under test, and Otto is happy with this, as its vanilla JS, but any variable with global scope in the file is still not visible from my test file, so there is no linkage.
Any thoughts?
From a quick look at the Otto docs, it looks like Otto only wants whole files and (as you've said) doesn't recogise commonjs modules from node.
If you've got many files I would recommend bundling them into a single file with webpack/browserify/etc, which is how most people convert modules for use in the browser, which similarily doesn't recognise commonjs modules without tooling.
Alternatively, you could convert all the module.exports to simple var declarations, concatenate the files together and hope you don't have a naming collision.
I don't see anything in the docs about having access to a window or global object to hang globals onto, which limits your options
One of my colleague came up with a suggestion to use closure in the file under test which gets deployed into the cloud instance, if you are running under Nodejs, and conditionally do the export. I added the small anonymous closure below to do this, and Otto doesn't complain.
(function () {
if (typeof module != 'undefined') {
module.exports = pdp_virtual_endpoint;
}
}());
Not sure why I didn't think about this earlier :)

Can I access global ES5 variable inside ES6 module?

I'm trying to gradually modularize and rewrite in ES6 a project written in ES5.
With this I have common scripts with classes and variables as well as modules using the type = "module" attribute when loading ES6 modules.
Example:
<script src="constants.js"></script>
<script src="main.js"></script>
<script src="banners.js" type="module"></script>
My problem is the following, I want to access inside the module "banners.js" the constants of the file "constants.js"
At first I thought this was possible, as linux chrome and firefox accept calling a global variable within the banners.js module, but unfortunately the iPad / iOS11 chrome does not accept and is accusing error: ReferenceError: Can't find variable
Unfortunately I can not convert the constants.js file in a module to use the export / import syntax because these constants are used in ES5 parts of the code that can not yet be converted to ES6 modules and could not read the constants if I convert the constants into an ES6 module.
Is there a way to access the global scope from within an ES6 module? Or some other way to get the variables from the file "constants.js"?
Maybe this is a chrome bug for iOS and the Linux version shows the correct behavior?
This difference in behavior between operating systems really left me confused as to the scope of the modules and their ability to access the global scope.

Access webpack modules / variables from global scope

I have my react application compiled through from webpack. I'm using google recaptca's callback url like so:
<script defer src='https://www.google.com/recaptcha/api.js?render=explicit&onload=mywebpackfn'></script>
mywebpackfn is defined inside my webpack compiled js file. api.js can't find it. How can I get access to the webpack js scope from outside?
You could simply expose your function to global scope. Inside your code
if( typeof window !== 'undefined' ) { // browser env
window.mywebpackfn = yourFunction
}
Or something fancy to access global scope
// I know kung fu
(new Function('return this')()).mywebpackfn = yourFunction
Also you might want to compile your code as library https://webpack.js.org/configuration/output/#output-library
Webpack config
output: {
..
library: 'mywebpackfn',
libraryTarget: 'window'
}
If you are familiar with nodejs then you can create your node server outside of that webpack and api.js. In such a way that node server will be common to both webpack and api.js.
In that way you can export your file from webpack that will still be required by api.js by that nodejs server.
Hope this will help.
If you want to keep things controlled via webpack, rather than assign to window directly in your codebase, you can use the expose-loader
https://github.com/webpack-contrib/expose-loader
Or you can specify the output.library option of webpack which will expose the exports of your entry file as an object in global scope - you could export your callback from there

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];
}

Typescript: how to switch off ambient declarations when using AMD

I'm just starting to migrate from internal modules to external modules in Typescript. Until now in my .d.ts files I have used the "declare var ..." part, because everything was used from the global namespace. But now with AMD I want my IDE to highlight errors if I use something without a corresponding import statement, so I do not want any ambiet declarations. How do I achieve that without modifying all my definition files manually (which would not work well with my tsd retrieval tool if I needed to do any updates)
Thanks!
Sorry : Can't be done without modifying the declaration files manually.

Categories

Resources