Universal CPT archive template and half working pagination

Ok. So thanks to @Milo I figure out it how it should be done. First of all in archive should be a standard loop. Then in functions.php I just add a pre_get_posts function directly for archive pages and it’s look like this:

archive-cpt.php loop:

<div class="center">
                    <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
                    <?php include 'product.php' ?>
                    <?php endwhile ?>
                    <nav class="pagination">
                        <?php
    $big = 999999999; // need an unlikely integer
    echo paginate_links( array(
    'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
    'format' => '?paged=%#%',
    'current' => max( 1, get_query_var('paged') ),
    'total' => $wp_query->max_num_pages,
    'prev_text'          => __(' « '),
    'next_text'          => __(' » '),
) );
    ?>
                    </nav>
                    <?php else : ?>
                    <p>
                        <?php esc_html_e( 'Sorry, no posts matched your criteria.' ); ?>
                    </p>
                    <?php endif; ?>
                </div>

and in functions.php:

function archive($query) {
  if ( !is_admin() && $query->is_main_query() ) {
    if ($query->is_archive) {
      $query->set('post_status', 'publish');
      $query->set('meta_key', 'order');
      $query->set('orderby', 'meta_value_num');
      $query->set('order', 'asc');
    }
  }
}

add_action('pre_get_posts','archive');

The point is do not create a new WP_Query but modifying existing. Then pagination and others functionality works fine. In pre_get_posts we can also add additional parameters to loop like ‘order’ etc using

$query->set('order', 'asc');

now everything is working.

Here’s a usefull links about:
https://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts