What is the best practice of creating community users? Is it by using Site.createExternalUser api or directly inserting user object?
Creating a user and a contact in the same transaction is not allowed. You end up with a
MIXED_DML exception. Workarounds exist, but are not ideal. If you use
Site.createExternalUser, it will create the user and contact (if necessary) all in one step. In addition, you can also set their default password (or any supplied password) at once, which can also be used with
Site.validatePassword to make sure the passwords match and match the org's password policies. In other words, you should not be using a standard DML operation to create external community users. The Site method is the recommended approach.