Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-24293] Alloy: iOS - Using require() without "/" prefix will try to load file relatively node_modules first, other unrelated logs and behavior changes

GitHub Issuen/a
TypeBug
PriorityCritical
StatusClosed
ResolutionDuplicate
Resolution Date2017-05-02T17:21:37.000+0000
Affected Version/sRelease 6.0.0, Release 6.0.1
Fix Version/sRelease 6.1.0
ComponentsiOS
Labelsmerge-6.0.2, require
ReporterRene Pot
AssigneeFeon Sua Xin Miao
Created2017-01-11T13:07:26.000+0000
Updated2017-05-02T17:21:37.000+0000

Description

We're using a lot of requires in the app. Also with databinding we use require for every row. This used to work great with 5.# but now it seems to try something else. It tries to load the node_module first, then tries to find the controller/lib file resulting in a log like this:
[DEBUG] :  Loading: /Users/renepot/Library/Developer/CoreSimulator/Devices/58DEF941-13A4-4852-A765-F23042B1F82B/data/Containers/Bundle/Application/34E19F4B-9A68-48FC-BA03-2A5B02D168BE/Roamler.app/node_modules/libs/Location, Resource: node_modules/libs/Location
[DEBUG] :  Loading: /Users/renepot/Library/Developer/CoreSimulator/Devices/58DEF941-13A4-4852-A765-F23042B1F82B/data/Containers/Bundle/Application/34E19F4B-9A68-48FC-BA03-2A5B02D168BE/Roamler.app/node_modules/libs/Location.js, Resource: node_modules/libs/Location_js
[DEBUG] :  Loading: /Users/renepot/Library/Developer/CoreSimulator/Devices/58DEF941-13A4-4852-A765-F23042B1F82B/data/Containers/Bundle/Application/34E19F4B-9A68-48FC-BA03-2A5B02D168BE/Roamler.app/node_modules/libs/Location.json, Resource: node_modules/libs/Location_json
[DEBUG] :  Loading: /Users/renepot/Library/Developer/CoreSimulator/Devices/58DEF941-13A4-4852-A765-F23042B1F82B/data/Containers/Bundle/Application/34E19F4B-9A68-48FC-BA03-2A5B02D168BE/Roamler.app/node_modules/libs/Location/package.json, Resource: node_modules/libs/Location/package_json
[DEBUG] :  Loading: /Users/renepot/Library/Developer/CoreSimulator/Devices/58DEF941-13A4-4852-A765-F23042B1F82B/data/Containers/Bundle/Application/34E19F4B-9A68-48FC-BA03-2A5B02D168BE/Roamler.app/node_modules/libs/Location/index.js, Resource: node_modules/libs/Location/index_js
[DEBUG] :  Loading: /Users/renepot/Library/Developer/CoreSimulator/Devices/58DEF941-13A4-4852-A765-F23042B1F82B/data/Containers/Bundle/Application/34E19F4B-9A68-48FC-BA03-2A5B02D168BE/Roamler.app/node_modules/libs/Location/index.json, Resource: node_modules/libs/Location/index_json
[DEBUG] :  Loading: /Users/renepot/Library/Developer/CoreSimulator/Devices/58DEF941-13A4-4852-A765-F23042B1F82B/data/Containers/Bundle/Application/34E19F4B-9A68-48FC-BA03-2A5B02D168BE/Roamler.app/node_modules/libs/Location, Resource: node_modules/libs/Location
[DEBUG] :  Loading: /Users/renepot/Library/Developer/CoreSimulator/Devices/58DEF941-13A4-4852-A765-F23042B1F82B/data/Containers/Bundle/Application/34E19F4B-9A68-48FC-BA03-2A5B02D168BE/Roamler.app/node_modules/libs/Location.js, Resource: node_modules/libs/Location_js
[DEBUG] :  Loading: /Users/renepot/Library/Developer/CoreSimulator/Devices/58DEF941-13A4-4852-A765-F23042B1F82B/data/Containers/Bundle/Application/34E19F4B-9A68-48FC-BA03-2A5B02D168BE/Roamler.app/node_modules/libs/Location.json, Resource: node_modules/libs/Location_json
[DEBUG] :  Loading: /Users/renepot/Library/Developer/CoreSimulator/Devices/58DEF941-13A4-4852-A765-F23042B1F82B/data/Containers/Bundle/Application/34E19F4B-9A68-48FC-BA03-2A5B02D168BE/Roamler.app/node_modules/libs/Location/package.json, Resource: node_modules/libs/Location/package_json
[DEBUG] :  Loading: /Users/renepot/Library/Developer/CoreSimulator/Devices/58DEF941-13A4-4852-A765-F23042B1F82B/data/Containers/Bundle/Application/34E19F4B-9A68-48FC-BA03-2A5B02D168BE/Roamler.app/node_modules/libs/Location/index.js, Resource: node_modules/libs/Location/index_js
[DEBUG] :  Loading: /Users/renepot/Library/Developer/CoreSimulator/Devices/58DEF941-13A4-4852-A765-F23042B1F82B/data/Containers/Bundle/Application/34E19F4B-9A68-48FC-BA03-2A5B02D168BE/Roamler.app/node_modules/libs/Location/index.json, Resource: node_modules/libs/Location/index_json
[DEBUG] :  Loading: /Users/renepot/Library/Developer/CoreSimulator/Devices/58DEF941-13A4-4852-A765-F23042B1F82B/data/Containers/Bundle/Application/34E19F4B-9A68-48FC-BA03-2A5B02D168BE/Roamler.app/libs/Location, Resource: libs/Location
[DEBUG] :  Loading: /Users/renepot/Library/Developer/CoreSimulator/Devices/58DEF941-13A4-4852-A765-F23042B1F82B/data/Containers/Bundle/Application/34E19F4B-9A68-48FC-BA03-2A5B02D168BE/Roamler.app/libs/Location.js, Resource: libs/Location_js
This happens for every require.
require('libs/location.js');
Is how it was implemented. This solves the node_modules problem in the log
require('/libs/location.js');
sidenote: we have a libs folder in our lib folder, it is not a typo

