【问题标题】:TypeScript: How to replace imports with window objects?TypeScript:如何用窗口对象替换导入?
【发布时间】:2016-11-12 14:41:36
【问题描述】:

我创建了一个需要第三方库的 TypeScript 模块:

import Dexie from "dexie";

namespace storage {
  ...
}

当我编译我的 TypeScript 文件时,我得到以下 JavaScript 输出:

"use strict";
var dexie_1 = require("dexie");
var storage;
(function (storage) {
  ...
})(storage || (storage = {}));

在 Node.js 环境中使用输出时我可以接受。但是对于在浏览器中的使用,我想将 var dexie_1 = require("dexie"); 替换为来自 window 的对象,例如:var dexie_1 = window.Dexie;

我可以用来自window(全局命名空间)的对象替换我编译的JS 中的require 语句吗?是否有 Gulp 插件或某事。类似吗?

我的 tsconfig.json 是这样的:

{
  "compilerOptions": {
    "module": "commonjs",
    "moduleResolution": "node",
    "target": "es5"
  },
  "exclude": [
    "node_modules",
    "typings/browser",
    "typings/browser.d.ts"
  ]
}

【问题讨论】:

  • 你可以评估使用 requirejs 吗?

标签: typescript requirejs commonjs tsc window-object


【解决方案1】:

如何用窗口对象替换导入?

这是不可能的。有两种选择:

使用全局对象

在浏览器中,当<script> 加载对象时,您的代码会将其用作全局变量。在 TypeScript 中,您必须使用全局声明文件。这里没有用到模块,所以没有import可以做。

使用捆绑器或加载器

您可以使用捆绑程序 for example Webpack。或a loader like SystemJS

【讨论】:

    【解决方案2】:

    Webpack 可以将require("dexie"); 映射到window.Dexie

    您所要做的就是在您的 webpack.config.js 中声明以下内容:

    module.exports = {
      externals: {
        'dexie': 'Dexie'
      }
    };
    

    为了完整起见,这里是一个最小的工作示例

    目录布局:

    • bower_components(来自bower install的目录)
    • dist(来自gulp default的目录)
    • node_modules(来自npm install的目录)
    • src(TypeScript 源代码目录)
    • 打字(来自typings install的目录)
    • bower.json(前端依赖)
    • gulpfile.js(构建配置)
    • index.html(用于测试 webpacked 代码的演示页面)
    • index.js(分发的主要入口点)
    • package.json(工作流程和构建依赖项)
    • tsconfig.json(TypeScript 编译器配置)
    • webpack.config.json(Webpack 配置)

    src/storage.ts

    /// <reference path="../typings/index.d.ts" />
    import Dexie from "dexie";
    
    namespace storage {
      export function setupDatabase():void {
        let db = new Dexie('MyDatabase');
    
        db.version(1).stores({
          friends: 'name, age'
        });
    
        db.open().then(function () {
          console.log('Initialized database: ' + db.name);
        });
      }
    }
    
    module.exports = storage;
    

    bower.json

    {
      "name": "storage",
      "main": "dist/webpacked.js",
      "private": true,
      "dependencies": {
        "dexie": "^1.4.1"
      }
    }
    

    gulpfile.js

    var gulp = require('gulp');
    var rename = require('gulp-rename');
    var runSequence = require('run-sequence');
    var ts = require('gulp-typescript');
    var tsProject = ts.createProject('tsconfig.json');
    var webpack = require('webpack-stream');
    
    gulp.task('build', function () {
      return gulp.src('src/**/*.ts')
        .pipe(ts(tsProject))
        .pipe(gulp.dest('dist'));
    });
    
    gulp.task('webpack', function () {
      return gulp.src('dist/index.js')
        .pipe(webpack(require('./webpack.config.js')))
        .pipe(rename('webpacked.js'))
        .pipe(gulp.dest('dist'));
    });
    
    gulp.task('default', function (done) {
      runSequence('build', 'webpack', done);
    });
    

    index.html

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <title>Demo</title>
        <script src="bower_components/dexie/dist/dexie.js"></script>
        <script src="dist/webpacked.js"></script>
      </head>
      <body>
        <script>
          document.addEventListener("DOMContentLoaded", function() {
            storage.setupDatabase();
          }, false);
        </script>
      </body>
    </html>
    

    index.js

    window.storage = require('./dist/storage');
    

    package.json

    {
      "name": "storage",
      "private": true,
      "devDependencies": {
        "dexie": "^1.4.1",
        "gulp": "^3.9.1",
        "gulp-rename": "^1.2.2",
        "gulp-typescript": "^2.13.6",
        "run-sequence": "^1.2.2",
        "webpack-stream": "^3.2.0"
      }
    }
    

    tsconfig.json

    {
      "compilerOptions": {
        "module": "commonjs",
        "moduleResolution": "node",
        "target": "es5"
      },
      "exclude": [
        "node_modules",
        "typings/browser",
        "typings/browser.d.ts"
      ]
    }
    

    typings.json

    {
      "globalDependencies": {
        "node": "registry:dt/node#6.0.0+20160709114037"
      }
    }
    

    注意:node 条目来自 typings install dt~node --global --save,TypeScript 需要在 module.exports 语句中解析 module

    webpack.config.js

    module.exports = {
      externals: {
        'dexie': 'Dexie'
      }
    };
    

    方法:

    TypeScript 代码导入 Dexie 并使用命名空间 storage 声明自己。要遵循 commonjs 的依赖管理方式(在 tsconfig.json 中声明),TypeScript 代码需要将 storage 命名空间导出为具有:module.exports = storage 的模块。

    因为 TypeScript 不知道 module 对象,我们需要得到它的定义。 module 定义是node 类型定义的一部分,我们使用typings install dt~node --global --save 使用typings 工具从DefinitelyTyped 存储库中获得它。要在 TypeScript 中链接节点检索到的类型定义,我们需要声明 /// &lt;reference path="../typings/index.d.ts" /&gt;

    编译 TypeScript 代码后(使用gulp build),我们需要声明一个入口点以使我们的代码可访问。这是在index.js 中完成的。成功的构建会输出我们的dist/storage.js 文件,该文件在index.js 中引用。

    构建完成后,我们可以对我们的代码进行 webpack(将其捆绑到 HTML5 浏览器中)。我们的webpack.config.js 将我们的依赖项(dexie)的“require”名称映射到全局命名空间(window.Dexie)中的一个对象。这向我们保证,Dexie 不是我们编译代码的一部分 (dist/webpacked.js)。

    一旦我们有了webpacked.js,我们就可以在浏览器中使用它。但是我们必须确保在我们的 HTML 页面中引用了所有外部依赖项(这就是为什么 Dexie 也使用 Bower 声明为前端依赖项的原因)。

    【讨论】:

      猜你喜欢
      • 2019-08-16
      • 1970-01-01
      • 1970-01-01
      • 2016-05-16
      • 2021-09-16
      • 2020-09-14
      • 1970-01-01
      • 2019-07-21
      • 1970-01-01
      相关资源
      最近更新 更多