如何将本地TypeScript包与依赖项打包,以便在其他本地Next.js项目中使用?

kyks70gy  于 12个月前  发布在  TypeScript
关注(0)|答案(5)|浏览(142)

我正在做一个项目,我有以下结构:

/         # repository root
/core     # A local, unpublished npm package used by both projectA and projectB
/projectA # A Next.js app
/projectB # Another Next.js app

字符串
我有一个/core/package.json/core/tsconfig.json,它把tsc && npm pack'd转换成一个core-1.0.0.tgz文件。这个 * 看起来 * 都在工作; tscnpm pack命令没有错误地完成,.tgz文件似乎有我所期望的所有转译的.js代码。
/core/tsconfig.json

{
  "compilerOptions": {
    "lib": ["es2022", "DOM"],
    "module": "commonjs",
    "target": "es2022",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "outDir": ".compiled",
    "declaration": true,
    "jsx": "react"
  },
  "include": ["./index.ts"]
}


/core/package.json

{
  "name": "core",
  "version": "1.0.0",
  "engines": {
    "node": "18.15.0"
  },
  "main": "./.compiled/index.js",
  "types": "./.compiled/index.d.ts",
  "files":[
    "./.compiled/**"
  ],
  "scripts": {
    "test": "ts-node ./tests.ts",
    "build": "npm install && npm run test && tsc && npm pack"
  },
  "dependencies": {
    ...
    "@uppy/aws-s3": "3.3.1",
    ...
  }
  ...
}


然后,我将core包添加到projectA,方法是将以下内容添加到/projectA/package.json

...
"dependencies": {
  ...
  "core": "../core/core-1.0.0.tgz",
  ...
},
...


我在/projectA中运行npm install,事情似乎也在工作。我在projectA/node_modules中查看,我不仅看到我的core文件夹和编译的JS,而且我还看到core中的dependencies已经被取出并安装到projectA/node_modules中。
然而,当我 * 运行 * projectA时,我立即收到一个来自core导入的错误:

Error: require() of ES Module C:\dev\repo\projectA\node_modules\@uppy\aws-s3\lib\index.js from C:\dev\repo\projectA\node_modules\core\.compiled\library\components\file-uploader\FileUploader.js not supported.
Instead change the require of index.js in C:\dev\repo\projectA\node_modules\core\.compiled\library\components\file-uploader\FileUploader.js to a dynamic import() which is available in all CommonJS modules.


@uppy/aws-s3core的子依赖之一。FileUploader.js是我创建的FileUploader.ts React组件的转译版本,它提供了一个围绕@uppy的小UI Package 器。我看到了错误消息中的文字,但我有点迷失在层之间。我怀疑我需要改变我的/core/tsconfig.json中的一些东西,但我还没找到具体需要改变的地方
/core/.../FileUploader.ts

import UppyAwsS3 from '@uppy/aws-s3'
import Uppy, { SuccessResponse, UppyFile } from '@uppy/core'
import UppyDashboard from '@uppy/dashboard'
import cx from 'classnames'
import React from 'react'

interface Props {
  className?: string
  fullWidth: boolean
  ...
}

interface State {}

class FileUploader extends React.Component<Props, State> {
  ...
  render = () => {
    return (
      <div className={cx('FileUploader', this.props.className, this.props.fullWidth && 'FileUploader--fullWidth')}>
        ...
      </div>
    )
  }
}

export default FileUploader


/projectA/tsconfig.json,供参考

{
  "compilerOptions": {
    "strict": true,
    "esModuleInterop": true,
    "jsx": "preserve",
    "lib": ["ES2022", "dom"],
  },
  "exclude": [
    "node_modules"
  ]
}


有没有人对我如何设置这个共享的TypeScript包有什么见解?我有什么看起来不对劲吗?

编辑有人建议看看this question。不幸的是,这是不一样的。我写的是TypeScript,而不是原始的vanilla JS。我问的是如何让tsc编译正确的导入语法,以便Next.js可以利用我的core CommonJS包中的共享FileReader组件,该组件依赖于ESM包@uppy/aws-s3
**更新:**我已经创建了一个显示错误的最小示例项目。它是available here

