Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-23490] iOS: Hybrid CommonJS and Native modules don't export commonjs

GitHub Issuen/a
TypeBug
PriorityCritical
StatusClosed
ResolutionFixed
Resolution Date2017-05-08T20:15:25.000+0000
Affected Version/sn/a
Fix Version/sRelease 6.1.0
ComponentsTooling
Labelsmerge-6.1.0, mobilesdk, module, user_experience, validate
ReporterAndrea Vitale
AssigneeChristopher Williams
Created2015-06-16T22:03:31.000+0000
Updated2017-06-08T17:50:17.000+0000

Description

When I create a pure Javascript Module, any exported method is accessible. In detail for the module I've:

Created a new Mobile Module Project, from Appcelerator Studio, with id (for example) it.module.test

Inside _assets_ folder, I've created a js file called _it.module.test.js_

Into _it.module.test.js_ I have:

module.exports = { 
   something: "hi" 
}
Now I package this module directly from Appcelerator Studio and install this module inside a Test Application. Into this application I do:
var module = require("it.module.test");
Ti.API.info(module.something);
And the result is *null*. The problem is that the native module classes are being called instead of the CommonJS ones as per the docs. __UPDATE__ After several tests, it seems that the problem is the Titanium SDK 4.0.0. When I create the module project inside Appcelerator Studio and selecting a previous version of Titanium SDK (3.4.1 for example) all works perfectly with the same code.

Attachments

FileDateSize
module with 3.4.1GA.png2015-07-01T09:17:04.000+000022307
module with 4.0.0GA.png2015-07-01T09:20:57.000+000027205
package_log.txt2017-05-05T17:37:49.000+000031291

