3
votes

Webpack 4 ne charge pas la page dans l'ordre

Je suis passé au webpack 4 pour Rails. Je l'utilise avec Vue.js 2. J'utilise également des morceaux dans ma configuration. Mais depuis la mise à niveau, j'ai remarqué que l'ordre de chargement des pages était bizarre. La page charge le HTML avant les styles et JS a été chargé, ce qui n'est pas ce qui s'est produit auparavant. J'ai joint des liens vers les vidéos d'avant et d'après pour mieux comprendre le problème.

J'ai cherché ici et partout pour trouver quelqu'un avec le même problème, mais je n'ai pas pu ...

Avec Webpack 3 (avant)

Avec Webpack 4 (après)

Voici mes fichiers de configuration:

Dev Config

#app{ data: { signed_in: "#{user_signed_in?}", errors: flash[:errors] } }
  .landing-top
    .row.banner
      %top-navigation{ ":user" => user, "logo" => logo }
      .row.start-sm.around-sm.middle-sm.center-xs.landing-hero
        .col-lg-4.col-md-4.col-sm-4.col-xs-12
          %h1= t 'static.banner.headline'
          %p= t 'static.banner.subtitle'
          .actions
            %a.no-decoration{ class: "el-button el-button--success", href: "/events" }
              See upcoming events
        .col-lg-6.col-md-6.col-sm-6.col-xs-12
          = video_tag("https://s3.eu-west-2.amazonaws.com/vras-assets/product_preview_new.webm",
                      poster: preview_poster,
                      class: "preview-video", autoplay: "true",
                      muted: "true",          loop: "true" )
  .landing-body.site-padding
    .row.around-lg.middle-lg.middle-md.features
      .col-md-4.col-xs-12.feature-column
        = inline_svg 'icons/potion.svg', class: 'svg-icon'
        %text-section{ "title" => t('static.first_section.title_one'),
                       "text"  => t('static.first_section.text_one') }
      .col-md-4.col-xs-12.feature-column
        = inline_svg 'icons/map.svg', class: 'svg-icon'
        %text-section{ "title" => t('static.first_section.title_two'),
                       "text"  => t('static.first_section.text_two') }
      .col-md-4.col-xs-12.feature-column
        = inline_svg 'icons/unicorn.svg', class: 'svg-icon'
        %text-section{ "title" => t('static.first_section.title_third'),
                       "text"  => t('static.first_section.text_third') }
  .row.center-lg.center-xs.video-showcase
    .col-lg-10.col-md-10.col-xs-12
      = video_tag('https://s3.eu-west-2.amazonaws.com/vras-assets/preview.mp4',
                  poster: 'meta_cover.jpg',
                  class: 'preview-video',
                  autoplay: 'true',
                  muted: 'true',
                  loop: 'true')
    .col-lg-8.col-md-8.col-xs-10{ style: "padding-top: 20px" }
      %h3
        = image_tag("bigscreen_logo.png", width: "250px")
        %br
        = t('static.third_section.title')
      %text-section{ "text"  => t('static.third_section.text') }
  .landing-body.site-padding
    .row.around-lg.middle-lg.middle-md{ style: "margin-bottom: 100px" }
      .col-lg-6.col-md-6.col-xs-12
        %text-section{ "title" => t('static.second_section.title'),
                       "text"  => t('static.second_section.text') }
      .col-lg-6.col-md-6.col-xs-12.first-xs.last-lg.last-md{ style: "text-align: center" }
        %iframe{:title => "Discord Widget", :allowtransparency => "true", :frameborder => "0", :height => "519", :src => "https://discordapp.com/widget?id=402246704252059648&theme=dark", :width => "320"}
  = render "footer"

= javascript_packs_with_chunks_tag 'landing_page'
= stylesheet_packs_with_chunks_tag 'landing_page'

Config Env (partagé)

import 'element-ui/lib/theme-chalk/index.css';
import 'element-ui/lib/theme-chalk/display.css';
import 'flexboxgrid/css/flexboxgrid.css';

import Vue from 'vue/dist/vue.esm';
import VueCookies from 'vue-cookies';
import { DateTime } from 'luxon';

// ElementUI Components
import ElementUI from 'element-ui';
import locale from 'element-ui/lib/locale/lang/en';

// Custom Components
import TextSection from '../components/TextSection.vue';
import TopNavigation from '../components/navigation/TheTopNavigation.vue';

import { store } from '../store';

Vue.use(ElementUI, { locale });
Vue.use(VueCookies);

const app = new Vue({
  el: '#app',
  store,
  mounted() {
    var selector = document.querySelector("#app");
    var errors   = selector.dataset.errors;

    if (selector) {
      store.commit('base_states/authenticate',
        JSON.parse(selector.dataset.signedIn)
      );
    }

    if (errors) {
      this.$message({
        dangerouslyUseHTMLString: true,
        message: JSON.parse(errors).join("\n"),
        type: 'error'
      });
    }
  },
  components: { TextSection, TopNavigation },
});

