React4xp monorepo for the NPM dependency packages required by both lib-react4xp and parent projects running react4xp (for example the react4xp starter and anything derived from it).
These packages (with this project's package names in italics) are:
- react4xp-buildconstants (constants)
- react4xp-runtime-nashornpolyfills (nashornpolyfills)
Moved to it's own repository:
- react4xp-regions (regions)
These packages don't need separate installation, they are bundled as dependencies of the main react4xp package (react4xp).
Not intended for standalone installation or use. See the docs of each unique package, in the links above.
You'll need Gradle 5+ (a 6.2.1 gradle wrapper is included), Java JDK 11, Enonic XP 7+, and Node.
Use Node 12 for development in this project and in all projects when using npm link
for linking to these packages
locally. Usually, that's when developing lib-react4xp.
Commands:
npm install
(orgradlew npmInstall
): basic setupnpm clean
: remove npm foldersgradlew build
: build (includes npmInstall)gradlew clean
: clean built filesgradlew test
: test buildgradlew npmLink
: for local development; testing these packages in consuming projects before releasing:- This runs
npm link
in all subpackages. - After this command, run the /getlinks.sh bash script at the root (windows script is missing for now, sorry) _from the root of a consuming project (
/relative/path/getlinks.sh
etc) and after runningnpm install
in that project.
- This runs
Under the packages/ folder are:
- one "mother packages", react4xp. This corresponds to the react4xp NPM package.
- several subpackages.
The packages/react4xp mother package has 3 main purposes:
- It lists all react4xp-* subpackages as
dependencies
, so that one version of the react4xp package imports and locks in a working combination of all the react4xp subpackages in any consuming project. - It supplies the NPM dependencies for all the subpackages in one place (see the important part below) so that subpackages can simply list them under
peerDependencies
. - It supplies a few .gradle files, which can be used to aid the react4xp build in a consuming project.
All the sub-packages mentioned above are dependencies of this main react4xp package. In addition react4xp-buildconstants is a dependency of react4xp-runtime-nashornpolyfills:
To avoid falling back into interdependency hell (e.g. dependabot updating the same dependencies in different subpackages, which depend on one another and requiring a lot of extra work for maintaining!), follow these rules:
- As far as possible, none of the subpackages should any
dependencies
ordevDependencies
in their package.json. Instead, this is handled by the package.json files in the root project and packages/react4xp/, like this:- A dependency in a subpackage must be listed as a
peerDependency
in that package, and as adependency
in packages/react4xp/packages.json. It must also be listed indevDependencies
(ordependencies
) in the root project's package.json. - A devDependency in a subpackages must only be listed in
devDependencies
(ordependencies
) in the root project's package.json.
- A dependency in a subpackage must be listed as a
- If adding/removing subpackages:
- Update the list under
dependencies
in packages/react4xp/package.json.
- Update the list under
- If a subpackage is a dev-time dependency of another subpackage (eg. in testing), it should be handled with symlinks (eg. to avoid that testing happens with the downloaded-from-NPM-version of the subpackage instead of actually using locally changed code).
- Symlink-dir is used to automate this during dev build, in a crossplatform way and directly after
npm install
. See thepostinstall
scripts in the root package.json. The result should be this: - All subpackages exist as symlinks to their folders, under /packages/react4xp/node_modules.
- In addition, subpackages that are dev-time required by other subpackages, have similar symlinks under /node_modules.
- Symlink-dir is used to automate this during dev build, in a crossplatform way and directly after
When committing to git, please follow the conventional commits
pattern in your messages, at least use feat:
and BREAKING CHANGE
. Also leave tags and all versioning
to lerna with the version NPM script (see below) - which depends on using git this
way.
From the project root, handles the entire file structure: triggers the same tasks in subprojects under /packages/, where needed. Only sets up NPM basis, ready for actual project building.
-
npm run setup
: initial NPM install, run this first. When this is done, node_modules have been installed across all subprojects, and interlinked. -
npm run npmInstall
(orgradlew npmInstall
): Whennpm run setup
has been run once and node_modules exists in the project root, using thenpmInstall
script updates and re-links the NPM packages but skips initial boilerplate setup to save a little time. -
npm run clean
: NPM cleanup. Removes links and node_modules across all subprojects, including the project root. Does not clean up any files from the actual project build.
After the NPM script npmInstall
(and setup
, which runs it after installing boilerplate), the state is ready for
local development of this project and for local development of lib-react4xp which uses all these projects - and
usually downloads them from NPM but can now use npm link react4xp
etc for using these packages without having to
publish them to NPM before seeing them in action.
Thins ready state should be:
- All NPM packages for both main project setup and all subprojects are found in (project root)/node_modules.
- node_modules in all subpackages ar symlinked to (project root)/node_modules ( using symlink-dir for cross-platform symlinking).
- Each of the subprojects have their own symlink under (project root)/node_modules - taking care of cross-dependencies.
NOTE:
This creates a circular graph of symlinks under node_modules in the different packages. This is fine most of the time, but important to know for two reasons:
- Occasionally, this will cause the error message
Maximum call stack size exceeded
, preventing further progress. If this happens, rebuild completely, in this order: >
gradlew clean
npm run clean
rm -rf node_modules build .gradle
npm run setup
gradlew build
> > (or if these steps are hampered too, do it manually: delete node_modules at root and in all packages and preferrably built files as described in each package's package.json, underfiles
, before finally running setup and build again)
- The packages must never be published with this circular graph. For this reason, the
versionAndPublish
task assumes it's at a ready-to-publish state (where everything is built and tested already: rungradlew build test
first), and starts by wiping all these symlinks before proceding to publish.
Again, these commands are only used from the project root:
-
gradlew build
: main build command: builds file structure ready for testing and publishing to NPM -
gradlew test
: main test command -
gradlew clean
: deletes everything built by gradle (but leaves the NPM structure alone).
gradlew versionAndPublish [ -Pdry ] [ -Pmessage='...' ]
: Auto-versions all changed packages, and publishes to NPM, after updating internal cross-dependency references. After committing your changes, run this to let lerna handle independent versioning in the packages, by tracking changes across them (use conventional-commit flags from your commit messages to track major:minor:patch versions), tagging the commit and auto-updating version tags everywhere. IMPORTANT: before runningversion
, you should have run thetest
task. And afterversionAndPublish
, verify that the react4xp-* references in all packages/*/package-lock.json files are up-to-date (i.e. don't still refer to the previous versions for their dependencies). Further description in comments in versionAndPublish.gradle. Optional parameters:-Pdry
: dry-run-Pmessage='...'
: Common description of the entire release for all changed packages, will be used in commit messages to clarify and group the multiple commits that will occur during the process.