Minification-Induced Symbol Loss in Production Titanium SDK Builds
0 reputation · 28 Sept 2025, 07:49 UTC
0 reputation · 28 Sept 2025, 07:49 UTC
A persistent discrepancy exists between Titanium SDK development and production builds for code that depends on JavaScript symbol identity. The precise goal is to determine how applications relying on function name introspection, parameter inspection, or computed require() paths can maintain consistent behavior across both build configurations.
Production builds minify JavaScript by default, renaming local symbols and eliminating unresolved dynamic references, while development builds skip this step entirely, creating a behavioral gap that manifests as runtime errors or silent failures on device or store releases. Key constraints include the absence of an official 'do not minify' annotation, the optimization-disabling flag's trade-offs of increased bundle size and reduced obfuscation, and platform-specific engine differences that may exacerbate or obscure minification edge cases. No current API reliably preserves symbol names without disabling optimization entirely.
Given these limitations, what approaches can mitigate minification-induced symbol loss? Are there undocumented configuration options or planned SDK features to address this? Should source map completeness be prioritized as a first-step improvement?
35275 reputation · 28 Sept 2025, 19:23 UTC
To keep function‑name introspection, parameter inspection, or computed require() calls working in both development and production Titanium builds, you must either preserve the symbols that minification removes or avoid relying on them altogether.
Production builds run the JavaScript optimizer (UglifyJS in older SDKs, Terser in SDK 10.x+) via the --optimize flag. This step mangles local variable/function names and eliminates any require() call whose argument is not a static string literal that the optimizer can resolve at build time. Development builds skip this step (--no-optimize), so original symbol names and dynamic requires remain intact, creating the observed behavioral gap.
/* @no-minify */ to preserve individual symbols.<property name="ti.android.optimize.js" type="bool">false</property> in tiapp.xml or run ti build --no-optimize. This increases bundle size roughly 30‑50 % and reduces obfuscation..map files) are generated for production builds but they only map positions for debugging; they do not restore Function.name values or prevent the removal of dynamic require() calls.exports with string keys (exports['myFunc'] = myFunc), replacing computed require() with a static registry map, avoiding reliance on Function.name or Function.prototype.toString() for logic, and passing symbols via Ti.App.Properties or Ti.App.getArguments().--minify-exclude exists in recent SDKs; it accepts file globs (not symbol patterns) to keep entire files unminified.name property is inspected, and any modules loaded via a variable path.const MODS = { foo: require('foo'), bar: require('bar') } and use MODS[moduleName]. If a true dynamic path is unavoidable, move that code into a separate file and add that file to --minify-exclude (verify the flag works in your SDK version).exports['inspectMe'] = function inspectMe() { … }. Access it later via exports['inspectMe'] or require('mymodule')['inspectMe'].ti build --minify-exclude "path/to/special/**/*.js" flag; otherwise, accept the global --no-optimize trade‑off after measuring bundle size.Resources/app.js (or platform‑specific bundle) to ensure the identified functions still appear with their original names or are accessed via the export map.The exact behavior of --minify-exclude and the optimizer version (UglifyJS vs. Terser) depend on your Titanium SDK version. Knowing whether you are on SDK 9.x or SDK 10.x+ would confirm if this flag is available and what its syntax is, which could change the recommendation from a global disable‑optimization approach to a selective exclude.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.