Comments

  1. Fokke Zandbergen 2015-06-23

    [~Andrea.Vitale], the correct CommonJS syntax is to use:
       module.exports = {
         something: "hi"
       };
       
    or:
       exports.something = "hi";
       
    It might be easier to use [Titaniumifier](https://github.com/smclab/titaniumifier) to package CommonJS modules if you really want to, but you can also just drop the library in your Alloy project's lib folder (app/lib) and require it by name (without the .js)
  2. Andrea Vitale 2015-06-23

    Hi Fokke, thanks for your response. The problem using:
       module.exports = {
       something : "hi"
       };
       
    still persists.
  3. Andrea Vitale 2015-06-23

    @fokkezb I want to package my module [as per the docs at the bottom of this guide](http://docs.appcelerator.com/platform/latest/#!/guide/Titanium_Module_Concepts) because I've to distribute it inside a company so the code can't be legible. I tryied Titaniumifier but the result is not the same.
  4. Claus Stilborg 2015-09-16

    @Andrea I am facing the same problem trying to isolate some code in commonJS modules, I just cannot get it to work. I followed this fine tutorial but that did not work either http://code.tutsplus.com/tutorials/creating-titanium-mobile-modules-using-commonjs--mobile-16833 Did you find a solution?
  5. Andrea Vitale 2015-09-16

    @Claus Stilborg, I've wrote an update into issue description: when you create a module using Appcelerator Studio, select a Titanium SDK version prior to 4.0.0 (3.5.1 for example).
  6. Claus Stilborg 2015-09-16

    Thx, I will try that.
  7. Claus Stilborg 2015-09-16

    Well that did not help. I am going back to copying files around the lib folders. It horrifies me to think about how many hours I have spent trying to get this to work. I rarely give up, but this one is off the charts frustrating...
  8. Andrea Vitale 2016-06-09

    Any update on this? It is a year old issue and it is still unfixed..
  9. Kondal Kolipaka 2016-07-29

    [~cng]- Issue is reproducible with 5.4.0 and 6.0 SDK's it.module.test.js
       module.exports = { 
          something: "hi" 
       };
       
    index.js
       function doClick(e) {
           var module = require("it.module.test");
           alert("test->"+module.something); 
       
       }
       
       $.index.open();
       
  10. Andrea Vitale 2016-12-19

    I confirm that this issue is still alive also with Ti SDK 6.0.0.GA. How is possible that there is no plan to solve it?
  11. Andrea Vitale 2017-03-23

    Any update on this? This is really blocking for me. Thanks.
  12. Christopher Williams 2017-05-02

    I pushed a PR to fix iOS here: https://github.com/appcelerator/titanium_mobile/pull/9007 While doing this I also looked at Android. While i was able to push a fix for encrypting the main JS file into the native hybrid module, I don't see any support within the generated module for hooking the commonjs encrypted contents to the runtime. I suspect this may *never* have worked on the Android side. I'll have to take a deeper look if we want a fix there as well.
  13. Andrea Vitale 2017-05-02

    If you compile with 3.5.1.GA, it works well also on Android on a 5.5.1.GA app.
  14. Christopher Williams 2017-05-03

    I've cloned off a ticket to address Android's issue separately. This PR https://github.com/appcelerator/titanium_mobile/pull/9007 address the issue for iOS, which was that we were not sending *relative* file paths to titanium_prep for encryption, but instead *absolute* file paths in the CLI rewrite (way, w ay back in 4.x days). titanium_prep is brain-dead and assumes relative paths, so it effectively was outputting "empty" encrypted js into the module. Additionally, my require rewrite in 6.0.0 was slightly off in how to combine the two together, and required a 1-1 or 2- line change.
  15. Christopher Williams 2017-05-03

    For QE: - Create a new native module project from the cli named with id com.axway.hybrid.mod for iOS - in the module project's assets dir add a com.axway.hybrid.mod.js file with these contents:
        module.exports = { 
           something: "hi" 
        }
        
    - build that module from the cli using the SDK from this PR appc run -p ios --build-only - create a new titanium mobile project from cli for iOS - drop the built module into the mobile project, add it to tiapp.xml - Modify the app.js of the mobile project to be:
        var win1 = Titanium.UI.createWindow({
        	title : 'Test',
        	backgroundColor : "White",
        	layout : "vertical"
        });
        win1.open();
         
        var module = require('com.axway.hybrid.mod');
        alert(module.something);
        
    - appc run -p ios - an alert should pop up with the message 'hi'. If it has no message and just the *alert* title, then that is the bug.
  16. Abir Mukherjee 2017-05-05

    Tested with this environment: Node Version: 6.10.1 NPM Version: 3.10.10 Mac OS: 10.12.4 Appc CLI: 6.2.0 Appc CLI NPM: 4.2.9 Titanium SDK version: 6.2.0 (locally built on PR/9007) Appcelerator Studio, build: 4.8.1.201612050850 Xcode 8.3.2 FR did not pass. I tried with both sample codes (the original one in the Description, and the one in the comment specially written for QE). I tried these on the CLI and in Studio and saw this error. While building the module, the following error was seen:
        2017-05-05T00:11:10.394Z | ERROR  | An uncaught exception was thrown!
        Couldn't find preset "babili" relative to directory "/Users/amukherjee/projects/test1mod/iphone"
        2017-05-05T00:11:10.398Z | ERROR  | Couldn't find preset "babili" relative to directory "/Users/amukherjee/projects/test1mod/iphone"
        
    When I reverted back to SDK 6.0.4.GA, I was able to reproduce the original bug.
  17. Abir Mukherjee 2017-05-09

    The error described in my last comment was not related to this ticket (but needed to be fixed and merged before carrying out this test. After the fix on the unrelated ticket, I reran the test on this ticket and FR passed for 6.2.0. For 6.1.0, the PR was merged so I tested it on the installed SDK where the fix appears, 6.1.0.v20170509114242 Node Version: 6.10.1 NPM Version: 3.10.10 Mac OS: 10.12.4 Appc CLI: 6.2.0 Appc CLI NPM: 4.2.9 Titanium SDK version: 6.1.0.v20170509114242, and locally installed 6.2.0 Appcelerator Studio, build: 4.8.1.201612050850 Xcode 8.3.2 Android 6.0.1 device I used Chris's demo code above, and followed the appropriate test steps. I installed the app and saw an alert pop up with a message "hi".
  18. Andrea Vitale 2017-06-08

    Hi, I tested this using 6.1.0.GA and it works only for a single commonjs file. Suppose that you have a module called it.commonjs.test.module and in your assets folder you have two files called: - it.commonjs.test.module.js - another.module.js In the second one you have:
        module.exports = {
            sayWelcome: function() {
                Ti.API.info("Welcome from the second commonjs module");
            }
        };
        
    In the first one you have:
        module.exports = {
            sayHello: function() {
                alert("Hello!");
            },
            secondModule: require("it.commonjs.test.module/another.module")
        }
        
    You can successfully build the module but when you try to run an app that requires the it.commonjs.test.module module you get an error like:
        [ERROR] Script Error Couldn't find module: it.commonjs.test.module/another.module for architecture: i386
        
    If you try to build the module with 3.5.1.GA sdk everything is working fine. On Android is working also with 6.1.0.GA.
  19. Christopher Williams 2017-06-08

    [~Andrea.Vitale] I've cloned off TIMOB-24796 to handle this new bug report.

JSON Source