if (!app.$cookies.get('timezone')) {
  app.$cookies.set("timezone", DateTime.local().zoneName);
}

Pack lié à la page de la vidéo

const { environment } = require('@rails/webpacker')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const vue = require('./loaders/vue')

const additionalConfig = {
  plugins: [
    new VueLoaderPlugin(),
  ],
  optimization: {
    splitChunks: {
      cacheGroups: {
        default: false,
        vendor: {
          name: 'vendor',
          chunks: 'all',
          test: /[\\/]node_modules[\\/]/,
          minChunks: 3,
        },
      }
    }
  },
  module: {
    rules: [{
      test: /\.pug$/,
      loader: 'pug-plain-loader'
    }, {
      test: /\.sass$/,
      use: ['vue-style-loader', 'css-loader', 'sass-loader']
    }]
  },
  output: {
  },
  devtool: 'source-map',
}

environment.config.merge(additionalConfig);

environment.loaders.prepend('vue', vue)

module.exports = environment

Vue Rails pour cette page

const environment = require('./environment')
const BundleAnalyzerPlugin =
  require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

environment.plugins.append(
  'BundleAnalyzerPlugin',
  new BundleAnalyzerPlugin()
)


module.exports = environment.toWebpackConfig()

Mise à jour

Mes recherches m'ont amené à croire que c'est ce problème:

Cela se produit parce que vous associez avec style-loader, qui place votre CSS sous forme de chaîne dans votre bundle Javascript.

Le rendu HTML sera donc (très rapide) pendant que le navigateur analyse votre bundle JS (très lent). Vers la fin de ce bundle, le navigateur trouvera le module contenant votre chaîne CSS. Ensuite, il analysera cela et appliquera les styles avec Javascript.

Je ne trouve pas de moyen d'améliorer cela, donc pour l'instant j'ai extrait le CSS dont j'ai besoin dans le dossier Rails app / assets , pour le charger en dehors du webpack et de Vue . Cela a résolu les problèmes de pop-in dans une certaine mesure, mais j'ai toujours l'impression que ce n'est pas la bonne façon de procéder et ce n'est qu'une solution de contournement ...


0 commentaires

3 Réponses :


0
votes

Il semble que votre configuration avec webpack3 injecte du css en haut du html généré et que webpack4 le fasse en bas. Essayez de déplacer = stylesheet_packs_with_chunks_tag 'landing_page' vers le haut. Je ne suis pas sûr de ce que css va à la balise landing_page . Il peut être incomplet et le reste du css est chargé de manière asynchrone à partir de js. Inspectez le code html généré par webpack3 et webpack4 et vérifiez la liste des blocs css générés et leur ordre de chargement.


3 commentaires

Je pense qu'il se charge de manière asynchrone. J'ai déjà essayé de mettre les feuilles de style plus haut, mais cela n'a rien fait du tout. Pour contourner le problème, j'ai extrait le CSS critique dans des feuilles de style de rails, de sorte qu'il se charge en dehors du webpack et de Vue. Mais j'ai toujours l'impression qu'il ne devrait pas en être ainsi, que se passe-t-il si je décide d'avoir tous mes CSS dans des packs?


Consultez cette note github.com/rails/webpacker/blob/master/docs/...


Je l'ai vu et j'ai essayé de changer extract_css en true , mais je n'ai pas vraiment bien regardé cette chose spécifique. Je vais lui donner un autre regard



1
votes

Je suggérerais, pour s'assurer que la feuille de style fonctionne correctement, d'ajouter:

= yield :head

puis dans la mise en page de l'application (ou mise en page principale)

= content_for :head
  = stylesheet_packs_with_chunks_tag 'landing_page'


1 commentaires

Malheureusement, cela n'a pas résolu le problème. Quoi que je mette ou non les feuilles de style dans la tête, elles semblent toujours se charger dans le désordre. Je dirais même à la toute fin, d'après ce que je vois



0
votes

Bien que je ne sois pas tout à fait arrivé au fond des choses, j'ai trouvé une solution intermédiaire simple pour revenir aux comportements originaux du webpack 3, du blocage JS / CSS du chargement de la page, inspiré par ceci question

window.addEventListener('load', () => {
  ### Initialise Vue app
});

Cela oblige à attendre que la fenêtre charge tous les actifs JS / CSS, avant de charger ma Vue. Cela a fonctionné sur toutes les pages, sauf une, car tout, sauf la page de destination, est construit à partir de composants Vue uniquement.

Pour la page de destination, j'ai adopté la suggestion @Berto de déléguer la charge du pack JS / CSS à la tête, avec un rendement. Alors maintenant, nous bloquons également l'exécution sur la page de destination. Dans l'ensemble, je constate exactement le même comportement de chargement qu'avant.


0 commentaires