Usually the dApp take fees from user somehow, or it includes a token, which the developper gets a large amount of, and can sell as the token gains value. Its actually a pretty profitable market for a developper trust me haha
EDIT : ANSWER TO 2ND COMMENT : (You seem to be fairly new to decentralized finance (or even not familiar with the concept at all, in that case look it up 😊) and as im writing it this is turning into an essay on how the DeFi world works. Also English isn’t my native language so I hope its… readable)
Yes, the code is out there for anyone to mimic. (at least compiled bytecode is no matter what, its on the chain, and some people way smarter than me can make sense of it. But it is an extremely common practice to publish the solidity code as open source anyways (and its highly disregarded to not do so)) but that's just how it works. Blockchain is open source no matter what so you just deal with it. Assuming that you have good intentions, deploying a smart contract with any kind of exploit or anything wrong in it, or operating it wrong once its on chain implies A LOT of consequences (usually a huge lot of money lost, potentially legal trouble…) so if you’re an organization working on a project you REALLY want a developer that knows his stuff. Now there is people that’s going to hire developers to fork existing projects, but they’re usually kids or lazy guys that want to try to make some quick money by creating a token or something like that, they’re the “wrong” side of the fact that the blockchain is an open source world IMO.
You can also create a project by yourself, using some preexisting code or doing it from scratch if you want, that’s what a lot of blockchain developers do.
And for taking fees well, there’s plenty of ways to do it, it entirely depends on what your project is about. Let’s say you’re creating a staking pool where people can deposit ETH, and you want to take 2% on each deposit, you could write something like that :
address payable devWallet = yourWalletAddress;
mapping (address => uint256) stakedAmount; // You probably want to keep track of what people has staked in your contract
function payable deposit() {
uint256 devFee = msg.value.mul(2).div(100) // msg.value is the amount of ETH sent to the contract. .mul and .div are "safe" (=that checks for over/underflows) variants of the native operators. They're from the extremely widely used safeMath library.
devWallet.transfer(devFee) // This sends 'devFee' ETH to the dev wallet.
stakedAmount[msg.sender] = stakedAmount[msg.sender] + msg.value.sub(devFee); // Records in the stakedAmount mapping that the user has staked in the contract whatever he sent - the fees.
But once again, there's as many ways of doing it that there is projects out there 😊.