angular - Typescript - 执行文件中的代码而不导入它们

标签 angular typescript

有什么方法可以运行文件中的代码而不将它们导入到 TypeScript (Angular 项目)中?也许通过 tsconfig 中的某些配置指定文件模式?

我想做的是将一些类注册到全局对象中,但我不想在单个文件中维护类列表。我宁愿在每个类定义下都有一行简单的代码,如下所示:

export class MyClassToRegister {...}

GlobalRegistry.register(MyClassToRegister);

我知道此代码将在导入文件时执行,但有时为时已晚。有什么办法可以实现这一点吗?

最佳答案

是的,通过使用 Webpack 的 require.context(...)您可以将文件目录导入到您的包中。

快速说明:您仍在将文件导入到 bundle 中,但您不必静态定义每个导入路径,或者在添加/删除文件时手动保持它们最新。

文件结构:

让我们使用这个示例文件结构:

src/
    items/
        item1.ts
        item2.ts
        item3.ts
    registry.ts
    index.ts

以下是我们需要从目录中获取的项目:

//item1.ts, item2.ts, item3.ts
import GlobalRegistry from "../registry";

export class Item1 {
    //...
}
GlobalRegistry.register(Item1);

加载的项目将向此服务注册自己(或任何您的业务逻辑) - 这证明项目正在加载:

//registry.ts
export default class GlobalRegistry {

    static _items = [];

    static register(cls){
        console.log('Register class: ', cls.name);
        this._items.push(cls.name);
    }

    static getItems(){
        return this._items;
    }

}

require.context(...)

使用 require.context(...) 请求“items”目录下的所有文件:

//index.ts
import GlobalRegistry from './registry';

// Import all files under './items/*.ts'
var context = require.context('./items', true, /\.ts$/);
context.keys().forEach((key) => {
    context(key);
});

console.log('Loaded classes:', GlobalRegistry.getItems());

最后,为了让 TypeScript 满意,我们声明了 Webpack 提供的 require.context() 接口(interface):

//references.d.ts

// Extend @types/node NodeRequire type to define Webpack's context function
declare interface NodeRequire {
    context: (dir: string, includeSubdirs: boolean, filter: RegExp) => any;
}

// Tell TypeScript that there is a global `require` variable available to us
declare var require: NodeRequire;

结果:

当应用程序运行时,您应该看到此注销:

Register class:  Item1
Register class:  Item2
Register class:  Item3
Loaded classes: (3) ["Item1", "Item2", "Item3"]

注释:

<强>1。包含顺序 如果您首先引用各个类,则无法保证包含的顺序。

例如,如果您显式导入一个类型并将其用作值,那么该类型将在仅通过 require.context(...)< 包含的其他类型之前加载.

示例 - 使用 Item2 作为值:

//index.ts

/* require.context(...) stuff is here */

import {Item2} from './items/Item2';
let myItem = new Item2();   // use Item2 as a value

更改加载顺序:

Register class:  Item2
Register class:  Item1
Register class:  Item3
Loaded classes: (3) ["Item2", "Item1", "Item3"]

但请注意,仅按类型(而不是按值)引用不会更改加载顺序

let myItem: Item2;  // just referencing by type won't affect load order

<强>2。需要函数依赖警告

您可能会在构建过程中收到警告,例如:require 函数的使用方式无法静态提取依赖项

这不一定有什么错误,它只是 Webpack 让你知道你正在使用 require 做一些时髦的事情 - 这是真的:)

执行此动态要求可能会影响 bundle 的树摇动或其他静态分析(即,如果不使用这些类型,则不能从 bundle 中排除它们)。但这可能是一个公平的权衡,因为不必手动管理文件导入 - 您必须根据自己的要求/项目目标进行评估。

关于angular - Typescript - 执行文件中的代码而不导入它们,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51509767/

相关文章:

angular - 使用 try_files 指令禁用单个文件的缓存

javascript - anchor href 与 angular routerlink

html - Angular - 如何使用 [ngstyle] 将对象动态传递给 div 元素

Typescript 声明一个泛型函数并为其分配一个箭头函数

angular - 如何修复 iPhone 打印的 CSS

javascript - Nodemon ts-node 无法监视 JavaScript 更改

javascript - 如何在渲染后动态取消选中和选中 Nebular 复选框

css - 如何在 Angular 7 中动态地将 CSS 应用于按钮

javascript - Angular 2 过滤管

javascript - 将对象插入对象数组 - Typescript