Javascript 在浏览器中使用带有导入的es6样式类的TypeScript传输代码,而无需额外的传输步骤?

Javascript 在浏览器中使用带有导入的es6样式类的TypeScript传输代码,而无需额外的传输步骤?,javascript,reactjs,typescript,Javascript,Reactjs,Typescript,如果我使用target:“es5”来传输使用es6样式类和React的TypeScript代码,那么我的目标入口点(这里是一个名为App.ts)已经传输了如下代码: Object.defineProperty(exports, "__esModule", { value: true }); var react_1 = require("react"); var react_router_1 = require("react-router"

如果我使用
target:“es5”
来传输使用es6样式类和React的TypeScript代码,那么我的目标入口点(这里是一个名为
App.ts
)已经传输了如下代码:

Object.defineProperty(exports, "__esModule", { value: true });
var react_1 = require("react");
var react_router_1 = require("react-router");
当这个代码段中的第一行被命中时,我得到一个
uncaughtreferenceerror:exports-notdefined
错误。TypeScript的GitHub问题页面中描述了类似的问题

问题是,
导出
将存在于支持类加载的环境中

commonjs表示存在可用的导出变量。不能在浏览器中直接运行commonjs代码

这是我的html包装:

<!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>

你好,世界
ReactDOM.render(
React.createElement('App',null),
document.getElementById('root'))
);
通常的反应似乎是在TypeScript和将其发布到浏览器上的客户端之间增加一个透明步骤。等等,什么?我需要传输传输的代码?这有点像“商业广告”

另一个建议是使用模块加载库,如RequireJS或SystemJS(,)。这是有道理的,但我还没有看到向TypeScript编译代码添加模块加载库以交付到浏览器的示例。同样,TypeScript似乎可以在传输时智能地(如“使用最小重复代码”)包含这样一个库

(另外,RequireJS似乎至少在常规情况下与with
require
一起使用,其中
require(['lib1','lib2','lib3'],函数(lib1,lib2,lib3){…})
而不是更简单的
var lib1=require('lib1')
TypeScript正在生成。)

所以这里至少有两个相关的问题:

  • target=“es5”
    TypeScript传输代码的预期用例是什么
  • 如何将ES6TypeScript代码交付给浏览器而不需要TypeScript所能完成的透明步骤?
    • 也就是说,是否有一个
      平台:“browser”
      样式设置我错过了
    • 如果不是,RequireJS应该使用TS生成的代码吗?该如何“引导”/启动

  • 更新:(将我的评论从@felixmosh的答案转移到问题中)

    我尝试将
    “模块”:“es2015”
    添加到我的tsconfig.json中,但代码开始出现以下错误:
    从“/pages/Home”导入主页读取
    错误TS2307:找不到模块“./pages/Home”

    我的印象是
    module
    选项定义了在TypeScript中定义模块的方式,而不是在生成的JavaScript代码中如何传输模块。也就是说,如果这个选项只影响输出,为什么我的未翻译代码在添加/更改模块设置后会抛出错误,而不是简单地更改生成的JavaScript文件的语法

    @felixmosh还(有益地)建议使用类似这样的东西,但这确实是一个围绕加载模块的最终运行,它说编译,但它实际上只是将“小块代码聚合成更大、更复杂的东西”。将所有模块放在一个文件中是一种欺骗。(但为什么不至少进行这种聚集呢?)

    所以+1对felix来说&谢谢你的帮助,但我仍然不明白为什么TS会停在它停的地方——它产生的代码的用例是什么?TypeScript真的需要TS之外的步骤才能在交付给浏览器的代码中使用es6样式的类吗


    我为什么在乎?我以前使用过基于RequireJS的代码库,很高兴您的文件能够以一种比单一代码库更容易调试的方式进行分解。但是我也不明白为什么TS在这个用例中似乎不生成可部署的代码。

    如果您想保留es6的
    导入/导出
    ,您应该定义
    模块:“es2015”
    ,默认情况下,它将这些转换为节点中使用的cjs样式

    不支持节点的
    cjs
    样式,但支持
    es2015
    样式,因此需要指定该模块类型,并在脚本标记上指定
    type=“module”
    属性,类似于:

    <script type="module" src="entry-point.js"></script>
    
    
    
    目前,chrome仅支持模块,因此,目前的最佳做法是从使用导入创建的依赖关系树中创建一个捆绑包

    常见的边界是&,您可以读取它们的配置以生成在浏览器中运行的包


    typescript和webpack配置的小参考:

    我看到您正在开始构建typescript web应用程序。如果是这样,我的建议是:

    将TypeScript转换为JS是不可避免的

    不要使用RequireJS或SystemJS,而是使用捆绑工具,如包裹、网页包、汇总、浏览。我特别推荐包裹,因为它非常简单,而且打字脚本也很好

    • 使用bundler,摆脱所有那些defines()requires()SystemJs.calls()并只使用标准的JavaScript导入声明(import{foo}form'bar')。我也强烈推荐这个

    • 顺便说一句,避免使用require.js、AMD、UMD、SystemJS或类似工具。开始使用这些并不是一个好建议。只有在真正必要时才使用它们


    祝你好运

    我已经更新了我的答案,请查看,如果这不能解释我的想法,我很乐意进一步解释。浏览器中没有加载模块的本机支持(Chrome除外),因此Babel/TS将无法传输需要浏览器支持的内容。想想看,您有两个文件,a.ts依赖于b.ts,没有代码