How to use babel runtime with large nodejs/express app - node.js

I want to use babel runtime in a big/complex nodejs app. I don't want to use the babel require hook because the app is big and when I have tried to use it I get the following error:
RangeError: Maximum call stack size exceeded
And I only want to transpile a few JS files, at least for now.
The babel docs are a bit cryptic for the runtime support. After installing babel-runtime, they provide:
require("babel").transform("code", { optional: ["runtime"] });
Where does that code get included? And is "code" truly just a string? I have tried to add that to my main app.js file (express 3 app). Unfortunately, that doesn't work.

I cannot totally understand your questions, but I think I can answer part of it.
As explained in the babel api, transform() function takes a string that is supposed to be source code to be transpiled, and returns an object including three properties:
code the code generated
map the source map for the code
ast the syntax tree
This means, if you want to transpile your code in a folder, for each file you want to transpile, you should read the file with fs utility, give it to transform() function, and write the value of the code property in the object returned, to your output folder.
To simplify the step to read files, you could use the function transformFile provided by babel.
As for the problem you mention with your express app, I cannot help, unless you provide more information.

Related

Typescript and Node.js

I am learning the typescript also I am learning how to implement typescript in Node.js. Now, I have watched several videos and in those videos I found 2 methods to tie typescript with Node.js.
One is by using decorators and other is by using the generic method type(by defining request and response types - Usage of interfaces.)
The question is -> Which approach is preferable and which to use.(I am aware that there is no good or bad way I but still want to know the answer) In addition to performance, I also want to know which approach is easier for others to understand because in my opinion, both are quite difficult to understand.
Or is there any other and easier way to implement typescript with Node.JS?
There are some tools to help run TS in NodeJS, such as ts-node (https://www.npmjs.com/package/ts-node), but if you don't want to rely on that or, like me, can't figure out how to get it to work, you will want to have TS do what TS does, and transpile it to JS. Then in package.json, you'll want to have your start script reference the initial .js file.
To transpile TypeScript, simply use the command tsc if you have a tsconfig, or tsc [starting file] if you do not. This should compile the code first, and if compilation is successful, it will then transpile to JS in the designated folder.
In your package.json, ensure the command executed refers to the output folder's initial file. For example: "start": "node dist/app"

Why is webpack spitting out 10,000 extra lines?

I'm using webpack via the default laravel setup after having run npm install, with the default config.
In webpack.mix.js, I have the following:
mix.js('resources/assets/js/init.js', 'public/js');
And resources/assets/js/init.js contains the following:
(function ($) {
$(function () {
$('.button-collapse').sideNav();
}); // end of document ready
})(jQuery);
Why, then, does webpack emit a whopping 10,000+ lines for this file?!:
Here's the output in a gist.
Did I completely misunderstand webpack, or is a laravel or webpack default messed up? I expect basically a copy of the JS, as npm run dev is not supposed to minify and it doesn't have any ES6 syntax in it... So what is this? The same thing works perfectly to compile scss to css if I add the appropriate line to the mix.
Short Answer
As best I can tell from what code you've given - yep, that's right.
Long Answer
What webpack does isn't just to compile your app to ES5. Rather, what is designed to do is package every dependency together in a single file so the end user downloads a single JS file.
In your original file, I assume at some point you define jQuery using require or some other method. (I'm not familiar with mix, but I assume at some point jQuery must be defined.) When you use require('jquery'), webpack transforms that into all of the jQuery source code - which is likely where almost all of the 10,000 lines of code are from.
We see your original code at the very end of the webpack bundle, starting at line 10,302:
/* WEBPACK VAR INJECTION */(function(jQuery) {(function ($) {
$(function () {
$('.button-collapse').sideNav();
}); // end of document ready
})(jQuery);
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))
As you can see, it's basically what you wrote, but now it defines jQuery using the previous 10,000 lines of code. This way, it's not referencing any external files.
Splitting your code
If you don't want your webpack bundle to have a bunch of jQuery at the top, you can split your code into vendor and app files. According to the laravel docs, that's done like this:
mix.js('resources/assets/js/init.js', 'public/js')
.extract(['jquery'])
Then, your bundle will output three files instead of one - one file containing the webpack manifest, one file containing all of the libraries (such as jQuery in this case), and one file containing the main app code (the five lines you wrote in resources/assets/js/init.js).

Google Closure Compiler to concatenate files using requirejs

I am using Google Closure compiler to concatenate and minify files. I am using require and my module depends on some JS files. Part of the JS files belong to an internal JS framework and several others depend on modules which our team has written. My aim is to concatenate all the dependencies in 1 file and then minimize it. Following is the code (the files prefixed with 'oj' are the framework files)
define(['ojs/ojcore',
'knockout',
'jquery',
'generalApp',
'modules/helpers',
'modules/facade/mrd',
'modules/facade/trf',
'modules/facade/crf',
'modules/models/sm',
'modules/models/mm',
'modules/list/dls',
'modules/utils/cm',
'ojs/ojchart',
'ojs/ojmasonrylayout',
'ojs/ojmenu',
'ojs/ojbutton',
'ojs/ojfilmstrip',
'ojs/ojarraytabledatasource',
'ojs/ojselectcombobox',
'ojs/ojdialog',
'ojs/ojcheckboxset',
'ojs/ojpagingcontrol'
], function (oj, ko, $, app, helpers, mrf, trf,crf, sm, mm, dls, cm) {
});
These files are in-turn dependent on other JS files and I only want the dependent JS files to get concatenated in the final JS file. Any idea how to do the concatenation using the Google Closure Compiler?
I tried using --process_common_js_modules --transform_amd_modules flags but the compiler threw errors since its unable to find the framework files which are located under ojs. There is a requirejs configuration file in which we are declaring path variables but I dont know how to specify the config file during the concatenation process.
Thanks in advance
Closure-compiler does not know how to order dependencies natively with AMD modules. Instead, use the requirejs compiler to concatenate the files in the correct order and then use closure-compiler for minification. This is done by setting the requirejs optimize flag to none.

How do I write TypeScript tests that don't include the classes under test in the transpiled test code?

I have a TypeScript project that compiles down to a single JS file in /dist.
I have Jasmine tests, also written in TypeScript, that reference the various classes they test with references like:
/// <reference path="../../../src/script/classUnderTest.ts" />
When I compile the tests the TypeScript compiler pulls in all the referenced classes and I get a single JS file containing the test code and the code under test.
This actually works fine for just running the tests, but now I'd like code coverage too. From what I can tell, to get Istanbul to work I need to have the code under test separate from the test code. Also it would be nice to be testing exactly the JS file that will be live.
So, how can I get the type safety and autocomplete benefits of "/// reference" whilst using my compiled JS file when the tests are actually run?
(Or am I barking up the wrong tree entirely?)
Note, I am building this on a Mac, so from what I've read Chutzpah is not currently an option. I'm also currently using only npm scripts to do builds. I'd prefer to not bring in grunt or gulp unless it's absolutely necessary.
So, how can I get the type safety and autocomplete benefits of "/// reference" whilst using my compiled JS file when the tests are actually run?
Don't using TypeScript's --outFile option (few other reasons). Instead use modules e.g. --module commonsjs and a module loader e.g. webpack.
More
Browser quickstart : https://basarat.gitbooks.io/typescript/content/docs/quick/browser.html
Modules:
https://basarat.gitbooks.io/typescript/content/docs/project/modules.html

Use __dirname into class compiled in Typescript AMD

I'm looking for a solution to use __dirname (or equivalent) inside a TypeScript class compiled in AMD, __dirname doesn't exists there. And because it's typescript, I can't (or I don't know how) import module that contains uri, allowing me to get the uri.
I found the solution once, but I don't remember how and I can't find it again so far.
I took a look to this, but it's in pure javascript and I use typescript, I tried to import module, but I get a TS error.
https://stackoverflow.com/questions/9027429/how-to-use-nodejs-global-module-objects-in-requirejs-modules
One solution is to:
In app.js, create a global var:
__basePath = __dirname;
Then, in the AMD script, use __basepath + 'relativePathFromBasePath' to load the file.
I know I found another solution but I cannot remember how.
I do not use TypeScript, but on the basis of the TypeScript code I've seen and on the basis of what I know of RequireJS, I believe you should be able to access module.uri like this:
import module = require("module");
console.log(module.uri);
The name module is special. You could also use require.toUrl(<module name>) (that's Url as in URL whereas the variable above is uri as in URI) but it does not seem as useful as module.uri for this task. For one thing you'd have to include the module's name in the call.
module.uri may contain .., so it needs cleaning up. I understand your code to be running server-side, so in Node.js we'd call path.dirname(path.normalize(module.uri)).

Resources