6mzjoqzu

6mzjoqzu1#

您可能需要使用lerna
Lerna是一个快速、现代的构建系统,用于管理和发布来自同一存储库的多个JavaScript/TypeScript包。
Lerna主要用于管理多项目包。

lerna init

字符串
将创建包目录和你的地方包在这里.你可以链接这些包与

lerna add shared --scope=packageA


您可以将shared模块添加到packageA节点模块中。当您添加此依赖项时,您将在共享模块的package.json中使用name

// in packge,json of packageA
  "dependencies": {
    "nameOfPackageJsonOfSharedModule": "^1.0.0",
  }


此时,您应该能够在packageA中使用shared模块

//  "nameOfPackageJsonOfSharedModule" this is the name of dependency above
const share=require("nameOfPackageJsonOfSharedModule")


如果这不起作用,你可以构建每个包并在导入模块时使用构建目录.假设你构建了shared模块,在shared模块的package.json中,添加这个

// when you import name this package, build/index.js will be executed
 "bin":"build/index.js""

disho6za

disho6za2#

您需要在compilerOptions中使用"module": "commonjs"。您可能需要根据您的确切配置稍微修改其他内容。
但是,我想鼓励你使用TurboRepo安装程序,这是由Next.js官方支持的。如果有帮助,你可以查看this template repo
我发布的一些软件包使用了这个设置

请随意探索更多。

x33g5p2x

x33g5p2x3#

您遇到的错误与Node.js中ES模块(ESM)和CommonJS模块之间的差异有关。您的共享包/core似乎使用ESM,而消费项目/projectA可能被配置为使用CommonJS,这可能导致兼容性问题。
要解决此问题,您需要确保共享包和使用项目都使用相同的模块系统,无论是ESM还是CommonJS。由于Next.js支持ESM,因此最好相应地更新配置。
1.更新共享软件包/core
在您的/core/tsconfig.json中,您应该将module选项设置为"ESNext""ES6",以指示您的软件包使用ESM。请确保将outDir设置为将保存生成的ESM文件的位置。

{
  "compilerOptions": {
    "lib": ["es2022", "DOM"],
    "module": "ESNext", // Change to "ES6" if you prefer ES6 syntax
    "target": "es2022",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "outDir": ".compiled", // Make sure it points to the correct location
    "declaration": true,
    "jsx": "react"
  },
  "include": ["./index.ts"]
}

字符串
1.更新消耗项目/projectA
/projectA/tsconfig.json中,通过将module选项设置为"ESNext""ES6",确保模块系统设置为ESM。

{
  "compilerOptions": {
    "strict": true,
    "esModuleInterop": true,
    "jsx": "preserve",
    "lib": ["ES2022", "dom"],
    "module": "ESNext", // Change to "ES6" if you prefer ES6 syntax
  },
  "exclude": [
    "node_modules"
  ]
}


通过进行这些更改,您可以确保共享包和使用项目使用相同的ESM模块系统,这应该可以解决兼容性问题。

hgqdbh6s

hgqdbh6s4#

使用pnpm而不是npm。它将依赖项打包,以便直接在其他项目中使用
https://pnpm.io/的一个。

edqdpe6u

edqdpe6u5#

我能够让我的示例成功地编译和链接!在大量的死胡同和工具研究之后,我能够让事情运行 * 而无需 * 安装任何额外的包,依赖项或工具。
以下是变化:

  • 第一个月
  • 根据Icekid's recommendation,将compilerOptions.modulecompilerOptions.target更改为ES6
  • 添加compilerOptions.moduleResolution: "Node";没有这个TypeScript似乎不喜欢我在运行tsc时的import语句。
  • projectA/next.config.js
  • 添加transpilePackages: ['core']. This is a quirk of Next.js;它的编译器不会自动将本地导入的ES6模块转译到tsconfig.json上。(这是一个ES6模块)在projectA * 中手动编译似乎正确,没有来自Next.js的抱怨。我不知道为什么有些包能够自动编译,但我的自定义本地core包需要手动告诉得到转译。

就这样,其他的设置都能保持。

相关问题