     end
   end
 
-  defp consult_app_file(path) do
+  # Optimize the ones coming from deps by avoiding code/erl_prim_loader
+  defp read_app(app, deps, lib_path) when is_map_key(deps, app) do
+    File.read("#{lib_path}/#{app}/ebin/#{app}.app")
+  end
+
+  defp read_app(app, _deps, _lib_path) do
+    name = Atom.to_charlist(app) ++ '.app'
+
+    with [_ | _] = path <- :code.where_is_file(name),
+         {:ok, bin, _full_name} <- :erl_prim_loader.get_file(path),
+         do: {:ok, bin}
+  end
+
+  defp consult_app_file(bin) do
     # The path could be located in an .ez archive, so we use the prim loader.
-    with {:ok, bin, _full_name} <- :erl_prim_loader.get_file(path),
-         {:ok, tokens, _} <- :erl_scan.string(String.to_charlist(bin)) do
+    with {:ok, tokens, _} <- :erl_scan.string(String.to_charlist(bin)) do
       :erl_parse.parse_term(tokens)
     end
   end

    Mix.Project.get!()
    config = Mix.Project.config()
    validate_compile_env? = "--no-validate-compile-env" not in args

    # Make sure Mix.Dep is cached to avoid loading dependencies
    # during compilation. It is likely this will be invoked anyway,


  ## App loading helpers

  defp load_apps(config, lib_path, validate_compile_env?) do
    {runtime, optional} = Mix.Tasks.Compile.App.project_apps(config)
    parent = self()
    opts = [ordered: false, timeout: :infinity]
    deps = for dep <- Mix.Dep.cached(), into: %{}, do: {dep.app, true}

    stream_apps(runtime ++ optional)
    |> Task.async_stream(&load_app(&1, parent, deps, lib_path, validate_compile_env?), opts)
    |> Stream.run()
  end

  defp load_app(app, parent, deps, lib_path, validate_compile_env?) do
    children =
      case load_app(app, deps, lib_path, validate_compile_env?) do
        :ok ->
          Application.spec(app, :applications) ++ Application.spec(app, :included_applications)

