如何使用一些可选模块构建多包节点模块
Posted
技术标签:
【中文标题】如何使用一些可选模块构建多包节点模块【英文标题】:How to build a multi package node module with some optional modules 【发布时间】:2021-01-29 19:16:01 【问题描述】:几天以来,我一直在尝试构建一个节点模块,该模块将被 React 应用程序使用。
今天我的模块被打包成一个用 webpack 打包的大 javascript 文件。
此节点模块的某些部分是可选的,仅当我们想要使用某些功能(通过配置激活)时才需要。为了避免加载不必要的代码部分,我首先尝试按照 webpack 的解释使用 chunking 和 dynamic import 但这并没有工作:在dist/
文件夹中创建和打包块,但是当从反应应用程序调用时,我从未成功在节点模块中运行动态导入。应用程序抱怨无法从应用程序加载块。这对我来说很有意义,因为这个 webpack 功能更多地是为了动态加载应用程序的一部分,而不是作为节点模块依赖项按需加载代码的内部机制(但我可能是错的)。
我查看了其他项目,如 babel 或 react-router,其中模块使用 lerna 和 yarn 拆分为多个包包。所以我尝试用 lerna 和不同的包来构建库:
my-library
core/
src/
index.js
another-package/
src/
index.js
我希望 core
中的 index.js
文件仅在需要且仅在安装了节点模块 @my-library/another-package
的情况下才能从 index.js
从 another-package
调用方法。但我从来没有找到解决方案。
是否可以通过ES5
/ES6
和webpack
/lerna
实现这一目标,还是我采取了错误的方法?
10 月 27 日更新
所以经过几次测试,我能够使用带有纯 html/JS (https://github.com/PixelDuck/lerna-webpack/blob/main/a-react-app/src/client/test.html) 的 Aram 解决方案,但该解决方案不适用于带有 webpack https://github.com/PixelDuck/lerna-webpack/blob/main/a-react-app/src/client/App.js 的 React 应用程序包。
代码可在此处获得:https://github.com/PixelDuck/lerna-webpack。
打开终端到my-lerna-library
并运行
yarn install
yarn link:all
,这将为每个包创建符号链接
`yarn dev',这将创建包并监听变化
然后打开一个新终端到文件夹a-react-app
:
yarn install
yarn link "my-lerna-library"
yarn link "@my-lerna-library/another-package"
`纱线开发`
将在http://0.0.0.0:3000
上打开一个页面,您将看到模块@my-lerna-library/another-package
未找到。
如果你打开http://0.0.0.0:5000/test.html
plainJS 测试,一切看起来都很好。
似乎问题出在 react 应用程序的 webpack 方面,因为在调试应用程序时,我可以看到核心包正在寻找库名称 my_lerna_library__WEBPACK_IMPORTED_MODULE_3__
,这不是 webpack 在加载另一个时使用的库名称包_my_lerna_library_another_package__WEBPACK_IMPORTED_MODULE_2___default
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "./node_modules/react/index.js");
/* harmony import */ var _App_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./App.css */ "./src/client/App.css");
/* harmony import */ var _App_css__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_App_css__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _my_lerna_library_another_package__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @my-lerna-library/another-package */ "../my-lerna-library/packages/another-package/dist/index.bundle.js");
/* harmony import */ var _my_lerna_library_another_package__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_my_lerna_library_another_package__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var my_lerna_library__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! my-lerna-library */ "../my-lerna-library/packages/core/dist/index.bundle.js");
/* harmony import */ var my_lerna_library__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(my_lerna_library__WEBPACK_IMPORTED_MODULE_3__);
【问题讨论】:
【参考方案1】:如果您需要一个带有可选依赖项的包,您可以创建一个核心包以及几个功能包(它们是不是 甚至列在 peerDependencies 中)。您可以在optionalDependencies
中明确列出这些功能包。
此外,您的核心包的设计应使其不需要功能包,但如果已安装,则可以正确使用它们。比如这样https://***.com/a/50841764/14451484。
【讨论】:
您好,您的解决方案听起来很有希望,但我无法让它发挥作用。更改后,核心库中的方法总是返回此错误:``` 错误:在 webpackEmptyContext at loadOptionalPackage at Object../src/index.js 上找不到模块 '@my-lerna-library/another-package' b>nested_webpack_require_5300 在 index.bundle.js:19 在 index.bundle.js:192 在 webpackUniversalModuleDefinition 在 Object../node_modules/my-lerna-library/dist/index.bundle.js 在 webpack_require (引导程序:21)``` 注意 optionalDependencies 让 webpack dev 卡在核心包上,所以我不得不使用optionalPeerDependencies
。
如果你有时间看看的话,我已经在 github 上用一些新闻和一个测试用例更新了我的问题.....【参考方案2】:
在你的 my-lerna-library > 包中:-
(1) another-package package.json 文件替换为这段代码
"name": "@my-lerna-library/another-package",
"private": true,
"version": "1.0.0",
"scripts":
"dev": "webpack --watch --devtool inline-source-map --mode development",
"build": "webpack --mode production"
,
"dependencies":
"@my-lerna-library/core": "1.0.0"
和
(2) 核心 package.json 文件替换为这段代码
"name": "@my-lerna-library/core",
"private": true,
"version": "1.0.0",
"scripts":
"dev": "webpack --watch --devtool inline-source-map --mode development",
"build": "webpack --mode production"
和 my-lerna-library package.json 文件替换这样的工作区,
"workspaces":
"packages": [
"packages/**"
]
,
然后运行命令“yarn run dev”。我觉得这对你有用!!
【讨论】:
嗨。谢谢你的时间。我已经尝试过了,但它不起作用。在为核心生成的代码中,我可以看到 ``` anotherPackage = __webpack_require__(Object(function webpackMissingModule() var e = new Error("Cannot find module '@my-lerna-library/another-package'"); e。代码 = 'MODULE_NOT_FOUND'; 抛出 e; ())); ``` 所以这行不通。将核心 another-package 定义为 optionalPeerDependencies 并在 webpack 配置中声明为 external 修复代码:``` anotherPackage = __webpack_require__(/*!@my-lerna-library/another-package */ "@my-lerna-library/another -package");``` Web 应用程序上仍然存在问题: ../my-lerna-library/packages/core/dist/index.bundle.js 中的警告 6:13-57 [1] 未找到模块:错误:无法解析“/Users/olmartin/dev/js/lerna-webpack/my-lerna-library/packages/core/dist”中的“@my-lerna-library/another-package”检查分支@987654321 @ 我认为问题不在于库方面,而在于 webapp 方面,我无法在范围内导入依赖项并使核心库使用 require() 查看它。【参考方案3】:我终于能够实现我想要的。 代码在这里:https://github.com/PixelDuck/lerna-webpack
所以想法是将另一个包 webpack 配置设置为输出库为“全局”并在核心包上,查看这个全局变量
function isMyLernaLibraryAnotherPackageDefined()
return typeof myLernaLibraryAnotherPackage !== 'undefined';
testFromAnotherPackage()
if (isMyLernaLibraryAnotherPackageDefined())
return new myLernaLibraryAnotherPackage.AnotherClass().test();
现在在 react 应用程序上,如果我正在导入 import '@my-lerna-library/another-package';
then 消息和 svg 会显示。
如果我正在评论这一行,则找不到模块并且没有显示任何内容
【讨论】:
以上是关于如何使用一些可选模块构建多包节点模块的主要内容,如果未能解决你的问题,请参考以下文章