Webpack 4 не загружает страницу по порядку - PullRequest
3 голосов
/ 17 марта 2019

Я обновился до Webpack 4 для Rails. Я использую его с Vue.js 2. Я также использую чанки в своей конфигурации. Но после обновления я заметил, что порядок загрузки страниц странный. Страница загружает HTML до того, как стили и JS были загружены, чего не было раньше. Я добавил ссылки на видео до и после, чтобы лучше понять проблему.

Я искал здесь и везде, чтобы найти кого-то с той же проблемой, но я не мог ...

С Webpack 3 (до)

С Webpack 4 (после)

Вот мои файлы конфигурации:

Dev Config

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

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


module.exports = environment.toWebpackConfig()

Конверт (общий доступ) Конфиг

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

Пакет, связанный со страницей в видео

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);
}

Рельсы для этой страницы #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' Обновление Мои исследования привели меня к мысли, что это проблема: Это происходит потому, что вы связываете с style-loader, который помещает ваш CSS как строку в ваш комплект Javascript. Таким образом, HTML будет отображаться (очень быстро), пока браузер анализирует ваш JS-пакет (очень медленно). В конце этого пакета браузер найдет модуль, содержащий вашу строку CSS. Затем он проанализирует это и применит стили с помощью Javascript. Я не могу найти способ улучшить это, поэтому сейчас я извлек нужный мне CSS-файл в папку Rails app/assets, чтобы загрузить его из webpack и Vue. Это до некоторой степени устранило проблемы с всплывающими окнами, но я все еще чувствую, что это неправильный путь, и это просто обходной путь ...

Ответы [ 3 ]

0 голосов
/ 26 марта 2019

Я бы посоветовал убедиться, что таблица стилей работает правильно, добавив:

= content_for :head
  = stylesheet_packs_with_chunks_tag 'landing_page'

и затем в макете приложения (или в основном макете)

= yield :head

Это обеспечит загрузку таблиц стилей до DOM и будет готово, когда javascript вступит в действие.

0 голосов
/ 30 марта 2019

Хотя я не совсем понял до конца, но я нашел временное простое решение, чтобы вернуться к оригинальному поведению webpack 3, к блокировке загрузки страницы JS / CSS, вдохновленной этим вопрос

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

Это заставляет ждать, пока окно загрузит все ресурсы JS / CSS, перед загрузкой моего Vue.Это работало на всех, кроме одной страницы, так как все, кроме целевой страницы, построено только из компонентов Vue.

Для целевой страницы я принял предложение @Berto делегировать загрузку пакета JS / CSS на голову, сдоход.Так что теперь мы также блокируем выполнение на целевой странице.В совокупности я вижу то же поведение при загрузке, что и раньше.

0 голосов
/ 25 марта 2019

Похоже, ваша конфигурация с webpack3 внедряет css вверху сгенерированного html, а webpack4 делает это внизу. Попробуйте переместить = stylesheet_packs_with_chunks_tag 'landing_page' наверх. Я не уверен, что CSS идет на тег landing_page. Это может быть неполным, и остальная часть CSS загружается асинхронно из js. Проверьте HTML-код, сгенерированный webpack3 и webpack4, и проверьте список сгенерированных кусков CSS и их порядок загрузки.

...