Caching additional repositories that are used to build the project

Hello everyone, we have this config.yml
In place of private, links to repositories

version: 2.1
orbs:
  node: circleci/node@4.2.0

# Reusable commands

commands:
  checkout-project-repos:
    parameters:
      branch:
        default: "develop"
        type: string
    steps:
      - run:
          name: Checkout project repos
          command: |
            git clone -q --branch= private
            git clone -q --branch= private
            git clone -q --branch= private
  install-dependencies:
    steps:
      - run:
          name: Install dependencies
          command: |
            cd ./Implementation/build
            npm install
            sudo npm install --force grunt-cli -g
            sudo npm install grunt
            cd ./
            npm install
  build-code-version:
    parameters:
      target:
        default: "development"
        type: string
    steps:
      - run:
          name: Build code version
          command: |
            cd ./Implementation/build
            grunt build --target=<<parameters.target>>
  upload-code-version:
    parameters:
      target:
        default: "development"
        type: string
    steps:
      - run:
          name: Upload code version
          command: |
            cd ./Implementation/build
            grunt upload --target=<<parameters.target>>
  activate-code-version:
    parameters:
      target:
        default: "development"
        type: string
    steps:
      - run:
          name: Activate code version
          command: |
            cd ./Implementation/build
            grunt activate --target=<<parameters.target>>

When we git clone, grunt fires installs dependencies and builds the code.
Each of the connected repositories is like a separate dependency of our project.

The problem is that changes in some of these repositories are extremely rare.

And their assembly takes 5-10 minutes, which is very long.

I want to optimize this process and for example cache it.

So that the “Checkout project repos” step will save the collected repositories, and if nothing has changed in them, do not re-do git clone, npm i, and so on.

But if there are changes on the side of the repository that we want to clone, so that it pulls it up and builds it again.
Perhaps you can suggest which solution would be the most correct for me?