Short version:
I'm updating some old libs to try to get them in AMD/requirejs format for management, but some of them have dependencies on old code.
Main Question:
I'm primarily confused as to what to list in the:
define(['what','goes','here'],function('what','needs','to','be','here'){})
and what goes in the shim dependencies list when dealing with combinations of AMD and non-AMD tools, and things like jquery-ui and jquery plugins.
ADDITIONAL INFO
The problem:
One of the older libraries depends on .draggable() from (and older version of) jquery-ui, some old version of a jquery plugin called 'onScreen', a spinner modal called spin.js -- all of which are not AMD friendly. (I also implemented an update to an AMD friendly new version of dropzone)
Two of the older libraries also use a modal library called vex which requires a dependency of vex.dialog. The existing site has an old version that is uglified.
I'm trying not to completely revamp this code as the longer term goal would be to remove those dependencies entirely, but I may not have to the time now to figure out what they are doing.
I've tried every combination of define(['list','of','stuff']) I can think of, but some of the libraries like spin (class Spinner), vex/vex.dialog and onScreen still don't always load properly. (sometimes I get one, but then lose another)
Can I define a shim AND include a list of AMD modules in the define? And if so, do I include the AMD list of dependencies in the shim in require.config? What goes where and why?
My libraries:
ImageSelector (requires AwsHelper, Utilities and ImageLayout below)
-- uses jquery (AMD), dropzone (AMD) and an old jquery plugin called jquery.onscreen.js (non-AMD)
-- depends on vex and vex.dialog (non-AMD)
-- uses .draggable() from old jquery-ui (non-AMD)
-- calls a global function 'loadSpinner' which uses spin.js (non-AMD -- see Utilities below)
ImageLayout (requires AwsHelper and Utilities - has attached instance of ImageSelector as a property .selector for methods that work in conjunction with the selector)
-- uses jquery (AMD)
-- also utilizes vex/vex.dialog (non-AMD)
Utilities
-- I'm trying to move the loadSpinner() function that requires spin.js (class Spinner, non-AMD) into this
-- I've managed thus far to avoid dependencies on things like jquery in this by refactoring code
Long version:
I'm trying to update some website code to use require.js for dependency management and to make the code more portable. But I'm running into a number of dependencies on old code that don't appear to be AMD-ready. Where possible, I'm trying to replace these with updated code and/or replace their functionality entirely, but in a number of cases, the code is minified and it's difficult to get a quick handle on what it's doing.
Rather than getting mired in minutia of trying to figure out and either replace or update these things, I read about how 'shim' can be used in some cases to handle these types of non-AMD code, but I'm still unclear on how to configure them.
Here's what I have... I have three libraries I have updated and one new one I created. One called 'ImageSelector' builds a web-gui to allow uploading files with dropzone. (My reason for updating it is that I converted it from using a local filesystem to using Amazon AWS S3 storage.) A second one called 'ImageLayout' handles the business logic of creating a product layout of photos selected by the user. (ImageSelector is split into two frames, a left one for uploading and sorting user files into folders, a right one for building the layout. Thus ImageSelector is dependent on ImageLayout)
The third library is one I created just with a number of repeatedly use 'utility' functions used across the website. There is an existing structured-code version of this in global scope with just a list of functions like roundPrecision(), sanitizeFilename(), escapeRegex(), baseName(), etc. I was going to build this with static methods, but then realized I can customize it if I spawn instances of it instead (e.g. I can change the characters 'sanitized' for different applications with global instance parameters)
The new one is the AwsHelper which is not a problem as it's entirely new code and handles all the interaction with Amazon AWS and S3. It was created in a define() AMD format while the others I have converted to define()/export format.
Anyway, some functions of the ImageLayout can be used independently by the order system, but for the most part, it's used as a dependency of the ImageSelector. AwsHelper is used mostly by ImageSelector but there are two functions in ImageLayout that utilize it. All of the above use the Utilities library.
My guess is something like this in the config (using ImageSelector as an example, but I'm wondering if "jquery" an "dropzone" need to be in there or the function define or both?)
shim: {
"ImageSelector": {
deps: ["jquery","dropzone","vex","vex.dialog","jquery-ui","jquery.onscreen"]
}
}
Additional require.js semantic questions:
(I'll post these separately if needed, but they may be short-answer and related)
Is there anything anywhere that shows how require.js searches for files? e.g. I understand about r.js for uglifying, but in some cases I can't track down the original code for these things. Can filenames include .min.js on the end or version numbers and will require.js still find them or should I rename and/or symlink files? e.g. jquery.js vs jquery-1.7.min.js for example.
The spin.js referenced above actually includes a class definition called 'Spinner'. How do I represent that in the config/shim?
Well, I posted that based on my experimenting the last 3 days riddled with failures, expecting more trouble. But apparently, shim was straightforward and having the required libs in more than one place (shim definitions and define([])) wasn't a problem.
I took a blind guess going through the examples on the require.js and came up with this configuration and amazingly it worked first try! (which makes me nervous as this is the first time I've gotten this code to work with no errors since trying to import it to require.js)
Here's what I came up with:
requirejs.config({
"baseUrl": "/js/lib",
"paths": {
"ImageSelector" : "../awsS3/ImageSelector",
"ImageLayout" : "../awsS3/ImageLayout",
"AwsHelper" : "../awsS3/AwsHelper",
"Utilities" : "../awsS3/Utilities"
},
"shim": {
"jquery.onscreen": {
"deps": ['jquery'],
"exports": 'jQuery.fn.onScreen'
},
"jquery-ui" : ['jquery'],
"vex.dialog" : ['jquery','vex'],
"vex" : ['jquery'],
"spin" : {
"exports": "Spinner"
},
"aws-sdk" : {
"exports" : "AWS"
},
"Utilities": ["spin"],
"AwsHelper": ["jquery","aws-sdk"],
"ImageSelector": {
"deps" : ["jquery","dropzone","vex","vex.dialog","jquery-ui","jquery.onscreen","ImageLayout","AwsHelper","Utilities"]
},
"ImageLayout": {
"deps" : ["jquery","vex","vex.dialog","Utilities"]
}
}
});
I also noted that some of the version naming was handled in the paths, thus I just named my libs in the paths and got rid of my "app/" directory reference altogether.
Can someone tell me how to get protoc to generate dart files with a leading library directive?
I'm using the dart-protoc-plugin (v0.10.2) to generate my dart, c++, c#, js and java models from proto files. I was under the impression there was no way to get protoc to add a 'library' directive to the generated dart files, until I noticed the directive appearing in another project (see date.pb.dart).
If I take the same file (date.proto) I cannot get protoc to generate a dart file containing a 'library' directive.
In short: I want to take a .proto file with the following content
syntax = "proto3";
package another.proj.nspace;
message MyObj {
...
}
and produce a .dart file with a leading 'library' directive similar to the following snippet
///
// Generated code. Do not modify.
///
// ignore_for_file: non_constant_identifier_names,library_prefixes
library another.proj.nspace;
...
NOTE: I don't care about the actual value of the directive since I can restructure my code to get the desired result. I just need a way for protoc to add the library directive...
The basic command I'm using to generate the dart files is
protoc --proto_path=./ --dart_out="./" ./another/proj/nspace/date.proto
Unfortunately the dart-protoc-plugin's README isn't very helpful and I had to go through the source to find out which options are available; and currently it seems like the only dart-specific option is related to grpc.
I've tried options from the other languages (e.g. 'library', and 'basepath') without any success.
It would simplify my workflow quite a bit if this is possible, but I'm starting to get the impression that the library directive in date.pb.dart is added after the code was generated...
After asking around a little bit, it seems that the library directive was removed from the protoc plugin at some stage (see pull request), thus it is no longer supported.
Unlike inclusion of global.jsp with every component jsp in CQ5, sightly does not include any such dependency. How does it actually access all the global objects. What is the backend process of it. And how sightly code compiles to java??
how sightly code compiles to java?
Sling sightly API has two bundles to support this, the first step is to compile sightly into Abstract Syntax Tree (The Abstract Syntax Tree maps plain Java source code in a tree form. This tree is more convenient and reliable to analyse and modify programmatically than text-based source.) This is done by Apache Sling Scripting Sightly Compiler
Next is to convert (transpile) the Abstract Syntax Tree into java source code. This is achieved in bundle Java Compiler
How does it actually access all the global objects.
To understand this you need to understand how script resolution occurs in Sling and how are resource resolved to scripts which is core to Sling Scripting engine. To understand basics of ScriptEngine look at java docs here, implementation of this is SightlyScriptEngine
The way script resolution works is that the resource is adapted to DefaultSlingScript , this is done by SlingScriptAdapterFactory.
SlingScriptAdapterFactory has references to BindingsValuesProvider which is passed to the DefaultSlingScript. One of the implementation of BindingsValuesProvider is AEMSightlyBindingsValuesProvider (you can see this as a service in /system/console/services) which provides the default objects.
The DefaultSlingScript then responsible for invoking SightlyScriptEngine and calling its method eval which populates the default objects in binding and then setting this binding as request attribute.
I'm currently playing with the Dart version of Angular 2.
I have seen that the library is using a lot of Metadata as #Component for example.
I would like to know how are those directives working?
I went on http://www.darlang.org. They explain how to define an annotation but not how to use it to construct an object as it is done in angular.io.
Could someone explain how the magic is working?
In Dart annotations by itself don't do anything than exist beside the code element where they are added.
At runtime:
You can use dart:mirrors to query the imported libraries for elements like fields, functions, classes, parameters, ... for these annotations.
dart:mirrors is discouraged for browser applications. In this case you can use the reflectable package with quite similar capabilities.
See also:
https://www.dartlang.org/articles/reflection-with-mirrors/
https://api.dartlang.org/1.14.1/dart-mirrors/dart-mirrors-library.html
https://stackoverflow.com/search?q=%5Bdart-mirrors%5D+annotations
At buildtime
You can create a transformer and register it in pubspec.yaml to be run by pub serve and pub build.
In this case the Dart analyzer can be utilized to query the source files for annotations and, like Angular does, modify the source code in a build step to add/replace/remove arbitrary code.
For more details about transformers
- https://www.dartlang.org/tools/pub/assets-and-transformers.html
- https://www.dartlang.org/tools/pub/transformers/
- https://www.dartlang.org/tools/pub/transformers/examples/
- https://www.dartlang.org/tools/pub/transformers/aggregate.html
- https://pub.dartlang.org/packages/code_transformers
Is there a way to customize the way Asp.Net MVC4 bundling&minification feature minifies the js files?
Meaning, I don't want to completely turn off minification, but "as is" it just breaks AngularJs.
Since AngularJs uses DI and IoC approach for injecting services in controllers, the following:
function MyController($scope) { }
Once minified, becomes:
function MyController(n) { }
Normally that wouldn't be a problem, but AngularJs uses the parameter names to understand which service to inject. So $scope should remain $scope, as well as any other parameter in angular controllers. Everything else, like local variables, etc, should be minified normally.
I can't find any clear documentation on how to configure Mvc4 minification, and it seems rather dumb for it to be "all or nothing" so I think I'm missing something.
Thanks.
Actually you can (and should!) write AngularJS code so it is "minification safe". Details are described in the "Dependency Annotation" section of http://docs.angularjs.org/guide/di but in short, for globally defined controllers you can write:
MyController.$inject = ['$scope'];
Please note that globally defined controllers are polluting global namespace (see this for more details) and should be avoided. If you declare a controller on a module level you can make it minification-safe as well:
angular.module('mymodule', []).controller('MyController', ['$scope', function($scope){
//controller code goes here
}]);
if you still want to control what to minify and what not (or if you want to include an already minified version by the plugin vendor) just declare two bundles, and only minify one of them on your BundleConfig.cs:
var dontMinify = new Bundle("~/bundles/toNotMinify").Include(
"~/Scripts/xxxxx.js");
bundles.Add(dontMinify);
var minify = new Bundle("~/bundles/toNotMinify").Include(
"~/Scripts/yyyyyy.js");
minify.Transforms.Add(new JsMinify());
bundles.Add(minify);
For those of you who don't want/can't be arsed to write the "minification-safe" angular-DI syntax, and don't care about variable names being obfuscated, I used BundleTransfomer along with Yui Js minifier - available via nuget:
Install-Package BundleTransformer.Core
Install-Package BundleTransformer.Yui
Gives VERY fine-grained control over minification/obfuscation. In the angular world, just set the obfuscateJavascript within the yui web.config section to false.