If I use target:"es5"
to transpile TypeScript code that uses es6-style classes & React, my intended entry point (here a file called App.ts
) has transpiled code that looks like this:
Object.defineProperty(exports, "__esModule", { value: true });
var react_1 = require("react");
var react_router_1 = require("react-router");
When that first line in this snippet gets hit, I get an Uncaught ReferenceError: exports is not defined
error. A similar issue is described on TypeScript's GitHub Issues pages here.
The quick answer is that exports
will exist in an environment that supports class loading.
commonjs means there's an exports variable available. You can't run commonjs code directly in a browser.
Here's my html wrapper:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World</title>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="./components/App.js"></script>
</head>
<body>
<div id="root"></div>
<script>
ReactDOM.render(
React.createElement('App', null),
document.getElementById('root')
);
</script>
</body>
</html>
It would appear (1, 2, 3) that the usual response is to put an additional transpilation step between your TypeScript and its release to a client on a browser. Wait, what? I need to transpile the transpiled code? This kinda smells like one of those "I thought the dishwasher washed the dishes" commercials.
Another recommendation is to use a module loading library like RequireJS or SystemJS (1, 2). That makes sense, but I haven't seen an example of adding a module loading lib to TypeScript compiled code for delivery to a browser. And, again, it seems like TypeScript could've intelligently (as in "with minimally duplicated code") included such a lib when it was transpiling.
(It also seems like RequireJS is at least conventionally used with a different syntax with require
where you require(['lib1', 'lib2', 'lib3'], function (lib1, lib2, lib3) {...}})
rather than the simpler var lib1 = require('lib1')
TypeScript is producing, though perhaps I'm missing something?)
So at least two related questions here:
- What's the expected use case for the
target="es5"
TypeScript transpiled code? - How does one deliver es6 TypeScript code to the browser without transpilation steps beyond what TypeScript can do?
- That is, is there a
platform:"browser"
-style setting I've missed? - If not, should RequireJS work with the code TS has produced? How should that be "bootstrapped"/started?
- That is, is there a
UPDATE: (Moving my comments from @felixmosh's answer into the question)
I have tried adding "module":"es2015"
to my tsconfig.json, but the code started lighting up with errors on lines like this: import Home from './pages/Home';
that read error TS2307: Cannot find module './pages/Home'
.
My impression was that the module
option defined the way modules are defined in the TypeScript rather than how they'll be transpiled in the resultant JavaScript code. That is, if this option only affected output, why would my untranspiled code throw errors once the module setting is added/changed rather than simply change the resulting JavaScript files' syntax?
@felixmosh also [helpfully] suggests using something like RollUp.js, but that does an end run around loading modules by, well, it says compiles, but it's really just conglomerating "small pieces of code into something larger and more complex". Putting all the modules into one file is sort of cheating. (Though why doesn't TS at least do this conglomeration?)
So +1 to felix & thanks for the help, but I still don't understand why TS stops where it stops -- What's the use case for the code it does produce? Does TypeScript really require a step outside of TS to use es6-style classes in code delivered to browsers?
Why do I care? I've worked with RequireJS based codebases before, and it is nice to have your files broken out in a way that you can debug more easily than a monolithic codebase. But I also don't understand why TS seems like it doesn't produce deployable code in this use case.
create-react-app
create-react-app my-app --scripts-version=react-scripts-ts
– Andrew