To complete @leymannx answer, after exporting into Feature and adding the views into Config Ignore, the following hooks can be added for additional precaution to prevent any alteration of the views.
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\views\Entity\View;
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* Implements hook_entity_predelete().
*/
function MYMODULE_entity_predelete(EntityInterface $entity) {
if ($entity instanceof View) {
// Protecting only non-local environments.
if (strpos($entity->id(), 'MYVIEW_') === 0) {
// Views are protected from deletion.
drupal_set_message(t("This view can't be deleted as it is crucial for the system to work correctly."), 'error', FALSE);
$response = new RedirectResponse('/admin/structure/views');
$response->send();
// Preventing any success messages from appearing.
exit;
}
}
}
/**
* Implements hook_entity_presave().
*/
function MYMODULE_entity_presave(EntityInterface $entity) {
// Protecting only non-local environments.
if ($entity instanceof View) {
if (!$entity->isNew() && strpos($entity->id(), 'MYVIEW_') === 0) {
// Views are protected from modification.
drupal_set_message(t("This view can't be modified as it is crucial for the system to work correctly."), 'error', FALSE);
$response = new RedirectResponse(\Drupal::request()->getRequestUri());
$response->send();
// Preventing any success messages from appearing.
exit;
}
}
}
/**
* Implements hook_form_alter().
*/
function MYMODULE_form_alter(&$form, FormStateInterface $form_state, $form_id) {
// Protecting only non-local environments.
if ($form_id === 'view_edit_form' && empty($_POST)) {
foreach ($form['#cache']['tags'] as $tag) {
if (strpos($tag, 'config:views.view.MYVIEW_') === 0) {
// Views are protected from modification.
drupal_set_message(t("Note that changes to this view won't be visible across the page. The view, in its original state, is crucial for the system to work correctly."), 'warning', FALSE);
return;
}
}
}
}
Note: Extra conditions can be added as needed like if (empty($GLOBALS['APP_ISPROD']))
or similar.