React: Disable minification for a given library - reactjs

I am in the process of testing the release build of a react native app and found that the minification process is breaking the xml parser library. In this case, there is a [ReferenceError: Can't find variable: dc], which I found out by diving through the minified bundle and logging, to be related to the above referenced library.
Is there a way to disable minification only for this library?
Also, would this be the best approach to tackle this kinds of minification problems?

Disable minification for React App
What is the current behavior?
When bundling production builds for React Native, names are mangled by default. This can break code (if it relies on Function.name) and the issue is kinda hard to track down (especially if the code accessing Function.name is deep into your dependency tree).
What is the expected behavior?
There should be at least an option to disable mangling, but I believe ideally it should be opt-in rather than opt-out. (Since it can break code in unpredictable ways)
For now relying on manually patching minify.js
Solved by disabling mangling:
Prevent UglifyJS from changing function argument names.
According to the documentation you can use mangle options to do that:
mangle (default true) — pass false to skip mangling names, or pass an object to specify mangling options.
Object options:
except - pass an Array of identifiers that should be excluded from mangling
toplevel — mangle names declared in the toplevel scope (disabled by default).
eval — mangle names visible in scopes where eval or with are used (disabled by default).
keep_fnames - default false. Pass true to not mangle function names. Useful for code relying on Function.prototype.name.
in node_modules/metro-bundler/src/JSTransformer/worker/minify.js
function minify(filename, code, sourceMap) {
const minifyResult = uglify.minify(code, {
fromString: true,
inSourceMap: sourceMap,
outSourceMap: true,
mangle: false, // ADD THIS LINE
output: {
ascii_only: true,
screw_ie8: true,
},
});
})
OR
May be your issue is due to the combination of running webpack -p and using Uglify Plugin.
Try omitting -p when running build and use uglify plugin, might this fix your issue.

Related

How to avoid conflict between "dom" and "webworker" libs?

I am using TypeScript with React, and one of the things I want to achieve is background sync for offline support.
To enable typings for service worker, I have to include the WebWorker lib, but it conflicts with DOM lib and produces an error:
(25,1): Definitions of the following identifiers conflict with those in another file:
EventListenerOrEventListenerObject, BlobPart, HeadersInit, BodyInit,
RequestInfo, DOMHighResTimeStamp, PerformanceEntryList, PushMessageDataInit,
VibratePattern, BufferSource, DOMTimeStamp, FormDataEntryValue,
IDBValidKey, MessageEventSource, BinaryType, ClientTypes,
IDBCursorDirection, IDBRequestReadyState, IDBTransactionMode,
NotificationDirection, NotificationPermission, PushEncryptionKeyName,
PushPermissionState, ReferrerPolicy, RequestCache, RequestCredentials,
RequestDestination, RequestMode, RequestRedirect, ResponseType,
ServiceWorkerState, ServiceWorkerUpdateViaCache, VisibilityState,
WorkerType, XMLHttpRequestResponseType
So I am wondering if there is any workaround except for typing most of my arguments any.
You can split your project into multiple parts with separate tsconfig.json files: one part that includes the dom lib and one part that includes the webworker lib. You can make another part for common code that doesn't depend on either library. You can use project references to help automate the build. If this doesn't fully solve the problem, please update the question to describe the outstanding issues.

What does the module keyword mean in typescript?

