Goal
I would like a specific JavaScript file to be referenced by multiple JavaScript Azure Functions that are managed by different users in different Azure subscriptions. All the subscriptions are within an enterprise subscription. I would also like these multiple users to be able to alter this single-sourced file.
Proposed solution
My best guess on how to accomplish this is to store the file in a public GitHub repository and have each Function reference it.
Problem
Referencing an external script (in my case, the script hosted in GitHub) in standard ways (as I understand them) does not seem to work when implemented in a JavaScript Azure Function.
Code
Structure:
var abc = require('<external reference>');
Sample external JS file:
https://github.com/<username>/<repo>/blob/master/file.js
Failed attempts
There seem to be many outdated methods documented on SO (e.g., rawgit) but I am looking at the answers last edited in 2018.
https://github.com/<username>/<repo>/blob/master/file.js
https://raw.githubusercontent.com/<username>/<repo>/master/file.js
http://cdn.jsdelivr.net/gh/<username>/<repo>/file.js
Alternatives
I know that in the case that multiple Functions within a single Azure Function (and therefore within the same Azure subscription) can reference a centrally managed file by:
Placing it in a Shared folder, adding "watchDirectories": [ "Shared" ] to host.json, and referencing it with require('../Shared/file.js')
Referencing code in one Function from another (e.g., in Function-2 I can use require('../Function-1/file.js'))
However, unless I misunderstand, neither meets the requirements that the Functions can reside in different Functions in different Azure subscriptions.
I am new to JS. Thank you for any guidance. There may be other ways to satisfy these requirements that I am not thinking of.
You won't be able to require the js files in the typical sense from inside a function, as require uses the filesystem to resolve files, which wouldn't really exist inside of a function. If the js you want to run is available on github you could download the source from github. And use the JS Function constructor to run the create a function you can call. Very roughly it might look something like:
let myfunc;
fetchCodeToRun().then(codeString=>myfunc=new Function(codeString)); //untested
Please note that I'm not specifically too familiar with Azure, and I only have a tiny amount of experience with serverless infrastructure so it's very possible that there's a better way of accomplishing this.
Function constructor docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function
Related
I'm creating a simple UI with an HTML+CSS+JS setup that uses a third-party API requiring a key and I'd like to keep the key in a file that I can gitignore and access from my Javascript file. I'm not going to be deploying this project, I just want to be able to push it to GitHub without temporarily deleting the variable before every commit.
All responses I've found are related to setups with Node.js, React/Webpack, or other server setups, but I don't have a server or transpiler and don't want to add a bunch of cruft and configurations just for this. Is there a way to do that? I tried storing it in a separate JS file and import/export, but either I couldn't get the syntax right or what I was trying needed a transpiler. Every attempt variation resulted in a syntax error or undefined variable.
Key information:
This is project run entirely locally--as in, just opening index.html in my browser--so I don't think I need to worry about the key being exposed in the client.
My setup pretty much just includes index.html, main.js, and style.css.
I want to push the project to GitHub, so I want to store the api key as a variable in a file separate from main.js that I can add to .gitignore but access in main.js.
I'm keeping this as simple as possible without frameworks, etc. Unless it's super simple and lightweight, I don't want to add libraries just to get this working.
Your best bet is to pull whatever secrets you need from the environment itself, either your environment variables or a secrets store.
The specific implementation will depend on what serverless provider you're using, but for example AWS Lambda lets you configure env vars:
https://docs.aws.amazon.com/lambda/latest/dg/env_variables.html
and you can use the Key Management Service or Parameter Store depending on your preference and requirements:
https://aws.amazon.com/blogs/mt/the-right-way-to-store-secrets-using-parameter-store/
Leaving the above in place in case folks find this via looking at the Serverless tag. Updates below based on the updated question.
So, if I understand the updated question correctly, you want to check in all your code to git except the API key, serve the files only on your local file system and have that local copy be able to access the API key.
The simplest way to do this would be to just have another .js file that defines the variable(s) in question like so:
// config.js
var config = { // this should be const instead if you're using ES6 standards
apiKey : '123456789XYZ'
}
Then, in index.html have another script tag that calls that before any scripts that need the config, e.g.:
<script src='./config.js'></script>
<script src='./main.js'></script>
</body>
In main.js you will then be able to reference the variable config for use, and similarly you can .gitignore 'config.js'.
If you use MVC, try to write in php variabel. Than open in script javasript with echo ...
Here's what I'm looking for:
I want to use the wonderful features of SIMPLE mode minification while disabling just one specific feature (disable local function inline).
UPDATE: The answer is NO, it's not possible given my setup. But for me there is a workaround given I am using Grails.
As #Chad has explained below, "This violates core assumptions of the compiler". See my UPDATE3 below for more info.
IN QUESTION FORM:
I'm using CompilationLevel.SIMPLE_OPTIMIZATIONS which does everything I want, except that it's inlining my local functions.
Is there any way around this? For example, is there a setting I can place in my JS files to tell Google Closure not to inline my local functions?
It would be cool to have some directives at the top of my javascript file such as:
// This is a JS comment...
// google.closure.compiler = [inlineLocalFunctions: false]
I'm developing a Grails app and using the Grails asset-pipeline plugin, which uses Google Closure Compiler (hereafter, Compiler). The plugin supports the different minification levels that Compiler supports via the Grails config grails.assets.minifyOptions. This allows for 'SIMPLE', 'ADVANCED', 'WHITESPACE_ONLY'.
AssetCompiler.groovy (asset-pipeline plugin) calls ClosureCompilerProcessor.process()
That eventually assigns SIMPLE_OPTIMIZATIONS on the CompilerOptions object. And by doing so, CompilerOptions.inlineLocalFunctions = true as a byproduct (this is hard coded behavior in Compiler). If I were to use WHITESPACE_ONLY the result would be inlineLocalFunctions=false.
So by using Asset Pipeline's 'SIMPLE' setting, local functions are being inlined and that is causing me trouble. Example: ExtJS ext-all-debug.js which uses lots of local functions.
SO post Is it possible to make Google Closure compiler *not* inline certain functions? provides some help. I can use its window['dontBlowMeAway'] = dontBlowMeAway trick to keep my functions from inlining. However I have LOTS of functions and I'm not about to manually do this for each one; nor would I want to write a script to do it for me. Creating a JS model and trying to identity local functions doesn't sound safe, fun nor fast.
The previous SO post directs the reader to https://developers.google.com/closure/compiler/docs/api-tutorial3#removal, where the window['bla'] trick is explained, and it works.
Wow thanks for reading this long.
Help? :-)
UPDATE1:
Okay. While spending all the effort in writing this question, I may have a trick that could work. Grails uses Groovy. Groovy makes method call interception easy using its MetaClass API.
I'm going to try intercepting the call to:
com.google.javascript.jscomp.Compiler.compile(
List<T1> externs, List<T2> inputs, CompilerOptions options)
My intercepting method will look like:
options.inlineLocalFunctions=false
// Then delegate call to the real compile() method
It's bed time so I'll have to try this later. Even so, it would be nice to solve this without a hack.
UPDATE2:
The response in a similar post (Is it possible to make Google Closure compiler *not* inline certain functions?) doesn't resolve my problem because of the large quantity of functions I need inlined. I've already explained this point.
Take the ExtJS file I cited above as an example of why the above similar SO post doesn't resolve my problem. Look at the raw code for ext-all-debug.js. Find the byAttribute() function. Then keep looking for the string "byAttribute" and you'll see that it is part of strings that are being defined. I am not familiar with this code, but I'm supposing that these string-based values of byAttribute are later being passed to JS's eval() function for execution. Compiler does not alter these values of byAttribute when it's part of a string. Once function byAttribute is inlined, attempts to call the function is no longer possible.
UPDATE3: I attempted two strategies to resolve this problem and both proved unsuccessful. However, I successfully implemented a workaround. My failed attempts:
Use Groovy method interception (Meta Object Protocol, aka MOP) to intercept com.google.javascript.jscomp.Compiler.compile().
Fork the closure-compiler.jar (make my own custom copy) and modify com.google.javascript.jscomp.applySafeCompilationOptions() by setting options.setInlineFunctions(Reach.NONE); instead of LOCAL.
Method interception doesn't work because Compiler.compile() is a Java class which is invoked by a Groovy class marked as #CompileStatic. That means Groovy's MOP is not used when process() calls Google's Compiler.compile(). Even ClosureCompilerProcessor.translateMinifyOptions() (Groovy code) can't be intercepted because the class is #CompileStatic. The only method that can be intercepted is ClosureCompilerProcessor.process().
Forking Google's closure-compiler.jar was my last ugly resort. But just like #Chad said below, simply inserting options.setInlineFunctions(Reach.NONE) in the right place didn't resurrect my inline JS functions names. I tried toggling other options such as setRemoveDeadCode=false to no avail. I realized what Chad said was right. I would end up flipping settings around and probably destroying how the minification works.
My solution: I pre-compressed ext-all-debug.js with UglifyJS and added them to my project. I could have named the files ext-all-debug.min.js to do it more cleanly but I didn't. Below are the settings I placed in my Grails Config.groovy:
grails.assets.minifyOptions = [
optimizationLevel: 'SIMPLE' // WHITESPACE_ONLY, SIMPLE or ADVANCED
]
grails.assets.minifyOptions.excludes = [
'**ext-all-debug.js',
'**ext-theme-neptune.js'
]
Done. Problem solved.
Keywords: minify, minification, uglify, UglifyJS, UglifyJS2
In this case, you would either need to make a custom build of the compiler or use the Java API.
However - disabling inlining is not enough to make this safe. Renaming and dead code elimination will also cause problems. This violates core assumptions of the compiler. This local function is ONLY referenced from within strings.
This code is only safe for the WHITESPACE_ONLY mode of the compiler.
Use the function constructor
var fnc = new Function("param1", "param2", "alert(param1+param2);");
Closure will leave the String literals alone.
See https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Function
So two part question here. Basically, what is the proper practise for javascript function locations? I assumed it would be to have several MyScriptFile.js files, each with a few functions instead of one huge AllMyScripts.js file, as not every page needs every function.
However I'm not sure how to reference another function from outside of this file...
My situation: I'm using an AJAX request in many of my pages. Each request response is different (drawn from different files, etc) and is very hard to make dynamic (one-script-fits-all would be difficult). However, I do have my MakeAJAXRequest() function which creates the request object, which is standard to all DoSomethingWithRequest() functions.
How do I include MakeAJAXRequest() in the other files which contain the DoSomethingWithRequest() functions? It seems as though I should have been able to find this.. but I havn't come across it.
tl;dr I have MakeObject.js and UseObject.js. How does UseObject() reference MakeObject()?
EDIT: Found that if you include MakeObject BEFORE UseObject in your HTML <script> tags, UseObject will be able to reference MakeObject. Seems a little dirty still, as anybody who wants to use the UseObject script will have to be aware of the MakeObject dependency...
If you want to ensure your dependencies are loaded, you could use a function such as this: http://phpjs.org/functions/include:433 There is also include_once(), require(), and require_once()
I'm developing a networked application between the browser and a server running node.js. I'm sharing a lot of code right now, but when I actually deploy this I'd like the client to only get client specific code. My options right now are:
1.) Implement any browser/node.js differences using inheritance. I've tried this in a few places and I end up with a lot of classes that are very, very basic customizations of their parent often only partially specializing a single function. This is not a style I like very much because it means a lot indirection when you're trying to find out what's actually going on.
2.) Define a constant like IS_BROWSER at global scope and then check it whenever I need to change code paths on the browser vs node.js. Then closure compile all js with advanced optimizations to remove dead code on the browser (setting IS_BROWSER = true). Are there any problems with this approach assuming I do whatever I need to do to get advanced optimizations going in closure compiler?
3.) ?? I'm open to suggestions.
If you use advanced compilation, any unused code should be removed; if you use the compiler's export system correctly, any server-side code that your client code does not call will not be in the compiled version of the client code.
You could write all of your code in one big blob then, for your client, add one file with contents like
goog.require('my.client.app');
goog.exportSymbol('my.app.entryPoint', my.client.app.entryPoint);
the compiled code will not include anything that is not in the call tree of my.client.app.entryPoint. Likewise, if your compilation only exports a server entry point, client code will be excluded.
The above style is for writing your script to provide some function which will then get called by an inline script; to make the whole thing into a single script you could do something much simpler:
goog.require('my.client.app');
my.client.app.entryPoint();
To verify that you are not getting a lot of dead code in your compilation output, you could play around with something like this: ScriptCover
I am currently maintaining a large number of JS files and the dependency issue is growing over my head. Right now I have each function in a separate file and I manually maintain a database to work out the dependencies between functions.
This I would like to automate. For instance if I have the function f
Array.prototype.f = function() {};
which is referenced in another function g
MyObject.g = function() {
var a = new Array();
a.f();
};
I want to be able to detect that g is referencing f.
How do I go about this? Where do I start? Do I need to actually write a compiler or can I tweak Spidermonkey for instance? Did anyone else already do this?
Any pointers to get me started is very much appreciated
Thanks
Dok
Whilst you could theoretically write a static analysis tool that detected use of globals defined in other files, such as use of MyObject, you couldn't realistically track usage of prototype extension methods.
JavaScript is a dynamically-typed language so there's no practical way for any tool to know that a, if passed out of the g function, is an Array, and so if f() is called on it there's a dependency. It only gets determined what variables hold what types at run-time, so to find out you'd need an interpreter and you've made yourself a Turing-complete problem.
Not to mention the other dynamic aspects of JavaScript that completely defy static analysis, such as fetching properties by square bracket notation, the dreaded eval, or strings in timeouts or event handler attributes.
I think it's a bit of a non-starter really. You're probably better of tracking dependencies manually, but simplifying it by grouping related functions into modules which will be your basic unit of dependency tracking. OK, you'll pull in a few more functions that you technically need, but hopefully not too much.
It's also a good idea to namespace each module, so it's very clear where each call is going, making it easy to keep the dependencies in control manually (eg. by a // uses: ThisModule, ThatModule comment at the top).
Since extensions of the built-in prototypes are trickier to keep track of, keep them down to a bare minimum. Extending eg. Array to include the ECMAScript Fifth Edition methods (like indexOf) on browsers that don't already have them is a good thing to do as a basic fixup that all scripts will use. Adding completely new arbitrary functionality to existing prototypes is questionable.
Have you tried using a dependency manager like RequireJS or LabJS? I noticed no one's mentioned them in this thread.
From http://requirejs.org/docs/start.html:
Inside of main.js, you can use require() to load any other scripts you
need to run:
require(["helper/util"], function(util) {
//This function is called when scripts/helper/util.js is loaded.
//If util.js calls define(), then this function is not fired until
//util's dependencies have loaded, and the util argument will hold
//the module value for "helper/util".
});
You can nest those dependencies as well, so helper/util can require some other files within itself.
As #bobince already suggested, doing static analysis on a JavaScript program is a close to impossible problem to crack. Google Closure compiler does it to some extent but then it also relies on external help from JSDoc comments.
I had a similar problem of finding the order in which JS files should be concatenated in a previous project, and since there were loads of JS files, manually updating the inclusion order seemed too tedious. Instead, I stuck with certain conventions of what constitutes a dependency for my purposes, and based upon that and using simple regexp :) I was able to generated the correct inclusion order.
The solution used a topological sort algorithm to generate a dependency graph which then listed the files in the order in which they should be included to satisfy all dependencies. Since each file was basically a pseudo-class using MooTools syntax, there were only 3 ways dependencies could be created for my situation.
When a class Extended some other class.
When a class Implemented some other class.
When a class instantiated an object of some other class using the new keyword.
It was a simple, and definitely a broken solution for general purpose usage but it served me well. If you're interested in the solution, you can see the code here - it's in Ruby.
If your dependencies are more complex, then perhaps you could manually list the dependencies in each JS file itself using comments and some homegrown syntax such as:
// requires: Array
// requires: view/TabPanel
// requires: view/TabBar
Then read each JS file, parse out the requires comments, and construct a dependency graph which will give you the inclusion order you need.
It would be nice to have a tool that can automatically detect those dependencies for you and choose how they are loaded. The best solutions today are a bit cruder though. I created a dependency manager for my particular needs that I want to add to the list (Pyramid Dependency Manager). It has some key features which solve some unique use cases.
Handles other files (including inserting html for views...yes, you can separate your views during development)
Combines the files for you in javascript when you are ready for release (no need to install external tools)
Has a generic include for all html pages. You only have to update one file when a dependency gets added, removed, renamed, etc
Some sample code to show how it works during development.
File: dependencyLoader.js
//Set up file dependencies
Pyramid.newDependency({
name: 'standard',
files: [
'standardResources/jquery.1.6.1.min.js'
]
});
Pyramid.newDependency({
name:'lookAndFeel',
files: [
'styles.css',
'customStyles.css',
'applyStyles.js'
]
});
Pyramid.newDependency({
name:'main',
files: [
'createNamespace.js',
'views/buttonView.view', //contains just html code for a jquery.tmpl template
'models/person.js',
'init.js'
],
dependencies: ['standard','lookAndFeel']
});
Html Files
<head>
<script src="standardResources/pyramid-1.0.1.js"></script>
<script src="dependencyLoader.js"></script>
<script type="text/javascript">
Pyramid.load('main');
</script>
</head>
It does require you to maintain a single file to manage dependencies. I am thinking about creating a program that can automatically generate the loader file for you based on includes in the header but since it handles many different types of dependencies, maintaining them in one file might actually be better.
JSAnalyse uses static code analysis to detect dependencies between javascript files:
http://jsanalyse.codeplex.com/
It also allows you to define the allowed dependencies and to ensure it during the build, for instance. Of course, it cannot detect all dependencies because javascript is dynamic interpretet language which is not type-safe, like already mentioned. But it at least makes you aware of your javascript dependency graph and helps you to keep it under control.
I have written a tool to do something like this: http://github.com/damonsmith/js-class-loader
It's most useful if you have a java webapp and you structure your JS code in the java style. If you do that, it can detect all of your code dependencies and bundle them up, with support for both runtime and parse-time dependencies.