TypeScript:如何用 window 对象替换导入?

TypeScript: How to replace imports with window objects?

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

import Dexie from "dexie";

namespace storage {
  ...
}

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

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

在 Node.js 环境中使用输出时,我对此表示满意。但是为了在浏览器中使用,我想用 window 中的对象替换 var dexie_1 = require("dexie");,例如: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"
  ]
}

How to replace imports with window objects?

这不可能。有两种选择:

使用全局对象

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

使用打包器或加载器

您可以使用捆绑器,for example Webpack. Or a loader like SystemJS

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.js开启(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 --saveDefinitelyTyped repository with the typings 工具中获得。对于 link 节点在 TypeScript 中的检索类型定义,我们需要声明 /// <reference path="../typings/index.d.ts" />.

编译 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 的前端依赖项)。