I'm trying to figure some things related to ES6 modules. How to use namespaces together with angular and typescript.
Assume the following code represents an angular directive. Does anyone know what the module keyword mean and how can you access MyClass in other file.
// file1.ts
module NSpace.Space {
export class MyClass {
constructor() { ... }
...
}
}
I have tried accessing on another file using and re-exporting, however
// file2.ts
import {MyClass} from 'file1';
export {MyClass}
I get this error: error TS2306: File 'file.ts' is not a module
My questions are:
why do I get this?
what is this module keyword?
do we create ES6 modules only based on the directory structure or can
we actually use this notation? module Space.Space1.Space2 ...
From what I've read and experienced so far it seems that ES6 modules are defined based on file structure, that's why I get this error.
I have not written this code, that's why I'm asking. Also it might be useful to mention that I'm using System.JS for importing.
The module keyword in TypeScript caused a bit of confusion, so it is going to be renamed namespace.
Rather than use namespaces, though, you can organise your code by files / file system (which means the actual file location will match the perceived namespace. This is how "exteral modules" (TypeScript) work - and also how ECMAScript 2015 modules work.
So with a quick adjustment, you'll have:
// file1.ts
export class MyClass {
constructor() { ... }
...
}
And then this will work:
import {MyClass} from 'file1';
If you compile targeting ES6, you'll notice that this line of code needs no translation, it matches the standard for module imports. If you target ES5 or lower, TypeScript will transform this statement for you (you can choose the transformation using the --module flag.
I tend to use the UMD compilation option, which means the output will work in web browsers (with RequireJS) or on Node. System JS is actually gaining a lot of traction currently, so you may want to consider that too. Eventually, browsers will simply natively support module loading.

Silencing JSLint warnings in brackets

I just started a gulp-angular Yeoman project and opened it in brackets, and nearly everywhere I'm getting 'something' was used before it was defined, specifically 'angular' was used before it was defined. I've messed around with extensions and other fixes, but I honestly don't know what I'm doing and I haven't been able to find any good documentation.
What can I do to silence these warnings across the entire project? In other words, how can I avoid using /*global angular*/ in pretty much every file in my project?
Here's a quick example of one of my controller declarations:
/*global console*/
(function () {
'use strict';
angular
.module('sbk')
.controller('MainController', MainController);
/** #ngInject */
function MainController() {
console.log('Woo!');
}
})();
Which results in the following JSLint warnings:
'angular' was used before it was defined.
'MainController' was used before it was defined.
'MainController' was used before it was defined.
Move the invocation into the parens that contain the function.
Edit: updated to make my issue a little clearer
http://jshint.com/docs/options/#globals
Provide a list of globals, and you're done.
It's not clear if you're using jshint or jslint; your tags say one, your text another.
Okay, so remember that JSLint is just a JavaScript file, and most JSLint plugins I've used has the source shoved in the install somewhere (though the Visual Studio plugin embeds it into a dll!), so you can always get it to do what you want [within reason].
In your case, the absolute worst case is that you initialize the list of predefined variables with the namespaces you want JSLint to assume are always considered to be in scope. I'm going to show you how to set that globally within Brackets, which might not always be the best thing to do, and you need to keep in mind if you're linting another project that doesn't have Angular, well, you've screwed up JSLint.
(Honestly, I'm disappointed that Brackets doesn't have global as a global in its preferences.json file. Guess I should submit a patch.)
There are lots of ways we could do this. I'm going to add a namespace to the standard object. You could also limit its exposure by adding to the browser collection of globals (line 497 in my Bracket install's jslint file). We could also create a new JSLint directive option, similar to browser. That's not quick 'n' dirty, but is probably The Right Way to do this without submitting a Brackets patch. But for now, let's just do the quick 'n' dirty fix.
I'm using Windows. If you're not, YMWV. I do not use Brackets daily, so I haven't tested this in a production coding environment. If anything doesn't work, I'd be interested to hear it, however, and I'll see if I can find what's wrong.
TL;DR. Just the code, ma'am.
The jslint.js file you want is here, if you went with the default install location:
C:\Program Files (x86)\Brackets\www\extensions\default\JSLint\thirdparty\jslint
(Just for fun, notice that the version of JSLint we're using is from 2011!!?! Come on, Brackets guys!)
standard is, in my file, on line 974. Here's what it had originally:
// standard contains the global names that are provided by the
// ECMAScript standard.
standard = array_to_object([
'Array', 'Boolean', 'Date', 'decodeURI', 'decodeURIComponent',
'encodeURI', 'encodeURIComponent', 'Error', 'eval', 'EvalError',
'Function', 'isFinite', 'isNaN', 'JSON', 'Math', 'Number', 'Object',
'parseInt', 'parseFloat', 'RangeError', 'ReferenceError', 'RegExp',
'String', 'SyntaxError', 'TypeError', 'URIError'
], false),
Here's a test JavaScript snippet I want to lint that uses my global object, util:
/*jslint sloppy:true, white:true */
utils.spam();
utils.spammySpam();
smutils.spam();
All we need to do is to add , 'utils' to standard, and we're done.
standard = array_to_object([
'Array', 'Boolean', 'Date', 'decodeURI', 'decodeURIComponent',
'encodeURI', 'encodeURIComponent', 'Error', 'eval', 'EvalError',
'Function', 'isFinite', 'isNaN', 'JSON', 'Math', 'Number', 'Object',
'parseInt', 'parseFloat', 'RangeError', 'ReferenceError', 'RegExp',
'String', 'SyntaxError', 'TypeError', 'URIError', 'utils'
], false),
To be overly clear, you'd add 'angular' and 'MainController' to your standard object in place of 'utils'.
Btw, Crockford (JSLint's creator and maintainer) would hate that we did that. I don't really blame him.
Now I get an error for smutils, but not utils. Luckily, the global directive still works with this setup:
/*jslint sloppy:true, white:true */
/*global smutils */
utils.spam();
utils.spammySpam();
smutils.spam();
And we're JSLint friendly again.
Hacking JSLint directly might not have most favored option status, but it works.
Btw, re: Dave's comment, "IMO JSLint has been popularly deprecated in favor of JSHint or JSCS," I'm not so sure. Just as an example, which does Brackets use out of the box? The best part about JSLint is how much less subjective discussion has to happen to get a large team on the same page. And trust me, Crockford's not going to tell you to do something that's indefensibly wrong.
He might hurt your feelings, and he might ask you to do something that hurts at first, but I really think JSLint can teach a team a lot about JavaScript best practices. It's worth living in JSLint for a while before jumping to JSHint.

when defining an angular module - should I wrap in self executing function?

(function (angular) {
"use strict";
angular.module('module')
.filter('leFilter', function() { ... });
})(angular);
Saw this code in a new project I'm working on.
I usually just begin the module at the root of the file and dont use 'strict' mode.
angular.module('module')
.filter('leFilter', function() { ... });
I've never ran into a single issue doing this.
In the context of an angular application, is there really anything to gain from the self-executing function and 'strict' mode?
I really don't see any major benefit from running it in an IIFE(Immediately-Invoked Function Expression), especially with how good angular is about wrapping things in closures itself (such as in your filter). You will insulate yourself from naming collisions thanks to the scope created by using them, but they decrease readability. They would be a bit more useful in this regard if you stored your angular modules in variables upon instantiation and used those when adding controllers/filters/etc. rather than using the module getter, but I don't recommend doing that.
If you are using a build system such as Gulp or Grunt then it might be worth having it compile these files inside of IIFE, and leaving your source without them.
I always recommend using "use strict" because it makes you write cleaner code with less chance of having casting issues. But, again, it doesn't necessarily help you "gain" anything so much as it prevents something bad from possible occurring.
Both of these are essentially safe-guards more-so than giving you some sort of advantage.
strict mode means you have less chance of running into type casting issue while self executing function is to avoid polluting global namespace.

angularjs promises use the word finally. grunt jshint complains

AngularJS allows the use of finally after the return of a promise. However, when I have a grunt-jshint running I keep getting
Expected an identifier and instead saw 'finally' (a reserved word).
Does any one know how to turn this off in jshint?
es5 option
This option enables syntax first defined in the ECMAScript 5.1
specification. This includes allowing reserved keywords as object
properties.
If you are using a version of jshint prior to 2.0.0, then you have the option of setting an es5 flag. Starting with 2.0.0, es5 is the default. I assume you are using an older version.
Alternatively
You can also say promise['finally'](function(){}); rather than promise.finally(function(){});
See
http://jshint.com/docs/options/#es5
https://jslinterrors.com/expected-an-identifier-and-instead-saw-a-a-reserved-word
http://jshint.com/blog/2013-05-07/2-0-0/

Resources