如何使用一些可选模块构建多包节点模块

How to build a multi package node module with some optional modules

几天以来我一直在尝试构建一个将由反应应用程序使用的节点模块。

今天我的模块被打包成一个大的 javascript 文件,用 webpack 打包。 此节点模块的某些部分是可选的,仅当我们想要使用某些功能(通过配置激活)时才需要。为了避免加载不必要的代码部分,我首先尝试使用 chunkingdynamic import ,如 webpack 所解释 但这没有用:块是在 dist/ 文件夹中创建和打包的,但是当从 React 应用程序调用时,我从未成功 运行 节点模块中的动态导入。应用程序抱怨无法从应用程序加载块。这对我来说很有意义,因为这个 webpack 功能更多的是为了动态加载应用程序的一部分而构建的,而不是作为节点模块依赖项按需加载代码的内部机制(但我可能是错的)。

我查看了其他项目,例如 babelreact-router,其中使用 将模块拆分为多个包lerna 纱线包 。所以我尝试用 lerna 和不同的包来构建库:

my-library
  core/
    src/
      index.js
  another-package/
    src/
      index.js

我希望来自 coreindex.js 文件仅在需要且仅当节点模块 @my-library/another-package 已安装。但我从来没有找到解决办法。 是否可以使用 ES5/ES6webpack/lerna 来实现这一点,还是我采取了错误的方法?

10 月 27 日更新

所以经过几次测试,我能够使用 Aram 解决方案和一个普通的 HTML/JS (https://github.com/PixelDuck/lerna-webpack/blob/main/a-react-app/src/client/test.html) but the solution is not working with a react app package with webpack https://github.com/PixelDuck/lerna-webpack/blob/main/a-react-app/src/client/App.js.

代码在那里可用:https://github.com/PixelDuck/lerna-webpack

打开 my-lerna-library 和 运行 的终端 yarn install yarn link:all,这将为每个包创建符号 link `yarn dev',这将创建包并监听变化

然后打开一个新终端到文件夹 a-react-appyarn 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__);

如果您需要一个具有可选依赖项的包,您可以创建一个 核心包 以及几个 功能包 (它们是 not 甚至列在 peerDependencies 中)。您可以在 optionalDependencies.

中明确列出这些功能包

另外,你的核心包应该被设计成不需要功能包,但如果安装了它们就可以正确地使用它们。例如这样 .

在您的 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 运行 dev”。我觉得这对你有用!!

我终于实现了我想要的。 此处代码:https://github.com/PixelDuck/lerna-webpack

所以想法是将 another-package webpack 配置设置为输出库作为 'global' 和核心包,用

查看这个全局变量
function isMyLernaLibraryAnotherPackageDefined() {
  return typeof myLernaLibraryAnotherPackage !== 'undefined';
}
testFromAnotherPackage() {
  if (isMyLernaLibraryAnotherPackageDefined())
    return new myLernaLibraryAnotherPackage.AnotherClass().test();
}

现在在 React 应用程序上,如果我正在导入 import '@my-lerna-library/another-package';,则会显示消息和 svg。 如果我评论这一行,找不到模块并且没有显示任何内容