How do you setup a require.js config with typescri

2019-01-24 00:12发布

问题:

Ok, I've been reading a lot of questions and answers about this, and a lot of it is rubbish.

I have a very simple question. How do I do the equivalent of this:

require.config({
    paths: {
        "blah": '/libs/blah/blah',
    }
}); 
require(['blah'], function(b) {
    console.log(b); 
});

In typescript?

This doesn't work:

declare var require;
require.config({
    paths: {
        "blah": '/libs/blah/blah',
    }
});
import b = require('blah');
console.log(b);

s.ts(8,1): error TS2071: Unable to resolve external module ''blah''.
s.ts(8,1): error TS2072: Module cannot be aliased to a non-module type.
error TS5037: Cannot compile external modules unless the '--module' flag is provided.

Compiling with the --module flag, with a dummy blah.ts shim compiles, but the output is:

define(["require", "exports", 'blah'], function(require, exports, b) {
    require.config({
        paths: {
            "blah": '/libs/blah/blah'
        }
    });

    console.log(b);
});

Looks like it might work, but actually no, the require.config is inside the require block, it is set after it is already needed.

SO! I've ended up so far with this as a solution:

class RequireJS {

    private _r:any = window['require'];

    public config(config:any):void {
        this._r['config'](config);
    }

    public require(reqs:string[], callback:any):void {
        this._r(reqs, callback);
    }
}

var rjs = new RequireJS();
rjs.config({
    paths: {
        "jquery": '/libs/jquery/jquery',
        "slider": '/js/blah/slider'
    }
});

rjs.require(['slider'], function(slider) {
    console.log(slider);
});

Which seems terrible.

So be clear, inside modules that depend on each other, this sort of thing works perfectly fine:

import $ = require('jquery');
export module blah {
   ...
}

I just need a proper way to setting the requirejs config at a top level, so that the imported paths for the various named modules are correct.

(...and this is because, largely, 3rd party dependencies are resolved using bower, and installed in the /lib/blah, where as the shim files I have for their definitions are in src/deps/blah.d.ts, so the default import paths are incorrect after moving the generated modules files into /js/ on the site)

NB. I've mentioned jquery here, but the problem is not that jquery doesn't work property as an AMD module; I have a shim jquery.ts.d file for this. The issue here is the requirejs paths.

回答1:

Yesterday I wrote up a solution to this exact issue on my blog - http://edcourtenay.co.uk/musings-of-an-idiot/2014/11/26/typescript-requirejs-and-jquery:

TL;DR - create a config file config.ts that looks something like:

requirejs.config({
    paths: {
        "jquery": "Scripts/jquery-2.1.1"
    }
});

require(["app"]);

and ensure your RequireJS entry point points to the new config file:

<script src="Scripts/require.js" data-main="config"></script>

You can now use the $ namespace from within your TypeScript files by simply using

import $ = require("jquery")

Hope this helps



回答2:

This post is 3 years old, and there's a lot of changes that have been made when using Typescript. Anyway, after some search on the web,some research on TS documentation-these guys made some good job, I found something that could help. so this can apply to the latest current of TS (2.2.1) you probably know that you can use

npm install --save @types/jquery

do the same for your 3rd party JS librairies such as require now you need to define what your TypeScript Compiler has to do, and how, so create a tsconfig.json file that contains:

// tsconfig.json file
{
   "compilerOptions": {
   "allowJs": true,
   "baseUrl": "./Scripts",//Same as require.config
   "module": "amd",
   "moduleResolution": "Node",//to consider node_modules/@types folders
   "noImplicitAny": false,
   "target": "es5", // or whatever you want
   "watch": true
}

now, let's focus on require's configuration

// require-config.ts
declare var require: any;
require.config({
   baseUrl: "./Scripts/",
   paths: {
      "jquery": "vendor/jquery/jquery.x.y.z"
      // add here all the paths your want
      // personnally, I just add all the 3rd party JS librairies I used
      // do not forget the shims with dependencies if needed...
   }
});

so far so good now focus on your module written in TS that would use jquery and that is located in Scripts/Module folder:

// module/blah.ts
/// <amd-module name="module/blah" />
import $ = require("jquery");
export function doSomething(){
    console.log("jQuery version :", $.version);
}

So this answer looks the same as Ed Courtenay's, doesn't it? and user210757 mentioned that it does NOT work!!! and it does not! if you type in your console tsc -w --traceResolution, you'll see that tsc cannot find any definition for jquery here's how to alleviate assuming you previously launchnpm install --save @types/jquery` by doing this, in a folder named node_modules\@types , you should get the TS definition for jquery

  • select the package.json file in jquery subfolder
  • look for the "main" property
  • set it to "jquery", the same as the alias you are using in your require.config and done! your module would be transpiled as

    define("module/blah", ["require", "exports", "jquery"], function (require, exports, $) {
       "use strict";
       Object.defineProperty(exports, "__esModule", { value: true });
       function doSomething() {
         console.log("jQuery version:", $.fn.jQuery);
       }
       exports.doSomething = doSomething;
    });
    

and that JS code looks good to me! I just don't like the fact that our module dependencies list "require" & "exports", that sounds like a TS issue, but anyway IT WORKS!



回答3:

if you want to use import for javascript modules you need to tell typescript about it so,

declare var require;
require.config({
    paths: {
        "blah": '/libs/blah/blah',
    }
});

// Important, place in an external.d.ts: 
declare module 'blah'{
   // your opportunity to give typescript more information about this js file
   // for now just stick with "any"
   var mainobj:any;
   export = mainobj;
}

import b = require('blah');
console.log(b);

alternatively you could simply do:

var b = require('blah'); and it should work as well