首页 > 解决方案 > Typescript 中的可摇树策略模式

问题描述

我一直在尝试构建一个库,该库要求其消费者对每个目标使用特定的策略。我目前的架构如下:

[应用程序] -> 包含 -> [播放器] -> 包含 -> [渲染器]

目前,Renderer是不同平台需要更换的接口:

我可以自由使用任何捆绑器——目前使用 Webpack 作为应用程序,使用 Rollup 作为库——我可以实现的目标如下:

我的库导出一个Player接口和一个createPlayer返回PlayerInterface. 然后,在应用程序端,我有一个 Webpack 别名,它根据构建输入解析正确的平台库。

例如:

import { createPlayer } from "my-lib";


const player = createPlayer()

然后我们构建应用程序

npm run build --platform=web

webpack 会将my-lib导入转换为my-lib/platforms/web,其中还包含一个createPlayer使用正确渲染器的导出函数。

我的问题是,从应用程序的角度来看,我们如何确保在构建时为每个平台导入正确的渲染器,同时允许摇树(所以只包括正确的源)?我发现使用构建系统来做这件事是很模糊的,因为它没有留下清晰的痕迹。

有没有更好的方法来做到这一点?

最好的,

标签: javascripttypescriptnpmwebpack

解决方案


你有几个选择。我建议不要使用编译时开关,因为这需要您分发库的多个副本(这不是惯用的)。但是,如果您真的想这样做,我建议在构建时使用 webpackProvidePluginresolve.aliasconfig 字段将您的代码动态链接到适当的渲染器。

在我看来,更实用的方法是为您的应用程序设置两个入口点,并允许实现者选择使用哪个入口点。这类似于react-dom浏览器渲染和服务器渲染之间的切换(即react-domvs react-dom/server):

// index.js

export * from './shared';
export {default as renderer} from './renderers/web';
// mobile/index.js

export * from '../shared';
export {default as renderer} from '../renderers/mobile';

然后,使用您的图书馆的人可以import {renderer, foo} from 'your-lib'import {renderer, foo} from 'your-lib/mobile'.

上述两种方法都在构建时起作用。

虽然后一种方法通常会强制您选择在代码中使用哪个版本的库,但您可以使用 webpack 的resolve.alias配置字段来强制将导入your-lib重定向到your-lib/mobile.


推荐阅读