Circular dependency in webpack

Viewed 169
1 Answers

It's an old question but I am just posting an answer, hoping it could help someone.

In most cases, such circular dependency can be solved by separating things that do not necessarily in the same file.

The diagram below shows how the code is currently organized in files. The diagram is a class diagram, but please regard each box as a javascript file.

enter image description here

Look at step-1.js. initStep1 function and the other part of the code does not need to be in the same file. The same thing applies to step-2.js.

So, then, let's separate it into another file. As you can see below, there is no circular dependency anymore.

enter image description here


After solving the circular dependency, I think the code can be organised a bit better way.

Stepping into the code, the code implies the existence of an interface, like in the diagram below.

enter image description here

From such an aspect, IMO, it is more natural to have all the implementation of the interface in a single place. Then, the code is now organized like in the diagram below.

enter image description here

The followings are the final code. You can execute it at my CodeSandbox project at https://codesandbox.io/s/stackoverflow-circular-dependency-in-webpack-5ry7hl

index.js
import "./step-1";
import "./step-2";
step-1.js
import { goToStep } from "./go-to-step";
import allStep from "./allStep";

const btnResolve = document.querySelector(".btn-resolve-1");

btnResolve.addEventListener("click", () => {
  goToStep(allStep.step1); // <<--
});
step-2.js
import { goToStep } from "./go-to-step";
import allStep from "./allStep";

const btnResolve = document.querySelector(".btn-resolve-2");

btnResolve.addEventListener("click", () => {
  goToStep(allStep.step2); // <<--
});
go-to-step.js
export const goToStep = (step) => {
  step.init();
  let label = document.querySelector(".current-step-label");
  label.innerHTML = `<b>${step.name}</b>`;
};
allStep.js
import * as step1 from "./step-1-def";
import * as step2 from "./step-2-def";
export default { step1, step2 };
step-1-def.js
export const name = "Step 1";
export const async = true;
export function init() {
  console.log("Initializing Step 1");
}
step-2-def.js
export const name = "Step 2";
export const async = false;
export function init() {
  console.log("Initializing Step 2");
}
Related