Kan jeg bruge requirejs til at indlæse moduler i TypeScript-kode?
Jeg bruger typescript og requirejs. Jeg vil importere mit bibliotekskode som moduler for at undgå at gøre alting til globale variable. Mit problem er, at enhver brug af import eller export i en typescript-fil gør hele filen til et modul. I tilfælde af min applikationskode betyder det, at den ikke kan blive kaldt direkte.
Her er en prøveapp.
index.html
<!DOCTYPE html>
<html>
<head>
<title>My Test App</title>
<script src="require.js"></script>
<script src="app1.js"></script>
<script src="app2.js"></script>
</head>
</html>
tsconfig.json
{
"compilerOptions": {
"module": "amd",
"target": "es5",
"noImplicitAny": false,
"sourceMap": false
}
}
greeter.ts
export function greet(name: string) {
alert(`Hello ${name}`);
}
app1.ts
import { greet } from './greeter';
greet('alice');
app2.ts
import { greet } from './greeter';
greet('bob');
tsc kører uden problemer, men her er en af de filer, jeg får som output.
tsc output: app1.js
define(["require", "exports", './greeter'], function (require, exports, greeter_1) {
"use strict";
greeter_1.greet('alice');
});
Det virker ikke. Fra require.js
Sørg for at indlæse alle scripts, der kalder define(), via RequireJS API'en. Indsæt ikke manuelt script-tags i HTML for at indlæse scripts, der har define()-opkald i sig.
Så hvordan kan jeg overbevise TypeScript-kompilatoren om at producere output uden et define()-kald i det? I app1.ts har jeg ikke tænkt mig at definere et modul, blot bruge andre moduler. require() virker mere passende til det. Er der en måde at få import til at kompilere til require()?
Svar #1
Hvis du har et enkelt modul, der starter alt, hvad der skal indlæses for din side, kan du bruge data-main. Hvis du har brug for at starte indlæsningen med mere end ét modul, skal du bruge require til at indlæse modulerne:
<script src="require.js"></script>
<script>
require(["app1", "app2"]);
</script>
Du er måske vant til altid at give et enkelt strengargument til require, men dette er AMD. Den native AMD require tager et array af afhængigheder som det første argument og en valgfri callback som det andet.
Hvis du bruger require.config, kan du bruge deps-muligheden til det samme formål:
<script src="require.js"></script>
<script>
require.config({
// You could have more config here... in addition to:
deps: ["app1", "app2"]
});
</script>
Der er i øjeblikket ingen måde at få tsc til at outputte require i stedet for define. Jeg vil ikke holde vejret på at vente på, at en sådan funktion bliver tilføjet, fordi der allerede findes nemme måder at opnå de samme slutresultater, som en sådan funktion ville muliggøre.
Svar #2
Reparer
Fra de dokumenter, du allerede har fundet:
Sørg for at indlæse alle scripts, der kalder define(), via RequireJS API'en.
Også fra dokumenternes start-side: http://requirejs.org/docs/start.html
og referer kun til require.js med et requirejs-kald som følger for at indlæse dit script:
<script data-main="scripts/main" src="scripts/require.js"></script>
^dette er script-tagget, der skal indlæse din applikations startpunkt.
Mere
Så hvordan kan jeg overbevise TypeScript-kompilatoren om at producere output uden et define()-kald i det.
Ja. Men hvis du vil bruge requirejs, så er dette det forkerte spørgsmål at stille. Løsningen er, som jeg nævnte, altså brug den korrekte script-tag.
