Pesquisa de site

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:

  1. Crie um projeto de aplicação web Node.js em branco no VS
  2. Adicione um .ts com uma linha de importação ou exportação
  3. Adicione algum HTML chamando o .js resultante
  4. 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'.

Artigos relacionados