I hope I can make myself be understood...
I'm writing a CEP extension for Adobe products. The good thing is that they include NodeJS - which allows me, for example, to access the filesystem.
Now I want to use a js library that has dependencies on NodeJS (crypto, fs and path). The problem is that within the Adobe extension, all NodeJS functionality is accessible through cep_node.crypto (for example).
The js library that I want to use doesn't know that, naturally. So it tells me:
ERROR in ./node_modules/dynamsoft-javascript-barcode/dist/dbr.min.js
Module not found: Error: Can't resolve 'crypto' in '.\node_modules\dynamsoft-javascript-barcode\dist'
The question is - how can I kind of overwrite the reference 'crypto' for example - so it gets accessed by cep_node.crypto?
Note this answer is attempting to be helpful (without code in the question it would be impossible to give a direct answer to the problem)
I think it would help to have a good understanding of CEP before you begin incorporating node imports.
CEP extension has a few different elements to it.
The html. Here you build the interface and can load JS files. You would have to make sure node is activated to be able to import.
Js files. Here you can execute your node js files. Not that this area is separate from the actual scripting area (which runs on an antiquated JS engine, you CANNOT load node product with in that engine).
The JSX which runs with in the adobe scripting engine.
In html I load my cep.
Then in a js file I can load my node using the cep require:
FS as an example:
const fs = cep_node.require('fs');
const csiRun = new CSInterface();
csiRun.evalScript(`buildHtml()`, (returnedImg) => {
// buildHtml is a method in a JSX that runs with in the adobe scripting //engine. It cannot handle the node. I can return a value then do //something like this:
fs.writeFile()
// notice the node module used here.
})
Related
I'm trying to load multiple modules on the fly via chokidar (watchdog) using Meteor 1.6 beta, however after doing extensive research on the matter I just can't seem to get it to work.
From what I gather require by design will not take in anything other than static strings, i.e.
require("test/string/here")
Since if I try:
var path = "test/string/here"
require(path)
I just get Error: Cannot find module, even though the strings are identical.
Now the thing is I'm uncertain how to go on about this, am I really forced to either use import or static strings when using meteor or is there some workaround this?
watchdog(cmddir, (dir) => {
match = "." + regex_cmd.exec(dir);
match = dir;
loader.emit("loadcommand", match)
});
loader.on('loadcommand', (file) => {
require(file);
});
There is something intrinsically weird in what you describe.
chokidar is used to watch actual files and folders.
But Meteor compiles and bundles your code, resulting in an app folder after build that is totally different from your project structure.
Although Meteor now supports dynamic imports, the mechanism is internal to Meteor and does not rely on your actual project files, but on Meteor built ones.
If you want to dynamically require files like in Node, including with dynamically generated module path, you should avoid import and require statements, which are automatically replaced by Meteor built-in import mechanism. Instead you would have to make up your own loading function, taking care of the fact that your app built folder is different from your project folder.
That may work for example if your server is watching files and/or folders in a static location, different from where your app will be running.
In the end, I feel this is a sort of XY problem: you have not described your objective in the first place, and the above issue is trying to solve a weird solution that does not seem to fit how Meteor works, hence which may not be the most appropriate solution for your implicit objective.
#Sashko does a great job of explaining Meteor's dynamic imports here. There are also docs
A dynamic import is a function that returns a promise instead of just importing statically at build time. Example:
import('./component').then((MyComponent) => {
render(MyComponent);
});
The promise runs once the module has been loaded. If you try to load the module repeatedly then it only gets loaded once and is immediately available on subsequent requests.
afaict you can use a variable for the string to import.
PROBLEM DESCRIPTION.
I'm trying to follow https://github.com/lucascosta/facebook-js-ads-sdk to install the Javascript SDK for Facebook. Before anyone objects, I am absolutely aware of the compact version (https://developers.facebook.com/docs/javascript/quickstart), but that API is absolutely useless to me. I need the one produced by Lucas Costa, in order to be able to make changes to my ads account, which the recommended script by Facebook does not enable.
As usual installation instructions (see github.com/lucascosta/facebook-js-ads-sdk) are horribly predicated on mysterious conditions, that are unbeknown to me. I cannot get the SDK to work and would like someone to tell me explicitly what to do. The crux of the problem is the paradoxical situation: I am supposed to use a require('...') command (where??) to include the SDK (where is this supposed to be saved??) and yet require cannot be used on folders, but on scripts. Maybe somewhere there is a require.config file, I'm supposed to set up, but I have no idea, as, like I said, the instructions completely bypass any mention of the necessary starting conditions.
Here is what I have done so far. My folder-structure looks like this (I don't even know if this is right, as no-one explains it anywhere!):
[Serverroot]
— [folder with my website]
– facebook-ads-sdk (the folder one gets by downloading)
– css — pagestyles.css
– js — lib
require.js
— app
( some header scripts )
– img
( some images )
index.php
In index.php I have a block of html followed by some javascript. It is here, that I try to insert the setup / example code from . The browser cannot even get past the line const adsSdk = require('facebook-ads-sdk');. I have tried a number of things: require('./facebook-ads-sdk');, moving all this to the folder ./js/app in a script main.js and then writing in my html in index.php where main and require are located. Setting up a require.config (or requirejs.config) replacing require by requirejs, etc. and including the appropriate scripts in the <head> part of index.php. Nothing helps. Here are the errors: first with const adsSdk = require('facebook-ads-sdk'); I get
Error: Module name "facebook-ads-sdk" has not been loaded yet for context: _. Use require([])
Okay. How do I ‘load the Module for the context _’?? Reading requirejs.org/docs/start.html is of no help here. I tried require([], function() {require('facebook-ads-sdk')}); Same error. I tried require(['facebook-ads-sdk']);
I tried using the following commands in my script in index.php:
require.config({
shim: {
'facebook': {
exports: 'adsSdk',
},
},
paths: {
'sdk': './facebook-ads-sdk',
}
});
var adsSdk = require(['sdk']);
Then I get the error
Failed to load resource: http:// .... /facebook-ads-sdk.js the server responded with a status of 404 (Not Found)
Ie, the browser thinks I'm trying to include a script facebook-ads-sdk.js, but I’m supposed to(???) ‘require’ the entire folder! What is going on? Can someone please give me thorough instructions about the necessary folder structure and command, in order to get this SDK working?
Why is this so infuriatingly vaguely described online? Is there some kind of mysterious way of installing SDKs, about which ‘everyone’ knows, but never mentions?
UPDATE: SOLUTION. For any future google-searches for this same problem: via the following simple methods, one can install & embed the Javascript-FB-Ads-SDK:
install via npm install --save facebook-ads-sdk a copy of the npm modul Lucas Costa’s facebook-ads SDK.
Copy this folder to your website’s architecture (actually you possibly just need one subfolder / file).
in your HTML include the script (via <script type='text/javascript' src='...'></script>) with the src pointing to the file in the facebook-ads-sdk folder: /dist/iife.js.
In your page’s script, you now have access to then API via the global variable fb.
alternatively to 3:
3’. in your HTML headers make sure to include the require.js script via a <script>-tag. Then in your website’s javascript apply the following commands anywhere:
require.config({
paths: {
'sdk': './[FOLDERNAME OF SDK]/dist/iife',
}
});
require(['sdk']);
Credit and special thanks goes to #SLaks and #KhauriMcClain (I would give you up-points if I could) for this solution.
The instructions are assuming that you're using a bundling system like Webpack or Browserify.
If you are, the instructions "just work"; you can require() it and everything will work fine.
If you're building a non-trivial codebase, you really should use such a system.
If you aren't, you can reference iife.js in a <script> tag and that will create global variables.
You need to change the way you are using require.
You cannot use the synchronous require method to load dependencies if they have not been loaded before. Hence const adsSdk = require('facebook-ads-sdk'); will not work. You will need to use the form require(['name-of-script'], callback).
Require does not allow you to load an entire folder. You have to find the exact script you are trying to work with so var adsSdk = require(['sdk']); will not work.
Ultimately your code should look something like:
require(['some-facebook-script'], function(someFacebookScript) {
// Do some work here
});
The parameter passed to the callback function will be the loaded module you are trying to consume. When using the asynchronous version (as I just demonstrated) the return from require is not useful.
I am trying to understand how requireJS and backbone work. With this site when I open the DevTools in Chrome and opened a Sources Tab. I see a long list of folders/files (see image below) which seems to be the source code when it's uncompressed. However, I don't see it being loaded via the Network Tab.
I wonder how does it tie in and is it normal that the source code gets exposed like this, and whether it is normal that all views are being loaded even I just requested one page (i.e. the search page, see image below). I understand that modern Javascript applications like Angular likes to preload the application before it's presented. But wouldn't it be causing a lot of unnecessary traffic to users? especially those on mobile view?
First, your question mixes two things.
BackboneJS and RequireJS are completely unrelated
What you observe (module dependency structure in the scripting panel vs. all those files actually not downloaded) is due to the Debugger support of "Source maps"
Since I guess your confusion is caused by this I'll start with ...
Source maps
Modern browsers support source maps. Their intention is to reveal the original source code when it has been concatenated and/or minified into one file.
The source map file describes e.g. the symbol ZZyb at line 1 char 20563 is mapped to e.g. the file/somewhere/in/the/tree at line 34 char 1 and is named someView.
Minified files reference the source map using the
# sourceMappingURL=getaround-min.js.map
signature.
More on source maps: http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/
When downloading the minified file (https://www.getaround.com/js/150502002818/getaround-min.js) on that website you've linked, you will observe that signature at the end of the file:
//# sourceMappingURL=getaround-min.js.map
You can then download that file. This is what your debugger does.
RequireJS vs. BackboneJS
You can use RequireJS to modularize your own code or in conjunction with other Frameworks that do not already ship with such technologies.
AngularJS for example has it's own dependency management which allows you to define named dependencies and finally you start the application. This allows you to just concatenate (and minify) all sources into one file without taking care of the definition order.
Even though Backbone and Require are unrelated they work very well together.
RequireJS
RequireJS implements the so called AMD spec.
A module defines dependencies and a callback to implement that module.
depA:
// Require depB and depC and after they've been loaded
// call the callback function and pass those
// dependencies. Finally return that module.
define(["depB", "depC"], function(depB, depC){
// by convention depB will resolve to depB.js relative
// to "depA"'s path
// object, string, number, function your module is made of
return something;
});
RequireJS will download the dependencies, store (cache) them intenally and pass them to the callback. This process repeats down the dependency tree. When a dependency has already been downloaded (by another upstream module) it can be passed directly without downloading it again.
depB:
define(["depC", "depD"], function(depC, depD){
// depC has already been loaded and cached - doesn't
// need to be downloaded again
});
RequireJS optimization
Downloading all dependencies file by file can (and - on internet seites - should) be avoided by packaging them using r.js. The modules will be converted into into one file during build time.
Is there any way I can include an external JS library in my pebble code?
Conventionally on a webpage I would do this in my head tags:
<script type='text/javascript' src='https://cdn.firebase.com/js/client/1.0.11/firebase.js'></script>
But in pebble, I am unable to do that since I am only using JS. So how can I include an external library for a JavaScript file.
At present, you cannot include external JS files.
If you're using CloudPebble, then the only way to do this is to copy and paste the content of the JS library files into your JS file.
If you're doing native development, you can modify the wscript file to combine multiple JS files into one at build time.
I think there's some confusion over Pebble.js vs PebbleKit JS (v3.8.1). Pebble.js is a fledgling SDK where eventually the programmer will be able to write pure JavaScript. It's still cooking so there's some functionality missing like the ability to draw a line or obtain the screen dimensions. The repo is a mix of C and JS sources where you can add C code to augment missing functionality but otherwise all your code lives in src/js/app.js or src/js/app/. Anyway, Pebble.js does support require.
I don't use CloudPebble but I got the impression that it either supports Pebble.js (and hence require) or is planning to. I think all this SDK boilerplate code would be hidden.
PebbleKit JS does not support require out of the box AFAIK. I've made a demo that ports require support from Pebble.js to PKJS. The summary of changes is:
Move your project's src/js/pebble-js-app.js to src/js/app/index.js.
Remove any ready event listener from src/js/app/index.js. index.js will
be loaded when the ready event is emitted.
Add src/js/loader.js from Pebble.js.
Add a src/js/main.js that calls require('src/js/app') on the ready event.
Update your wscript with the following
deltas.
When adding new modules, place them under src/js/app/ and require('./name') will work.
I've tried to cover this all in the demo's readme.
BTW, here's the official breakdown of all the different SDKs but it's a little confusing.
I am not sure if there have been changes since the above answer, but it looks like there is in fact a way to include additional resources while keeping things tidy. On the pebbleJS page, there is the following section with an some information on the subject.
GLOBAL NAMESPACE - require(path)
Loads another JavaScript file allowing you to write a multi-file project. Package loading loosely follows the CommonJS format. path is the path to the dependency.
You can then use the following code to "require" a JS library in your pebble project. This should be usable on both Cloud Pebble as well as native development.
// src/js/dependency.js
var dep = require('dependency');
You can then use this as shown below:
dep.myFunction(); // run a function from the dependency
dep.myVar = 2; // access or change variables
Update:
After some digging into this for my own, I have successfully gotten CloudPebble to work with this functionality. It is a bit convoluted, but follows the ECMAScript 6 standards. Below I am posting a simple example of getting things set up. Additionally, I would suggest looking at this code from PebbleJS for a better reference of a complex setup.
myApp.js
var resource = require('myExtraFile'); // require additional library
console.log(resource.value); // logs 42
resource.functionA(); // logs "This is working now"
myExtraFile.js
var myExtraFile = { // create a JSON object to export
"value" : 42, // variable
functionA : function() { // function
console.log("This is working now!");
}
};
this.exports = myExtraFile; // export this function for
// later use
I was wondering if anyone had experience using require.js with the Adobe CQ5 platform. I'm writing a Chaplin.js(backbone-based) single page app that will be integrated into the rest of CQ5-based site we're working on. Chaplin requires the use of a module system like AMD/Common.js and I want to make sure my compiled javascript file will usable within CQ5's clientlibs. Is it as simple as adding require.js as a dependency in clientlibs prior to loading in my javascript modules? Someone's insight who has experience in doing this would be greatly appreciated.
I've implemented this as a solution of organize in a better way all the modules such as:
//public/js/modules/myModule.js
define('myModule',[ /* dependencies */] ,function( /* stuff here */ ))
and in the components such:
<% //components/component.jsp %>
<div>
<!-- stuff here -->
</div>
componentJS:
//components/component/clientlibs/js/component.js
require(['modules/myModule']);
and finally I've configured require (config.js) and I've stored the JSs modules in a new different design folder. Located the compiled JS after close </body> to guarantee the JS is always located at the bottom after the HTML.
<!-- page/body.jsp -->
...
<cq:includeClientLib js="specialclientlibs.footer"/>
</body>
solving with this the issue of have "ready" all the content before the JS is executed. I've had some problems to resolve with this async stuff managed for the clienlibs compilation tool, in production the problem was different, however, in development, the order in what CQ compiles the JS has produced me some lacks in terms of order of the JS. The problem really was a little bit more complex than the explanation because the number of JS was really big and the team too, but in simple terms it was the best way I've discovered so far..
The Idea
I think you can compile your Chaplin.js with one of the AMDShims to make it self contained, wraps every dependencies it needs inside a function scope, expose an entry point as global variable (which is a bad practise, but CQ do it all the time...) and then use the compiled.js inside a normal clientlib:
AMD Shims
https://github.com/jrburke/requirejs/wiki/AMD-API-Shims
Example
Here is an example of how we make the one of our libs self-contained:
https://github.com/normanzb/chuanr/blob/master/gruntfile.js
Basically, in source code level the lib "require"s the other modules just as usual. However after compiled, the generated chuanr.js file contains everything its needs, even wrapped a piece of lightweight AMD compatible implementation.
check out compiled file here: https://github.com/normanzb/chuanr/blob/master/Chuanr.js
and the source code: https://github.com/normanzb/chuanr/tree/master/src
Alternative
Alternatively rather than compile every lib you are using to be independent/self-contained, what we do in our project is simply use below amdshim instead of the real require.js. so on cq component level you can call into require() function as usual:
require(['foo/bar'], function(){});
The amd shim will not send the http request to the module immediately, instead it will wait until someone else loads the module.
and then at the bottom of the page, we collect all the dependencies, send the requirements to server side handler (scriptmananger) for dynamic merging (by internally calling into r.js):
var paths = [];
for (var path in amdShim.waiting){
paths.push(path);
}
document.write('/scriptmananger?' + paths.join(','));
The amdShim we are using: https://github.com/normanzb/amdshim/tree/exp/defer