Load minified files generated by WebEssentials with RequireJS - javascript

I used WebEssential tool to generate some minified version typescript files, so right now i have all the .min.js files.
Now I want to use that minified files version on the project, but they was never loaded.
I use to import modules like this:
import Controller1 = require('ctls/Controller1');
but it loads the normal .js file .
So how to change this behaviour and load the minified version ?

You can use a require config entry. See here: http://requirejs.org/docs/api.html#config
For example this might let you switch back and forth easily:
var minifiedPaths = { "Controller1": "ctls/Controller1.min" };
var devPaths = { "Controller1": "ctls/Controller1" };
require.config({
paths: minifiedPaths
});
And you could change your require call to import Controller1 = require('Controller1');
Note that TypeScript has issues with aliasing AMD modules like this, so you might need to keep the same name if you want to continue to get strong typing (or store a the d.ts file in the same location as the emitted library).

Related

Typescript - including 3rd party code in released code

Having a simple Typescript project I'm using Gulp to build individual JS files from my TS files (I'm doing this as I have multiple HTML files which are to remain separate).
var tsResult = gulp.src('./src/ts/**/*.ts')
.pipe(ts(tsProject));
return merge([ // Merge the two output streams, so this task is finished when the IO of both operations are done.
tsResult.dts.pipe(gulp.dest('release/definitions')),
tsResult.js.pipe(gulp.dest('release/js'))
]);
So inside my HTML I'll have something like -
<script src="./js/myTSfileTranspiledToJS.js"></script>
Lets say that the TS file had a reference to a 3rd party code base such as jQuery. The code builds and deploys fine with no errors, but when I go to call a method in my TS/JS that contains the jQuery it fails.
This is because when runs it has no jQuery code.
Now I can include the jQuery code using a script tag -
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
but I'd rather not. Is there any way of including/bundling the 3rd party code into the transpiled JS files.
EDIT
To be clear - I'm looking to have a Typescript project that generates some JS files and anything that those JS files depend on should be bundled with them without the need to load them separately.
So if A.js requires B.js, then I want the build to see that and include B.js with A.js to save me adding B.js to some html file.
As an answer below has suggested - Broswerify, but I've not figured that out yet in my setup.
You can just do something like here, where you add the script tag to the document with JavaScript:
<script type="text/javascript">
document.write("\<script src='//ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js' type='text/javascript'>\<\/script>");
</script>
Another method would be to use Browserify or RequireJS. However you must always check the license of any project you include in yours. It wouldn't be anything unusual to provide a Get Started code block and include a
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
in it on the other hand, and that is what I'd recommend as many people use jQuery also on their own in their JS projects.
Using mainbowerfiles in gulp (pulled in jquery with bower)
Install jquery with bower
bower install --save jquery
In the html
<script src="./js/site.min.js"></script>
in your gulp file
var gulp = require('gulp'),
uglify = require("gulp-uglify"), //uglify
filter = require("gulp-filter"), //filters
concat = require("gulp-concat"), //concat files
mainBowerFiles = require('main-bower-files'); //auto get bower modules
var paths = {};
paths.jsSource = mainBowerFiles().concat(["js/myTSfileTranspiledToJS.js"]);
paths.baseReleaseFolder = "js";
paths.baseJSReleaseFile = "site.min.js";
gulp.task("min:js", function () {
var jsFilter = filter('**/*.js', { restore: true });
return gulp
.src(paths.jsSource)
.pipe(jsFilter)
.pipe(sourcemaps.init({loadMaps:true}))
.pipe(uglify())
.pipe(concat(paths.baseReleaseFolder + "/" + paths.baseJSReleaseFile))
.pipe(sourcemaps.write("."))
.pipe(gulp.dest("."))
.pipe(jsFilter.restore);
});
The answer to my question is to use webpack and the below link is a clear example which shows how to create a Typescript project and include 3rd party library's such as jQuery here - http://www.jbrantly.com/typescript-and-webpack/
This does have one downside at the moment in that it works with tsd.json config which is now deprecated in favour of using typings.json.
Still it answers this question, even if it leads to another.

RequireJS: Cannot find module 'domReady'

