javascript - Como corrigir "ReferenceError: exports não está definido" em um projeto TypeScript puro?
Se eu escrever um .ts com qualquer tipo de instrução de importação ou exportação, o .js resultante gerará o seguinte erro quando carregado em uma página HTML: "ReferenceError: exports is not defined"
Como reproduzir:
- Crie um projeto de aplicação web Node.js em branco no VS
- Adicione um .ts com uma linha de importação ou exportação
- Adicione algum HTML chamando o .js resultante
- Inicie um servidor HTTP (
http-server -g [porta]) e acesse seu HTML
Eu tentei:
- Alvejando ES5
- Removendo a linha
"module": "commonjs"do tsconfig.json` - Instalando CommonJS e SystemJS
- Compilando o .ts usando
tsc - Alguma outra solução que o Stack Overflow tenha em perguntas semelhantes
- Todas as possíveis permutações do acima.
Meu .ts (pode ser qualquer coisa se tiver uma instrução de importação):
import { setTimeout } from "timers";
setTimeout(() => console.log("asdf"), 1000);
O HTML possui apenas um corpo simples referenciando o script
package.json
{
"name": "nodejs-web-app4",
"version": "0.0.0",
"description": "NodejsWebApp4",
"main": "server.js",
"author": {
"name": ""
},
"devDependencies": {
"@types/node": "^8.0.14"
}
}
tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"lib": ["es6"],
"sourceMap": true
},
"exclude": [
"node_modules"
]
}
.js resultante:
A partir da compilação do VS (resulta em ReferenceError: exports is not defined):
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const timers_1 = require("timers");
timers_1.setTimeout(() => console.log("asdf"), 1000);
//# sourceMappingURL=home-script.js.map
A partir do comando tsc [filename].ts (resulta em ReferenceError: exports is not defined):
"use strict";
exports.__esModule = true;
var timers_1 = require("timers");
timers_1.setTimeout(function () { return console.log("asdf"); }, 1000);
Do VS Build mas removendo "module": "commonjs" do tsconfig (resultado em SyntaxError: import declarations may only appear at top level of a module):
import { setTimeout } from "timers";
setTimeout(() => console.log("asdf"), 1000);
//# sourceMappingURL=asdf.js.map
Todo o HTML e ts serão chamados de "estáticos" (sem MVC)
É errado usar http-server para ver HTML estático do meu projeto VS? Esse é o problema?
Deveria construir de outra forma? Usar uma configuração diferente?
Eu tenho uma solução alternativa (ou seja, manter tudo o que eu preciso no mesmo arquivo TypeScript), mas me confunde o fato de eu não conseguir criar e visualizar um projeto simples com Node/TS.
Resposta #1
Os navegadores não suportam módulos commonjs. Você precisará usar alguma ferramenta (webpack, rollup, browserify) para empacotar seus módulos após a compilação.
Se você remover a opção module no tsconfig.json ou se você definir como es2015 ou esnext, as declarações import e export permanecerão como estavam no arquivo original.
import { foo } from './bar.js';
export default class Baz {}
Pode funcionar porque alguns navegadores já suportam módulos ES nativos, mas é necessário adicionar à tag script um atributo type e defini-lo como module.
<script type="module" src="foo.js"></script>
Se você não fizer isso, receberá algum erro como o 'SyntaxError: import declarations may only appear at top level of a module'.
