[ALOY-1734] JS files imported in "alloy.js" don't have access to Alloy globals as of Titanium 9.0.0
GitHub Issue | n/a |
---|---|
Type | Bug |
Priority | High |
Status | Closed |
Resolution | Fixed |
Resolution Date | 2020-08-11T20:24:48.000+0000 |
Affected Version/s | n/a |
Fix Version/s | CLI Release 8.1.0 |
Components | n/a |
Labels | alloy, globals, regression |
Reporter | Joshua Quick |
Assignee | Ewan Harris |
Created | 2020-07-30T20:48:49.000+0000 |
Updated | 2020-08-11T20:24:48.000+0000 |
Description
*Summary:*
As of Titanium 9.0.0, a JS files loaded via Open project file:
import
in the "alloy.js" won't have access to globals Alloy
, Backbone
, or _
(aka: lodash).
This is not an issue if JS files are loaded via the require()
function.
*Steps to reproduce:*
Download [kitchensink-v2](https://github.com/appcelerator/kitchensink-v2).
Open project file: ./app/lib/actionbar.js
Add the following line to the end of the JS file:
console.log("@@@ Alloy = " + (typeof Alloy));
Build and run on Android or iOS.
Notice the following gets logged as undefined.
[INFO] @@@ Alloy = undefined
*Cause:*
Look at the "app.js" that gets generated. The babel transpile is turning the JavaScript import
statement into a require()
function call at the top of the "app.js", above where we assign Alloy
globals. Also note that "var" variables in "app.js" and "alloy.js" no longer have global scope as of Titanium 9.0.0, which is why it wasn't an issue before.
The top of the generated "app.js" looks like this.
var _actionbar=_interopRequireDefault(require("actionbar"));
function _interopRequireDefault(obj){
return obj&&obj.__esModule?obj:{default:obj}
}
"use strict";
var Alloy=require("/alloy"),
_=Alloy._,
Backbone=Alloy.Backbone;
global.Alloy=Alloy,
global._=_,
global.Backbone=Backbone,
*Note:*
JavaScript import
statements are "hoisted". This is in the ES6 specification, which means this is not a babel transpile issue. So, import
statements will always be executed first within the same JS file.
*Possible Fix:*
Add an "alloy.bootstrap.js" to the project and assign the Alloy globals there. Bootstrap scripts are loaded before the "app.js", which works-around the problem. This also means we can remove the global Alloy assignment from the generated "app.js".
*Work-Around:*
Don't import
JS files in the "alloy.js". Use require()
function instead.
Adding the bootstrap file will be the only solution here, bable is adhering to the modules spec by hoisting the import statements like they would if they were actually ran in a JS environment (as opposed to being transpiled) https://exploringjs.com/es6/ch_modules.html#_imports-are-hoisted
I can think of another solution. Instead of inserting the "alloy.js" code into the "app.js" template's
__MAPMARKER_ALLOY_JS__
, we could keep the "alloy.js" file and require it in instead. https://github.com/appcelerator/alloy/blob/master/Alloy/template/app.js So Alloy's "app.js" code becomes the below.This means we're no longer generating an "app.js" and we would just copy this file and the developer's "alloy.js" as-is.
Could we also (as a workaround) move not only the Alloy.Globals but the whole alloy.js contents to the bootstrap? Does this affect boot time?
bq. Could we also (as a workaround) move not only the Alloy.Globals but the whole alloy.js contents to the bootstrap? Does this affect boot time? Yes, that's exactly what I'm suggesting. And it wouldn't effect the boot time. We would simply be loading the "alloy.js" sooner than before (ie: before the "app.js"). A bootstrap script can only add a delay when using its optional async execute function, which we're not going to do in this case. Also, it looks like JS imports being "hoisted" above JS statements is part of the ES6 specification. So, this isn't a babel issue. The babel transpile is doing the correct thing.
PR: https://github.com/appcelerator/alloy/pull/964 I did some small tests to see how this impacted the startup time of KS-v2 on Android and there's averaged out I'm seeing similar numbers, I'll continue to try collect data and also get some results for iOS
Available in alloy 1.15.0 and appc CLI 8.1.0-master.9. Appc cli currently only preprod, so internal only
Verified on: Mac OS: 10.15.4 SDK: 9.1.0.v20200810095016 Appc CLI: 8.1.0-master.9 JDK: 11.0.4 Node: 10.17.0