摘要
我有一个使用Typescript的封闭源代码Next.js站点。我试图从外部开源Next.js项目(我也拥有)导入一些React组件。我试图以一种共享node_modules
的方式来完成这一任务,或者完全从封闭源代码项目中导入,并且当我修改外部项目中的文件时,我可以在Next.js中进行热重新加载。
我正在努力寻找tsconfig.json
和next.config.js
/webpack.config
的组合,以实现我想要的。
问题详情
我有两个使用Typescript的Next.js项目:
- “A”是闭源的。这是一个使用Typescript的Next.js站点。它是闭源的,因为这个站点有身份验证,安全性等。这个项目从项目B导入。
- “B”是开源的。这个项目主要包含一个大型的
Editor
组件(想想一个代码编辑器)。我希望这个项目是开源的,因为我希望编辑器是开源的。为了方便,这个项目也是一个Next.js应用程序,这样你就可以在本地运行一个热重载的服务器来在编辑器上开发,而不需要访问闭源项目。
文件夹结构类似于
A/ (closed source)
node_modules/
tsconfig.json
next.config.jstsx
pages/
index.tsx
B/ (open source)
node_modules/
tsconfig.json
next.config.js
components/
Editor.tsx
pages/
index.tsx
字符串
最终,我想做的是,在项目A中能够从项目B导入文件,就像它们是项目A本地的一样:
import Editor from '../../B/components/Editor.tsx`
型
例如:
- 当我在项目A中运行Next.js应用程序,并在项目B中修改Editor组件时,Next.js站点会热重载更改
- 当
Editor.tsx
做类似import React from 'react';
的事情时,它使用项目A的依赖项,以避免将两个版本的React捆绑到本地站点。
项目B中的Editor.tsx
还导入了一些项目A中当前没有的Node模块,比如一些第三方React库。理想情况下,我希望在A中运行的Next.js站点能够弄清楚这些依赖项需要来自B/node_modules,而像React这样的 common 库来自A/node_modules,但我也可以强迫A安装这些相同的依赖项。
我在这方面遇到的麻烦是找到next.config.js
和tsconfig.json
的正确组合来使其工作,我不清楚Next.js的热重新加载和加载如何与Typescript的外部依赖项相互作用。
我最近尝试的是把这个放在我的next.config.js
中:
transpilePackages: [
path.resolve(__dirname, '../B'),
],
型
在我的tsconfig.json
中:
"references": [
{ "path": "../B" }
],
型
为了测试这是做什么我想,我rm -rf node_modules
在项目B,以确保这些节点模块没有被使用。
但是在我的A站点中,当我导入../B/components/Editor.tsx
时,我得到:
- error ../B/src/plugins/Editor.tsx
Module not found: Can't resolve 'react/jsx-dev-runtime'
型
这告诉我,Next.js试图从B/node_modules
使用React,即使React安装在A/
我尝试过tsconfig的rootDirs
和paths
的一些配置,以及next.config.js
的transpileModules
',以及尝试修改webpack.config.rules
和webpack.config.snapshot.managedPaths
和webpack.config.watchOptions
。但我不清楚所有这些如何一起发挥作用(或不发挥作用),特别是考虑到Typescript和Webpack的相互作用。
很抱歉问了这么长的问题,我试图列出我的假设,以防我有什么错,或者你看到一个创造性的解决方案来满足我的需求。
1条答案
按热度按时间7rtdyuoh1#
这是一个非常具体的请求。在我看来,有两个选项,但模块联合选项可能是你真正想要的......我会谈到这个。
选项1:软件包B是软件包A的依赖项在我看来,您上面的设置的问题是您试图将组件用作依赖项目B,B的根位于项目A的根之外.这不起作用,因为项目B的模块解析在项目B的
node_modules
目录内查找。解决方法是将项目B放在项目A的node_modules中。
但是这种方法有一个问题,项目B是Next.js项目,所以它并没有真正配置为导出
Editor
组件。为了解决这个问题,你可以添加一个构建步骤,在项目B上运行tsc
,然后在package.json中暴露编辑器,如下所示:字符串
然而,这是一种混乱海事组织,这导致我什么是'正常'的做法,这种情况将是.
选项1A:编辑器为共享模块
这就是大多数人处理在软件包之间共享组件的方法,也就是说,将编辑器移到它自己的仓库中。也许你有足够多的这样的情况,有一个共享组件库是有意义的,不管是什么情况,你会创建一个像
MyComponentLib
这样的软件包,它成为项目A和B的直接依赖。对我来说,选项1A是可以的,但开始引入依赖地狱。你可以通过将项目A和B放在一个monorepo中来在某种程度上解决这个问题,但这是一个完全不同的对话,这让我想到...
选项二:模块联合
Module federation是Webpack 5的一项功能,允许您从远程构建导入模块。从概念上讲,项目A将拥有自己的(next.js)构建,而项目B将拥有单独的构建(就像他们现在所做的那样)。使用模块联合,您可以将Editor组件作为项目B的联合模块公开,并配置项目A以使用该模块。
在next.js中使用时,需要nextjs-mf plugin。
型
查看软件包自述文件中的示例,了解如何配置项目A。注意,
NextFederationPlugin
选项的shared
属性允许您指定在项目A和B之间共享哪些依赖项,这满足了您不捆绑重复依赖项的要求。请注意,react和其他一些东西默认使用此插件共享(请参阅DEFAULT_SHARE_SCOPE
)。注意事项:
但是,这种方法的优点在于,无论何时构建和部署项目B,项目A都会自动获取这些更改,根本不需要部署项目A!