Webpack 4 不按顺序加载页面
Webpack 4 doesn't load page in order
我已经为 Rails 升级到 webpack 4。我将它与 Vue.js 2 一起使用。我还在我的配置中使用块。但是自升级以来,我注意到页面加载顺序很奇怪。页面在样式和 JS 加载之前加载 HTML,这不是以前发生的情况。我附上了之前和之后的视频链接,以便更好地理解问题。
我一直在这里和到处寻找有同样问题的人,但我不能...
这是我的配置文件:
开发配置
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);
}
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'
更新
我的研究让我相信这是这个问题:
This is happening because you're bundling with style-loader, which puts your CSS as a string inside your Javascript bundle.
So the HTML will render (very fast) while the browser is parsing your JS bundle (very slow). Towards the end of that bundle, the browser will find the module containing your CSS string. Then it'll parse that and apply the styles with Javascript.
我找不到改进它的方法,所以现在我已经将我需要的 CSS 提取到 Rails app/assets
文件夹中,以便在 webpack 之外加载和看。这在一定程度上解决了弹出问题,但我仍然觉得这是错误的解决方法,只是一种解决方法...
看起来你的 webpack3 配置在生成的 html 的顶部注入 css 而 webpack4 在底部注入。尝试将 = stylesheet_packs_with_chunks_tag 'landing_page'
移到顶部。我不确定 css 会转到 landing_page
标签。它可能不完整,css 的其余部分是从 js 异步加载的。检查由 webpack3 和 webpack4 生成的 html 代码,并检查生成的 css 块列表及其加载顺序。
对于确保样式表正常工作的问题,我建议添加:
= content_for :head
= stylesheet_packs_with_chunks_tag 'landing_page'
然后在应用布局(或主布局)中
= yield :head
这将确保在 DOM 之前加载样式表,并在 javascript 生效时准备就绪。
虽然我没有完全弄清楚这个问题,但我找到了一个临时的简单解决方案来恢复原来的 webpack 3 行为,JS/CSS 阻止页面加载,灵感来自这个
window.addEventListener('load', () => {
### Initialise Vue app
});
它强制等待 window 加载所有 JS/CSS 资产,然后再加载我的 Vue。这适用于所有页面,但只有一个页面,因为除了登录页面之外的所有内容都是仅由 Vue 组件构建的。
对于着陆页,我采纳了@Berto 的建议,将 JS/CSS 打包负载委托给头部,并产生收益。所以现在我们也阻止了登陆页面上的执行。结合起来,我看到了与以前完全相同的加载行为。
我已经为 Rails 升级到 webpack 4。我将它与 Vue.js 2 一起使用。我还在我的配置中使用块。但是自升级以来,我注意到页面加载顺序很奇怪。页面在样式和 JS 加载之前加载 HTML,这不是以前发生的情况。我附上了之前和之后的视频链接,以便更好地理解问题。
我一直在这里和到处寻找有同样问题的人,但我不能...
这是我的配置文件:
开发配置
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);
}
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'
更新
我的研究让我相信这是这个问题:
This is happening because you're bundling with style-loader, which puts your CSS as a string inside your Javascript bundle.
So the HTML will render (very fast) while the browser is parsing your JS bundle (very slow). Towards the end of that bundle, the browser will find the module containing your CSS string. Then it'll parse that and apply the styles with Javascript.
我找不到改进它的方法,所以现在我已经将我需要的 CSS 提取到 Rails app/assets
文件夹中,以便在 webpack 之外加载和看。这在一定程度上解决了弹出问题,但我仍然觉得这是错误的解决方法,只是一种解决方法...
看起来你的 webpack3 配置在生成的 html 的顶部注入 css 而 webpack4 在底部注入。尝试将 = stylesheet_packs_with_chunks_tag 'landing_page'
移到顶部。我不确定 css 会转到 landing_page
标签。它可能不完整,css 的其余部分是从 js 异步加载的。检查由 webpack3 和 webpack4 生成的 html 代码,并检查生成的 css 块列表及其加载顺序。
对于确保样式表正常工作的问题,我建议添加:
= content_for :head
= stylesheet_packs_with_chunks_tag 'landing_page'
然后在应用布局(或主布局)中
= yield :head
这将确保在 DOM 之前加载样式表,并在 javascript 生效时准备就绪。
虽然我没有完全弄清楚这个问题,但我找到了一个临时的简单解决方案来恢复原来的 webpack 3 行为,JS/CSS 阻止页面加载,灵感来自这个
window.addEventListener('load', () => {
### Initialise Vue app
});
它强制等待 window 加载所有 JS/CSS 资产,然后再加载我的 Vue。这适用于所有页面,但只有一个页面,因为除了登录页面之外的所有内容都是仅由 Vue 组件构建的。
对于着陆页,我采纳了@Berto 的建议,将 JS/CSS 打包负载委托给头部,并产生收益。所以现在我们也阻止了登陆页面上的执行。结合起来,我看到了与以前完全相同的加载行为。