I am trying since several days to build a node module which will be used by a react application.
Today my module is packaged as a big javascript file packaged with webpack.
Some part of this node module is optional and is only needed if we want to use certain features (activated through config). In order to avoid loading unecessary part of the code, I have tried first to use chunking and dynamic import as explained by webpack but this has not worked: chunks are created and packaged in the dist/
folder but i never succeed to run the dynamic import in the node module when called from the react app. The application complains that the chunk cannot be loaded from the app. This make sense for me as this webpack feature was more built to load dynamically part of the application and not as an internal mechanism for a node module dependency to load code on demand (but i could be wrong).
I looked at other projects like babel or react-router where the module is split in several package using lerna and yarn package. So i have tried to build the library with lerna with different packages:
my-library
core/
src/
index.js
another-package/
src/
index.js
I want the index.js
file from core
to call a method from index.js
from another-package
only if needed and only if the node-module @my-library/another-package
was installed. But i never found the solution to do it.
Is it possible to achieve this with ES5
/ES6
with webpack
/lerna
or did i took the wrong approach?
UPDATE October 27TH
So after several tests, I was able to use Aram solution with a plain 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.
The code is available there: https://github.com/PixelDuck/lerna-webpack.
Open a terminal to my-lerna-library
and run
yarn install
yarn link:all
, this will create symbolic link for each packages
`yarn dev', this will create bundle and listen to changes
then open a new terminal to folder a-react-app
:
yarn install
yarn link "my-lerna-library"
yarn link "@my-lerna-library/another-package"
`yarn dev``
a page will be open on http://0.0.0.0:3000
and you will see that module @my-lerna-library/another-package
is not found.
If you open http://0.0.0.0:5000/test.html
the plainJS test, everything is looking fine.
It seems that the issue is on the webpack side for the react app because when debugging the application i can see that the core package is looking to a library name my_lerna_library__WEBPACK_IMPORTED_MODULE_3__
which is not the one used by webpack when loading the other package _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__);
Finally i was able to achieve what i want. Code here: https://github.com/PixelDuck/lerna-webpack
So the idea was to set another-package webpack config to output library as 'global' and on core package, looking at this global variable with
function isMyLernaLibraryAnotherPackageDefined() {
return typeof myLernaLibraryAnotherPackage !== 'undefined';
}
testFromAnotherPackage() {
if (isMyLernaLibraryAnotherPackageDefined())
return new myLernaLibraryAnotherPackage.AnotherClass().test();
}
Now on the react app, if i am importing import '@my-lerna-library/another-package';
then message and svg are displayed.
If i am commenting this line, module is not found and nothing is displayed