简体   繁体   English

Webpack 4不按顺序加载页面

[英]Webpack 4 doesn't load page in order

I've upgraded to webpack 4 for Rails. 我已经升级到webpack 4 for Rails。 I use it with Vue.js 2. I also use chunks in my configuration. 我在Vue.js 2中使用它。我也在配置中使用块。 But since upgrading, I've noticed that the page load order is weird. 但是自升级以来,我注意到页面加载顺序很奇怪。 The page loads HTML before styles and JS has been loaded, which is not what happened before. 页面在加载样式和JS之前加载HTML,这不是之前发生的事情。 I've attached links to the videos for before and after to understand the issue better. 我已经附加了之前和之后的视频链接,以便更好地了解问题。

I've been looking in here and everywhere to find anyone with the same issue, but I couldn't... 我一直在这里和任何地方寻找有同样问题的人,但我不能......

With Webpack 3(before) 使用Webpack 3(之前)

With Webpack 4(after) 使用Webpack 4(之后)

Here are my configuration files: 这是我的配置文件:

Dev Config 开发者配置

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

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


module.exports = environment.toWebpackConfig()

Env (shared) Config 环境(共享)配置

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

Pack related to the page in the video 与视频中的页面相关的包

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

Rails view for that page 该页面的Rails视图

#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'

Update 更新

My research led me to believe its this issue: 我的研究让我相信它的这个问题:

This is happening because you're bundling with style-loader, which puts your CSS as a string inside your Javascript bundle. 之所以发生这种情况,是因为您正在使用样式加载器进行捆绑,它将您的CSS作为字符串放入Javascript包中。

So the HTML will render (very fast) while the browser is parsing your JS bundle (very slow). 因此,当浏览器解析您的JS包时,HTML将呈现(非常快)(非常慢)。 Towards the end of that bundle, the browser will find the module containing your CSS string. 在该捆绑包的末尾,浏览器将找到包含CSS字符串的模块。 Then it'll parse that and apply the styles with Javascript. 然后它将解析它并使用Javascript应用样式。

I can't find a way to improve this, so for now I've extracted the CSS I need into Rails app/assets folder, to load outside of webpack and Vue. 我找不到改进方法,所以现在我已经将我需要的CSS解压缩到Rails app/assets文件夹中,加载到webpack和Vue之外。 That fixed the pop-in issues to a degree, but I still feel like its the wrong way to go about it and is just a workaround... 这在一定程度上修复了弹出式问题,但我仍然认为这是一种错误的方法,只是一种解决方法......

It looks like your configuration with webpack3 injects css at the top of the generated html and webpack4 does it at the bottom. 看起来您的webpack3配置会在生成的html顶部注入css,而webpack4会在底部注入css。 Try to move = stylesheet_packs_with_chunks_tag 'landing_page' to the top. 尝试将= stylesheet_packs_with_chunks_tag 'landing_page'移到顶部。 I am not sure what css goes to the landing_page tag. 我不确定css会转到landing_page标记。 It might be incomplete and the rest of the css is loaded asynchronously from js. 它可能是不完整的,其余的css是从js异步加载的。 Inspect the html code generated by webpack3 and webpack4 and check the list of generated css chunks and their load order. 检查webpack3和webpack4生成的html代码,并检查生成的css块及其加载顺序列表。

I would suggest for a matter for making sure the stylesheet works properly add: 我建议确保样式表正常添加:

= content_for :head
  = stylesheet_packs_with_chunks_tag 'landing_page'

and then in the application layout (or main layout) 然后在应用程序布局(或主要布局)

= yield :head

That will ensure that stylesheets are loaded before the DOM and it is ready when javascript comes into action. 这将确保样式表在DOM 之前加载并在javascript开始运行时就绪。

While I didn't quite get to the bottom of this, but I have found an interim simple solution to get back to the original webpack 3 behaviours, of JS/CSS blocking loading of the page, inspired by this question 虽然我没有完全了解这一点,但我找到了一个临时的简单解决方案来回到原始的webpack 3行为,JS / CSS阻止加载页面,受此问题的启发

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

It forces to wait till window loads all the JS/CSS assets, before loading my Vue. 在加载我的Vue之前,它会强制等待窗口加载所有JS / CSS资源。 This worked on all, but one page, as everything except landing page is built from Vue components only. 这适用于所有页面,但只有一页,因为除了登录页面之外的所有内容都只是从Vue组件构建的。

For landing page, I've adopted @Berto suggestion to delegate JS/CSS pack load to the head, with a yield. 对于登陆页面,我已经采用@Berto建议将JS / CSS包加载委托给负责人。 So now we are also blocking execution on the landing page as well. 所以现在我们也阻止了登陆页面上的执行。 Combined, I am seeing exactly the same loading behaviour as before. 结合起来,我看到与以前完全相同的加载行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM