我试图创建一个通用的React和Typescript通用库,为了完全开发库和应用程序,在配置项目工作区时遇到了太多困难
project
├─ app
│ ├─ package.json
│ ├─ tsconfig.json
│ ├─ webpack.config.js
│ ├─ ... (other config files)
│ ├─ node_modules
│ │ ├─ ...
│ │ ├─ @types
│ │ │ ├─ ...
│ │ │ └─ react
│ │ └─ symlink(lib A)
│ └─ src
│ ├─ *.ts files
│ ├─ *.tsx files
│ └─ index.ts
│
└─ libA
├─ package.json
├─ tsconfig.json
├─ other config files
├─ node_modules
│ ├─ ...
│ └─ @types
│ ├─ ...
│ └─ react
└─ src
├─ *.ts files
├─ *.tsx files
└─ index.ts
如果 libA 中的源文件位于 app 中,则所有内容都会编译并按预期运行。
在此配置下, libA 已成功构建(tsc)。
在此配置下, app 不能与以下内容一起编译:
../libA/node_modules/@types/react/index.d.ts:2963:13 - error TS2717: Subsequent property declarations must have the same type. Property 'view' must be of type 'SVGProps<SVGViewElement>', but here has type 'SVGProps<SVGViewElement>'.
一些Google搜索建议我应该从 libA 中的node_modules中删除反应类型,但这会破坏开发过程的便利性,因为 libA 无法编译。 / p>
更多详细信息:
I develop on Mac.
npm: 6.4.1
node: 8.15.0
typescript: 3.3.3333
webpack: 4
tsconfig libA:
{
"compilerOptions": {
"strict": true,
"noUnusedLocals": true,
"declaration": true,
"sourceMap": true,
"target": "es5",
"module": "commonjs",
"outDir": "dist",
"moduleResolution": "node",
"jsx": "react",
"experimentalDecorators": true,
"baseUrl": "src"
},
"include": [
"src/**/*.ts",
"src/**/*.tsx"
],
"exclude": [
"node_modules"
]
}
tsconfig应用程序:
{
"compilerOptions": {
"strict": true,
"noUnusedLocals": true,
"removeComments": true,
"sourceMap": true,
"target": "es5",
"module": "commonjs",
"outDir": "dist",
"moduleResolution": "node",
"jsx": "react",
"lib": [
"es5",
"es6",
"es7",
"dom"
],
"baseUrl": "src"
},
"include": [
"src/**/*.ts",
"src/**/*.tsx"
],
"exclude": [
"node_modules"
]
}
我不不想使用 skipLibCheck ,因为类型是我一开始就爱上打字稿的原因...
可以肯定地认为我做错了什么。.因为我要花近一个星期的时间来打开它,并且无法确定正确的配置。.欢迎任何指导...
经过进一步调查,我发现唯一有所作为的是我是否通过npm链接使用到 libA 的符号链接
答案 0 :(得分:0)
最好,最简单的方法就是使用webpack或包裹
您将希望您的配置类似于以下内容。
const path = require("path");
const fs = require("fs");
const TerserPlugin = require('terser-webpack-plugin');
const appIndex = path.join(__dirname, "../src/main.tsx");
const appBuild = path.join(__dirname, "../build");
const { TsConfigPathsPlugin } = require('awesome-typescript-loader');
module.exports = {
context: fs.realpathSync(process.cwd()),
mode: "production",
bail: true,
devtool: false,
entry: appIndex,
output: {
path: appBuild,
filename: "dist/Components.bundle.js",
publicPath: "/",
libraryTarget: "commonjs"
},
externals: {
react: {
root: 'React',
commonjs2: 'react',
commonjs: 'react',
amd: 'react'
},
'react-dom': {
root: 'ReactDOM',
commonjs2: 'react-dom',
commonjs: 'react-dom',
amd: 'react-dom'
},
"styled-components": {
root: "styled-components",
commonjs2: "styled-components",
commonjs: "styled-components",
amd: "styled-components"
}
},
optimization: {
minimizer: [
new TerserPlugin({
terserOptions: {
parse: {
ecma: 8,
},
compress: {
ecma: 5,
warnings: false,
comparisons: false,
inline: 2,
},
mangle: {
safari10: true,
},
output: {
ecma: 5,
comments: false,
ascii_only: true,
},
},
parallel: true,
cache: true,
sourceMap: false,
})
],
},
resolve: {
extensions: [".web.js", ".mjs", ".js", ".json", ".web.jsx", ".jsx", ".ts", ".tsx"],
alias: {
"react-native": "react-native-web",
},
},
module: {
strictExportPresence: true,
rules: [
{ parser: { requireEnsure: false } },
{
test: /\.(ts|tsx)$/,
loader: require.resolve("tslint-loader"),
enforce: "pre",
},
{
oneOf: [
{
test: /\.(tsx?)$/,
loader: require.resolve('awesome-typescript-loader'),
options: {
configFileName: 'tsconfig.prod.json'
}
},
],
},
],
},
plugins: [
new TsConfigPathsPlugin()
],
node: {
dgram: "empty",
fs: "empty",
net: "empty",
tls: "empty",
child_process: "empty",
},
performance: false,
};
要了解的重要事项: libraryTarget:commonjs必须与您的tsconfig中的“模块” commonjs相匹配。 awesome-typescript-loader / webpack-cli可以是运行此程序的最新版本。 您将需要tsconfig.prod.json或更改配置的一部分。
react / reactdom / styled-components被列为“外部”,这意味着它们将不会与您的应用程序捆绑在一起,webpack会在您要导入的包中查找那些模块。
Main.tsx应该只继续导出到commonjs捆绑包中所需的每个组件,它应该看起来像这样。 // main.tsx
export { Button } from "./components/Button/Button";
export { Checkbox } from "./components/Checkbox/Checkbox";
export { DataTable } from "./components/DataTable/DataTable
测试此构建的一种快速方法是删除所有“外部”构建,然后尝试require(“ .. path ... to..bundle”)。按钮并用console.log记录。
您需要index.js和index.d.ts才能发布到私有或公共npm包
编辑:您将使用类似以下内容的webpack命令。
"build": "webpack --config ./folder/to/config//webpack.component-prod.js",
答案 1 :(得分:0)
我建议将lerna与纱线的工作区功能一起使用。
您的问题是,当您有多个软件包(取决于同一个软件包)时,它们可能引用同一个类型定义,该定义在不同的路径中存在两个副本(由于符号链接)。
请参阅:https://github.com/Microsoft/typescript/issues/6496
更多详细信息,请搜索以下关键字:“ lerna打字稿重复标识符符号链接”
接口可以合并,但类不能合并。因此,如果您从不同的包中导入模块,或者使用lerna的symlink安装依赖项,并且有两个不同的路径来查找相同的类型定义,则对类的typecheck将失败。
因此,您需要确保只有一个版本/位置的包具有类型定义。这正是yarn的工作区功能所做的-在工作区的顶层安装所有子包的依赖项。
但是请注意,由于webpack的模块解析策略,纱线的工作区功能破坏了webpack的外部选项。
答案 2 :(得分:0)
所以这是一个非常非常漫长的旅程。.但是我们已经完成了..从那时起,我们采用了最初的POC并将其转换为完整的框架。