【问题标题】:Typescript including different files depending on compilation command打字稿包括不同的文件,具体取决于编译命令
【发布时间】:2018-05-11 08:48:51
【问题描述】:

我使用creat-react-app 来初始化一些我想在本机和网络之间共享的代码。在我的package.json 中,我有两个单独的命令用于使用react-scripts-tsreact-native-scripts-ts 为每个平台启动:

package.json

...,
"scripts": {
    "tsc": "tsc",
    "clean": "rimraf artifacts",
    "build": "npm run clean && npm run tsc --",
    "start-web": "npm run build && react-scripts-ts start",
    "start-native": "npm run build && react-native-scripts start",
},
...

(有关如何执行此操作的详细说明可在此处找到https://medium.com/@yannickdot/write-once-run-anywhere-with-create-react-native-app-and-react-native-web-ad40db63eed0

太好了,我可以在两个平台上使用react-native 组件。我遇到的问题是当我尝试使用 react-routing 等外部包时。

我将react-router-nativereact-router-dom 都包含在我的package.json 中。我正在尝试实现本文(https://medium.com/@yannickdot/hi-jared-2650fbb2eda1)中描述的内容,但使用的是打字稿而不是 JS,给我:

routing.native.tsx

export {
  NativeRouter as Router, // Rename
  Switch,
  Route,
  Link
} from 'react-router-native'

routing.web.tsx

export {
  BrowserRouter as Router,
  Switch,
  Route,
  Link
} from 'react-router-dom'

但是,与文章中描述的相反,使用 typescript 时,不会自动识别应该包含哪个文件。我得到一个简单的错误:

src/App.tsx:10:26 - error TS2307: Cannot find module './routing'.

10 import Router                        from "./routing";

这是有道理的,因为当我查看编译器的输出时,没有模块 routing 存在:

artifacts
   | App.js
   | routing 
        | routing.native.js
        | routing.web.js

如何告诉 typescript 编译器在运行 start-native 命令时包括所有 *.native.tsx 文件,在运行 start-web 命令时包括所有 *.web.tsx 文件?

理想情况下,这应该可以在编译时实现,将额外的参数传递给打字稿编译器,从而覆盖tsconfig.json。示例:

tsc --exclude="./**/*.native.tsx"

我知道这可以通过黑客解决方案来完成,例如通过编写脚本来复制整个源,删除所有不需要的文件,保留正确的文件,并编译复制的源文件夹,但我想知道是否有更简洁的方法来做到这一点。

提前致谢!

【问题讨论】:

  • 您是否将代码与 Webpack 之类的工具捆绑在一起?
  • 不 - 还没有。如果不添加另一个额外的工具,就没有办法实现这一点吗?
  • 查看我的答案以获得可能的解决方案。

标签: reactjs typescript react-native tsc tsconfig


【解决方案1】:

不使用外部工具的可能解决方案:

1。创建一个检查平台运行的函数

this question on Stackoverflow

export default function getPlatform(): string {
    if (typeof document != 'undefined') {
        // I'm on the web!
        return 'web';
    }
    else if (typeof navigator != 'undefined' && navigator.product == 'ReactNative') {
        // I'm in react-native
        return 'native';
    }
    else {
        // I'm in node js
        return 'node';
    }    
}

2。创建路由/index.ts

import getPlatfrom from '../getPlatform';

const platform = getPlatfrom();
const routing = platform === 'web' ? require('./routing.web') : require('./routing.native');

export const {Router, Switch, Route, Link} = routing;

3。使用路由

import { Route } from './routing/index';

你可以在routing/index中添加一个接口IRouting和一些类型转换,这样你就不会失去类型安全和自动补全......

【讨论】:

  • 在本机上我得到错误:.../routing/index.js:4:15 calls to 'require' expect exactly 1 string literal argument, but this was found 'require(\"routing.\" + platform.toLowerCase())' 在网络上我得到错误:./node_modules/react-router-native/NativeRouter.js Module parse failed: Unexpected token (11:2) You may need an appropriate loader to handle this file type. | */ | const NativeRouter = (props) => ( | <MemoryRouter {...props}/> | ) |
  • 特别是网络错误很奇怪,因为我知道它导入了正确的文件(我也检查了正确的内容),即从 react-router-dom 导入的 web 但它抱怨 @987654331 @类
  • 我更新了第 2 部分。创建 routing/index.ts,以避免在 require 中包含变量。我认为这应该解决第一个问题
  • 谢谢,第一个问题已解决 - 这就是接受答案的原因。第二个问题仍然存在,但这甚至可能与这个问题无关
  • 尝试在routing/index 中用eval('require')('./routing.native') 替换require('./routing.native'),看看它是否适用于两者
猜你喜欢
  • 1970-01-01
  • 2012-11-09
  • 2017-06-10
  • 1970-01-01
  • 2013-08-19
  • 2017-12-16
  • 1970-01-01
  • 2020-10-25
  • 1970-01-01
相关资源
最近更新 更多