Skip to content
This repository has been archived by the owner on Aug 7, 2021. It is now read-only.

exports.{MethodName} = function... not working #820

Open
vtrifonov opened this issue Feb 22, 2019 · 1 comment
Open

exports.{MethodName} = function... not working #820

vtrifonov opened this issue Feb 22, 2019 · 1 comment
Projects

Comments

@vtrifonov
Copy link
Contributor

vtrifonov commented Feb 22, 2019

Environment
Provide version numbers for the following components (information can be retrieved by running tns info in your project folder or by inspecting the package.json of the project):

  • CLI: 5.2.0
  • Cross-platform modules: 5.2.0
  • Android Runtime: 5.2.0
  • iOS Runtime: 5.2.0

Describe the bug
Method exports like this:

exports.onLoaded = function(args: EventData) {
    console.log('Inner non-working loaded');
    let page = <Page>args.object;
    page.bindingContext = new InnerViewModel();
}

are not working when you use --bundle. The same works without the --bundle flag. If you export the method using the following syntax it works:

export function onLoaded(args: EventData) {
    console.log('Inner working loaded');
    let page = <Page>args.object;
    page.bindingContext = new InnerViewModel();
}

To Reproduce
Export a method using the first approach and start the app with --bundle.

Expected behavior
Both export syntaxes should work.

Sample project
You can check this project webpack-issue.zip. There are two inner pages, one of them working, one not. The only difference is in the way the onLoaded method is exported.

Additional context
The issue was introduced in official version 0.18.5, it works in 0.18.3

@rosen-vladimirov rosen-vladimirov changed the title exports.{MethodName} = function... not working since version 0.18.5 exports.{MethodName} = function... not working Feb 22, 2019
@rosen-vladimirov
Copy link
Contributor

rosen-vladimirov commented Feb 24, 2019

Indeed when using the attached project and trying it with nativescript-dev-webpack 0.18.3 the application is working. However, the problem is that the project is TypeScript and before version 0.18.5, nativescript-dev-webpack was using both .ts and .js files in the application when generating the bundle. As the attached project has been used with tns run <platform> (without passing --bundle), NativeScript CLI had generated .js files in the app folder, right next to .ts files of the application. When nativescript-dev-webpack 0.18.3 is used, it gets all files, including the already generated .js files and the application works. In case you delete the .js files from the app directory of the attached application and try to run it with tns run <platform> --bundle, neither of the buttons will work.
Since nativescript-dev-webpack 0.18.5 the .ts files of the application are taken and the file with export function... is working correctly.
So, the actual problem is that tns run <platform> works with exports.onLoaded code in TypeScript, but tns run <platform> --bundle does not work (and it had never worked).
Here comes another difference when --bundle is used - nativescript-dev-webpack uses tsconfig.tns.json file, while tns run <platform> (without --bundle) uses the default tsconfig.json. There's one major difference between the two files and that's the module value - in tsconfig.json it is commonjs, while in tsconfig.tns.json the value is es2015.
As exports.<smth> is the same as module.exports.<smth>, which is the commonjs way to export something from modules, when we use commonjs for module resolution, all files are converted to exports.<smth>. This way TypeScript and webpack produce bundle.js in which the JavaScript content is placed in modules used as commonjs ones, i.e. TypeScript itself coverts export function statements to exports.<smth>.
When es2015 is used, TypeScript does not convert export function statements, as they are correct according to ES2015 specification. However, TypeScript does not convert the commonjs exports to export statements. This way, in the bundle.js we receive modules with different resolutions - TypeScript should have generated all modules as es2015, but one of them has exports. statement, i.e. it is commonjs module.
Webpack also respects the module type, so it generates different content based on the module type. When we use es2015 modules (i.e. the one that does not work with exports statements, for the non-working page webpack generates the following code:

/***/ "./inner-non-working/inner-page.ts":
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _inner_view_model__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./inner-non-working/inner-view-model.ts");

exports.onLoaded = function (args) {
    console.log('Inner non-working loaded');
    var page = args.object;
    page.bindingContext = new _inner_view_model__WEBPACK_IMPORTED_MODULE_0__["InnerViewModel"]();
};
;
    if (false) {}


/***/ }),

When commonjs is used, webpack generates the following code:

/***/ "./inner-non-working/inner-page.ts":
/***/ (function(module, exports, __webpack_require__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var inner_view_model_1 = __webpack_require__("./inner-non-working/inner-view-model.ts");
exports.onLoaded = function (args) {
    console.log('Inner non-working loaded');
    var page = args.object;
    page.bindingContext = new inner_view_model_1.InnerViewModel();
};
;
    if (false) {}


/***/ }),

In the first case webpack uses __webpack_exports__ and in the second - exports directly.

Basically, there are two problems here:

  • NativeScript CLI uses different tsconfig.json files when --bundle is passed and when it is not, so the generated JavaScript output is not the same.
  • TypeScript (and possibly webpack) does not convert commonjs exports to es2015 export when the module compiler option is es2015.

As a workaround for both issues, you can set module property in tsconfig.tns.json to commonjs.

Useful resources:

  1. TypeScript compiler options, check docs for module option.
  2. TypeScript docs for code generation for modules
  3. Node.js docs for exports variable
  4. Difference between module.exports and exports
  5. Webpack 4 - import and commonjs modules
  6. Understanding JavaScript modules

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
CLI Team
  
Inbox
Development

No branches or pull requests

2 participants