I have quite an annoying, but probably simple, problem that I just cannot figure out.
In a TypeScript file I have defined the following line:
import test1 = require('domReady');
This "domReady" module is defined in a main.js file that is loaded as the entry point for RequireJS. The definition is as followed:
require.config({
paths: {
'domReady': '../domReady',
}
However... in my TypeScript file I simply get a "cannot find module 'domReady'" and it is driving me insane, as I have double checked the pathing to the file and it is indeed in the correct location with the correct name. Additionally, I am fairly certain that the domReady.js file IS AMD compatible, so it should define an external module just fine! (domReady GitHub Link).
I seriously can't understand why the module can't be found in the import statement. Does anyone have any ideas to what the problem may be?
EDIT 1
The directory structure is as follows:
.
+--App
| +--main.js
| +--dashboard.js
+--domReady.js
The import statement takes place in the "dashboard.js" file, and the config for require.js happens in "main.js".
In order for TypeScript to find a module, you must actually provide module information to TypeScript.
TypeScript doesn’t yet support AMD-style paths configuration, it doesn’t ever use calls within your JavaScript code (like require.config()) to configure itself, and it won’t treat JavaScript files on disk as modules when compiling. So right now, you aren’t doing anything to actually give the compiler the information it needs to successfully process the import statement.
For your code to compile without error, you have to explicitly declare an ambient declaration for the module you’re importing within the compiler, in a separate d.ts file:
// in domReady.d.ts
declare module 'domReady' {
function domReady(callback: () => any): void;
export = domReady;
}
Then, include this d.ts in the list of files you pass to the compiler:
tsc domReady.d.ts App/main.ts App/dashboard.ts
Any other third party JavaScript code that you import also needs ambient declarations to compile successfully; DefinitelyTyped provides d.ts files for many of these.
I've had problems before when the path key and the directory name or file name are the same (in your case, domReady). Might not work, but worth giving it a quick try, i.e.
either
'domReadyModule': '../domReady',
require('domReadyModule')
or rename domReady.js to e.g. domReady-1.0.js and use
'domReady': '../domReady-1.0',
require('domReady')
If that doesn't work, I'd check the relative directories between main.js and the file that is doing the require, or else try importing another library in the same fashion, or finally compare with other libraries that you are importing successfully.
Good luck, hope you resolve the problem!

Defining an imported external module with WebPack + TypeScript

I'm trying to get WebPack set up with TypeScript and some external libraries, but having some trouble.
I'm importing the src version of jQuery in order to let WebPack choose the required modules (this was needed to get the Boostrap-SASS loader working), so am importing the library like this in my TS:
import jquery = require( 'jquery/src/jquery.js' );
When compiling, this throws the error cannot find external module 'jquery/src/jquery'. If I create a manual .d.ts file to define the library, like so:
declare module "jquery/src/jquery"{}
then the compiler works, but warns:
cannot invoke an expression whose type lacks a call signature
Alternatively, if I change the import line to
var jquery = require( 'jquery/src/jquery' );
(which I think is a CommonJS style import?) then it all compiles (and runs) fine. So, questions:
Is there a better way of requiring/including the source files using WebPack?
What's the correct way to define the module so it doesn't lack a call sig?
Should I be worried about using var instead of import or just roll with it if it's working?
I've only just picked up WebPack so it's entirely possible I'm doing something stupid. Please correct me if so!
Edit:
As I was thinking about how to phrase the question this came to me:
declare module "jquery/src/jquery" { export = $; }
which seems to let me use "import..." - but is that a good way to handle this?
Edit 2:
In reply to #basarat's answer below (my comment got a bit long to be read without line breaks):
I'm already using the jquery def from DefinitelyTyped, but it doesn't work by itself because the module I'm requiring is "jquery/src/jquery" and not just "jquery". If I use "jquery" then the compiled dist version of jquery is loaded, which doesn't work with the Bootstrap loader.
So the declare module "jquery/src/jquery" { export = $; } is, I think, extending the existing definition but using the path that I need to load it from.
import jquery = require( 'jquery/src/jquery.js' );
Use the definitely typed definition for jquery instead : https://github.com/borisyankov/DefinitelyTyped/blob/master/jquery/jquery.d.ts#L3158-L3160 which already allows you to do import jquery = require('jquery').
To answer my own question, this is what I ended up doing.
NB I don't know if this is the "correct" way of achieving this (I suspect not), so I'm open to anyone with a better answer!
In my TS definitions file tsd.d.ts I have the Definitely Typed jQuery definition:
/// <reference path="jquery/jquery.d.ts" />
but on its own this wasn't enough for the compiler to pick up the jQuery source files from within the node_modules folder.
So further down tsd.d.ts I've added:
declare module "jquery/src/jquery"
{
export = $;
}
The compiler can now locate the jQuery source files.
I also had to edit one of the jQuery source files for the WebPack compiler to play nicely with it: selector.js doesn't have a factory function included by default, and WebPack requires one to be present.
There's a loader that says it fixes this but I couldn't get it to work, so I just changed the code in selector.js to:
define([ "./selector-sizzle" ], function(){});
This all feels a little bit hacky... but it got me over this particular hurdle.

Use Browserify with JavaScript libraries such as Backbone or Underscore?

I know I can install underscore using npm but that's not what I can do in my work environment. I need to be able to download the Underscore.js library and then make it "browserify-compatible".
So let's assume Underscore.js looks something like this:
(function() {
var root = this;
// Rest of the code
}.call(this));
I downloaded that file on my hard drive and saved it as under.js.
My file that requires underscore looks like this:
var underscore = require("./under");
console.log(underscore);
And then I run browserify from the cli.
I have an HTML page called test.html and basically all it does is load the generated bundle.js.
However, the console.log(underscore) line fails - says that underscore is undefined.
What have I tried?
Obviously I added module.exports to the first line - right before the function definition in under.js, and that's how I got the error mentioned above. I also tried the method from this answer , still got the same error.
So, how would I use Browserify to load libraries such as Underscore.js or Backbone without using npm-installed modules?
That's because browserify does not add variables to the global scope. The version you download is identical to the version that you install via NPM.
You need to explicitly attach it to the window to export it to the top level scope.
If you create a file called "expose_underscore.js" and put this in it:
var _ = require('./under');
window._ = _;
Will do it, followed by: browserify expose_underscore.js > bundle.js and then add bundle.js as a <script> tag you will be able to do the following in your console:
HOWEVER, you shouldn't do this if you're using browserify. The point behind it (and Node's version of commonJS) is that you explicitly require it everywhere you need it. So every file you have that needs underscore should import it to a local variable.
Don't worry -- you will still only have one copy loaded.
I typically add my vendor libs like Underscore as script tags. Underscore will attach itself to the global scope, so then you don't need to require it anywhere to use it.
If you do want to use it in a Browserified fashion, verify that you have the correct path in your require statement (browserify requires are relative paths) and move the module.exports statement to the end of the file.

Load scripts with requireJs, issue with absolute path

I'm trying to load scripts using requireJs() function, based on requirejs.
Here my app.js:
// Other stuff...
__config.path.base = __dirname + '/../';
requireJs = require('requirejs'),// To use to require AMD typescript files.
requireJs.config({
baseUrl: __config.path.base,
nodeRequire: require
});
But I got an issue... This script isn't app.js actually, it's /config/boostrap.js, now, if I want to import a file in the file /api/db/models/UserModel.ts, the path is actually '/$APPPATH/' instead of '/$APPPATH/api/db/models/'
So, when I try to import, from /api/db/models/UserModel.ts:
import model = require('./Model');
It fails, because it tries to load the file '/$APPPATH/Model.js' instead of '/$APPPATH/api/db/models/Model.ts'.
If I try to import differently like that:
import model = require('./../api/db/models/Model');
Typescript display an error and doesn't compile anymore, because it cannot find the file.
So, how can I fix this? My solution here was to change the compilation mode and don't use requireJs to load file into /api (CommonJs), but I'm not sure I won't have other problem later, I would prefer use the same compilation mode everywhere if it's possible!
Typescript's import statement (using requireJS) will always use your application root path for the start point, as will the compiler.
From /api/db/models/UserModel.ts:
import model = require('api/db/models/Model');
Make sure Model.ts is structured like...
class Model {
...
}
export = Model;

Categories

Resources