Comments

  1. Hans Knöchel 2017-01-11

    [~cbarber] cb-tooling?
  2. Rene Pot 2017-01-11

    There is no workaround for
    <Require src="myFile" />
    This is generated to be a require without a prefixed slash. And it does try to load node_modules first even if I add a prefixed slash to the src.
  3. Chris Barber 2017-01-11

    I doubt this is a tooling thing. [~cwilliams] did you touch require() on iOS? Any idea?
  4. Hans Knöchel 2017-01-11

    Here is an example of this behavior: app.js
       var win = Ti.UI.createWindow({
           backgroundColor: '#fff'
       });
       
       var btn = Ti.UI.createButton({
           title: 'Trigger'
       });
       
       btn.addEventListener('click', function() {
           var more = require('more');
           alert(more.test);
       });
       
       win.add(btn);
       win.open();
       
    more.js
       exports.test = 'Hello world!';
       
    And the output when hitting the trigger button once (!):
       2017-01-11 21:40:43.321 Titanium[18334:371252] [DEBUG] Loading: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/71AEF689-1EC2-4030-A030-7E2388538EA2/data/Containers/Bundle/Application/61BBCAF8-F029-480A-B327-325BFA0193BC/Titanium.app/more/more.js, Resource: more/more_js
       2017-01-11 21:40:43.321 Titanium[18334:371252] [DEBUG] Loading: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/71AEF689-1EC2-4030-A030-7E2388538EA2/data/Containers/Bundle/Application/61BBCAF8-F029-480A-B327-325BFA0193BC/Titanium.app/more/more.js.js, Resource: more/more_js_js
       2017-01-11 21:40:43.322 Titanium[18334:371252] [DEBUG] Loading: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/71AEF689-1EC2-4030-A030-7E2388538EA2/data/Containers/Bundle/Application/61BBCAF8-F029-480A-B327-325BFA0193BC/Titanium.app/more/more.js.json, Resource: more/more_js_json
       2017-01-11 21:40:43.322 Titanium[18334:371252] [DEBUG] Loading: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/71AEF689-1EC2-4030-A030-7E2388538EA2/data/Containers/Bundle/Application/61BBCAF8-F029-480A-B327-325BFA0193BC/Titanium.app/more/package.json, Resource: more/package_json
       2017-01-11 21:40:43.322 Titanium[18334:371252] [DEBUG] Loading: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/71AEF689-1EC2-4030-A030-7E2388538EA2/data/Containers/Bundle/Application/61BBCAF8-F029-480A-B327-325BFA0193BC/Titanium.app/more/index.js, Resource: more/index_js
       2017-01-11 21:40:43.322 Titanium[18334:371252] [DEBUG] Loading: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/71AEF689-1EC2-4030-A030-7E2388538EA2/data/Containers/Bundle/Application/61BBCAF8-F029-480A-B327-325BFA0193BC/Titanium.app/more/index.json, Resource: more/index_json
       2017-01-11 21:40:43.323 Titanium[18334:371252] [DEBUG] Loading: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/71AEF689-1EC2-4030-A030-7E2388538EA2/data/Containers/Bundle/Application/61BBCAF8-F029-480A-B327-325BFA0193BC/Titanium.app/node_modules/more, Resource: node_modules/more
       2017-01-11 21:40:43.323 Titanium[18334:371252] [DEBUG] Loading: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/71AEF689-1EC2-4030-A030-7E2388538EA2/data/Containers/Bundle/Application/61BBCAF8-F029-480A-B327-325BFA0193BC/Titanium.app/node_modules/more.js, Resource: node_modules/more_js
       2017-01-11 21:40:43.323 Titanium[18334:371252] [DEBUG] Loading: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/71AEF689-1EC2-4030-A030-7E2388538EA2/data/Containers/Bundle/Application/61BBCAF8-F029-480A-B327-325BFA0193BC/Titanium.app/node_modules/more.json, Resource: node_modules/more_json
       2017-01-11 21:40:43.324 Titanium[18334:371252] [DEBUG] Loading: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/71AEF689-1EC2-4030-A030-7E2388538EA2/data/Containers/Bundle/Application/61BBCAF8-F029-480A-B327-325BFA0193BC/Titanium.app/node_modules/more/package.json, Resource: node_modules/more/package_json
       2017-01-11 21:40:43.324 Titanium[18334:371252] [DEBUG] Loading: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/71AEF689-1EC2-4030-A030-7E2388538EA2/data/Containers/Bundle/Application/61BBCAF8-F029-480A-B327-325BFA0193BC/Titanium.app/node_modules/more/index.js, Resource: node_modules/more/index_js
       2017-01-11 21:40:43.324 Titanium[18334:371252] [DEBUG] Loading: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/71AEF689-1EC2-4030-A030-7E2388538EA2/data/Containers/Bundle/Application/61BBCAF8-F029-480A-B327-325BFA0193BC/Titanium.app/node_modules/more/index.json, Resource: node_modules/more/index_json
       2017-01-11 21:40:43.324 Titanium[18334:371252] [DEBUG] Loading: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/71AEF689-1EC2-4030-A030-7E2388538EA2/data/Containers/Bundle/Application/61BBCAF8-F029-480A-B327-325BFA0193BC/Titanium.app/node_modules/more, Resource: node_modules/more
       2017-01-11 21:40:43.325 Titanium[18334:371252] [DEBUG] Loading: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/71AEF689-1EC2-4030-A030-7E2388538EA2/data/Containers/Bundle/Application/61BBCAF8-F029-480A-B327-325BFA0193BC/Titanium.app/node_modules/more.js, Resource: node_modules/more_js
       2017-01-11 21:40:43.325 Titanium[18334:371252] [DEBUG] Loading: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/71AEF689-1EC2-4030-A030-7E2388538EA2/data/Containers/Bundle/Application/61BBCAF8-F029-480A-B327-325BFA0193BC/Titanium.app/node_modules/more.json, Resource: node_modules/more_json
       2017-01-11 21:40:43.325 Titanium[18334:371252] [DEBUG] Loading: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/71AEF689-1EC2-4030-A030-7E2388538EA2/data/Containers/Bundle/Application/61BBCAF8-F029-480A-B327-325BFA0193BC/Titanium.app/node_modules/more/package.json, Resource: node_modules/more/package_json
       2017-01-11 21:40:43.325 Titanium[18334:371252] [DEBUG] Loading: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/71AEF689-1EC2-4030-A030-7E2388538EA2/data/Containers/Bundle/Application/61BBCAF8-F029-480A-B327-325BFA0193BC/Titanium.app/node_modules/more/index.js, Resource: node_modules/more/index_js
       2017-01-11 21:40:43.326 Titanium[18334:371252] [DEBUG] Loading: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/71AEF689-1EC2-4030-A030-7E2388538EA2/data/Containers/Bundle/Application/61BBCAF8-F029-480A-B327-325BFA0193BC/Titanium.app/node_modules/more/index.json, Resource: node_modules/more/index_json
       2017-01-11 21:40:47.878 Titanium[18334:371252] [DEBUG] Loading: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/71AEF689-1EC2-4030-A030-7E2388538EA2/data/Containers/Bundle/Application/61BBCAF8-F029-480A-B327-325BFA0193BC/Titanium.app/more, Resource: more
       2017-01-11 21:40:47.878 Titanium[18334:371252] [DEBUG] Loading: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/71AEF689-1EC2-4030-A030-7E2388538EA2/data/Containers/Bundle/Application/61BBCAF8-F029-480A-B327-325BFA0193BC/Titanium.app/more.js, Resource: more_js
       
    So the effort here would be to detect the correct location earlier to prevent the above file operations that cause the app to slow down as described. The behavior can be debugged by setting a break-point [here](https://github.com/appcelerator/titanium_mobile/blob/master/iphone/Classes/KrollBridge.m#L916) and po path to the see path. The log is generated by the loadAppResource method.
  5. Hans Knöchel 2017-01-14

    More test-cases incoming! Using my open-sourced canteen app (), there are 10x more logs in 6.0.1.GA compared to 5.5.1.GA: - 6.0.1.GA: https://gist.github.com/hansemannn/104345f36377cfd434c967e379ae2347 - 5.5.1.GA: https://gist.github.com/hansemannn/ab1f0e0978a393064846a1ffc13c59ba I also noted the following other differences: 5.5.1.GA:
       -- Start simulator log -------------------------------------------------------
       [INFO]  Application started
       [DEBUG] Reading stylesheet from: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/B1E64A97-DC1C-482D-BA35-CCC66CFF1479/data/Containers/Bundle/Application/E05B2B87-41C8-48B4-A106-F9DB29FAFDC9/Mensa.app/stylesheet.plist
       [INFO]  Mensa/3.0.0 (5.5.1.b18727f)
       
    6.0.1.GA:
       -- Start simulator log -------------------------------------------------------
       [DEBUG] Loading: /Users/hknoechel/Library/Developer/CoreSimulator/Devices/B1E64A97-DC1C-482D-BA35-CCC66CFF1479/data/Containers/Bundle/Application/EECBC008-0CA2-47B5-9A0B-EA022A8A89E7/Mensa.app/lloy/controllers/lunches/node_modules/alloy.js, Resource: lloy/controllers/lunches/node_modules/alloy_js
       [DEBUG] {"tiSDKVersion":"6.0.1","githash":"__GITHASH__","deployType":"development","appId":"de.hansknoechel.mensaapp","version":"3.0.0","guid":"46ee97ea-53fa-43fe-9888-47e86daea053","name":"Mensa"}
       
    So either we removed those logs as part of the logs-changes in 6.0.1.GA or their output it missing. Also, there is a path "/lloy/" (instead of /alloy/). Note: this only happens when trying to load the alloy.js in /node_modules/ (which also does not exist).
  6. Rene Pot 2017-01-17

    Lets keep in mind it also slows down the app massively and is possibly blocking a release with 6.0.1 because we use a LOT of requires in our app (lots of alloy requires inside xml files). Will this please be released as a hotfix of 6.0.1?
  7. Christopher Williams 2017-01-17

    This is not a tooling thing. This is intentional - we changed require behavior to be more in line with Node.JS/CommonJS style. When we run into an un-prefixed path we don't know if it's intentionally un-prefixed or not, and we need to try and preserve the ability to handle un-prefixed paths as we did before when it isn't. So If it's a single path segment that's un-prefixed - yeah we will attempt to see if it's a core(read: native) module first, then we'll see if it's a CommonJS module, then we'll try and see if it might be a node_module, and lastly we'll fall back to legacy Titanium behavior of assuming it's actually intended to be an "absolute" path with no prefix. Form Hans' logs above, I see a bug in that we appear to be checking the node_modules area twice - if that's consistent, that is a bug to be fixed. We should update alloy to generate prefixed paths in Titanium 6+, to help trim the possibility set of where we look (and I think we already have a ticket for this). I think it'd also be useful to gather a little more timing data to see what slowdowns this may be causing and where exactly. Looking at Hans's logs above it appears that the "misses" look to be taking roughly 1/3 to 1/4ms each, which doesn't seem huge to me. But I **do** see a major slowdown between the node_modules check to the legacy fallback of ~4.5s - is that just an aberration, or consistent?
  8. Rene Pot 2017-01-17

    A common functionality is to have a transform function with data binding. Within this transform function we call a couple methods from lib files. Without it actually being specified a big listview (with hundreds of models) caused delays of 1-2 seconds compared to previously. With the leading / it was fixed. Another common problem, where we have a lot in the app, is using require inside the xml files. These try the same functionality and there it is impossible to fix it ourselves. With big views, and loads of requires, that too caused big delays for us. This in combination with each other made a very slow app. If the leading "/" is a requirement now it should also work with Alloy XML files and communicated clearly as a breaking change. Until now it was never communicated it was a requirement, and if my memory is correct it at first didn't even work correctly in the past. The blogpost for 6.0 didn't mention this, and in the releasenotes nothing is told about it being required if you want to keep performance high, only it will fall back to the default. So conclusion, for a couple requires it is not that bad, but many apps use A LOT, which slows down the app massively
  9. Rene Pot 2017-03-02

    I'm sad this ticket didn't make it into 6.0.2. It really is a critical thing. This also happens for any require inside an alloy view. So if you use a require in, say, a controller for a row in tableview, a tableview filled with 100 items will trigger 100 times... every time. It is heavily slowing down everything in the app
  10. Rene Pot 2017-03-07

        
        Alloy.createController = function(name, args) {
            return new (require("/alloy/controllers/" + name))(args);
        };
        
        Alloy.createModel = function(name, args) {
            return new (require("/alloy/models/" + ucfirst(name)).Model)(args);
        };
        
        Alloy.createCollection = function(name, args) {
            return new (require("/alloy/models/" + ucfirst(name)).Collection)(args);
        };
        
    Adding this code to Alloy.js will greatly improve performance of the app. But it still is a performance hit on the app as there still are many logs still like this:
        [DEBUG] :  Loading: /Users/renepot/Library/Developer/CoreSimulator/Devices/58DEF941-13A4-4852-A765-F23042B1F82B/data/Containers/Bundle/Application/2BD2A8E3-6D77-4476-AADA-097C7D2FB7A2/Roamler.app/libs/Utils/Display, Resource: libs/Utils/Display
        [DEBUG] :  Loading: /Users/renepot/Library/Developer/CoreSimulator/Devices/58DEF941-13A4-4852-A765-F23042B1F82B/data/Containers/Bundle/Application/2BD2A8E3-6D77-4476-AADA-097C7D2FB7A2/Roamler.app/libs/Utils/Display.js, Resource: libs/Utils/Display_js
        
    Compared to Pre 6.0 it was much faster and these logs didn't show up. Note: disabling logs (production builds) are also slower without the manual improvements, so it for sure is everywhere.
  11. Rene Pot 2017-03-07

    This adjustment to the createController function made it, compared to above, blazing fast:
        
        var requiredControllers = {};
        Alloy.createController = function(name, args) {
            if (!requiredControllers[name]){
                requiredControllers[name] = require("/alloy/controllers/" + name);
            }
            return new (requiredControllers[name])(args);
        };
        
    Same works for other 2 functions. As you can see I store the result of the require. It now feels, in terms of speed, what is was before 6.0
  12. Hans Knöchel 2017-04-10

    [~topener] Have this changes been included in require-fix Alloy PR from recently? I remember you said something related. Thanks man!
  13. Brenton House 2017-04-10

    Although there is a performance hit with searching for the module, I would not want to vary at from looking in node_modules first, if the '/' prefix is not used, as this is the way nodejs resolves module locations. A lot of the performance issues could be handled at compile time (instead of at runtime). See nativeloop (https://github.com/nativeloop/nativeloop) for an example of resolving module paths at compile time.
  14. Feon Sua Xin Miao 2017-05-02

    Fixed by ALOY-1523.

JSON Source