Preston had faltered in the second half after a good first-half performance and Millwall probably deserved a point.
Simon Lynch had a right-foot shot saved by Graham Stack's legs from an Eddie Lewis pass after eight minutes and Jonathan Gould saved a shot from David Livermore soon after.
A Paul McKenna cross was headed on by Richard Cresswell and the keeper saved but the referee blew for a foul on Darren Ward.
On 15 minutes Preston winger Lewis broke the deadlock with a 20-yard shot into the bottom corner intercepting Josh Simpson's pass and beating Kevin Muscat.
A 70 yard lobed shot was saved by Stack and he also saved Cresswell's header when he pushed the ball for a corner from Graham Alexander's cross.
On the half hour Gould saved a free-kick from Jo Tessem who was replaced at half-time by Paul Ifill.
New signing Scott Dobie had an overhead kick which went wide and Daniele Dichio replaced Muscat.
Omar Daley and McKenna had shots off target and substitute Dichio hit the side netting with a shot after 77 minutes.
Hayles had a close-range shot saved with seven minutes to go and Ifill saw an 18-yard shot hit the bar with substitute Dichio volleying the rebound over the bar.
Millwall equalised with three minutes to go when Gould and Chris Lucketti collided and Gould punched the ball to Hayles whose 12 yard header went into the top right-hand corner of the net.