node.js - 创建一个 Typescript + React 通用库
问题描述
我尝试创建一个通用的 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的源代码在应用程序中,则所有内容都会编译构建并按预期运行。
在此配置下,libA已成功构建(tsc)。
在此配置下,应用程序不会使用以下内容进行编译:
../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>'.
一些谷歌搜索建议我应该从 libA 的 node_modules 中删除反应类型,但这会破坏开发过程的便利性,因为libA不会编译。
更多细节:
I develop on Mac.
npm: 6.4.1
node: 8.15.0
typescript: 3.3.3333
webpack: 4
tsconfig 库:
{
"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 link 来使用libA的符号链接
解决方案
最好和最简单的方法就是使用 webpack 或 parcel
你会希望你的配置类似于这样的东西..
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").Button 和 console.log 它。
您需要 index.js 和 index.d.ts 才能发布到私有或公共 npm 包
编辑:您将使用该 webpack 命令与类似..
"build": "webpack --config ./folder/to/config//webpack.component-prod.js",